]> git.eshelyaron.com Git - emacs.git/commitdiff
Expand spectrum of window change functions
authorMartin Rudalics <rudalics@gmx.at>
Thu, 17 Jan 2019 09:21:07 +0000 (10:21 +0100)
committerMartin Rudalics <rudalics@gmx.at>
Thu, 17 Jan 2019 09:21:07 +0000 (10:21 +0100)
* src/window.c (run_window_change_functions): Run window
change functions for Qwindow_state_change_functions.
(resize_frame_windows): Set frame's window_change slot when
single-window frames change size.
(Qwindow_state_change_functions): New symbol.
(Vwindow_state_change_functions): New Lisp variable.
* doc/lispref/windows.texi (Selecting Windows): Mention
'window-selection/state-change-functions' and add reference to
Window Hooks.
(Window Hooks): Document 'window-state-change-functions'.
* etc/NEWS: Mention new hook 'window-state-change-functions'.

doc/lispref/windows.texi
etc/NEWS
src/window.c

index 6b5aa66a9557e6800074cf5a962f651922153a2a..afb81e6874f99e87a91b8c912de29a5c115cd721 100644 (file)
@@ -1758,7 +1758,7 @@ raise the frame or make sure input focus is directed to that frame.
 @xref{Input Focus}.
 @end defun
 
-@cindex select window hook
+@cindex select window hooks
 @cindex running a hook when a window gets selected
 For historical reasons, Emacs does not run a separate hook whenever a
 window gets selected.  Applications and internal routines often
@@ -1774,8 +1774,8 @@ useful.
   However, when its @var{norecord} argument is @code{nil},
 @code{select-window} updates the buffer list and thus indirectly runs
 the normal hook @code{buffer-list-update-hook} (@pxref{Buffer List}).
-Consequently, that hook provides a reasonable way to run a function
-whenever a window gets selected more ``permanently''.
+Consequently, that hook provides one way to run a function whenever a
+window gets selected more ``permanently''.
 
   Since @code{buffer-list-update-hook} is also run by functions that are
 not related to window management, it will usually make sense to save the
@@ -1787,6 +1787,13 @@ temporarily passes a non-@code{nil} @var{norecord} argument.  If
 possible, the macro @code{with-selected-window} (see below) should be
 used in such cases.
 
+  Emacs also runs the hook @code{window-selection-change-functions}
+whenever the redisplay routine detects that another window has been
+selected since last redisplay.  @xref{Window Hooks}, for a detailed
+explanation.  @code{window-state-change-functions} (described in the
+same section) is another abnormal hook run after a different window
+has been selected but is triggered by other window changes as well.
+
 @cindex most recently selected windows
   The sequence of calls to @code{select-window} with a non-@code{nil}
 @var{norecord} argument determines an ordering of windows by their
@@ -6039,7 +6046,7 @@ buffer are (re)fontified because a window was scrolled or its size
 changed.  @xref{Other Font Lock Variables}.
 
 @cindex window change functions
