Run window change functions during redisplay

* doc/lispref/windows.texi (Window Sizes): Move (and rename)
descriptions of 'window-pixel-height-before-size-change' and
'window-pixel-width-before-size-change' to Window Hooks
section.
(Window Configurations): Remove warning against use of
'save-window-excursion' in 'window-size-change-functions'.
(Window Hooks): Rewrite section according to redesign of
window change functions.
* lisp/erc/erc-track.el (erc-window-configuration-change)
(erc-modified-channels-update): Call latter directly from
'window-configuration-change-hook' instead via
'post-command-hook'.
* lisp/frame.el (frame-size-changed-p): Change nomenclature
in let bindings.
* lisp/net/rcirc.el (rcirc-window-configuration-change)
(rcirc-window-configuration-change-1): Call latter directly
from 'window-configuration-change-hook' instead via
'post-command-hook'.
* lisp/window.el (window-pixel-width-before-size-change)
(window-pixel-height-before-size-change): Defalias.
(window--resize-mini-window, window-resize)
(adjust-window-trailing-edge, delete-window)
(delete-other-windows, balance-windows): Don't run
'window-configuration-change-hook' any more from here.
(split-window): Don't run 'window-configuration-change-hook'
from here.  'run-window-scroll-functions' from here.
(window--adjust-process-windows): Run from
'window-configuration-change-hook' only.
* src/frame.c (old_selected_frame): New Lisp variable.
(make_frame): Initialize frame's change_stamp slot.
(Fold_selected_frame): New function.
* src/frame.h (struct frame): New slots old_selected_window,
window_change, change_stamp and number_of_windows.
(fset_old_selected_window): New inlined function.
(FRAME_WINDOW_CHANGE, FRAME_OLD_SELECTED_WINDOW): New macros.
* src/window.c (old_selected_window): New Lisp variable.
(wset_old_buffer): New inlined function.
(Fframe_old_selected_window, Fold_selected_window)
(Fwindow_old_buffer): New functions.
(Fwindow_old_pixel_width, Fwindow_old_pixel_height): Rename
from Fwindow_pixel_width_before_size_change and
Fwindow_pixel_height_before_size_change.  Update doc-strings.
(Fwindow_old_body_pixel_width, Fwindow_old_body_pixel_height):
New functions.
(Fdelete_other_windows_internal): Set frame's window_change
slot instead of running 'window-configuration-change-hook'.
(Frun_window_configuration_change_hook): In doc-string tell
that this function is no more needed.
(Frun_window_scroll_functions): Amend doc-string.  Run with
window's buffer current.
(window_sub_list, window_change_record_windows)
(window_change_record_frame, window_change_record)
(run_window_change_functions_1, run_window_change_functions):
New functions.
(set_window_buffer): Set frame's window_change slot instead of
running 'window-configuration-change-hook'.
(make_window): Don't initialize pixel_width_before_size_change
and pixel_height_before_size_change slots.
(window_resize_apply, Fdelete_window_internal): Set frame's
window_change slot.
(Fsplit_window_internal): Set frame's window_change slot.
Don't run 'window-scroll-functions' from here.
* src/window.h (struct window): New slots old_buffer,
change_stamp, old_pixel_width (renamed from
pixel_width_before_size_change), old_pixel_height (renamed
from pixel_height_before_size_change), old_body_pixel_width
and old_body_pixel_height.
* src/xdisp.c (init_iterator): Set frame's window_change slot
when the body height or width changes.
(prepare_menu_bars): Don't run_window_size_change_functions.
(redisplay_internal): Don't run_window_size_change_functions,
run_window_change_functions instead.
This commit is contained in:
Martin Rudalics 2019-01-11 10:02:47 +01:00
parent 470082de55
commit e567ac1495
11 changed files with 961 additions and 395 deletions

View file

