Expand spectrum of window change functions

* 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'.
This commit is contained in:
Martin Rudalics 2019-01-17 10:21:07 +01:00
parent 978cf88bda
commit 0aece3e118
3 changed files with 98 additions and 10 deletions

View 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

View file

@ -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

View 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.