-   The remainder of this section covers four hooks that are called at
+   The remainder of this section covers five hooks that are called at
 the end of redisplay provided a significant, non-scrolling change of a
 window has been detected.  For simplicity, these hooks and the
 functions they call will be collectively referred to as @dfn{window
@@ -6108,10 +6115,37 @@ window has changed since the last time window change functions were
 run.  In this case the frame is passed as argument.
 @end defvar
 
+@cindex window state change
+The fourth of these hooks is run after a @dfn{window state change} has
+been detected, which means that at least one of the three preceding
+window changes has occurred.
+
+@defvar window-state-change-functions
+This variable specifies functions called at the end of redisplay when
+a window buffer or size change occurred or the selected window or a
+frame's selected window has changed.  The value should be a list of
+functions that take one argument.
+
+Functions specified buffer-locally are called for any window showing
+the corresponding buffer if that window has been added or assigned
+another buffer, total or body size or has been selected or deselected
+(among all windows or among all windows on its frame) since the last
+time window change functions were run.  In this case the window is
+passed as argument.
+
+Functions specified by the default value are called for a frame if at
+least one window on that frame has been added, deleted or assigned
+another buffer, total or body size or that frame has been selected or
+deselected or the frame's selected window has changed since the last
+time window change functions were run.  In this case the frame is
+passed as argument.
+@end defvar
+
 @cindex window configuration change
-The fourth of these hooks is run when a @dfn{window configuration
+The fifth of these hooks is run when a @dfn{window configuration
 change} has been detected which means that either the buffer or the
-size of a window changed.
+size of a window changed.  It differs from the four preceding hooks in
+the way it is run.
 
 @defvar window-configuration-change-hook
 This variable specifies functions called at the end of redisplay when
index 02503073c1cacd1808ac354fd36289c855222e6c..10bcc5a2ecc4bddef44ac9f1561cc07783ede5e1 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1303,14 +1303,17 @@ of the Emacs Lisp Reference manual for more detail.
 
 +++
 ** Window change functions have been redesigned completely.
+
 Hooks reacting to window changes run now only when redisplay detects
-that a change has actually occurred.  The four hooks provided are:
+that a change has actually occurred.  The five hooks provided are:
 'window-buffer-change-functions' (run after window buffers have
 changed), 'window-size-change-functions' (run after a window was
 assigned a new buffer or size), 'window-configuration-change-hook'
-(like the former but run also when a window was deleted) and
+(like the former but run also when a window was deleted),
 'window-selection-change-functions' (run when the selected window
-changed).  'window-scroll-functions' are unaffected by these changes.
+changed) and 'window-state-change-functions' (run when any of the
+preceding ones is run).  'window-scroll-functions' are unaffected by
+these changes.
 
 In addition, a number of functions now allow the caller to detect what
 has changed since last redisplay: 'window-old-buffer' returns for any
index 7eb532f78cf07085e69d50282b3e15e1e162c47c..c0d745995a802fac1ea0b08e102c32183a2f3f4f 100644 (file)
@@ -3799,7 +3799,7 @@ run_window_change_functions (void)
            run_window_change_functions_1
              (Qwindow_size_change_functions, buffer, window);
 
-         /* This window's selection has changed when it it was
+         /* This window's selection has changed when it was
             (de-)selected as its frame's or the globally selected
             window.  */
          if (((frame_selected_change
@@ -3811,6 +3811,21 @@ run_window_change_functions (void)
              && WINDOW_LIVE_P (window))
            run_window_change_functions_1
              (Qwindow_selection_change_functions, buffer, window);
+
+         /* This window's state has changed when its buffer or size
+            changed or it was (de-)selected as its frame's or the
+            globally selected window.  */
+         if ((window_buffer_change
+              || window_size_change
+              || ((frame_selected_change
+                   && (EQ (window, old_selected_window)
+                       || EQ (window, selected_window)))
+                  || (frame_selected_window_change
+                      && (EQ (window, FRAME_OLD_SELECTED_WINDOW (f))
+                          || EQ (window, FRAME_SELECTED_WINDOW (f))))))
+             && WINDOW_LIVE_P (window))
+           run_window_change_functions_1
+             (Qwindow_state_change_functions, buffer, window);
        }
 
       /* When the number of windows on a frame has decreased, at least
@@ -3840,6 +3855,15 @@ run_window_change_functions (void)
        run_window_change_functions_1
          (Qwindow_selection_change_functions, Qnil, frame);
 
+      /* A frame has changed state when a size or buffer change
+        occurrd or its selected window has changed or when it was
+        (de-)selected.  */
+      if ((frame_selected_change || frame_selected_window_change
+          || frame_buffer_change || window_deleted || frame_size_change)
+         && FRAME_LIVE_P (f))
+       run_window_change_functions_1
+         (Qwindow_state_change_functions, Qnil, frame);
+
       /* A frame's configuration changed when one of its windows has
         changed buffer or size or at least one window was deleted.  */
       if ((frame_size_change || window_deleted) && FRAME_LIVE_P (f))
@@ -4650,16 +4674,26 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise)
     /* For a leaf root window just set the size.  */
     if (horflag)
       {
+       bool changed = r->pixel_width != new_pixel_size;
+
        r->total_cols = new_size;
        r->pixel_width = new_pixel_size;
+
+       if (changed && !WINDOW_PSEUDO_P (r))
+         FRAME_WINDOW_CHANGE (f) = true;
       }
     else
       {
+       bool changed = r->pixel_height != new_pixel_size;
+
        r->top_line = FRAME_TOP_MARGIN (f);
        r->pixel_top = FRAME_TOP_MARGIN_HEIGHT (f);
 
        r->total_lines = new_size;
        r->pixel_height = new_pixel_size;
+
+       if (changed && !WINDOW_PSEUDO_P (r))
+         FRAME_WINDOW_CHANGE (f) = true;
       }
   else
     {
@@ -7953,6 +7987,7 @@ syms_of_window (void)
   Fput (Qscroll_down, Qscroll_command, Qt);
 
   DEFSYM (Qwindow_configuration_change_hook, "window-configuration-change-hook");
+  DEFSYM (Qwindow_state_change_functions, "window-state-change-functions");
   DEFSYM (Qwindow_size_change_functions, "window-size-change-functions");
   DEFSYM (Qwindow_buffer_change_functions, "window-buffer-change-functions");
   DEFSYM (Qwindow_selection_change_functions, "window-selection-change-functions");
@@ -8074,6 +8109,22 @@ the frame's selected window has changed since the last redisplay.  In
 this case the frame is passed as argument.  */);
   Vwindow_selection_change_functions = Qnil;
 
+  DEFVAR_LISP ("window-state-change-functions", Vwindow_state_change_functions,
+              doc: /* Functions called during redisplay when the window state changed.
+The value should be a list of functions that take one argument.
+
+Functions specified buffer-locally are called for each window showing
+the corresponding buffer if and only if that window has been added,
+resized, changed its buffer or has been (de-)selected since the last
+redisplay.  In this case the window is passed as argument.
+
+Functions specified by the default value are called for each frame if
+at least one window on that frame has been added, deleted, changed its
+buffer or its total or body size or the frame has been (de-)selected
+or its selected window has changed since the last redisplay.  In this
+case the frame is passed as argument.  */);
+  Vwindow_selection_change_functions = Qnil;
+
   DEFVAR_LISP ("window-configuration-change-hook", Vwindow_configuration_change_hook,
               doc: /* Functions called during redisplay when window configuration has changed.
 The value should be a list of functions that take no argument.