@ -568,12 +568,6 @@ its pixel height is the pixel height of the screen areas spanned by its
children.
@end defun
@defun window-pixel-height-before-size-change &optional Lisp_Object &optional window
This function returns the height of window @var{window} in pixels at the
time @code{window-size-change-functions} was run for the last time on
@var{window}'s frame (@pxref{Window Hooks}).
@end defun
@cindex window pixel width
@cindex pixel width of a window
@cindex total pixel width of a window
@ -588,12 +582,6 @@ If @var{window} is an internal window, its pixel width is the width of
the screen areas spanned by its children.
@end defun
@defun window-pixel-width-before-size-change &optional Lisp_Object &optional window
This function returns the width of window @var{window} in pixels at the
time @code{window-size-change-functions} was run for the last time on
@var{window}'s frame (@pxref{Window Hooks}).
@end defun
@cindex full-width window
@cindex full-height window
The following functions can be used to determine whether a given
@ -5705,10 +5693,6 @@ prevent the code in @var{forms} from opening new windows, because new
windows might be opened in other frames (@pxref{Choosing Window}), and
@code{save-window-excursion} only saves and restores the window
configuration on the current frame.
Do not use this macro in @code{window-size-change-functions}; exiting
the macro triggers execution of @code{window-size-change-functions},
leading to an endless loop.
@end defmac
@defun window-configuration-p object
@ -5827,10 +5811,10 @@ This function sets @var{window}'s value of @var{parameter} to
is the selected window.
@end defun
By default, the functions that save and restore window configurations or the
states of windows (@pxref{Window Configurations}) do not care about
window parameters. This means that when you change the value of a
parameter within the body of a @code{save-window-excursion}, the
By default, the functions that save and restore window configurations
or the states of windows (@pxref{Window Configurations}) do not care
about window parameters. This means that when you change the value of
a parameter within the body of a @code{save-window-excursion}, the
previous value is not restored when that macro exits. It also means
that when you restore via @code{window-state-put} a window state saved
earlier by @code{window-state-get}, all cloned windows have their
@ -6019,27 +6003,26 @@ applications. It might be replaced by an improved solution in future
versions of Emacs.
@end table
@node Window Hooks
@section Hooks for Window Scrolling and Changes
@cindex hooks for window operations
This section describes how a Lisp program can take action whenever a
window displays a different part of its buffer or a different buffer.
There are three actions that can change this: scrolling the window,
switching buffers in the window, and changing the size of the window.
The first two actions run @code{window-scroll-functions}; the last runs
@code{window-size-change-functions}.
This section describes how Lisp programs can take action after a
window has been scrolled or other window modifications occurred. We
first consider the case where a window shows a different part of its
buffer.
@defvar window-scroll-functions
This variable holds a list of functions that Emacs should call before
redisplaying a window with scrolling. Displaying a different buffer in
the window also runs these functions.
redisplaying a window with scrolling. Displaying a different buffer
in a window and making a new window also call these functions.
This variable is not a normal hook, because each function is called with
two arguments: the window, and its new display-start position. At the
time of the call, the display-start position of the window argument is
already set to its new value, and the buffer to be displayed in the
window is already set as the current buffer.
This variable is not a normal hook, because each function is called
with two arguments: the window, and its new display-start position.
At the time of the call, the display-start position of the argument
window is already set to its new value, and the buffer to be displayed
in the window is set as the current buffer.
These functions must take care when using @code{window-end}
(@pxref{Window Start and End}); if you need an up-to-date value, you
@ -6050,63 +6033,226 @@ is scrolled. It's not designed for that, and such use probably won't
work.
@end defvar
@defun run-window-scroll-functions &optional window
This function calls @code{window-scroll-functions} for the specified
@var{window}, which defaults to the selected window.
@end defun
@defvar window-size-change-functions
This variable holds a list of functions to be called if the size of any
window changes for any reason. The functions are called once per
redisplay, and once for each frame on which size changes have occurred.
Each function receives the frame as its sole argument. To find out
whether a specific window has changed size, compare the return values of
@code{window-pixel-width-before-size-change} and
@code{window-pixel-width} respectively
@code{window-pixel-height-before-size-change} and
@code{window-pixel-height} for that window (@pxref{Window Sizes}).
The buffer-local value of this hook is run once for the buffer and the
frame in question, provided at least one window showing the buffer on
that frame has changed its size. As it still receives the frame as
its sole argument, any function called on a buffer-local basis will be
oblivious to which window(s) showing the buffer changed its (their)
size and has to check out these windows by using the method described
in the previous paragraph.
These function are usually only called when at least one window was
added or has changed size since the last time this hook was run for
the associated frame. In some rare cases this hook also runs when a
window that was added intermittently has been deleted afterwards. In
these cases none of the windows on the frame will appear to have
changed its size.
@end defvar
@defvar window-configuration-change-hook
A normal hook that is run every time the window configuration of a
frame changes. Window configuration changes include splitting and
deleting windows, and the display of a different buffer in a window.
The hook can be also used for tracking changes of window sizes. It
is, however, not run when the size of a frame changes or automatic
resizing of a minibuffer window (@pxref{Minibuffer Windows}) changes
the size of another window. As a rule, adding a function to
@code{window-size-change-functions}, see above, is the recommended way
for reliably tracking size changes of any window.
The buffer-local value of this hook is run once for each window on the
affected frame, with the relevant window selected and its buffer
current. The global value of this hook is run once for the modified
frame, with that frame selected.
@end defvar
@defun run-window-configuration-change-hook &optional frame
This function runs @code{window-configuration-change-hook} for the
specified @var{frame}, which defaults to the selected frame.
@end defun
In addition, you can use @code{jit-lock-register} to register a Font
In addition, you can use @code{jit-lock-register} to register a Font
Lock fontification function, which will be called whenever parts of a
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 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
change functions}.
@cindex window buffer change
The first of these hooks is run after a @dfn{window buffer change} is
detected, which means that a window was created, deleted or assigned
another buffer.
@defvar window-buffer-change-functions
This variable specifies functions called at the end of redisplay when
window buffers have 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 created or assigned
that buffer 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 since the last time window change functions were run.
In this case the frame is passed as argument.
@end defvar
@cindex window size change
The second of these hooks is run after a @dfn{window size change} has
been detected which means that a window was created, assigned another
buffer, or changed its total size or that of its text area.
@defvar window-size-change-functions
This variable specifies functions called at the end of redisplay when
a window size change occurred. 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 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 or assigned another
buffer, total or body size since the last time window change functions
were run. In this case the frame is passed as argument.
@end defvar
@cindex window selection change
The third of these hooks is run after a @dfn{window selection change}
has selected another window since the last redisplay.
@defvar window-selection-change-functions
This variable specifies functions called at the end of redisplay when
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 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
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
change} has been detected which means that either the buffer or the
size of a window changed.
@defvar window-configuration-change-hook
This variable specifies functions called at the end of redisplay when
either the buffer or the size of a window has changed. The value
should be a list of functions that take no argument.
Functions specified buffer-locally are called for any window showing
the corresponding buffer if at least one window on that frame has been
added, deleted or assigned another buffer, total or body size since
the last time window change functions were run. Each call is
performed with the window showing the buffer temporarily selected and
its buffer current.
Functions specified by the default value are called for each frame if
at least one window on that frame has been added, deleted or assigned
another buffer, total or body size since the last time window change
functions were run. Each call is performed with the frame temporarily
selected and the selected window's buffer current.
@end defvar
Window change functions are called at the end of redisplay for each
frame as follows: First, any buffer-local window buffer change
function, window size change function and selected window change
functions are called in this order. Next, the default values for
these functions are called in the same order. Then any buffer-local
window configuration change functions are called followed by functions
specified by the default value of those functions.
Window change functions are run for a specific frame only if a
corresponding change was registered for that frame earlier. Such
changes include the creation or deletion of a window or the assignment
of another buffer or size to a window. Note that even when such a
change has been registered, this does not mean that any of the hooks
described above is run. If, for example, a change was registered
within the scope of a window excursion (@pxref{Window
Configurations}), this will trigger a call of window change functions
only if that excursion still persists at the time change functions are
run. If it is exited earlier, hooks will be run only if registered by
a change outside the scope of that excursion.
While window change functions are run, the functions described next
can be called to get more insight into what has changed for a specific
window or frame since the last redisplay. All these functions take a
live window as single, optional argument, defaulting to the selected
window.
@defun window-old-buffer &optional window
This function returns the buffer shown in @var{window} at the last
time window change functions were run for @var{window}'s frame. If it
returns @code{nil}, @var{window} has been created after that. If it
returns @code{t}, @var{window} was not shown at that time but has been
restored from a previously saved window configuration afterwards.
Otherwise, the return value is the buffer shown by @code{window} at
that time.
@end defun
@defun window-old-pixel-width &optional window
This function returns the total pixel width of @var{window} the
last time window change functions found @code{window} live on its
frame. It is zero if @code{window} was created after that.
@end defun
@defun window-old-pixel-height &optional window
This function returns the total pixel height of @var{window} the last
time window change functions found @code{window} live on its frame.
It is zero if @code{window} was created after that.
@end defun
@defun window-old-body-pixel-width &optional window
This function returns the pixel width of @var{window}'s text area the
last time window change functions found @code{window} live on its
frame. It is zero if @code{window} was created after that.
@end defun
@defun window-old-body-pixel-height &optional window
This function returns the pixel height of @var{window}'s text area the
last time window change functions found @code{window} live on its
frame. It is zero if @code{window} was created after that.
@end defun
In order to find out which window or frame was selected the last time
window change functions were run, the following functions can be used:
@defun frame-old-selected-window &optional frame
This function returns the selected window of @var{frame} at the last
time window change functions were run. If omitted or @code{nil}
@var{frame} defaults to the selected frame.
@end defun
@defun old-selected-window
This function returns the selected window at the last time window
change functions were run.
@end defun
@defun old-selected-frame
This function returns the selected frame at the last time window
change functions were run.
@end defun
Note that window change functions provide no information about which
windows have been deleted since the last time they were run. If
necessary, an application should remember any window showing a
specific buffer in a local variable of that buffer and update it in a
function run by the default value of
@code{window-buffer-change-functions} or
@code{window-configuration-change-hook} (the only hooks triggered by
the deletion of windows).
The following caveats should be considered when adding a function
to window change functions:
@itemize @bullet
@item
Some operations will not trigger a call of window change functions.
These include showing another buffer in a minibuffer window or any
change of a tooltip window.
@item
Window change functions should not create or delete windows or change
the buffer, size or selection status of any window because there is no
guarantee that the information about such a change will be propagated
to other window change functions. If at all, any such change should
be executed only by the last function listed by the default value of
@code{window-configuration-change-hook}.
@item
Macros like @code{save-window-excursion}, @code{with-selected-window}
or @code{with-current-buffer} can be used when running window change
functions.
@item
Running window change functions does not save and restore match data.
Unless running @code{window-configuration-change-hook} it does not
save or restore the selected window or frame or the current buffer
either.
@item
Any redisplay triggering the run of window change functions may be
aborted. If the abort occurs before window change functions have run
to their completion, they will be run again with the previous values,
that is, as if redisplay had not been performed. If aborted later,
they will be run with the new values, that is, as if redisplay had
been actually performed.
@end itemize

