diff options
| author | Martin Rudalics | 2019-03-09 11:13:18 +0100 |
|---|---|---|
| committer | Martin Rudalics | 2019-03-09 11:13:18 +0100 |
| commit | 4e082ce3941a9c1fcaae509897761d3e24e08625 (patch) | |
| tree | c50e17baec00f63098e74ae750db28d8ba45f32b | |
| parent | d2270d8fc93b5fb0b82fec4d85d122ea4e38dff3 (diff) | |
| download | emacs-4e082ce3941a9c1fcaae509897761d3e24e08625.tar.gz emacs-4e082ce3941a9c1fcaae509897761d3e24e08625.zip | |
Further redesign of window change functions
* doc/lispref/windows.texi (Window Hooks): Revise description
of window change functions. Add documentation for
'window-state-change-hook' and window state change flag.
* etc/NEWS: Update entry for window change functions.
* src/frame.c (Fframe_window_state_change)
(Fset_frame_window_state_change): New functions.
* src/frame.h (struct frame): New boolean window_state_change.
(FRAME_WINDOW_STATE_CHANGE): New macro.
* src/window.c (window_change_record_frames): New static
boolean.
(window_change_record_frame): Remove function - code moved to
window_change_record.
(window_change_record): Record frame changes here taking
window_change_record_frames into account.
(run_window_change_functions_1): Set window_change_record_frames
whenever we run one of our hooks.
(run_window_change_functions): Run hooks also when
FRAME_WINDOW_STATE_CHANGE has been set. Run
Vwindow_state_change_hook. Leave decision whether to record
changes for all frames to window_change_record.
(Vwindow_state_change_functions): Update doc-string.
(Vwindow_state_change_hook): New normal hook.
| -rw-r--r-- | doc/lispref/windows.texi | 106 | ||||
| -rw-r--r-- | etc/NEWS | 18 | ||||
| -rw-r--r-- | src/frame.c | 36 | ||||
| -rw-r--r-- | src/frame.h | 8 | ||||
| -rw-r--r-- | src/window.c | 195 |
5 files changed, 247 insertions, 116 deletions
diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index 6ac7aa67286..6b716323357 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi | |||
| @@ -6046,8 +6046,8 @@ buffer are (re)fontified because a window was scrolled or its size | |||
| 6046 | changed. @xref{Other Font Lock Variables}. | 6046 | changed. @xref{Other Font Lock Variables}. |
| 6047 | 6047 | ||
| 6048 | @cindex window change functions | 6048 | @cindex window change functions |
| 6049 | The remainder of this section covers five hooks that are called at | 6049 | The remainder of this section covers six hooks that are called |
| 6050 | the end of redisplay provided a significant, non-scrolling change of a | 6050 | during redisplay provided a significant, non-scrolling change of a |
| 6051 | window has been detected. For simplicity, these hooks and the | 6051 | window has been detected. For simplicity, these hooks and the |
| 6052 | functions they call will be collectively referred to as @dfn{window | 6052 | functions they call will be collectively referred to as @dfn{window |
| 6053 | change functions}. | 6053 | change functions}. |
| @@ -6058,9 +6058,9 @@ detected, which means that a window was created, deleted or assigned | |||
| 6058 | another buffer. | 6058 | another buffer. |
| 6059 | 6059 | ||
| 6060 | @defvar window-buffer-change-functions | 6060 | @defvar window-buffer-change-functions |
| 6061 | This variable specifies functions called at the end of redisplay when | 6061 | This variable specifies functions called during redisplay when window |
| 6062 | window buffers have changed. The value should be a list of functions | 6062 | buffers have changed. The value should be a list of functions that |
| 6063 | that take one argument. | 6063 | take one argument. |
| 6064 | 6064 | ||
| 6065 | Functions specified buffer-locally are called for any window showing | 6065 | Functions specified buffer-locally are called for any window showing |
| 6066 | the corresponding buffer if that window has been created or assigned | 6066 | the corresponding buffer if that window has been created or assigned |
| @@ -6074,14 +6074,14 @@ In this case the frame is passed as argument. | |||
| 6074 | @end defvar | 6074 | @end defvar |
| 6075 | 6075 | ||
| 6076 | @cindex window size change | 6076 | @cindex window size change |
| 6077 | The second of these hooks is run after a @dfn{window size change} has | 6077 | The second of these hooks is run when a @dfn{window size change} has |
| 6078 | been detected which means that a window was created, assigned another | 6078 | been detected which means that a window was created, assigned another |
| 6079 | buffer, or changed its total size or that of its text area. | 6079 | buffer, or changed its total size or that of its text area. |
| 6080 | 6080 | ||
| 6081 | @defvar window-size-change-functions | 6081 | @defvar window-size-change-functions |
| 6082 | This variable specifies functions called at the end of redisplay when | 6082 | This variable specifies functions called during redisplay when a |
| 6083 | a window size change occurred. The value should be a list of | 6083 | window size change occurred. The value should be a list of functions |
| 6084 | functions that take one argument. | 6084 | that take one argument. |
| 6085 | 6085 | ||
| 6086 | Functions specified buffer-locally are called for any window showing | 6086 | Functions specified buffer-locally are called for any window showing |
| 6087 | the corresponding buffer if that window has been added or assigned | 6087 | the corresponding buffer if that window has been added or assigned |
| @@ -6097,13 +6097,13 @@ argument. | |||
| 6097 | @end defvar | 6097 | @end defvar |
| 6098 | 6098 | ||
| 6099 | @cindex window selection change | 6099 | @cindex window selection change |
| 6100 | The third of these hooks is run after a @dfn{window selection change} | 6100 | The third of these hooks is run when a @dfn{window selection change} |
| 6101 | has selected another window since the last redisplay. | 6101 | has selected another window since the last redisplay. |
| 6102 | 6102 | ||
| 6103 | @defvar window-selection-change-functions | 6103 | @defvar window-selection-change-functions |
| 6104 | This variable specifies functions called at the end of redisplay when | 6104 | This variable specifies functions called during redisplay when the |
| 6105 | the selected window or a frame's selected window has changed. The | 6105 | selected window or a frame's selected window has changed. The value |
| 6106 | value should be a list of functions that take one argument. | 6106 | should be a list of functions that take one argument. |
| 6107 | 6107 | ||
| 6108 | Functions specified buffer-locally are called for any window showing | 6108 | Functions specified buffer-locally are called for any window showing |
| 6109 | the corresponding buffer if that window has been selected or | 6109 | the corresponding buffer if that window has been selected or |
| @@ -6118,13 +6118,13 @@ run. In this case the frame is passed as argument. | |||
| 6118 | @end defvar | 6118 | @end defvar |
| 6119 | 6119 | ||
| 6120 | @cindex window state change | 6120 | @cindex window state change |
| 6121 | The fourth of these hooks is run after a @dfn{window state change} has | 6121 | The fourth of these hooks is run when a @dfn{window state change} has |
| 6122 | been detected, which means that at least one of the three preceding | 6122 | been detected, which means that at least one of the three preceding |
| 6123 | window changes has occurred. | 6123 | window changes has occurred. |
| 6124 | 6124 | ||
| 6125 | @defvar window-state-change-functions | 6125 | @defvar window-state-change-functions |
| 6126 | This variable specifies functions called at the end of redisplay when | 6126 | This variable specifies functions called during redisplay when a |
| 6127 | a window buffer or size change occurred or the selected window or a | 6127 | window buffer or size change occurred or the selected window or a |
| 6128 | frame's selected window has changed. The value should be a list of | 6128 | frame's selected window has changed. The value should be a list of |
| 6129 | functions that take one argument. | 6129 | functions that take one argument. |
| 6130 | 6130 | ||
| @@ -6141,6 +6141,10 @@ another buffer, changed its total or body size or that frame has been | |||
| 6141 | selected or deselected or the frame's selected window has changed | 6141 | selected or deselected or the frame's selected window has changed |
| 6142 | since the last time window change functions were run. In this case | 6142 | since the last time window change functions were run. In this case |
| 6143 | the frame is passed as argument. | 6143 | the frame is passed as argument. |
| 6144 | |||
| 6145 | Functions specified by the default value are also run for a frame when | ||
| 6146 | that frame's window state change flag (see below) has been set since | ||
| 6147 | last redisplay. | ||
| 6144 | @end defvar | 6148 | @end defvar |
| 6145 | 6149 | ||
| 6146 | @cindex window configuration change | 6150 | @cindex window configuration change |
| @@ -6150,9 +6154,9 @@ size of a window changed. It differs from the four preceding hooks in | |||
| 6150 | the way it is run. | 6154 | the way it is run. |
| 6151 | 6155 | ||
| 6152 | @defvar window-configuration-change-hook | 6156 | @defvar window-configuration-change-hook |
| 6153 | This variable specifies functions called at the end of redisplay when | 6157 | This variable specifies functions called during redisplay when either |
| 6154 | either the buffer or the size of a window has changed. The value | 6158 | the buffer or the size of a window has changed. The value should be a |
| 6155 | should be a list of functions that take no argument. | 6159 | list of functions that take no argument. |
| 6156 | 6160 | ||
| 6157 | Functions specified buffer-locally are called for any window showing | 6161 | Functions specified buffer-locally are called for any window showing |
| 6158 | the corresponding buffer if at least one window on that frame has been | 6162 | the corresponding buffer if at least one window on that frame has been |
| @@ -6168,14 +6172,29 @@ window change functions were run. Each call is performed with the | |||
| 6168 | frame temporarily selected and the selected window's buffer current. | 6172 | frame temporarily selected and the selected window's buffer current. |
| 6169 | @end defvar | 6173 | @end defvar |
| 6170 | 6174 | ||
| 6171 | Window change functions are called at the end of redisplay for each | 6175 | Finally, Emacs runs a normal hook that generalizes the behavior of |
| 6172 | frame as follows: First, any buffer-local window buffer change | 6176 | @code{window-state-change-functions}. |
| 6173 | function, window size change function, selected window change and | 6177 | |
| 6174 | window state change functions are called in this order. Next, the | 6178 | @defvar window-state-change-hook |
| 6175 | default values for these functions are called in the same order. Then | 6179 | The default value of this variable specifies functions called during |
| 6176 | any buffer-local window configuration change functions are called | 6180 | redisplay when a window state change has been detected or the window |
| 6177 | followed by functions specified by the default value of those | 6181 | state change flag has been set on at least one frame. The value |
| 6178 | functions. | 6182 | should be a list of functions that take no argument. |
| 6183 | |||
| 6184 | Applications should put a function on this hook only if they want to | ||
| 6185 | react to changes that happened on (or have been signaled for) two or | ||
| 6186 | more frames since last redisplay. In every other case, putting the | ||
| 6187 | function on @code{window-state-change-functions} should be preferred. | ||
| 6188 | @end defvar | ||
| 6189 | |||
| 6190 | Window change functions are called during redisplay for each frame as | ||
| 6191 | follows: First, any buffer-local window buffer change function, window | ||
| 6192 | size change function, selected window change and window state change | ||
| 6193 | functions are called in this order. Next, the default values for | ||
| 6194 | these functions are called in the same order. Then any buffer-local | ||
| 6195 | window configuration change functions are called followed by functions | ||
| 6196 | specified by the default value of those functions. Finally, functions | ||
| 6197 | on @code{window-state-change-hook} are run. | ||
| 6179 | 6198 | ||
| 6180 | Window change functions are run for a specific frame only if a | 6199 | Window change functions are run for a specific frame only if a |
| 6181 | corresponding change was registered for that frame earlier. Such | 6200 | corresponding change was registered for that frame earlier. Such |
| @@ -6189,6 +6208,27 @@ only if that excursion still persists at the time change functions are | |||
| 6189 | run. If it is exited earlier, hooks will be run only if registered by | 6208 | run. If it is exited earlier, hooks will be run only if registered by |
| 6190 | a change outside the scope of that excursion. | 6209 | a change outside the scope of that excursion. |
| 6191 | 6210 | ||
| 6211 | @cindex window state change flag | ||
| 6212 | The @dfn{window state change flag} of a frame, if set, will cause | ||
| 6213 | the default values of @code{window-state-change-functions} (for that | ||
| 6214 | frame) and @code{window-state-change-hook} to be run during next | ||
| 6215 | redisplay regardless of whether a window state change actually | ||
| 6216 | occurred for that frame or not. After running any functions on these | ||
| 6217 | hooks, the flag is reset for each frame. Applications can set that | ||
| 6218 | flag and inspect its value using the following functions. | ||
| 6219 | |||
| 6220 | @defun set-frame-window-state-change &optional frame arg | ||
| 6221 | This function sets @var{frame}'s window state change flag if @var{arg} | ||
| 6222 | is non-@code{nil} and resets it otherwise. @var{frame} must be a live | ||
| 6223 | frame and defaults to the selected one. | ||
| 6224 | @end defun | ||
| 6225 | |||
| 6226 | @defun frame-window-state-change &optional frame | ||
| 6227 | This functions returns @code{t} if @var{frame}'s window state change | ||
| 6228 | flag is set and @code{nil} otherwise. @var{frame} must be a live | ||
| 6229 | frame and defaults to the selected one. | ||
| 6230 | @end defun | ||
| 6231 | |||
| 6192 | While window change functions are run, the functions described next | 6232 | While window change functions are run, the functions described next |
| 6193 | can be called to get more insight into what has changed for a specific | 6233 | can be called to get more insight into what has changed for a specific |
| 6194 | window or frame since the last redisplay. All these functions take a | 6234 | window or frame since the last redisplay. All these functions take a |
| @@ -6250,12 +6290,10 @@ change functions were run. | |||
| 6250 | 6290 | ||
| 6251 | Note that window change functions provide no information about which | 6291 | Note that window change functions provide no information about which |
| 6252 | windows have been deleted since the last time they were run. If | 6292 | windows have been deleted since the last time they were run. If |
| 6253 | necessary, an application should remember any window showing a | 6293 | necessary, applications should remember any window showing a specific |
| 6254 | specific buffer in a local variable of that buffer and update it in a | 6294 | buffer in a local variable of that buffer and update it in a function |
| 6255 | function run by the default value of | 6295 | run by the default values of any of the hooks that are run when a |
| 6256 | @code{window-buffer-change-functions} or | 6296 | window buffer change was detected. |
| 6257 | @code{window-configuration-change-hook} (the only hooks triggered by | ||
| 6258 | the deletion of windows). | ||
| 6259 | 6297 | ||
| 6260 | The following caveats should be considered when adding a function | 6298 | The following caveats should be considered when adding a function |
| 6261 | to window change functions: | 6299 | to window change functions: |
| @@ -6272,7 +6310,7 @@ the buffer, size or selection status of any window because there is no | |||
| 6272 | guarantee that the information about such a change will be propagated | 6310 | guarantee that the information about such a change will be propagated |
| 6273 | to other window change functions. If at all, any such change should | 6311 | to other window change functions. If at all, any such change should |
| 6274 | be executed only by the last function listed by the default value of | 6312 | be executed only by the last function listed by the default value of |
| 6275 | @code{window-configuration-change-hook}. | 6313 | @code{window-state-change-hook}. |
| 6276 | 6314 | ||
| 6277 | @item | 6315 | @item |
| 6278 | Macros like @code{save-window-excursion}, @code{with-selected-window} | 6316 | Macros like @code{save-window-excursion}, @code{with-selected-window} |
| @@ -1424,18 +1424,20 @@ displaying the same buffer. See the node "(elisp) Face Remapping" | |||
| 1424 | of the Emacs Lisp Reference manual for more detail. | 1424 | of the Emacs Lisp Reference manual for more detail. |
| 1425 | 1425 | ||
| 1426 | +++ | 1426 | +++ |
| 1427 | ** Window change functions have been redesigned completely. | 1427 | ** Window change functions have been redesigned. |
| 1428 | 1428 | ||
| 1429 | Hooks reacting to window changes run now only when redisplay detects | 1429 | Hooks reacting to window changes run now only when redisplay detects |
| 1430 | that a change has actually occurred. The five hooks provided are: | 1430 | that a change has actually occurred. Six hooks are now provided: |
| 1431 | 'window-buffer-change-functions' (run after window buffers have | 1431 | 'window-buffer-change-functions' (run after window buffers have |
| 1432 | changed), 'window-size-change-functions' (run after a window was | 1432 | changed), 'window-size-change-functions' (run after a window was |
| 1433 | assigned a new buffer or size), 'window-configuration-change-hook' | 1433 | assigned a new buffer or size), 'window-configuration-change-hook' |
| 1434 | (like the former but run also when a window was deleted), | 1434 | (like the former but run also when a window was deleted), |
| 1435 | 'window-selection-change-functions' (run when the selected window | 1435 | 'window-selection-change-functions' (run when the selected window |
| 1436 | changed) and 'window-state-change-functions' (run when any of the | 1436 | changed) and 'window-state-change-functions' and |
| 1437 | preceding ones is run). 'window-scroll-functions' are unaffected by | 1437 | 'window-state-change-hook' (run when any of the preceding ones is |
| 1438 | these changes. | 1438 | run). Applications can enforce running the latter two using the new |
| 1439 | function 'set-frame-window-state-change'. 'window-scroll-functions' | ||
| 1440 | are unaffected by these changes. | ||
| 1439 | 1441 | ||
| 1440 | In addition, a number of functions now allow the caller to detect what | 1442 | In addition, a number of functions now allow the caller to detect what |
| 1441 | has changed since last redisplay: 'window-old-buffer' returns for any | 1443 | has changed since last redisplay: 'window-old-buffer' returns for any |
| @@ -1447,10 +1449,8 @@ during last redisplay. 'window-old-pixel-width' (renamed from | |||
| 1447 | 'window-old-body-pixel-width' and 'window-old-body-pixel-height' | 1449 | 'window-old-body-pixel-width' and 'window-old-body-pixel-height' |
| 1448 | return the total and body sizes of any window during last redisplay. | 1450 | return the total and body sizes of any window during last redisplay. |
| 1449 | 1451 | ||
| 1450 | One consequence of these changes is that all window change functions | 1452 | See the section "(elisp) Window Hooks" in the Elisp manual for a |
| 1451 | run now after functions run by 'post-command-hook'. See the section | 1453 | detailed explanation of the new behavior. |
| 1452 | "(elisp) Window Hooks" in the Elisp manual for a detailed explanation | ||
| 1453 | of the new behavior. | ||
| 1454 | 1454 | ||
| 1455 | +++ | 1455 | +++ |
| 1456 | ** New buffer display action alist entry 'dedicated'. | 1456 | ** New buffer display action alist entry 'dedicated'. |
diff --git a/src/frame.c b/src/frame.c index 1219569068e..c336369dbb5 100644 --- a/src/frame.c +++ b/src/frame.c | |||
| @@ -3611,6 +3611,40 @@ bottom edge of FRAME's display. */) | |||
| 3611 | 3611 | ||
| 3612 | return Qt; | 3612 | return Qt; |
| 3613 | } | 3613 | } |
| 3614 | |||
| 3615 | DEFUN ("frame-window-state-change", Fframe_window_state_change, | ||
| 3616 | Sframe_window_state_change, 0, 1, 0, | ||
| 3617 | doc: /* Return t if FRAME's window state change flag is set, nil otherwise. | ||
| 3618 | FRAME must be a live frame and defaults to the selected one. | ||
| 3619 | |||
| 3620 | If FRAME's window state change flag is set, the default values of | ||
| 3621 | `window-state-change-functions' and `window-state-change-hook' will be | ||
| 3622 | run during next redisplay, regardless of whether a window state change | ||
| 3623 | actually occurred on FRAME or not. After that, the value of this flag | ||
| 3624 | is reset. */) | ||
| 3625 | (Lisp_Object frame) | ||
| 3626 | { | ||
| 3627 | return FRAME_WINDOW_STATE_CHANGE (decode_live_frame (frame)) ? Qt : Qnil; | ||
| 3628 | } | ||
| 3629 | |||
| 3630 | DEFUN ("set-frame-window-state-change", Fset_frame_window_state_change, | ||
| 3631 | Sset_frame_window_state_change, 0, 2, 0, | ||
| 3632 | doc: /* Set FRAME's window state change flag according to ARG. | ||
| 3633 | Set FRAME's window state change flag if ARG is non-nil, reset it | ||
| 3634 | otherwise. | ||
| 3635 | |||
| 3636 | If FRAME's window state change flag is set, the default values of | ||
| 3637 | `window-state-change-functions' and `window-state-change-hook' will be | ||
| 3638 | run during next redisplay, regardless of whether a window state change | ||
| 3639 | actually occurred on FRAME or not. After that, the value of FRAME's | ||
| 3640 | window state change flag is reset. */) | ||
| 3641 | (Lisp_Object frame, Lisp_Object arg) | ||
| 3642 | { | ||
| 3643 | struct frame *f = decode_live_frame (frame); | ||
| 3644 | |||
| 3645 | return (FRAME_WINDOW_STATE_CHANGE (f) = !NILP (arg)) ? Qt : Qnil; | ||
| 3646 | } | ||
| 3647 | |||
| 3614 | 3648 | ||
| 3615 | /*********************************************************************** | 3649 | /*********************************************************************** |
| 3616 | Frame Parameters | 3650 | Frame Parameters |
| @@ -6256,6 +6290,8 @@ iconify the top level frame instead. */); | |||
| 6256 | defsubr (&Sframe_position); | 6290 | defsubr (&Sframe_position); |
| 6257 | defsubr (&Sset_frame_position); | 6291 | defsubr (&Sset_frame_position); |
| 6258 | defsubr (&Sframe_pointer_visible_p); | 6292 | defsubr (&Sframe_pointer_visible_p); |
| 6293 | defsubr (&Sframe_window_state_change); | ||
| 6294 | defsubr (&Sset_frame_window_state_change); | ||
| 6259 | 6295 | ||
| 6260 | #ifdef HAVE_WINDOW_SYSTEM | 6296 | #ifdef HAVE_WINDOW_SYSTEM |
| 6261 | defsubr (&Sx_get_resource); | 6297 | defsubr (&Sx_get_resource); |
diff --git a/src/frame.h b/src/frame.h index 544e0bef17a..5bac24b077e 100644 --- a/src/frame.h +++ b/src/frame.h | |||
| @@ -334,6 +334,10 @@ struct frame | |||
| 334 | frame. */ | 334 | frame. */ |
| 335 | bool_bf window_change : 1; | 335 | bool_bf window_change : 1; |
| 336 | 336 | ||
| 337 | /* True if running window state change functions has been explicitly | ||
| 338 | requested for this frame since last redisplay. */ | ||
| 339 | bool_bf window_state_change : 1; | ||
| 340 | |||
| 337 | /* True if the mouse has moved on this display device | 341 | /* True if the mouse has moved on this display device |
| 338 | since the last time we checked. */ | 342 | since the last time we checked. */ |
| 339 | bool_bf mouse_moved : 1; | 343 | bool_bf mouse_moved : 1; |
| @@ -944,6 +948,10 @@ default_pixels_per_inch_y (void) | |||
| 944 | window change functions were run on F. */ | 948 | window change functions were run on F. */ |
| 945 | #define FRAME_WINDOW_CHANGE(f) (f)->window_change | 949 | #define FRAME_WINDOW_CHANGE(f) (f)->window_change |
| 946 | 950 | ||
| 951 | /* True if running window state change functions has been explicitly | ||
| 952 | requested for this frame since last redisplay. */ | ||
| 953 | #define FRAME_WINDOW_STATE_CHANGE(f) (f)->window_state_change | ||
| 954 | |||
| 947 | /* The minibuffer window of frame F, if it has one; otherwise nil. */ | 955 | /* The minibuffer window of frame F, if it has one; otherwise nil. */ |
| 948 | #define FRAME_MINIBUF_WINDOW(f) f->minibuffer_window | 956 | #define FRAME_MINIBUF_WINDOW(f) f->minibuffer_window |
| 949 | 957 | ||
diff --git a/src/window.c b/src/window.c index 8543cbf5ae9..c498ae81cdb 100644 --- a/src/window.c +++ b/src/window.c | |||
| @@ -88,6 +88,9 @@ static Lisp_Object old_selected_window; | |||
| 88 | by setting it to nil. */ | 88 | by setting it to nil. */ |
| 89 | Lisp_Object Vwindow_list; | 89 | Lisp_Object Vwindow_list; |
| 90 | 90 | ||
| 91 | /* True mean window_change_record has to record all live frames. */ | ||
| 92 | static bool window_change_record_frames; | ||
| 93 | |||
| 91 | /* The mini-buffer window of the selected frame. | 94 | /* The mini-buffer window of the selected frame. |
| 92 | Note that you cannot test for mini-bufferness of an arbitrary window | 95 | Note that you cannot test for mini-bufferness of an arbitrary window |
| 93 | by comparing against this; but you can test for mini-bufferness of | 96 | by comparing against this; but you can test for mini-bufferness of |
| @@ -3426,8 +3429,8 @@ run_window_configuration_change_hook (struct frame *f) | |||
| 3426 | XSETFRAME (frame, f); | 3429 | XSETFRAME (frame, f); |
| 3427 | 3430 | ||
| 3428 | if (NILP (Vrun_hooks) | 3431 | if (NILP (Vrun_hooks) |
| 3429 | || !(f->can_x_set_window_size) | 3432 | || !f->can_x_set_window_size |
| 3430 | || !(f->after_make_frame)) | 3433 | || !f->after_make_frame) |
| 3431 | return; | 3434 | return; |
| 3432 | 3435 | ||
| 3433 | /* Use the right buffer. Matters when running the local hooks. */ | 3436 | /* Use the right buffer. Matters when running the local hooks. */ |
| @@ -3574,48 +3577,49 @@ window_change_record_windows (Lisp_Object window, int stamp, ptrdiff_t number) | |||
| 3574 | 3577 | ||
| 3575 | 3578 | ||
| 3576 | /** | 3579 | /** |
| 3577 | * window_change_record_frame: | ||
| 3578 | * | ||
| 3579 | * Record changes for FRAME. This records FRAME's selected window, | ||
| 3580 | * updates FRAME's change stamp, records the states of all live | ||
| 3581 | * windows of FRAME via window_change_record_windows and resets | ||
| 3582 | * FRAME's window_change flag. | ||
| 3583 | */ | ||
| 3584 | static void | ||
| 3585 | window_change_record_frame (Lisp_Object frame) | ||
| 3586 | { | ||
| 3587 | struct frame *f = XFRAME (frame); | ||
| 3588 | |||
| 3589 | /* Record selected window. */ | ||
| 3590 | fset_old_selected_window (f, FRAME_SELECTED_WINDOW (f)); | ||
| 3591 | |||
| 3592 | /* Bump up FRAME's change stamp. If this wraps, make it 1 to avoid | ||
| 3593 | that a new window (whose change stamp is always set to 0) gets | ||
| 3594 | reported as "existing before". */ | ||
| 3595 | f->change_stamp += 1; | ||
| 3596 | if (f->change_stamp == 0) | ||
| 3597 | f->change_stamp = 1; | ||
| 3598 | |||
| 3599 | /* Bump up the change stamps of all live windows on this frame so | ||
| 3600 | the next call of this function can tell whether any of them | ||
| 3601 | "existed before" and record state for each of these windows. */ | ||
| 3602 | f->number_of_windows | ||
| 3603 | = window_change_record_windows (f->root_window, f->change_stamp, 0); | ||
| 3604 | |||
| 3605 | /* Reset our flag. */ | ||
| 3606 | FRAME_WINDOW_CHANGE (f) = false; | ||
| 3607 | } | ||
| 3608 | |||
| 3609 | |||
| 3610 | /** | ||
| 3611 | * window_change_record: | 3580 | * window_change_record: |
| 3612 | * | 3581 | * |
| 3582 | * For each frame that has recorded changes, record its selected | ||
| 3583 | * window, update Fchange stamp, record the states of all its live | ||
| 3584 | * windows via window_change_record_windows and reset its | ||
| 3585 | * window_change and window_state_change flags. | ||
| 3586 | * | ||
| 3613 | * Record selected window in old_selected_window and selected frame in | 3587 | * Record selected window in old_selected_window and selected frame in |
| 3614 | * old_selected_frame. | 3588 | * old_selected_frame. |
| 3615 | */ | 3589 | */ |
| 3616 | static void | 3590 | static void |
| 3617 | window_change_record (void) | 3591 | window_change_record (void) |
| 3618 | { | 3592 | { |
| 3593 | if (window_change_record_frames) | ||
| 3594 | { | ||
| 3595 | Lisp_Object tail, frame; | ||
| 3596 | |||
| 3597 | FOR_EACH_FRAME (tail, frame) | ||
| 3598 | { | ||
| 3599 | struct frame *f = XFRAME (frame); | ||
| 3600 | |||
| 3601 | /* Record FRAME's selected window. */ | ||
| 3602 | fset_old_selected_window (f, FRAME_SELECTED_WINDOW (f)); | ||
| 3603 | |||
| 3604 | /* Bump up FRAME's change stamp. If this wraps, make it 1 to avoid | ||
| 3605 | that a new window (whose change stamp is always set to 0) gets | ||
| 3606 | reported as "existing before". */ | ||
| 3607 | f->change_stamp += 1; | ||
| 3608 | if (f->change_stamp == 0) | ||
| 3609 | f->change_stamp = 1; | ||
| 3610 | |||
| 3611 | /* Bump up the change stamps of all live windows on this frame so | ||
| 3612 | the next call of this function can tell whether any of them | ||
| 3613 | "existed before" and record state for each of these windows. */ | ||
| 3614 | f->number_of_windows | ||
| 3615 | = window_change_record_windows (f->root_window, f->change_stamp, 0); | ||
| 3616 | |||
| 3617 | /* Reset our flags. */ | ||
| 3618 | FRAME_WINDOW_CHANGE (f) = false; | ||
| 3619 | FRAME_WINDOW_STATE_CHANGE (f) = false; | ||
| 3620 | } | ||
| 3621 | } | ||
| 3622 | |||
| 3619 | /* Strictly spoken we don't need old_selected_window at all - its | 3623 | /* Strictly spoken we don't need old_selected_window at all - its |
| 3620 | value is the old selected window of old_selected_frame. */ | 3624 | value is the old selected window of old_selected_frame. */ |
| 3621 | old_selected_window = selected_window; | 3625 | old_selected_window = selected_window; |
| @@ -3647,8 +3651,18 @@ run_window_change_functions_1 (Lisp_Object symbol, Lisp_Object buffer, | |||
| 3647 | 3651 | ||
| 3648 | while (CONSP (funs)) | 3652 | while (CONSP (funs)) |
| 3649 | { | 3653 | { |
| 3650 | if (!EQ (XCAR (funs), Qt)) | 3654 | if (!EQ (XCAR (funs), Qt) |
| 3651 | safe_call1 (XCAR (funs), window_or_frame); | 3655 | && (NILP (buffer) |
| 3656 | ? FRAME_LIVE_P (XFRAME (window_or_frame)) | ||
| 3657 | : WINDOW_LIVE_P (window_or_frame))) | ||
| 3658 | { | ||
| 3659 | /* Any function called here may change the state of any | ||
| 3660 | frame. Make sure to record changes for each live frame | ||
| 3661 | in window_change_record later. */ | ||
| 3662 | window_change_record_frames = true; | ||
| 3663 | safe_call1 (XCAR (funs), window_or_frame); | ||
| 3664 | } | ||
| 3665 | |||
| 3652 | funs = XCDR (funs); | 3666 | funs = XCDR (funs); |
| 3653 | } | 3667 | } |
| 3654 | } | 3668 | } |
| @@ -3661,8 +3675,9 @@ run_window_change_functions_1 (Lisp_Object symbol, Lisp_Object buffer, | |||
| 3661 | * must be called from a "safe" position in redisplay_internal. | 3675 | * must be called from a "safe" position in redisplay_internal. |
| 3662 | * | 3676 | * |
| 3663 | * Do not run any functions for a frame whose window_change flag is | 3677 | * Do not run any functions for a frame whose window_change flag is |
| 3664 | * nil and where no window selection happened since the last time this | 3678 | * nil, where no window selection happened and whose window state |
| 3665 | * function was called. Also, skip any tooltip frame. | 3679 | * change flag was not set since the last time this function was |
| 3680 | * called. Never run any functions for tooltip frames. | ||
| 3666 | * | 3681 | * |
| 3667 | * The change functions run are, in this order: | 3682 | * The change functions run are, in this order: |
| 3668 | * | 3683 | * |
| @@ -3679,25 +3694,35 @@ run_window_change_functions_1 (Lisp_Object symbol, Lisp_Object buffer, | |||
| 3679 | * `window-selected-change-functions' run for a window that was | 3694 | * `window-selected-change-functions' run for a window that was |
| 3680 | * (de-)selected since the last time window change functions were run. | 3695 | * (de-)selected since the last time window change functions were run. |
| 3681 | * | 3696 | * |
| 3697 | * `window-state-change-functions' run for a window for which any of | ||
| 3698 | * the above three changes occurred. | ||
| 3699 | * | ||
| 3682 | * A buffer-local value of these functions is run if and only if the | 3700 | * A buffer-local value of these functions is run if and only if the |
| 3683 | * window for which the functions are run, currently shows the buffer. | 3701 | * window for which the functions are run currently shows the buffer. |
| 3684 | * Each call gets one argument - the window showing the buffer. This | 3702 | * Each call gets one argument - the window showing the buffer. This |
| 3685 | * means that the buffer-local value of these functions may be called | 3703 | * means that the buffer-local value of these functions may be called |
| 3686 | * as many times at the buffer is shown on the frame. | 3704 | * as many times as the buffer is shown on the frame. |
| 3687 | * | 3705 | * |
| 3688 | * The default value of these functions is called only after all | 3706 | * The default values of these functions are called only after all |
| 3689 | * buffer-local values for all of these functions have been run. Each | 3707 | * buffer-local values for all of these functions have been run. Each |
| 3690 | * such call receives one argument - the frame for which this function | 3708 | * such call receives one argument - the frame for which a change |
| 3691 | * is run. | 3709 | * occurred. Functions on `window-state-change-functions' are run |
| 3710 | * also if the corresponding frame's window state change flag has been | ||
| 3711 | * set. | ||
| 3692 | * | 3712 | * |
| 3693 | * After the three change functions cited above have been run in the | 3713 | * After the four change functions cited above have been run in the |
| 3694 | * indicated way, functions on 'window-configuration-change-hook' are | 3714 | * indicated way, functions on 'window-configuration-change-hook' are |
| 3695 | * run. A buffer-local value is run if a window shows that buffer and | 3715 | * run. A buffer-local value is run if a window shows that buffer and |
| 3696 | * has either changed its buffer or its body or total size or did not | 3716 | * has either changed its buffer or its body or total size or did not |
| 3697 | * appear on this frame since the last time window change functions | 3717 | * appear on this frame since the last time window change functions |
| 3698 | * were run. The functions are called without argument and the | 3718 | * were run. The functions are called without argument and with the |
| 3699 | * buffer's window selected. The default value is run without | 3719 | * buffer's window selected. The default value is run without |
| 3700 | * argument and the frame for which the function is run selected. | 3720 | * argument and with the frame for which the function is run selected. |
| 3721 | * | ||
| 3722 | * In a final step, functions on `window-state-change-hook' are run | ||
| 3723 | * provided a window state change has occurred or the window state | ||
| 3724 | * change flag has been set on at least one frame. Each of these | ||
| 3725 | * functions is called without argument. | ||
| 3701 | * | 3726 | * |
| 3702 | * This function does not save and restore match data. Any functions | 3727 | * This function does not save and restore match data. Any functions |
| 3703 | * it calls are responsible for doing that themselves. | 3728 | * it calls are responsible for doing that themselves. |
| @@ -3707,8 +3732,10 @@ run_window_change_functions (void) | |||
| 3707 | { | 3732 | { |
| 3708 | Lisp_Object tail, frame; | 3733 | Lisp_Object tail, frame; |
| 3709 | bool selected_frame_change = !EQ (selected_frame, old_selected_frame); | 3734 | bool selected_frame_change = !EQ (selected_frame, old_selected_frame); |
| 3710 | ptrdiff_t count_outer = SPECPDL_INDEX (); | 3735 | bool run_window_state_change_hook = false; |
| 3736 | ptrdiff_t count = SPECPDL_INDEX (); | ||
| 3711 | 3737 | ||
| 3738 | window_change_record_frames = false; | ||
| 3712 | record_unwind_protect_void (window_change_record); | 3739 | record_unwind_protect_void (window_change_record); |
| 3713 | specbind (Qinhibit_redisplay, Qt); | 3740 | specbind (Qinhibit_redisplay, Qt); |
| 3714 | 3741 | ||
| @@ -3725,19 +3752,21 @@ run_window_change_functions (void) | |||
| 3725 | || EQ (frame, selected_frame))); | 3752 | || EQ (frame, selected_frame))); |
| 3726 | bool frame_selected_window_change | 3753 | bool frame_selected_window_change |
| 3727 | = !EQ (FRAME_OLD_SELECTED_WINDOW (f), FRAME_SELECTED_WINDOW (f)); | 3754 | = !EQ (FRAME_OLD_SELECTED_WINDOW (f), FRAME_SELECTED_WINDOW (f)); |
| 3755 | bool frame_window_state_change = FRAME_WINDOW_STATE_CHANGE (f); | ||
| 3728 | bool window_deleted = false; | 3756 | bool window_deleted = false; |
| 3729 | Lisp_Object windows; | 3757 | Lisp_Object windows; |
| 3730 | ptrdiff_t number_of_windows; | 3758 | ptrdiff_t number_of_windows; |
| 3731 | ptrdiff_t count_inner = SPECPDL_INDEX (); | ||
| 3732 | 3759 | ||
| 3733 | if (!f->can_x_set_window_size | 3760 | if (!FRAME_LIVE_P (f) |
| 3761 | || !f->can_x_set_window_size | ||
| 3734 | || !f->after_make_frame | 3762 | || !f->after_make_frame |
| 3735 | || FRAME_TOOLTIP_P (f) | 3763 | || FRAME_TOOLTIP_P (f) |
| 3736 | || !(frame_window_change | 3764 | || !(frame_window_change |
| 3737 | || frame_selected_change | 3765 | || frame_selected_change |
| 3738 | || frame_selected_window_change)) | 3766 | || frame_selected_window_change |
| 3739 | /* Either we cannot run hooks for this frame yet or no window | 3767 | || frame_window_state_change)) |
| 3740 | change has been reported for this frame since the last time | 3768 | /* Either we are not allowed to run hooks for this frame or no |
| 3769 | window change has been reported for it since the last time | ||
| 3741 | we ran window change functions on it. */ | 3770 | we ran window change functions on it. */ |
| 3742 | continue; | 3771 | continue; |
| 3743 | 3772 | ||
| @@ -3745,8 +3774,6 @@ run_window_change_functions (void) | |||
| 3745 | windows = Fnreverse (window_sub_list (root, Qnil)); | 3774 | windows = Fnreverse (window_sub_list (root, Qnil)); |
| 3746 | number_of_windows = 0; | 3775 | number_of_windows = 0; |
| 3747 | 3776 | ||
| 3748 | record_unwind_protect (window_change_record_frame, frame); | ||
| 3749 | |||
| 3750 | /* The following loop collects all data needed to tell whether | 3777 | /* The following loop collects all data needed to tell whether |
| 3751 | the default value of a hook shall be run and runs any buffer | 3778 | the default value of a hook shall be run and runs any buffer |
| 3752 | local hooks right away. */ | 3779 | local hooks right away. */ |
| @@ -3857,13 +3884,21 @@ run_window_change_functions (void) | |||
| 3857 | (Qwindow_selection_change_functions, Qnil, frame); | 3884 | (Qwindow_selection_change_functions, Qnil, frame); |
| 3858 | 3885 | ||
| 3859 | /* A frame has changed state when a size or buffer change | 3886 | /* A frame has changed state when a size or buffer change |
| 3860 | occurrd or its selected window has changed or when it was | 3887 | occurred, its selected window has changed, when it was |
| 3861 | (de-)selected. */ | 3888 | (de-)selected or its window state change flag was set. */ |
| 3862 | if ((frame_selected_change || frame_selected_window_change | 3889 | if ((frame_selected_change || frame_selected_window_change |
| 3863 | || frame_buffer_change || window_deleted || frame_size_change) | 3890 | || frame_buffer_change || window_deleted |
| 3891 | || frame_size_change || frame_window_state_change) | ||
| 3864 | && FRAME_LIVE_P (f)) | 3892 | && FRAME_LIVE_P (f)) |
| 3865 | run_window_change_functions_1 | 3893 | { |
| 3866 | (Qwindow_state_change_functions, Qnil, frame); | 3894 | run_window_change_functions_1 |
| 3895 | (Qwindow_state_change_functions, Qnil, frame); | ||
| 3896 | /* Make sure to run 'window-state-change-hook' later. */ | ||
| 3897 | run_window_state_change_hook = true; | ||
| 3898 | /* Make sure to record changes for each live frame in | ||
| 3899 | window_change_record later. */ | ||
| 3900 | window_change_record_frames = true; | ||
| 3901 | } | ||
| 3867 | 3902 | ||
| 3868 | /* A frame's configuration changed when one of its windows has | 3903 | /* A frame's configuration changed when one of its windows has |
| 3869 | changed buffer or size or at least one window was deleted. */ | 3904 | changed buffer or size or at least one window was deleted. */ |
| @@ -3871,17 +3906,16 @@ run_window_change_functions (void) | |||
| 3871 | /* This will run any buffer local window configuration change | 3906 | /* This will run any buffer local window configuration change |
| 3872 | hook as well. */ | 3907 | hook as well. */ |
| 3873 | run_window_configuration_change_hook (f); | 3908 | run_window_configuration_change_hook (f); |
| 3874 | |||
| 3875 | if (!FRAME_LIVE_P (f)) | ||
| 3876 | continue; | ||
| 3877 | |||
| 3878 | /* Record changes (via window_change_record_frame) for this | ||
| 3879 | frame, even when an unhandled error occurred. */ | ||
| 3880 | unbind_to (count_inner, Qnil); | ||
| 3881 | } | 3909 | } |
| 3882 | 3910 | ||
| 3883 | /* Record selected window and frame. */ | 3911 | /* Run 'window-state-change-hook' if at least one frame has changed |
| 3884 | unbind_to (count_outer, Qnil); | 3912 | state. */ |
| 3913 | if (run_window_state_change_hook && !NILP (Vwindow_state_change_hook)) | ||
| 3914 | safe_run_hooks (Qwindow_state_change_hook); | ||
| 3915 | |||
| 3916 | /* Record changes for all frames (if asked for), selected window and | ||
| 3917 | frame. */ | ||
| 3918 | unbind_to (count, Qnil); | ||
| 3885 | } | 3919 | } |
| 3886 | 3920 | ||
| 3887 | /* Make WINDOW display BUFFER. RUN_HOOKS_P means it's allowed | 3921 | /* Make WINDOW display BUFFER. RUN_HOOKS_P means it's allowed |
| @@ -7999,6 +8033,7 @@ syms_of_window (void) | |||
| 7999 | Fput (Qscroll_down, Qscroll_command, Qt); | 8033 | Fput (Qscroll_down, Qscroll_command, Qt); |
| 8000 | 8034 | ||
| 8001 | DEFSYM (Qwindow_configuration_change_hook, "window-configuration-change-hook"); | 8035 | DEFSYM (Qwindow_configuration_change_hook, "window-configuration-change-hook"); |
| 8036 | DEFSYM (Qwindow_state_change_hook, "window-state-change-hook"); | ||
| 8002 | DEFSYM (Qwindow_state_change_functions, "window-state-change-functions"); | 8037 | DEFSYM (Qwindow_state_change_functions, "window-state-change-functions"); |
| 8003 | DEFSYM (Qwindow_size_change_functions, "window-size-change-functions"); | 8038 | DEFSYM (Qwindow_size_change_functions, "window-size-change-functions"); |
| 8004 | DEFSYM (Qwindow_buffer_change_functions, "window-buffer-change-functions"); | 8039 | DEFSYM (Qwindow_buffer_change_functions, "window-buffer-change-functions"); |
| @@ -8132,11 +8167,25 @@ redisplay. In this case the window is passed as argument. | |||
| 8132 | 8167 | ||
| 8133 | Functions specified by the default value are called for each frame if | 8168 | Functions specified by the default value are called for each frame if |
| 8134 | at least one window on that frame has been added, deleted, changed its | 8169 | at least one window on that frame has been added, deleted, changed its |
| 8135 | buffer or its total or body size or the frame has been (de-)selected | 8170 | buffer or its total or body size or the frame has been (de-)selected, |
| 8136 | or its selected window has changed since the last redisplay. In this | 8171 | its selected window has changed or the window state change flag has |
| 8137 | case the frame is passed as argument. */); | 8172 | been set for this frame since the last redisplay. In this case the |
| 8173 | frame is passed as argument. */); | ||
| 8138 | Vwindow_state_change_functions = Qnil; | 8174 | Vwindow_state_change_functions = Qnil; |
| 8139 | 8175 | ||
| 8176 | DEFVAR_LISP ("window-state-change-hook", Vwindow_state_change_hook, | ||
| 8177 | doc: /* Functions called during redisplay when the window state changed. | ||
| 8178 | The value should be a list of functions that take no argument. | ||
| 8179 | |||
| 8180 | This hook is called during redisplay when at least one window has been | ||
| 8181 | added, deleted, (de-)selected, changed its buffer or its total or body | ||
| 8182 | size or the window state change flag has been set for at least one | ||
| 8183 | frame. This hook is called after all other window change functions | ||
| 8184 | have been run and should be used only if a function should react to | ||
| 8185 | changes that happened on at least two frames since last redisplay or | ||
| 8186 | the function intends to change the window configuration. */); | ||
| 8187 | Vwindow_state_change_hook = Qnil; | ||
| 8188 | |||
| 8140 | DEFVAR_LISP ("window-configuration-change-hook", Vwindow_configuration_change_hook, | 8189 | DEFVAR_LISP ("window-configuration-change-hook", Vwindow_configuration_change_hook, |
| 8141 | doc: /* Functions called during redisplay when window configuration has changed. | 8190 | doc: /* Functions called during redisplay when window configuration has changed. |
| 8142 | The value should be a list of functions that take no argument. | 8191 | The value should be a list of functions that take no argument. |