diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index f61f08a..eac3bd6 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -545,6 +545,12 @@ Window Sizes children. @end defun address@hidden window-old-pixel-height &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 address@hidden's frame (@pxref{Window Hooks}). address@hidden defun + @cindex window pixel width @cindex pixel width of a window @cindex total pixel width of a window @@ -559,6 +565,12 @@ Window Sizes the screen areas spanned by its children. @end defun address@hidden window-old-pixel-width &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 address@hidden's frame (@pxref{Window Hooks}). address@hidden defun + @cindex full-width window @cindex full-height window The following functions can be used to determine whether a given @@ -4087,11 +4099,11 @@ Window Configurations The argument @var{configuration} must be a value that was previously returned by @code{current-window-configuration}. The configuration is restored in the frame from which @var{configuration} was made, whether -that frame is selected or not. This always counts as a window size -change and triggers execution of the @code{window-size-change-functions} -(@pxref{Window Hooks}), because @code{set-window-configuration} doesn't -know how to tell whether the new configuration actually differs from the -old one. +that frame is selected or not. In some rare cases this may trigger +execution of the @code{window-size-change-functions} (@pxref{Window +Hooks}) even if the size of windows did not change at all. The address@hidden functions will be called if and +only if at least one window was added to or deleted from the frame. If the frame from which @var{configuration} was saved is dead, all this function does is restore the three variables @code{window-min-height}, @@ -4378,33 +4390,37 @@ Window Hooks @end defvar @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 at the -beginning of a redisplay cycle, and just once for each frame on which -size changes have occurred. - -Each function receives the frame as its sole argument. There is no -direct way to find out which windows on that frame have changed size, or -precisely how. However, if a size-change function records, at each -call, the existing windows and their sizes, it can also compare the -present sizes and the previous sizes. - -Creating or deleting windows counts as a size change, and therefore -causes these functions to be called. Changing the frame size also -counts, because it changes the sizes of the existing windows. +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 address@hidden and @code{window-pixel-width} respectively address@hidden and @code{window-pixel-height} for that +window (@pxref{Window Sizes}). + +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. You may use @code{save-selected-window} in these functions (@pxref{Selecting Windows}). However, do not use @code{save-window-excursion} (@pxref{Window Configurations}); exiting -that macro counts as a size change, which would cause these functions -to be called over and over. +that macro counts as a size change, which would cause these functions to +be called again. @end defvar @defvar window-configuration-change-hook -A normal hook that is run every time you change the window configuration -of an existing frame. This includes splitting or deleting windows, -changing the sizes of windows, or displaying a different buffer in a -window. +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. Resizing the +frame or individual windows do not count as configuration changes. Use address@hidden, see above, when you want to track +size changes that are not caused by the deletion or creation of windows. The buffer-local part of this hook is run once for each window on the affected frame, with the relevant window selected and its buffer diff --git a/lisp/window.el b/lisp/window.el index e4669c1..1c679ae 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -3136,10 +3136,10 @@ window--sanitize-window-sizes (walk-window-tree (lambda (window) (let ((delta (- (window-min-size window horizontal nil t) - (window-size window horizontal t)))) - (when (> delta 0) - (if (window-resizable-p window delta horizontal nil t) - (window-resize window delta horizontal nil t) + (window-size window horizontal t)))) + (when (> delta 0) + (if (window-resizable-p window delta horizontal nil t) + (window-resize window delta horizontal nil t) (setq value nil)))))) value)) diff --git a/src/frame.c b/src/frame.c index 8c86afe..df473ae 100644 --- a/src/frame.c +++ b/src/frame.c @@ -591,8 +591,6 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit, || new_pixel_height != old_pixel_height); unblock_input (); - - run_window_configuration_change_hook (f); } /* Allocate basically initialized frame. */ diff --git a/src/frame.h b/src/frame.h index 71dab4b..d9424ab 100644 --- a/src/frame.h +++ b/src/frame.h @@ -288,8 +288,9 @@ struct frame cleared. */ bool_bf explicit_name : 1; - /* True if size of some window on this frame has changed. */ - bool_bf window_sizes_changed : 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 the mouse has moved on this display device since the last time we checked. */ @@ -828,10 +829,10 @@ default_pixels_per_inch_y (void) are frozen on frame F. */ #define FRAME_WINDOWS_FROZEN(f) (f)->frozen_window_starts -/* True if a size change has been requested for frame F - but not yet really put into effect. This can be true temporarily - when an X event comes in at a bad time. */ -#define FRAME_WINDOW_SIZES_CHANGED(f) (f)->window_sizes_changed +/* 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) /* The minibuffer window of frame F, if it has one; otherwise nil. */ #define FRAME_MINIBUF_WINDOW(f) f->minibuffer_window diff --git a/src/window.c b/src/window.c index e1a30ee..7267a25 100644 --- a/src/window.c +++ b/src/window.c @@ -720,6 +720,30 @@ the height of the screen areas spanned by its children. */) return make_number (decode_valid_window (window)->pixel_height); } +DEFUN ("window-old-pixel-width", Fwindow_old_pixel_width, Swindow_old_pixel_width, 0, 1, 0, + doc: /* Return the old width of window WINDOW in pixels. +WINDOW must be a valid window and defaults to the selected one. + +The return value is the pixel width of WINDOW at the last time +`window-size-change-functions' was run. It's zero if WINDOW was made +after that. */) + (Lisp_Object window) +{ + return make_number (decode_valid_window (window)->old_pixel_width); +} + +DEFUN ("window-old-pixel-height", Fwindow_old_pixel_height, Swindow_old_pixel_height, 0, 1, 0, + doc: /* Return the old height of window WINDOW in pixels. +WINDOW must be a valid window and defaults to the selected one. + +The return value is the pixel height of WINDOW at the last time +`window-size-change-functions' was run. It's zero if WINDOW was made +after that. */) + (Lisp_Object window) +{ + return make_number (decode_valid_window (window)->old_pixel_height); +} + DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 2, 0, doc: /* Return the height of window WINDOW in lines. WINDOW must be a valid window and defaults to the selected one. @@ -2879,6 +2903,7 @@ window-start value is reasonable when this function is called. */) Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta; ptrdiff_t startpos IF_LINT (= 0), startbyte IF_LINT (= 0); int top IF_LINT (= 0), new_top; + bool resize_failed = false; w = decode_valid_window (window); XSETWINDOW (window, w); @@ -2978,8 +3003,6 @@ window-start value is reasonable when this function is called. */) fset_redisplay (f); Vwindow_list = Qnil; - FRAME_WINDOW_SIZES_CHANGED (f) = true; - bool resize_failed = false; if (!WINDOW_LEAF_P (w)) { @@ -3229,6 +3252,76 @@ If WINDOW is omitted or nil, it defaults to the selected window. */) return Qnil; } + +/* Compare old and present pixel sizes of windows in tree rooted at W. + Return true iff any of these windows differs in size. */ + +static bool +window_size_changed (struct window *w) +{ + if (w->pixel_width != w->old_pixel_width + || w->pixel_height != w->old_pixel_height) + return true; + + if (WINDOW_INTERNAL_P (w)) + { + w = XWINDOW (w->contents); + while (w) + { + if (window_size_changed (w)) + return true; + + w = NILP (w->next) ? 0 : XWINDOW (w->next); + } + } + + return false; +} + +/* Set old pixel sizes of windows in tree rooted at W to their present + pixel sizes. */ + +static void +window_set_old_pixel_sizes (struct window *w) +{ + w->old_pixel_width = w->pixel_width; + w->old_pixel_height = w->pixel_height; + + if (WINDOW_INTERNAL_P (w)) + { + w = XWINDOW (w->contents); + while (w) + { + window_set_old_pixel_sizes (w); + w = NILP (w->next) ? 0 : XWINDOW (w->next); + } + } +} + + +void +run_window_size_change_functions (Lisp_Object frame) +{ + struct frame *f = XFRAME (frame); + struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f)); + Lisp_Object functions = Vwindow_size_change_functions; + + if (FRAME_WINDOW_CONFIGURATION_CHANGED (f) || + window_size_changed (r)) + { + while (CONSP (functions)) + { + if (!EQ (XCAR (functions), Qt)) + call1 (XCAR (functions), frame); + functions = XCDR (functions); + } + + window_set_old_pixel_sizes (r); + FRAME_WINDOW_CONFIGURATION_CHANGED (f) = false; + } +} + + /* 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. KEEP_MARGINS_P means that the current margins, fringes, and @@ -3263,15 +3356,9 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, if (!(keep_margins_p && samebuf)) { /* If we're not actually changing the buffer, don't reset hscroll - and vscroll. This case happens for example when called from - change_frame_size_1, where we use a dummy call to - Fset_window_buffer on the frame's selected window (and no - other) just in order to run window-configuration-change-hook - (no longer true since change_frame_size_1 directly calls - run_window_configuration_change_hook). Resetting hscroll and - vscroll here is problematic for things like image-mode and - doc-view-mode since it resets the image's position whenever we - resize the frame. */ + and vscroll. Resetting hscroll and vscroll here is problematic + for things like image-mode and doc-view-mode since it resets + the image's position whenever we resize the frame. */ w->hscroll = w->min_hscroll = w->hscroll_whole = 0; w->suspend_auto_hscroll = false; w->vscroll = 0; @@ -3283,10 +3370,8 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, w->start_at_line_beg = false; w->force_start = false; } - /* Maybe we could move this into the `if' but it's not obviously safe and - I doubt it's worth the trouble. */ - wset_redisplay (w); + wset_redisplay (w); wset_update_mode_line (w); /* We must select BUFFER to run the window-scroll-functions and to look up @@ -3314,7 +3399,7 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, if (run_hooks_p) { - if (! NILP (Vwindow_scroll_functions)) + if (!NILP (Vwindow_scroll_functions)) run_hook_with_args_2 (Qwindow_scroll_functions, window, Fmarker_position (w->start)); if (!samebuf) @@ -3559,6 +3644,8 @@ make_window (void) w->phys_cursor_width = -1; #endif w->sequence_number = ++sequence_number; + w->old_pixel_width = 0; + w->old_pixel_height = 0; w->scroll_bar_width = -1; w->scroll_bar_height = -1; w->column_number_displayed = -1; @@ -3922,7 +4009,6 @@ be applied on the Elisp level. */) window_resize_apply (r, horflag); fset_redisplay (f); - FRAME_WINDOW_SIZES_CHANGED (f) = true; adjust_frame_glyphs (f); unblock_input (); @@ -4087,7 +4173,6 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise) } } - FRAME_WINDOW_SIZES_CHANGED (f) = true; fset_redisplay (f); } @@ -4214,7 +4299,6 @@ set correctly. See the code of `split-window' for how this is done. */) p = XWINDOW (o->parent); fset_redisplay (f); - FRAME_WINDOW_SIZES_CHANGED (f) = true; new = make_window (); n = XWINDOW (new); wset_frame (n, frame); @@ -4383,7 +4467,6 @@ Signal an error when WINDOW is the only window on its frame. */) fset_redisplay (f); Vwindow_list = Qnil; - FRAME_WINDOW_SIZES_CHANGED (f) = true; wset_next (w, Qnil); /* Don't delete w->next too. */ free_window_matrices (w); @@ -4451,9 +4534,6 @@ Signal an error when WINDOW is the only window on its frame. */) } else unblock_input (); - - /* Must be run by the caller: - run_window_configuration_change_hook (f); */ } else /* We failed: Relink WINDOW into window tree. */ @@ -4527,7 +4607,6 @@ grow_mini_window (struct window *w, int delta, bool pixelwise) /* Enforce full redisplay of the frame. */ /* FIXME: Shouldn't window--resize-root-window-vertically do it? */ fset_redisplay (f); - FRAME_WINDOW_SIZES_CHANGED (f) = true; adjust_frame_glyphs (f); unblock_input (); } @@ -4567,7 +4646,6 @@ shrink_mini_window (struct window *w, bool pixelwise) /* Enforce full redisplay of the frame. */ /* FIXME: Shouldn't window--resize-root-window-vertically do it? */ fset_redisplay (f); - FRAME_WINDOW_SIZES_CHANGED (f) = true; adjust_frame_glyphs (f); unblock_input (); } @@ -4610,7 +4688,6 @@ DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini w->top_line = r->top_line + r->total_lines; fset_redisplay (f); - FRAME_WINDOW_SIZES_CHANGED (f) = true; adjust_frame_glyphs (f); unblock_input (); return Qt; @@ -5948,6 +6025,7 @@ struct saved_window Lisp_Object window, buffer, start, pointm, old_pointm; Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width; + Lisp_Object old_pixel_height, old_pixel_width; Lisp_Object left_col, top_line, total_cols, total_lines; Lisp_Object normal_cols, normal_lines; Lisp_Object hscroll, min_hscroll, hscroll_whole, suspend_auto_hscroll; @@ -6063,6 +6141,12 @@ the return value is nil. Otherwise the value is t. */) struct window *root_window; struct window **leaf_windows; ptrdiff_t i, k, n_leaf_windows; + /* Records whether a window has been added or removed wrt the + original configuration. */ + bool window_changed = false; + /* Records whether a window has changed its buffer wrt the + original configuration. */ + bool buffer_changed = false; /* Don't do this within the main loop below: This may call Lisp code and is thus potentially unsafe while input is blocked. */ @@ -6071,12 +6155,18 @@ the return value is nil. Otherwise the value is t. */) p = SAVED_WINDOW_N (saved_windows, k); window = p->window; w = XWINDOW (window); + + if (NILP (w->contents)) + /* A dead window that will be resurrected, the window + configuration will change. */ + window_changed = true; + if (BUFFERP (w->contents) && !EQ (w->contents, p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer))) /* If a window we restore gets another buffer, record the window's old buffer. */ - call1 (Qrecord_window_buffer, window); + call1 (Qrecord_window_buffer, window); } /* Disallow x_set_window_size, temporarily. */ @@ -6100,7 +6190,6 @@ the return value is nil. Otherwise the value is t. */) } fset_redisplay (f); - FRAME_WINDOW_SIZES_CHANGED (f) = true; /* Problem: Freeing all matrices and later allocating them again is a serious redisplay flickering problem. What we would @@ -6156,6 +6245,8 @@ the return value is nil. Otherwise the value is t. */) w->pixel_top = XFASTINT (p->pixel_top); w->pixel_width = XFASTINT (p->pixel_width); w->pixel_height = XFASTINT (p->pixel_height); + w->old_pixel_width = XFASTINT (p->old_pixel_width); + w->old_pixel_height = XFASTINT (p->old_pixel_height); w->left_col = XFASTINT (p->left_col); w->top_line = XFASTINT (p->top_line); w->total_cols = XFASTINT (p->total_cols); @@ -6203,6 +6294,9 @@ the return value is nil. Otherwise the value is t. */) if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer))) /* If saved buffer is alive, install it. */ { + if (!EQ (w->contents, p->buffer)) + /* Record buffer configuration change. */ + buffer_changed = true; wset_buffer (w, p->buffer); w->start_at_line_beg = !NILP (p->start_at_line_beg); set_marker_restricted (w->start, p->start, w->contents); @@ -6236,6 +6330,8 @@ the return value is nil. Otherwise the value is t. */) else if (!NILP (w->start)) /* Leaf window has no live buffer, get one. */ { + /* Record buffer configuration change. */ + buffer_changed = true; /* Get the buffer via other_buffer_safely in order to avoid showing an unimportant buffer and, if necessary, to recreate *scratch* in the course (part of Juanma's bs-show @@ -6283,7 +6379,10 @@ the return value is nil. Otherwise the value is t. */) /* Now, free glyph matrices in windows that were not reused. */ for (i = 0; i < n_leaf_windows; i++) if (NILP (leaf_windows[i]->contents)) - free_window_matrices (leaf_windows[i]); + { + free_window_matrices (leaf_windows[i]); + window_changed = true; + } /* Allow x_set_window_size again and apply frame size changes if needed. */ @@ -6303,7 +6402,8 @@ the return value is nil. Otherwise the value is t. */) /* Record the selected window's buffer here. The window should already be the selected one from the call above. */ - select_window (data->current_window, Qnil, false); + if (WINDOW_LIVE_P (data->current_window)) + select_window (data->current_window, Qnil, false); /* Fselect_window will have made f the selected frame, so we reselect the proper frame here. Fhandle_switch_frame will change the @@ -6313,7 +6413,32 @@ the return value is nil. Otherwise the value is t. */) if (FRAME_LIVE_P (XFRAME (data->selected_frame))) do_switch_frame (data->selected_frame, 0, 0, Qnil); - run_window_configuration_change_hook (f); + if (window_changed) + /* At least one window has been added or removed. Run + `window-configuration-change-hook' and make sure + `window-size-change-functions' get run later. + + We have to do this in order to capture the following + scenario: Suppose our frame contains two live windows W1 and + W2 and ‘set-window-configuration’ replaces them by two + windows W3 and W4 that were dead the last time + run_window_size_change_functions was run. If W3 and W4 have + the same values for their old and new pixel sizes but these + values differ from those of W1 and W2, the sizes of our + frame's two live windows changed but window_size_changed has + no means to detect that fact. + + Obviously, this will get us false positives, for example, + when we restore the original configuration with W1 and W2 + before run_window_size_change_functions gets called. */ + { + run_window_configuration_change_hook (f); + FRAME_WINDOW_CONFIGURATION_CHANGED (f) = true; + } + else if (buffer_changed) + /* At least one window has changed its buffer. Run + `window-configuration-change-hook' only. */ + run_window_configuration_change_hook (f); } if (!NILP (new_current_buffer)) @@ -6464,6 +6589,8 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, ptrdiff_t i) p->pixel_top = make_number (w->pixel_top); p->pixel_width = make_number (w->pixel_width); p->pixel_height = make_number (w->pixel_height); + p->old_pixel_width = make_number (w->old_pixel_width); + p->old_pixel_height = make_number (w->old_pixel_height); p->left_col = make_number (w->left_col); p->top_line = make_number (w->top_line); p->total_cols = make_number (w->total_cols); @@ -7246,6 +7373,16 @@ selected; while the global part is run only once for the modified frame, with the relevant frame selected. */); Vwindow_configuration_change_hook = Qnil; + DEFVAR_LISP ("window-size-change-functions", Vwindow_size_change_functions, + doc: /* Functions called during redisplay, if window sizes have changed. +The value should be a list of functions that take one argument. +During the first part of redisplay, for each frame, if any of its windows +have changed size since the last redisplay, or have been split or deleted, +all the functions in the list are called, with the frame as argument. +If redisplay decides to resize the minibuffer window, it calls these +functions on behalf of that as well. */); + Vwindow_size_change_functions = Qnil; + DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay, doc: /* Non-nil means `recenter' redraws entire frame. If this option is non-nil, then the `recenter' command with a nil @@ -7374,6 +7511,8 @@ displayed after a scrolling operation to be somewhat inaccurate. */); defsubr (&Swindow_use_time); defsubr (&Swindow_pixel_width); defsubr (&Swindow_pixel_height); + defsubr (&Swindow_old_pixel_width); + defsubr (&Swindow_old_pixel_height); defsubr (&Swindow_total_width); defsubr (&Swindow_total_height); defsubr (&Swindow_normal_size); diff --git a/src/window.h b/src/window.h index c29207d..dea1d19 100644 --- a/src/window.h +++ b/src/window.h @@ -214,6 +214,11 @@ 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 old_pixel_width; + int old_pixel_height; + /* The size of the window. */ int total_cols; int total_lines; @@ -499,15 +504,17 @@ wset_next_buffers (struct window *w, Lisp_Object val) #define WINDOW_LEAF_P(W) \ (BUFFERP ((W)->contents)) -/* True if W is a member of horizontal combination. */ +/* Non-nil if W is internal. */ +#define WINDOW_INTERNAL_P(W) \ + (WINDOWP ((W)->contents)) +/* True if W is a member of horizontal combination. */ #define WINDOW_HORIZONTAL_COMBINATION_P(W) \ - (WINDOWP ((W)->contents) && (W)->horizontal) + (WINDOW_INTERNAL_P (W) && (W)->horizontal) /* True if W is a member of vertical combination. */ - #define WINDOW_VERTICAL_COMBINATION_P(W) \ - (WINDOWP ((W)->contents) && !(W)->horizontal) + (WINDOW_INTERNAL_P (W) && !(W)->horizontal) /* WINDOW's XFRAME. */ #define WINDOW_XFRAME(W) (XFRAME (WINDOW_FRAME ((W)))) @@ -1014,6 +1021,7 @@ extern void shrink_mini_window (struct window *, bool); extern int window_relative_x_coord (struct window *, enum window_part, int); void run_window_configuration_change_hook (struct frame *f); +void run_window_size_change_functions (Lisp_Object); /* 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. */ diff --git a/src/xdisp.c b/src/xdisp.c index fed5879..4330f10 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -11786,24 +11786,7 @@ prepare_menu_bars (void) && !XBUFFER (w->contents)->text->redisplay) continue; - /* If a window on this frame changed size, report that to - the user and clear the size-change flag. */ - if (FRAME_WINDOW_SIZES_CHANGED (f)) - { - Lisp_Object functions; - - /* Clear flag first in case we get an error below. */ - FRAME_WINDOW_SIZES_CHANGED (f) = false; - functions = Vwindow_size_change_functions; - - while (CONSP (functions)) - { - if (!EQ (XCAR (functions), Qt)) - call1 (XCAR (functions), frame); - functions = XCDR (functions); - } - } - + run_window_size_change_functions (frame); menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run); #ifdef HAVE_WINDOW_SYSTEM update_tool_bar (f, false); @@ -13599,24 +13582,12 @@ redisplay_internal (void) 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 && FRAME_WINDOW_SIZES_CHANGED (sf)) + if (sf->redisplay) { - Lisp_Object functions; ptrdiff_t count1 = SPECPDL_INDEX (); record_unwind_save_match_data (); - - /* Clear flag first in case we get an error below. */ - FRAME_WINDOW_SIZES_CHANGED (sf) = false; - functions = Vwindow_size_change_functions; - - while (CONSP (functions)) - { - if (!EQ (XCAR (functions), Qt)) - call1 (XCAR (functions), selected_frame); - functions = XCDR (functions); - } - + run_window_size_change_functions (selected_frame); unbind_to (count1, Qnil); } @@ -13638,22 +13609,10 @@ redisplay_internal (void) { if (sf->redisplay) { - Lisp_Object functions; ptrdiff_t count1 = SPECPDL_INDEX (); record_unwind_save_match_data (); - - /* Clear flag first in case we get an error below. */ - FRAME_WINDOW_SIZES_CHANGED (sf) = false; - functions = Vwindow_size_change_functions; - - while (CONSP (functions)) - { - if (!EQ (XCAR (functions), Qt)) - call1 (XCAR (functions), selected_frame); - functions = XCDR (functions); - } - + run_window_size_change_functions (selected_frame); unbind_to (count1, Qnil); } @@ -31447,16 +31406,6 @@ If nil, disable message logging. If t, log messages but don't truncate the buffer when it becomes large. */); Vmessage_log_max = make_number (1000); - DEFVAR_LISP ("window-size-change-functions", Vwindow_size_change_functions, - doc: /* Functions called during redisplay, if window sizes have changed. -The value should be a list of functions that take one argument. -During the first part of redisplay, for each frame, if any of its windows -have changed size since the last redisplay, or have been split or deleted, -all the functions in the list are called, with the frame as argument. -If redisplay decides to resize the minibuffer window, it calls these -functions on behalf of that as well. */); - Vwindow_size_change_functions = Qnil; - DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions, doc: /* List of functions to call before redisplaying a window with scrolling. Each function is called with two arguments, the window and its new diff --git a/src/xfns.c b/src/xfns.c index 20ac627..2a50a5a 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -1313,7 +1313,6 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) } #endif /* not USE_X_TOOLKIT && not USE_GTK */ adjust_frame_glyphs (f); - run_window_configuration_change_hook (f); } c:\emacs-git\quick>c:/Programme/MinGW/msys/1.0/bin/bash.exe --login -i -c "cd /c/emacs-git/quick/ ; git status" c:/Programme/MinGW/msys/1.0/bin/bash.exe --login -i -c "cd /c/emacs-git/quick/ ; git status" On branch master Your branch is up-to-date with 'origin/master'. Changes not staged for commit: (use "git add ..." to update what will be committed) (use "git checkout -- ..." to discard changes in working directory) modified: doc/lispref/windows.texi modified: lisp/window.el modified: src/frame.c modified: src/frame.h modified: src/window.c modified: src/window.h modified: src/xdisp.c modified: src/xfns.c no changes added to commit (use "git add" and/or "git commit -a") c:\emacs-git\quick>c:/Programme/MinGW/msys/1.0/bin/bash.exe --login -i -c "cd /c/emacs-git/quick/ ; git diff" c:/Programme/MinGW/msys/1.0/bin/bash.exe --login -i -c "cd /c/emacs-git/quick/ ; git diff" diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index f61f08a..eac3bd6 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -545,6 +545,12 @@ Window Sizes children. @end defun address@hidden window-old-pixel-height &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 address@hidden's frame (@pxref{Window Hooks}). address@hidden defun + @cindex window pixel width @cindex pixel width of a window @cindex total pixel width of a window @@ -559,6 +565,12 @@ Window Sizes the screen areas spanned by its children. @end defun address@hidden window-old-pixel-width &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 address@hidden's frame (@pxref{Window Hooks}). address@hidden defun + @cindex full-width window @cindex full-height window The following functions can be used to determine whether a given @@ -4087,11 +4099,11 @@ Window Configurations The argument @var{configuration} must be a value that was previously returned by @code{current-window-configuration}. The configuration is restored in the frame from which @var{configuration} was made, whether -that frame is selected or not. This always counts as a window size -change and triggers execution of the @code{window-size-change-functions} -(@pxref{Window Hooks}), because @code{set-window-configuration} doesn't -know how to tell whether the new configuration actually differs from the -old one. +that frame is selected or not. In some rare cases this may trigger +execution of the @code{window-size-change-functions} (@pxref{Window +Hooks}) even if the size of windows did not change at all. The address@hidden functions will be called if and +only if at least one window was added to or deleted from the frame. If the frame from which @var{configuration} was saved is dead, all this function does is restore the three variables @code{window-min-height}, @@ -4378,33 +4390,37 @@ Window Hooks @end defvar @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 at the -beginning of a redisplay cycle, and just once for each frame on which -size changes have occurred. - -Each function receives the frame as its sole argument. There is no -direct way to find out which windows on that frame have changed size, or -precisely how. However, if a size-change function records, at each -call, the existing windows and their sizes, it can also compare the -present sizes and the previous sizes. - -Creating or deleting windows counts as a size change, and therefore -causes these functions to be called. Changing the frame size also -counts, because it changes the sizes of the existing windows. +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 address@hidden and @code{window-pixel-width} respectively address@hidden and @code{window-pixel-height} for that +window (@pxref{Window Sizes}). + +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. You may use @code{save-selected-window} in these functions (@pxref{Selecting Windows}). However, do not use @code{save-window-excursion} (@pxref{Window Configurations}); exiting -that macro counts as a size change, which would cause these functions -to be called over and over. +that macro counts as a size change, which would cause these functions to +be called again. @end defvar @defvar window-configuration-change-hook -A normal hook that is run every time you change the window configuration -of an existing frame. This includes splitting or deleting windows, -changing the sizes of windows, or displaying a different buffer in a -window. +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. Resizing the +frame or individual windows do not count as configuration changes. Use address@hidden, see above, when you want to track +size changes that are not caused by the deletion or creation of windows. The buffer-local part of this hook is run once for each window on the affected frame, with the relevant window selected and its buffer diff --git a/src/frame.c b/src/frame.c index 8c86afe..df473ae 100644 --- a/src/frame.c +++ b/src/frame.c @@ -591,8 +591,6 @@ adjust_frame_size (struct frame *f, int new_width, int new_height, int inhibit, || new_pixel_height != old_pixel_height); unblock_input (); - - run_window_configuration_change_hook (f); } /* Allocate basically initialized frame. */ diff --git a/src/frame.h b/src/frame.h index 71dab4b..d9424ab 100644 --- a/src/frame.h +++ b/src/frame.h @@ -288,8 +288,9 @@ struct frame cleared. */ bool_bf explicit_name : 1; - /* True if size of some window on this frame has changed. */ - bool_bf window_sizes_changed : 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 the mouse has moved on this display device since the last time we checked. */ @@ -828,10 +829,10 @@ default_pixels_per_inch_y (void) are frozen on frame F. */ #define FRAME_WINDOWS_FROZEN(f) (f)->frozen_window_starts -/* True if a size change has been requested for frame F - but not yet really put into effect. This can be true temporarily - when an X event comes in at a bad time. */ -#define FRAME_WINDOW_SIZES_CHANGED(f) (f)->window_sizes_changed +/* 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) /* The minibuffer window of frame F, if it has one; otherwise nil. */ #define FRAME_MINIBUF_WINDOW(f) f->minibuffer_window diff --git a/src/window.c b/src/window.c index e1a30ee..5b03a24 100644 --- a/src/window.c +++ b/src/window.c @@ -720,6 +720,30 @@ the height of the screen areas spanned by its children. */) return make_number (decode_valid_window (window)->pixel_height); } +DEFUN ("window-old-pixel-width", Fwindow_old_pixel_width, Swindow_old_pixel_width, 0, 1, 0, + doc: /* Return the old width of window WINDOW in pixels. +WINDOW must be a valid window and defaults to the selected one. + +The return value is the pixel width of WINDOW at the last time +`window-size-change-functions' was run. It's zero if WINDOW was made +after that. */) + (Lisp_Object window) +{ + return make_number (decode_valid_window (window)->old_pixel_width); +} + +DEFUN ("window-old-pixel-height", Fwindow_old_pixel_height, Swindow_old_pixel_height, 0, 1, 0, + doc: /* Return the old height of window WINDOW in pixels. +WINDOW must be a valid window and defaults to the selected one. + +The return value is the pixel height of WINDOW at the last time +`window-size-change-functions' was run. It's zero if WINDOW was made +after that. */) + (Lisp_Object window) +{ + return make_number (decode_valid_window (window)->old_pixel_height); +} + DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 2, 0, doc: /* Return the height of window WINDOW in lines. WINDOW must be a valid window and defaults to the selected one. @@ -2879,6 +2903,7 @@ window-start value is reasonable when this function is called. */) Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta; ptrdiff_t startpos IF_LINT (= 0), startbyte IF_LINT (= 0); int top IF_LINT (= 0), new_top; + bool resize_failed = false; w = decode_valid_window (window); XSETWINDOW (window, w); @@ -2978,8 +3003,6 @@ window-start value is reasonable when this function is called. */) fset_redisplay (f); Vwindow_list = Qnil; - FRAME_WINDOW_SIZES_CHANGED (f) = true; - bool resize_failed = false; if (!WINDOW_LEAF_P (w)) { @@ -3229,6 +3252,76 @@ If WINDOW is omitted or nil, it defaults to the selected window. */) return Qnil; } + +/* Compare old and present pixel sizes of windows in tree rooted at W. + Return true iff any of these windows differs in size. */ + +static bool +window_size_changed (struct window *w) +{ + if (w->pixel_width != w->old_pixel_width + || w->pixel_height != w->old_pixel_height) + return true; + + if (WINDOW_INTERNAL_P (w)) + { + w = XWINDOW (w->contents); + while (w) + { + if (window_size_changed (w)) + return true; + + w = NILP (w->next) ? 0 : XWINDOW (w->next); + } + } + + return false; +} + +/* Set old pixel sizes of windows in tree rooted at W to their present + pixel sizes. */ + +static void +window_set_old_pixel_sizes (struct window *w) +{ + w->old_pixel_width = w->pixel_width; + w->old_pixel_height = w->pixel_height; + + if (WINDOW_INTERNAL_P (w)) + { + w = XWINDOW (w->contents); + while (w) + { + window_set_old_pixel_sizes (w); + w = NILP (w->next) ? 0 : XWINDOW (w->next); + } + } +} + + +void +run_window_size_change_functions (Lisp_Object frame) +{ + struct frame *f = XFRAME (frame); + struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f)); + Lisp_Object functions = Vwindow_size_change_functions; + + if (FRAME_WINDOW_CONFIGURATION_CHANGED (f) || + window_size_changed (r)) + { + while (CONSP (functions)) + { + if (!EQ (XCAR (functions), Qt)) + call1 (XCAR (functions), frame); + functions = XCDR (functions); + } + + window_set_old_pixel_sizes (r); + FRAME_WINDOW_CONFIGURATION_CHANGED (f) = false; + } +} + + /* 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. KEEP_MARGINS_P means that the current margins, fringes, and @@ -3263,15 +3356,9 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, if (!(keep_margins_p && samebuf)) { /* If we're not actually changing the buffer, don't reset hscroll - and vscroll. This case happens for example when called from - change_frame_size_1, where we use a dummy call to - Fset_window_buffer on the frame's selected window (and no - other) just in order to run window-configuration-change-hook - (no longer true since change_frame_size_1 directly calls - run_window_configuration_change_hook). Resetting hscroll and - vscroll here is problematic for things like image-mode and - doc-view-mode since it resets the image's position whenever we - resize the frame. */ + and vscroll. Resetting hscroll and vscroll here is problematic + for things like image-mode and doc-view-mode since it resets + the image's position whenever we resize the frame. */ w->hscroll = w->min_hscroll = w->hscroll_whole = 0; w->suspend_auto_hscroll = false; w->vscroll = 0; @@ -3283,10 +3370,8 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, w->start_at_line_beg = false; w->force_start = false; } - /* Maybe we could move this into the `if' but it's not obviously safe and - I doubt it's worth the trouble. */ - wset_redisplay (w); + wset_redisplay (w); wset_update_mode_line (w); /* We must select BUFFER to run the window-scroll-functions and to look up @@ -3314,7 +3399,7 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, if (run_hooks_p) { - if (! NILP (Vwindow_scroll_functions)) + if (!NILP (Vwindow_scroll_functions)) run_hook_with_args_2 (Qwindow_scroll_functions, window, Fmarker_position (w->start)); if (!samebuf) @@ -3559,6 +3644,8 @@ make_window (void) w->phys_cursor_width = -1; #endif w->sequence_number = ++sequence_number; + w->old_pixel_width = 0; + w->old_pixel_height = 0; w->scroll_bar_width = -1; w->scroll_bar_height = -1; w->column_number_displayed = -1; @@ -3922,7 +4009,6 @@ be applied on the Elisp level. */) window_resize_apply (r, horflag); fset_redisplay (f); - FRAME_WINDOW_SIZES_CHANGED (f) = true; adjust_frame_glyphs (f); unblock_input (); @@ -4087,7 +4173,6 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise) } } - FRAME_WINDOW_SIZES_CHANGED (f) = true; fset_redisplay (f); } @@ -4214,7 +4299,6 @@ set correctly. See the code of `split-window' for how this is done. */) p = XWINDOW (o->parent); fset_redisplay (f); - FRAME_WINDOW_SIZES_CHANGED (f) = true; new = make_window (); n = XWINDOW (new); wset_frame (n, frame); @@ -4383,7 +4467,6 @@ Signal an error when WINDOW is the only window on its frame. */) fset_redisplay (f); Vwindow_list = Qnil; - FRAME_WINDOW_SIZES_CHANGED (f) = true; wset_next (w, Qnil); /* Don't delete w->next too. */ free_window_matrices (w); @@ -4451,9 +4534,6 @@ Signal an error when WINDOW is the only window on its frame. */) } else unblock_input (); - - /* Must be run by the caller: - run_window_configuration_change_hook (f); */ } else /* We failed: Relink WINDOW into window tree. */ @@ -4527,7 +4607,6 @@ grow_mini_window (struct window *w, int delta, bool pixelwise) /* Enforce full redisplay of the frame. */ /* FIXME: Shouldn't window--resize-root-window-vertically do it? */ fset_redisplay (f); - FRAME_WINDOW_SIZES_CHANGED (f) = true; adjust_frame_glyphs (f); unblock_input (); } @@ -4567,7 +4646,6 @@ shrink_mini_window (struct window *w, bool pixelwise) /* Enforce full redisplay of the frame. */ /* FIXME: Shouldn't window--resize-root-window-vertically do it? */ fset_redisplay (f); - FRAME_WINDOW_SIZES_CHANGED (f) = true; adjust_frame_glyphs (f); unblock_input (); } @@ -4610,7 +4688,6 @@ DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini w->top_line = r->top_line + r->total_lines; fset_redisplay (f); - FRAME_WINDOW_SIZES_CHANGED (f) = true; adjust_frame_glyphs (f); unblock_input (); return Qt; @@ -5948,6 +6025,7 @@ struct saved_window Lisp_Object window, buffer, start, pointm, old_pointm; Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width; + Lisp_Object old_pixel_height, old_pixel_width; Lisp_Object left_col, top_line, total_cols, total_lines; Lisp_Object normal_cols, normal_lines; Lisp_Object hscroll, min_hscroll, hscroll_whole, suspend_auto_hscroll; @@ -6063,6 +6141,12 @@ the return value is nil. Otherwise the value is t. */) struct window *root_window; struct window **leaf_windows; ptrdiff_t i, k, n_leaf_windows; + /* Records whether a window has been added or removed wrt the + original configuration. */ + bool window_changed = false; + /* Records whether a window has changed its buffer wrt the + original configuration. */ + bool buffer_changed = false; /* Don't do this within the main loop below: This may call Lisp code and is thus potentially unsafe while input is blocked. */ @@ -6071,6 +6155,12 @@ the return value is nil. Otherwise the value is t. */) p = SAVED_WINDOW_N (saved_windows, k); window = p->window; w = XWINDOW (window); + + if (NILP (w->contents)) + /* A dead window that will be resurrected, the window + configuration will change. */ + window_changed = true; + if (BUFFERP (w->contents) && !EQ (w->contents, p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer))) @@ -6100,7 +6190,6 @@ the return value is nil. Otherwise the value is t. */) } fset_redisplay (f); - FRAME_WINDOW_SIZES_CHANGED (f) = true; /* Problem: Freeing all matrices and later allocating them again is a serious redisplay flickering problem. What we would @@ -6156,6 +6245,8 @@ the return value is nil. Otherwise the value is t. */) w->pixel_top = XFASTINT (p->pixel_top); w->pixel_width = XFASTINT (p->pixel_width); w->pixel_height = XFASTINT (p->pixel_height); + w->old_pixel_width = XFASTINT (p->old_pixel_width); + w->old_pixel_height = XFASTINT (p->old_pixel_height); w->left_col = XFASTINT (p->left_col); w->top_line = XFASTINT (p->top_line); w->total_cols = XFASTINT (p->total_cols); @@ -6203,6 +6294,9 @@ the return value is nil. Otherwise the value is t. */) if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer))) /* If saved buffer is alive, install it. */ { + if (!EQ (w->contents, p->buffer)) + /* Record buffer configuration change. */ + buffer_changed = true; wset_buffer (w, p->buffer); w->start_at_line_beg = !NILP (p->start_at_line_beg); set_marker_restricted (w->start, p->start, w->contents); @@ -6236,6 +6330,8 @@ the return value is nil. Otherwise the value is t. */) else if (!NILP (w->start)) /* Leaf window has no live buffer, get one. */ { + /* Record buffer configuration change. */ + buffer_changed = true; /* Get the buffer via other_buffer_safely in order to avoid showing an unimportant buffer and, if necessary, to recreate *scratch* in the course (part of Juanma's bs-show @@ -6283,7 +6379,10 @@ the return value is nil. Otherwise the value is t. */) /* Now, free glyph matrices in windows that were not reused. */ for (i = 0; i < n_leaf_windows; i++) if (NILP (leaf_windows[i]->contents)) - free_window_matrices (leaf_windows[i]); + { + free_window_matrices (leaf_windows[i]); + window_changed = true; + } /* Allow x_set_window_size again and apply frame size changes if needed. */ @@ -6303,7 +6402,8 @@ the return value is nil. Otherwise the value is t. */) /* Record the selected window's buffer here. The window should already be the selected one from the call above. */ - select_window (data->current_window, Qnil, false); + if (WINDOW_LIVE_P (data->current_window)) + select_window (data->current_window, Qnil, false); /* Fselect_window will have made f the selected frame, so we reselect the proper frame here. Fhandle_switch_frame will change the @@ -6313,7 +6413,32 @@ the return value is nil. Otherwise the value is t. */) if (FRAME_LIVE_P (XFRAME (data->selected_frame))) do_switch_frame (data->selected_frame, 0, 0, Qnil); - run_window_configuration_change_hook (f); + if (window_changed) + /* At least one window has been added or removed. Run + `window-configuration-change-hook' and make sure + `window-size-change-functions' get run later. + + We have to do this in order to capture the following + scenario: Suppose our frame contains two live windows W1 and + W2 and ‘set-window-configuration’ replaces them by two + windows W3 and W4 that were dead the last time + run_window_size_change_functions was run. If W3 and W4 have + the same values for their old and new pixel sizes but these + values differ from those of W1 and W2, the sizes of our + frame's two live windows changed but window_size_changed has + no means to detect that fact. + + Obviously, this will get us false positives, for example, + when we restore the original configuration with W1 and W2 + before run_window_size_change_functions gets called. */ + { + run_window_configuration_change_hook (f); + FRAME_WINDOW_CONFIGURATION_CHANGED (f) = true; + } + else if (buffer_changed) + /* At least one window has changed its buffer. Run + `window-configuration-change-hook' only. */ + run_window_configuration_change_hook (f); } if (!NILP (new_current_buffer)) @@ -6464,6 +6589,8 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, ptrdiff_t i) p->pixel_top = make_number (w->pixel_top); p->pixel_width = make_number (w->pixel_width); p->pixel_height = make_number (w->pixel_height); + p->old_pixel_width = make_number (w->old_pixel_width); + p->old_pixel_height = make_number (w->old_pixel_height); p->left_col = make_number (w->left_col); p->top_line = make_number (w->top_line); p->total_cols = make_number (w->total_cols); @@ -7246,6 +7373,16 @@ selected; while the global part is run only once for the modified frame, with the relevant frame selected. */); Vwindow_configuration_change_hook = Qnil; + DEFVAR_LISP ("window-size-change-functions", Vwindow_size_change_functions, + doc: /* Functions called during redisplay, if window sizes have changed. +The value should be a list of functions that take one argument. +During the first part of redisplay, for each frame, if any of its windows +have changed size since the last redisplay, or have been split or deleted, +all the functions in the list are called, with the frame as argument. +If redisplay decides to resize the minibuffer window, it calls these +functions on behalf of that as well. */); + Vwindow_size_change_functions = Qnil; + DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay, doc: /* Non-nil means `recenter' redraws entire frame. If this option is non-nil, then the `recenter' command with a nil @@ -7374,6 +7511,8 @@ displayed after a scrolling operation to be somewhat inaccurate. */); defsubr (&Swindow_use_time); defsubr (&Swindow_pixel_width); defsubr (&Swindow_pixel_height); + defsubr (&Swindow_old_pixel_width); + defsubr (&Swindow_old_pixel_height); defsubr (&Swindow_total_width); defsubr (&Swindow_total_height); defsubr (&Swindow_normal_size); diff --git a/src/window.h b/src/window.h index c29207d..dea1d19 100644 --- a/src/window.h +++ b/src/window.h @@ -214,6 +214,11 @@ 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 old_pixel_width; + int old_pixel_height; + /* The size of the window. */ int total_cols; int total_lines; @@ -499,15 +504,17 @@ wset_next_buffers (struct window *w, Lisp_Object val) #define WINDOW_LEAF_P(W) \ (BUFFERP ((W)->contents)) -/* True if W is a member of horizontal combination. */ +/* Non-nil if W is internal. */ +#define WINDOW_INTERNAL_P(W) \ + (WINDOWP ((W)->contents)) +/* True if W is a member of horizontal combination. */ #define WINDOW_HORIZONTAL_COMBINATION_P(W) \ - (WINDOWP ((W)->contents) && (W)->horizontal) + (WINDOW_INTERNAL_P (W) && (W)->horizontal) /* True if W is a member of vertical combination. */ - #define WINDOW_VERTICAL_COMBINATION_P(W) \ - (WINDOWP ((W)->contents) && !(W)->horizontal) + (WINDOW_INTERNAL_P (W) && !(W)->horizontal) /* WINDOW's XFRAME. */ #define WINDOW_XFRAME(W) (XFRAME (WINDOW_FRAME ((W)))) @@ -1014,6 +1021,7 @@ extern void shrink_mini_window (struct window *, bool); extern int window_relative_x_coord (struct window *, enum window_part, int); void run_window_configuration_change_hook (struct frame *f); +void run_window_size_change_functions (Lisp_Object); /* 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. */ diff --git a/src/xdisp.c b/src/xdisp.c index fed5879..4330f10 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -11786,24 +11786,7 @@ prepare_menu_bars (void) && !XBUFFER (w->contents)->text->redisplay) continue; - /* If a window on this frame changed size, report that to - the user and clear the size-change flag. */ - if (FRAME_WINDOW_SIZES_CHANGED (f)) - { - Lisp_Object functions; - - /* Clear flag first in case we get an error below. */ - FRAME_WINDOW_SIZES_CHANGED (f) = false; - functions = Vwindow_size_change_functions; - - while (CONSP (functions)) - { - if (!EQ (XCAR (functions), Qt)) - call1 (XCAR (functions), frame); - functions = XCDR (functions); - } - } - + run_window_size_change_functions (frame); menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run); #ifdef HAVE_WINDOW_SYSTEM update_tool_bar (f, false); @@ -13599,24 +13582,12 @@ redisplay_internal (void) 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 && FRAME_WINDOW_SIZES_CHANGED (sf)) + if (sf->redisplay) { - Lisp_Object functions; ptrdiff_t count1 = SPECPDL_INDEX (); record_unwind_save_match_data (); - - /* Clear flag first in case we get an error below. */ - FRAME_WINDOW_SIZES_CHANGED (sf) = false; - functions = Vwindow_size_change_functions; - - while (CONSP (functions)) - { - if (!EQ (XCAR (functions), Qt)) - call1 (XCAR (functions), selected_frame); - functions = XCDR (functions); - } - + run_window_size_change_functions (selected_frame); unbind_to (count1, Qnil); } @@ -13638,22 +13609,10 @@ redisplay_internal (void) { if (sf->redisplay) { - Lisp_Object functions; ptrdiff_t count1 = SPECPDL_INDEX (); record_unwind_save_match_data (); - - /* Clear flag first in case we get an error below. */ - FRAME_WINDOW_SIZES_CHANGED (sf) = false; - functions = Vwindow_size_change_functions; - - while (CONSP (functions)) - { - if (!EQ (XCAR (functions), Qt)) - call1 (XCAR (functions), selected_frame); - functions = XCDR (functions); - } - + run_window_size_change_functions (selected_frame); unbind_to (count1, Qnil); } @@ -31447,16 +31406,6 @@ If nil, disable message logging. If t, log messages but don't truncate the buffer when it becomes large. */); Vmessage_log_max = make_number (1000); - DEFVAR_LISP ("window-size-change-functions", Vwindow_size_change_functions, - doc: /* Functions called during redisplay, if window sizes have changed. -The value should be a list of functions that take one argument. -During the first part of redisplay, for each frame, if any of its windows -have changed size since the last redisplay, or have been split or deleted, -all the functions in the list are called, with the frame as argument. -If redisplay decides to resize the minibuffer window, it calls these -functions on behalf of that as well. */); - Vwindow_size_change_functions = Qnil; - DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions, doc: /* List of functions to call before redisplaying a window with scrolling. Each function is called with two arguments, the window and its new diff --git a/src/xfns.c b/src/xfns.c index 20ac627..2a50a5a 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -1313,7 +1313,6 @@ x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) } #endif /* not USE_X_TOOLKIT && not USE_GTK */ adjust_frame_glyphs (f); - run_window_configuration_change_hook (f); }