View file

@ -1283,9 +1283,30 @@ displaying the same buffer. See the node "(elisp) Face Remapping"
of the Emacs Lisp Reference manual for more detail.
+++
** Special handling of buffer-local 'window-size-change-functions'.
A buffer-local value of this hook is now run only if at least one
window showing the buffer has changed its size.
** 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:
'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
'window-selection-change-functions' (run when the selected window
changed). '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
window the buffer it showed at that time. old-selected-window and
'old-selected-frame' return the window and frame that were selected
during last redisplay. 'window-old-pixel-width' (renamed from
'window-pixel-width-before-size-change'), 'window-old-pixel-height'
(renamed from 'window-pixel-height-before-size-change'),
'window-old-body-pixel-width' and 'window-old-body-pixel-height'
return the total and body sizes of any window during last redisplay.
One consequence of these changes is that all window change functions
run now after functions run by 'post-command-hook'. See the section
"(elisp) Window Hooks" in the Elisp manual for a detailed explanation
of the new behavior.
+++
** New buffer display action alist entry 'dedicated'.

View file

@ -640,7 +640,7 @@ only consider active buffers visible.")
(unless (minibuffer-window-active-p (minibuffer-window))
;; delay this until command has finished to make sure window is
;; actually visible before clearing activity
(add-hook 'post-command-hook 'erc-modified-channels-update)))
(erc-modified-channels-update)))
(defvar erc-modified-channels-update-inside nil
"Variable to prevent running `erc-modified-channels-update' multiple
@ -669,8 +669,7 @@ ARGS are ignored."
(erc-modified-channels-remove-buffer buffer))))
erc-modified-channels-alist)
(when removed-channel
(erc-modified-channels-display)))
(remove-hook 'post-command-hook 'erc-modified-channels-update)))
(erc-modified-channels-display)))))
(defvar erc-track-mouse-face (if (featurep 'xemacs)
'modeline-mousable

View file

@ -1745,20 +1745,17 @@ for FRAME."
(let* ((frame (window-normalize-frame frame))
(root (frame-root-window frame))
(mini (minibuffer-window frame))
(mini-height-before-size-change 0)
(mini-old-height 0)
(mini-height 0))
;; FRAME's minibuffer window counts iff it's on FRAME and FRAME is
;; not a minibuffer-only frame.
(when (and (eq (window-frame mini) frame) (not (eq mini root)))
(setq mini-height-before-size-change
(window-pixel-height-before-size-change mini))
(setq mini-old-height (window-old-pixel-height mini))
(setq mini-height (window-pixel-height mini)))
;; Return non-nil when either the width of the root or the sum of
;; the heights of root and minibuffer window changed.
(or (/= (window-pixel-width-before-size-change root)
(window-pixel-width root))
(/= (+ (window-pixel-height-before-size-change root)
mini-height-before-size-change)
(or (/= (window-old-pixel-width root) (window-pixel-width root))
(/= (+ (window-old-pixel-height root) mini-old-height)
(+ (window-pixel-height root) mini-height)))))
;;;; Frame/display capabilities.

View file

@ -2064,9 +2064,7 @@ activity. Only run if the buffer is not visible and
(defvar rcirc-visible-buffers nil)
(defun rcirc-window-configuration-change ()
(unless (minibuffer-window-active-p (minibuffer-window))
;; delay this until command has finished to make sure window is
;; actually visible before clearing activity
(add-hook 'post-command-hook 'rcirc-window-configuration-change-1)))
(rcirc-window-configuration-change-1)))
(defun rcirc-window-configuration-change-1 ()
;; clear activity and overlay arrows
@ -2090,9 +2088,7 @@ activity. Only run if the buffer is not visible and
rcirc-activity)))
;; update the mode-line string
(unless (equal old-activity rcirc-activity)
(rcirc-update-activity-string)))
(remove-hook 'post-command-hook 'rcirc-window-configuration-change-1))
(rcirc-update-activity-string))))
;;; buffer name abbreviation

View file

@ -2043,6 +2043,8 @@ doc-string of `window-resizable'."
;; Aliases of functions defined in window.c.
(defalias 'window-height 'window-total-height)
(defalias 'window-width 'window-body-width)
(defalias 'window-pixel-width-before-size-change 'window-old-pixel-width)
(defalias 'window-pixel-height-before-size-change 'window-old-pixel-height)
(defun window-full-height-p (&optional window)
"Return t if WINDOW is as high as its containing frame.
@ -2759,8 +2761,7 @@ as small) as possible, but don't signal an error."
;; The following routine catches the case where we want to resize
;; a minibuffer-only frame.
(when (resize-mini-window-internal window)
(window--pixel-to-total frame)
(run-window-configuration-change-hook frame))))))
(window--pixel-to-total frame))))))
(defun window--resize-apply-p (frame &optional horizontal)
"Return t when a window on FRAME shall be resized vertically.
@ -2858,9 +2859,7 @@ instead."
(window--resize-siblings window delta horizontal ignore))
(when (window--resize-apply-p frame horizontal)
(if (window-resize-apply frame horizontal)
(progn
(window--pixel-to-total frame horizontal)
(run-window-configuration-change-hook frame))
(window--pixel-to-total frame horizontal)
(error "Failed to apply resizing %s" window))))
(t
(error "Cannot resize window %s" window)))))
@ -3579,9 +3578,7 @@ move it as far as possible in the desired direction."
;; Don't report an error in the standard case.
(when (window--resize-apply-p frame horizontal)
(if (window-resize-apply frame horizontal)
(progn
(window--pixel-to-total frame horizontal)
(run-window-configuration-change-hook frame))
(window--pixel-to-total frame horizontal)
;; But do report an error if applying the changes fails.
(error "Failed adjusting window %s" window))))))))
@ -4112,7 +4109,6 @@ that is its frame's root window."
;; `delete-window-internal' has selected a window that should
;; not be selected, fix this here.
(other-window -1 frame))
(run-window-configuration-change-hook frame)
(window--check frame)
;; Always return nil.
nil))))
@ -4198,7 +4194,6 @@ any window whose `no-delete-other-windows' parameter is non-nil."
;; If WINDOW is the main window of its frame do nothing.
(unless (eq window main)
(delete-other-windows-internal window main)
(run-window-configuration-change-hook frame)
(window--check frame))
;; Always return nil.
nil)))
@ -5186,7 +5181,6 @@ frame. The selected window is not changed by this function."
(unless size
(window--sanitize-window-sizes horizontal))
(run-window-configuration-change-hook frame)
(run-window-scroll-functions new)
(window--check frame)
;; Always return the new window.
@ -5417,15 +5411,13 @@ window."
(balance-windows-1 window)
(when (window--resize-apply-p frame)
(window-resize-apply frame)
(window--pixel-to-total frame)
(run-window-configuration-change-hook frame))
(window--pixel-to-total frame))
;; Balance horizontally.
(window--resize-reset (window-frame window) t)
(balance-windows-1 window t)
(when (window--resize-apply-p frame t)
(window-resize-apply frame t)
(window--pixel-to-total frame t)
(run-window-configuration-change-hook frame))))
(window--pixel-to-total frame t))))
(defun window-fixed-size-p (&optional window direction)
"Return t if WINDOW cannot be resized in DIRECTION.
@ -9441,15 +9433,7 @@ displaying that processes's buffer."
(when size
(set-process-window-size process (cdr size) (car size))))))))))
;; Remove the following call in Emacs 27, running
;; 'window-size-change-functions' should suffice.
(add-hook 'window-configuration-change-hook 'window--adjust-process-windows)
;; Catch any size changes not handled by
;; 'window-configuration-change-hook' (Bug#32720, "another issue" in
;; Bug#33230).
(add-hook 'window-size-change-functions (lambda (_frame)
(window--adjust-process-windows)))
;; Some of these are in tutorial--default-keys, so update that if you
;; change these.

View file

@ -55,9 +55,11 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#endif
/* The currently selected frame. */
Lisp_Object selected_frame;
/* The selected frame the last time window change functions were run. */
Lisp_Object old_selected_frame;
/* A frame which is not just a mini-buffer, or NULL if there are no such
frames. This is usually the most recent such frame that was selected. */
@ -855,7 +857,8 @@ make_frame (bool mini_p)
f->ns_transparent_titlebar = false;
#endif
#endif
/* This one should never be zero. */
f->change_stamp = 1;
root_window = make_window ();
rw = XWINDOW (root_window);
if (mini_p)
@ -1451,7 +1454,8 @@ This function returns FRAME, or nil if FRAME has been deleted. */)
return do_switch_frame (frame, 1, 0, norecord);
}
DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 1, "^e",
DEFUN ("handle-switch-frame", Fhandle_switch_frame,
Shandle_switch_frame, 1, 1, "^e",
doc: /* Handle a switch-frame event EVENT.
Switch-frame events are usually bound to this function.
A switch-frame event is an event Emacs sends itself to
@ -1471,6 +1475,18 @@ DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
{
return selected_frame;
}
DEFUN ("old-selected-frame", Fold_selected_frame,
Sold_selected_frame, 0, 0, 0,
doc: /* Return the old selected FRAME.
FRAME must be a live frame and defaults to the selected one.
The return value is the frame selected the last time window change
functions were run. */)
(void)
{
return old_selected_frame;
}
DEFUN ("frame-list", Fframe_list, Sframe_list,
0, 0, 0,
@ -6098,9 +6114,10 @@ iconify the top level frame instead. */);
defsubr (&Swindow_system);
defsubr (&Sframe_windows_min_size);
defsubr (&Smake_terminal_frame);
defsubr (&Shandle_switch_frame);
defsubr (&Sselect_frame);
defsubr (&Shandle_switch_frame);
defsubr (&Sselected_frame);
defsubr (&Sold_selected_frame);
defsubr (&Sframe_list);
defsubr (&Sframe_parent);
defsubr (&Sframe_ancestor_p);

View file

@ -125,6 +125,10 @@ struct frame
The selected window of the selected frame is Emacs's selected window. */
Lisp_Object selected_window;
/* This frame's selected window when run_window_change_functions was
called the last time on this frame. */
Lisp_Object old_selected_window;
/* This frame's minibuffer window.
Most frames have their own minibuffer windows,
but only the selected frame's minibuffer window
@ -321,9 +325,14 @@ struct frame
cleared. */
bool_bf explicit_name : 1;
/* True if configuration of windows on this frame has changed since
last call of run_window_size_change_functions. */
bool_bf window_configuration_changed : 1;
/* True if at least one window on this frame changed since the last
call of run_window_change_functions. Changes are either "state
changes" (a window has been created, deleted or got assigned
another buffer) or "size changes" (the total or body size of a
window changed). run_window_change_functions exits early unless
either this flag is true or a window selection happened on this
frame. */
bool_bf window_change : 1;
/* True if the mouse has moved on this display device
since the last time we checked. */
@ -406,6 +415,20 @@ struct frame
/* Bitfield area ends here. */
/* This frame's change stamp, set the last time window change
functions were run for this frame. Should never be 0 because
that's the change stamp of a new window. A window was not on a
frame the last run_window_change_functions was called on it if
it's change stamp differs from that of its frame. */
int change_stamp;
/* This frame's number of windows, set the last time window change
functions were run for this frame. Should never be 0 even for
minibuffer-only frames. If no window has been added, this allows
to detect whether a window was deleted on this frame since the
last time run_window_change_functions was called on it. */
ptrdiff_t number_of_windows;
/* Number of lines (rounded up) of tool bar. REMOVE THIS */
int tool_bar_lines;
@ -662,6 +685,11 @@ fset_selected_window (struct frame *f, Lisp_Object val)
f->selected_window = val;
}
INLINE void
fset_old_selected_window (struct frame *f, Lisp_Object val)
{
f->old_selected_window = val;
}
INLINE void
fset_title (struct frame *f, Lisp_Object val)
{
f->title = val;
@ -908,10 +936,9 @@ default_pixels_per_inch_y (void)
are frozen on frame F. */
#define FRAME_WINDOWS_FROZEN(f) (f)->frozen_window_starts
/* True if the frame's window configuration has changed since last call
of run_window_size_change_functions. */
#define FRAME_WINDOW_CONFIGURATION_CHANGED(f) \
(f)->window_configuration_changed
/* True if at least one window changed on frame F since the last time
window change functions were run on F. */
#define FRAME_WINDOW_CHANGE(f) (f)->window_change
/* The minibuffer window of frame F, if it has one; otherwise nil. */
#define FRAME_MINIBUF_WINDOW(f) f->minibuffer_window
@ -919,8 +946,10 @@ default_pixels_per_inch_y (void)
/* The root window of the window tree of frame F. */
#define FRAME_ROOT_WINDOW(f) f->root_window
/* The currently selected window of the window tree of frame F. */
/* The currently selected window of frame F. */
#define FRAME_SELECTED_WINDOW(f) f->selected_window
/* The old selected window of frame F. */
#define FRAME_OLD_SELECTED_WINDOW(f) f->old_selected_window
#define FRAME_INSERT_COST(f) (f)->insert_line_cost
#define FRAME_DELETE_COST(f) (f)->delete_line_cost
@ -1215,6 +1244,7 @@ SET_FRAME_VISIBLE (struct frame *f, int v)
(f)->iconified = (eassert (0 <= (i) && (i) <= 1), (i))
extern Lisp_Object selected_frame;
extern Lisp_Object old_selected_frame;
#if ! (defined USE_GTK || defined HAVE_NS)
extern int frame_default_tool_bar_height;

File diff suppressed because it is too large Load diff

View file

@ -142,6 +142,11 @@ struct window
as well. */
Lisp_Object contents;
/* The old buffer of this window, set to this window's buffer by
run_window_change_functions every time it sees this window.
Unused for internal windows. */
Lisp_Object old_buffer;
/* A marker pointing to where in the text to start displaying.
BIDI Note: This is the _logical-order_ start, i.e. the smallest
buffer position visible in the window, not necessarily the
@ -229,6 +234,14 @@ struct window
/* Unique number of window assigned when it was created. */
EMACS_INT sequence_number;
/* The change stamp of this window. Set to 0 when the window is
created, it is set to its frame's change stamp every time
run_window_change_functions is run on that frame with this
window live. It is left alone when the window exists only
within a window configuration. Not useful for internal
windows. */
int change_stamp;
/* The upper left corner pixel coordinates of this window, as
integers relative to upper left corner of frame = 0, 0. */
int pixel_left;
@ -243,10 +256,13 @@ struct window
int pixel_width;
int pixel_height;
/* The pixel sizes of the window at the last time
`window-size-change-functions' was run. */
int pixel_width_before_size_change;
int pixel_height_before_size_change;
/* The pixel and pixel body sizes of the window at the last time
run_window_change_functions was run with this window live. Not
useful for internal windows. */
int old_pixel_width;
int old_pixel_height;
int old_body_pixel_width;
int old_body_pixel_height;
/* The size of the window. */
int total_cols;
@ -1023,6 +1039,7 @@ wset_next_buffers (struct window *w, Lisp_Object val)
This value is always the same as FRAME_SELECTED_WINDOW (selected_frame). */
extern Lisp_Object selected_window;
extern Lisp_Object old_selected_window;
/* This is a time stamp for window selection, so we can find the least
recently used window. Its only users are Fselect_window,
@ -1051,7 +1068,7 @@ extern void grow_mini_window (struct window *, int, bool);
extern void shrink_mini_window (struct window *, bool);
extern int window_relative_x_coord (struct window *, enum window_part, int);
void run_window_size_change_functions (Lisp_Object);
void run_window_change_functions (void);
/* Make WINDOW display BUFFER. RUN_HOOKS_P means it's allowed
to run hooks. See make_frame for a case where it's not allowed. */

View file

@ -2786,6 +2786,7 @@ init_iterator (struct it *it, struct window *w,
struct glyph_row *row, enum face_id base_face_id)
{
enum face_id remapped_base_face_id = base_face_id;
int body_width = 0, body_height = 0;
/* Some precondition checks. */
eassert (w != NULL && it != NULL);
@ -2962,7 +2963,7 @@ init_iterator (struct it *it, struct window *w,
{
/* Mode lines, menu bar in terminal frames. */
it->first_visible_x = 0;
it->last_visible_x = WINDOW_PIXEL_WIDTH (w);
it->last_visible_x = body_width = WINDOW_PIXEL_WIDTH (w);
}
else
{
@ -2982,8 +2983,12 @@ init_iterator (struct it *it, struct window *w,
else
it->first_visible_x =
window_hscroll_limited (w, it->f) * FRAME_COLUMN_WIDTH (it->f);
it->last_visible_x = (it->first_visible_x
+ window_box_width (w, TEXT_AREA));
body_width = window_box_width (w, TEXT_AREA);
if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
&& body_width != w->old_body_pixel_width)
FRAME_WINDOW_CHANGE (it->f) = true;
it->last_visible_x = it->first_visible_x + body_width;
/* If we truncate lines, leave room for the truncation glyph(s) at
the right margin. Otherwise, leave room for the continuation
@ -2997,7 +3002,8 @@ init_iterator (struct it *it, struct window *w,
}
it->header_line_p = window_wants_header_line (w);
it->current_y = WINDOW_HEADER_LINE_HEIGHT (w) + w->vscroll;
body_height = WINDOW_HEADER_LINE_HEIGHT (w);
it->current_y = body_height + w->vscroll;
}
/* Leave room for a border glyph. */
@ -3006,6 +3012,10 @@ init_iterator (struct it *it, struct window *w,
it->last_visible_x -= 1;
it->last_visible_y = window_text_bottom_y (w);
body_height += it->last_visible_y;
if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
&& body_height != w->old_body_pixel_height)
FRAME_WINDOW_CHANGE (it->f) = true;
/* For mode lines and alike, arrange for the first glyph having a
left box line if the face specifies a box. */
@ -12200,8 +12210,6 @@ prepare_menu_bars (void)
&& !XBUFFER (w->contents)->text->redisplay)
continue;
run_window_size_change_functions (frame);
if (FRAME_PARENT_FRAME (f))
continue;
@ -14119,20 +14127,6 @@ redisplay_internal (void)
{
echo_area_display (false);
/* If echo_area_display resizes the mini-window, the redisplay and
window_sizes_changed flags of the selected frame are set, but
it's too late for the hooks in window-size-change-functions,
which have been examined already in prepare_menu_bars. So in
that case we call the hooks here only for the selected frame. */
if (sf->redisplay)
{
ptrdiff_t count1 = SPECPDL_INDEX ();
record_unwind_save_match_data ();
run_window_size_change_functions (selected_frame);
unbind_to (count1, Qnil);
}
if (message_cleared_p)
update_miniwindow_p = true;
@ -14149,15 +14143,6 @@ redisplay_internal (void)
&& (current_buffer->clip_changed || window_outdated (w))
&& resize_mini_window (w, false))
{
if (sf->redisplay)
{
ptrdiff_t count1 = SPECPDL_INDEX ();
record_unwind_save_match_data ();
run_window_size_change_functions (selected_frame);
unbind_to (count1, Qnil);
}
/* Resized active mini-window to fit the size of what it is
showing if its contents might have changed. */
must_finish = true;
@ -14347,7 +14332,19 @@ redisplay_internal (void)
&& (w = XWINDOW (selected_window)) != sw)
goto retry;
/* We used to always goto end_of_redisplay here, but this
if (!NILP (Vrun_hooks))
{
run_window_change_functions ();
/* If windows or buffers changed or selected_window
changed, redisplay again. */
if ((windows_or_buffers_changed)
|| (WINDOWP (selected_window)
&& (w = XWINDOW (selected_window)) != sw))
goto retry;
}
/* We used to always goto end_of_redisplay here, but this
isn't enough if we have a blinking cursor. */
if (w->cursor_off_p == w->last_cursor_off_p)
goto end_of_redisplay;
@ -14706,9 +14703,22 @@ redisplay_internal (void)
/* If we just did a pending size change, or have additional
visible frames, or selected_window changed, redisplay again. */
if ((windows_or_buffers_changed && !pending)
|| (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw))
|| (WINDOWP (selected_window)
&& (w = XWINDOW (selected_window)) != sw))
goto retry;
if (!NILP (Vrun_hooks))
{
run_window_change_functions ();
/* If windows or buffers changed or selected_window changed,
redisplay again. */
if ((windows_or_buffers_changed)
|| (WINDOWP (selected_window)
&& (w = XWINDOW (selected_window)) != sw))
goto retry;
}
/* Clear the face and image caches.
We used to do this only if consider_all_windows_p. But the cache