aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMartin Rudalics2019-01-11 10:02:47 +0100
committerMartin Rudalics2019-01-11 10:02:47 +0100
commite567ac149518967f992b1286d90d94df6bb589b7 (patch)
tree32464d12a2b3fcc7ecf7e4cd5d6fc2d4ef7c729b /src
parent470082de55f7b1c1cde8aabbb5b8de55b4b08f83 (diff)
downloademacs-e567ac149518967f992b1286d90d94df6bb589b7.tar.gz
emacs-e567ac149518967f992b1286d90d94df6bb589b7.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/frame.c25
-rw-r--r--src/frame.h46
-rw-r--r--src/window.c767
-rw-r--r--src/window.h27
-rw-r--r--src/xdisp.c72
5 files changed, 680 insertions, 257 deletions
diff --git a/src/frame.c b/src/frame.c
index ca6704a44c0..6d93abd09bf 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -55,9 +55,11 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
55#endif 55#endif
56 56
57/* The currently selected frame. */ 57/* The currently selected frame. */
58
59Lisp_Object selected_frame; 58Lisp_Object selected_frame;
60 59
60/* The selected frame the last time window change functions were run. */
61Lisp_Object old_selected_frame;
62
61/* A frame which is not just a mini-buffer, or NULL if there are no such 63/* A frame which is not just a mini-buffer, or NULL if there are no such
62 frames. This is usually the most recent such frame that was selected. */ 64 frames. This is usually the most recent such frame that was selected. */
63 65
@@ -855,7 +857,8 @@ make_frame (bool mini_p)
855 f->ns_transparent_titlebar = false; 857 f->ns_transparent_titlebar = false;
856#endif 858#endif
857#endif 859#endif
858 860 /* This one should never be zero. */
861 f->change_stamp = 1;
859 root_window = make_window (); 862 root_window = make_window ();
860 rw = XWINDOW (root_window); 863 rw = XWINDOW (root_window);
861 if (mini_p) 864 if (mini_p)
@@ -1451,7 +1454,8 @@ This function returns FRAME, or nil if FRAME has been deleted. */)
1451 return do_switch_frame (frame, 1, 0, norecord); 1454 return do_switch_frame (frame, 1, 0, norecord);
1452} 1455}
1453 1456
1454DEFUN ("handle-switch-frame", Fhandle_switch_frame, Shandle_switch_frame, 1, 1, "^e", 1457DEFUN ("handle-switch-frame", Fhandle_switch_frame,
1458 Shandle_switch_frame, 1, 1, "^e",
1455 doc: /* Handle a switch-frame event EVENT. 1459 doc: /* Handle a switch-frame event EVENT.
1456Switch-frame events are usually bound to this function. 1460Switch-frame events are usually bound to this function.
1457A switch-frame event is an event Emacs sends itself to 1461A switch-frame event is an event Emacs sends itself to
@@ -1471,6 +1475,18 @@ DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
1471{ 1475{
1472 return selected_frame; 1476 return selected_frame;
1473} 1477}
1478
1479DEFUN ("old-selected-frame", Fold_selected_frame,
1480 Sold_selected_frame, 0, 0, 0,
1481 doc: /* Return the old selected FRAME.
1482FRAME must be a live frame and defaults to the selected one.
1483
1484The return value is the frame selected the last time window change
1485functions were run. */)
1486 (void)
1487{
1488 return old_selected_frame;
1489}
1474 1490
1475DEFUN ("frame-list", Fframe_list, Sframe_list, 1491DEFUN ("frame-list", Fframe_list, Sframe_list,
1476 0, 0, 0, 1492 0, 0, 0,
@@ -6098,9 +6114,10 @@ iconify the top level frame instead. */);
6098 defsubr (&Swindow_system); 6114 defsubr (&Swindow_system);
6099 defsubr (&Sframe_windows_min_size); 6115 defsubr (&Sframe_windows_min_size);
6100 defsubr (&Smake_terminal_frame); 6116 defsubr (&Smake_terminal_frame);
6101 defsubr (&Shandle_switch_frame);
6102 defsubr (&Sselect_frame); 6117 defsubr (&Sselect_frame);
6118 defsubr (&Shandle_switch_frame);
6103 defsubr (&Sselected_frame); 6119 defsubr (&Sselected_frame);
6120 defsubr (&Sold_selected_frame);
6104 defsubr (&Sframe_list); 6121 defsubr (&Sframe_list);
6105 defsubr (&Sframe_parent); 6122 defsubr (&Sframe_parent);
6106 defsubr (&Sframe_ancestor_p); 6123 defsubr (&Sframe_ancestor_p);
diff --git a/src/frame.h b/src/frame.h
index b7059027fbe..ab3efdfa926 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -125,6 +125,10 @@ struct frame
125 The selected window of the selected frame is Emacs's selected window. */ 125 The selected window of the selected frame is Emacs's selected window. */
126 Lisp_Object selected_window; 126 Lisp_Object selected_window;
127 127
128 /* This frame's selected window when run_window_change_functions was
129 called the last time on this frame. */
130 Lisp_Object old_selected_window;
131
128 /* This frame's minibuffer window. 132 /* This frame's minibuffer window.
129 Most frames have their own minibuffer windows, 133 Most frames have their own minibuffer windows,
130 but only the selected frame's minibuffer window 134 but only the selected frame's minibuffer window
@@ -321,9 +325,14 @@ struct frame
321 cleared. */ 325 cleared. */
322 bool_bf explicit_name : 1; 326 bool_bf explicit_name : 1;
323 327
324 /* True if configuration of windows on this frame has changed since 328 /* True if at least one window on this frame changed since the last
325 last call of run_window_size_change_functions. */ 329 call of run_window_change_functions. Changes are either "state
326 bool_bf window_configuration_changed : 1; 330 changes" (a window has been created, deleted or got assigned
331 another buffer) or "size changes" (the total or body size of a
332 window changed). run_window_change_functions exits early unless
333 either this flag is true or a window selection happened on this
334 frame. */
335 bool_bf window_change : 1;
327 336
328 /* True if the mouse has moved on this display device 337 /* True if the mouse has moved on this display device
329 since the last time we checked. */ 338 since the last time we checked. */
@@ -406,6 +415,20 @@ struct frame
406 415
407 /* Bitfield area ends here. */ 416 /* Bitfield area ends here. */
408 417
418 /* This frame's change stamp, set the last time window change
419 functions were run for this frame. Should never be 0 because
420 that's the change stamp of a new window. A window was not on a
421 frame the last run_window_change_functions was called on it if
422 it's change stamp differs from that of its frame. */
423 int change_stamp;
424
425 /* This frame's number of windows, set the last time window change
426 functions were run for this frame. Should never be 0 even for
427 minibuffer-only frames. If no window has been added, this allows
428 to detect whether a window was deleted on this frame since the
429 last time run_window_change_functions was called on it. */
430 ptrdiff_t number_of_windows;
431
409 /* Number of lines (rounded up) of tool bar. REMOVE THIS */ 432 /* Number of lines (rounded up) of tool bar. REMOVE THIS */
410 int tool_bar_lines; 433 int tool_bar_lines;
411 434
@@ -662,6 +685,11 @@ fset_selected_window (struct frame *f, Lisp_Object val)
662 f->selected_window = val; 685 f->selected_window = val;
663} 686}
664INLINE void 687INLINE void
688fset_old_selected_window (struct frame *f, Lisp_Object val)
689{
690 f->old_selected_window = val;
691}
692INLINE void
665fset_title (struct frame *f, Lisp_Object val) 693fset_title (struct frame *f, Lisp_Object val)
666{ 694{
667 f->title = val; 695 f->title = val;
@@ -908,10 +936,9 @@ default_pixels_per_inch_y (void)
908 are frozen on frame F. */ 936 are frozen on frame F. */
909#define FRAME_WINDOWS_FROZEN(f) (f)->frozen_window_starts 937#define FRAME_WINDOWS_FROZEN(f) (f)->frozen_window_starts
910 938
911/* True if the frame's window configuration has changed since last call 939/* True if at least one window changed on frame F since the last time
912 of run_window_size_change_functions. */ 940 window change functions were run on F. */
913#define FRAME_WINDOW_CONFIGURATION_CHANGED(f) \ 941#define FRAME_WINDOW_CHANGE(f) (f)->window_change
914 (f)->window_configuration_changed
915 942
916/* The minibuffer window of frame F, if it has one; otherwise nil. */ 943/* The minibuffer window of frame F, if it has one; otherwise nil. */
917#define FRAME_MINIBUF_WINDOW(f) f->minibuffer_window 944#define FRAME_MINIBUF_WINDOW(f) f->minibuffer_window
@@ -919,8 +946,10 @@ default_pixels_per_inch_y (void)
919/* The root window of the window tree of frame F. */ 946/* The root window of the window tree of frame F. */
920#define FRAME_ROOT_WINDOW(f) f->root_window 947#define FRAME_ROOT_WINDOW(f) f->root_window
921 948
922/* The currently selected window of the window tree of frame F. */ 949/* The currently selected window of frame F. */
923#define FRAME_SELECTED_WINDOW(f) f->selected_window 950#define FRAME_SELECTED_WINDOW(f) f->selected_window
951/* The old selected window of frame F. */
952#define FRAME_OLD_SELECTED_WINDOW(f) f->old_selected_window
924 953
925#define FRAME_INSERT_COST(f) (f)->insert_line_cost 954#define FRAME_INSERT_COST(f) (f)->insert_line_cost
926#define FRAME_DELETE_COST(f) (f)->delete_line_cost 955#define FRAME_DELETE_COST(f) (f)->delete_line_cost
@@ -1215,6 +1244,7 @@ SET_FRAME_VISIBLE (struct frame *f, int v)
1215 (f)->iconified = (eassert (0 <= (i) && (i) <= 1), (i)) 1244 (f)->iconified = (eassert (0 <= (i) && (i) <= 1), (i))
1216 1245
1217extern Lisp_Object selected_frame; 1246extern Lisp_Object selected_frame;
1247extern Lisp_Object old_selected_frame;
1218 1248
1219#if ! (defined USE_GTK || defined HAVE_NS) 1249#if ! (defined USE_GTK || defined HAVE_NS)
1220extern int frame_default_tool_bar_height; 1250extern int frame_default_tool_bar_height;
diff --git a/src/window.c b/src/window.c
index 72185f9340a..0fc4f622995 100644
--- a/src/window.c
+++ b/src/window.c
@@ -77,6 +77,11 @@ static void apply_window_adjustment (struct window *);
77 FRAME_SELECTED_WINDOW (selected_frame). */ 77 FRAME_SELECTED_WINDOW (selected_frame). */
78Lisp_Object selected_window; 78Lisp_Object selected_window;
79 79
80/* The value of selected_window at the last time window change
81 functions were run. This is always the same as
82 FRAME_OLD_SELECTED_WINDOW (old_selected_frame). */
83Lisp_Object old_selected_window;
84
80/* A list of all windows for use by next_window and Fwindow_list. 85/* A list of all windows for use by next_window and Fwindow_list.
81 Functions creating or deleting windows should invalidate this cache 86 Functions creating or deleting windows should invalidate this cache
82 by setting it to nil. */ 87 by setting it to nil. */
@@ -304,6 +309,12 @@ wset_buffer (struct window *w, Lisp_Object val)
304 adjust_window_count (w, 1); 309 adjust_window_count (w, 1);
305} 310}
306 311
312static void
313wset_old_buffer (struct window *w, Lisp_Object val)
314{
315 w->old_buffer = val;
316}
317
307DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0, 318DEFUN ("windowp", Fwindowp, Swindowp, 1, 1, 0,
308 doc: /* Return t if OBJECT is a window and nil otherwise. */) 319 doc: /* Return t if OBJECT is a window and nil otherwise. */)
309 (Lisp_Object object) 320 (Lisp_Object object)
@@ -428,6 +439,22 @@ return the selected window of that frame. */)
428 return window; 439 return window;
429} 440}
430 441
442DEFUN ("frame-old-selected-window", Fframe_old_selected_window,
443 Sframe_old_selected_window, 0, 1, 0,
444 doc: /* Return old selected window of FRAME.
445FRAME must be a live frame and defaults to the selected one.
446
447The return value is the window selected on FRAME the last time window
448change functions were run for FRAME. */)
449 (Lisp_Object frame)
450{
451 if (NILP (frame))
452 frame = selected_frame;
453 CHECK_LIVE_FRAME (frame);
454
455 return XFRAME (frame)->old_selected_window;
456}
457
431DEFUN ("set-frame-selected-window", Fset_frame_selected_window, 458DEFUN ("set-frame-selected-window", Fset_frame_selected_window,
432 Sset_frame_selected_window, 2, 3, 0, 459 Sset_frame_selected_window, 2, 3, 0,
433 doc: /* Set selected window of FRAME to WINDOW. 460 doc: /* Set selected window of FRAME to WINDOW.
@@ -465,6 +492,16 @@ selected windows appears and to which many commands apply. */)
465 return selected_window; 492 return selected_window;
466} 493}
467 494
495DEFUN ("old-selected-window", Fold_selected_window,
496 Sold_selected_window, 0, 0, 0,
497 doc: /* Return the old selected window.
498The return value is the window selected the last time window change
499functions were run. */)
500 (void)
501{
502 return old_selected_window;
503}
504
468EMACS_INT window_select_count; 505EMACS_INT window_select_count;
469 506
470/* If select_window is called with inhibit_point_swap true it will 507/* If select_window is called with inhibit_point_swap true it will
@@ -597,9 +634,33 @@ Return nil for an internal window or a deleted window. */)
597 (Lisp_Object window) 634 (Lisp_Object window)
598{ 635{
599 struct window *w = decode_any_window (window); 636 struct window *w = decode_any_window (window);
637
600 return WINDOW_LEAF_P (w) ? w->contents : Qnil; 638 return WINDOW_LEAF_P (w) ? w->contents : Qnil;
601} 639}
602 640
641DEFUN ("window-old-buffer", Fwindow_old_buffer, Swindow_old_buffer, 0, 1, 0,
642 doc: /* Return the old buffer displayed by WINDOW.
643WINDOW must be a live window and defaults to the selected one.
644
645The return value is the buffer shown in WINDOW at the last time window
646change functions were run. It is nil if WINDOW was created after
647that. It is t if WINDOW has been restored from a window configuration
648after that. */)
649 (Lisp_Object window)
650{
651 struct window *w = decode_live_window (window);
652
653 return (NILP (w->old_buffer)
654 /* A new window. */
655 ? Qnil
656 : (w->change_stamp != WINDOW_XFRAME (w)->change_stamp)
657 /* A window restored from a configuration. */
658 ? Qt
659 /* A window that was live the last time seen by window
660 change functions. */
661 : w->old_buffer);
662}
663
603DEFUN ("window-parent", Fwindow_parent, Swindow_parent, 0, 1, 0, 664DEFUN ("window-parent", Fwindow_parent, Swindow_parent, 0, 1, 0,
604 doc: /* Return the parent window of window WINDOW. 665 doc: /* Return the parent window of window WINDOW.
605WINDOW must be a valid window and defaults to the selected one. 666WINDOW must be a valid window and defaults to the selected one.
@@ -723,34 +784,32 @@ the height of the screen areas spanned by its children. */)
723 return make_fixnum (decode_valid_window (window)->pixel_height); 784 return make_fixnum (decode_valid_window (window)->pixel_height);
724} 785}
725 786
726DEFUN ("window-pixel-width-before-size-change", 787DEFUN ("window-old-pixel-width", Fwindow_old_pixel_width,
727 Fwindow_pixel_width_before_size_change, 788 Swindow_old_pixel_width, 0, 1, 0,
728 Swindow_pixel_width_before_size_change, 0, 1, 0, 789 doc: /* Return old total pixel width of WINDOW.
729 doc: /* Return pixel width of window WINDOW before last size changes.
730WINDOW must be a valid window and defaults to the selected one. 790WINDOW must be a valid window and defaults to the selected one.
731 791
732The return value is the pixel width of WINDOW at the last time 792The return value is the total pixel width of WINDOW after the last
733`window-size-change-functions' was run. It's zero if WINDOW was made 793time window change functions found WINDOW live on its frame. It is
734after that. */) 794zero if WINDOW was created after that. */)
735 (Lisp_Object window) 795 (Lisp_Object window)
736{ 796{
737 return (make_fixnum 797 return (make_fixnum
738 (decode_valid_window (window)->pixel_width_before_size_change)); 798 (decode_valid_window (window)->old_pixel_width));
739} 799}
740 800
741DEFUN ("window-pixel-height-before-size-change", 801DEFUN ("window-old-pixel-height", Fwindow_old_pixel_height,
742 Fwindow_pixel_height_before_size_change, 802 Swindow_old_pixel_height, 0, 1, 0,
743 Swindow_pixel_height_before_size_change, 0, 1, 0, 803 doc: /* Return old total pixel height of WINDOW.
744 doc: /* Return pixel height of window WINDOW before last size changes.
745WINDOW must be a valid window and defaults to the selected one. 804WINDOW must be a valid window and defaults to the selected one.
746 805
747The return value is the pixel height of WINDOW at the last time 806The return value is the total pixel height of WINDOW after the last
748`window-size-change-functions' was run. It's zero if WINDOW was made 807time window change functions found WINDOW live on its frame. It is
749after that. */) 808zero if WINDOW was created after that. */)
750 (Lisp_Object window) 809 (Lisp_Object window)
751{ 810{
752 return (make_fixnum 811 return (make_fixnum
753 (decode_valid_window (window)->pixel_height_before_size_change)); 812 (decode_valid_window (window)->old_pixel_height));
754} 813}
755 814
756DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 2, 0, 815DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 2, 0,
@@ -984,6 +1043,26 @@ window_body_width (struct window *w, bool pixelwise)
984 0); 1043 0);
985} 1044}
986 1045
1046DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 2, 0,
1047 doc: /* Return the width of WINDOW's text area.
1048WINDOW must be a live window and defaults to the selected one. Optional
1049argument PIXELWISE non-nil means return the width in pixels. The return
1050value does not include any vertical dividers, fringes or marginal areas,
1051or scroll bars.
1052
1053If PIXELWISE is nil, return the largest integer smaller than WINDOW's
1054pixel width divided by the character width of WINDOW's frame. This
1055means that if a column at the right of the text area is only partially
1056visible, that column is not counted.
1057
1058Note that the returned value includes the column reserved for the
1059continuation glyph. */)
1060 (Lisp_Object window, Lisp_Object pixelwise)
1061{
1062 return make_fixnum (window_body_width (decode_live_window (window),
1063 !NILP (pixelwise)));
1064}
1065
987DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 2, 0, 1066DEFUN ("window-body-height", Fwindow_body_height, Swindow_body_height, 0, 2, 0,
988 doc: /* Return the height of WINDOW's text area. 1067 doc: /* Return the height of WINDOW's text area.
989WINDOW must be a live window and defaults to the selected one. Optional 1068WINDOW must be a live window and defaults to the selected one. Optional
@@ -1001,24 +1080,34 @@ visible, that line is not counted. */)
1001 !NILP (pixelwise))); 1080 !NILP (pixelwise)));
1002} 1081}
1003 1082
1004DEFUN ("window-body-width", Fwindow_body_width, Swindow_body_width, 0, 2, 0, 1083DEFUN ("window-old-body-pixel-width",
1005 doc: /* Return the width of WINDOW's text area. 1084 Fwindow_old_body_pixel_width,
1006WINDOW must be a live window and defaults to the selected one. Optional 1085 Swindow_old_body_pixel_width, 0, 1, 0,
1007argument PIXELWISE non-nil means return the width in pixels. The return 1086 doc: /* Return old width of WINDOW's text area in pixels.
1008value does not include any vertical dividers, fringes or marginal areas, 1087WINDOW must be a live window and defaults to the selected one.
1009or scroll bars.
1010 1088
1011If PIXELWISE is nil, return the largest integer smaller than WINDOW's 1089The return value is the pixel width of WINDOW's text area after the
1012pixel width divided by the character width of WINDOW's frame. This 1090last time window change functions found WINDOW live on its frame. It
1013means that if a column at the right of the text area is only partially 1091is zero if WINDOW was created after that. */)
1014visible, that column is not counted. 1092 (Lisp_Object window)
1093{
1094 return (make_fixnum
1095 (decode_live_window (window)->old_body_pixel_width));
1096}
1015 1097
1016Note that the returned value includes the column reserved for the 1098DEFUN ("window-old-body-pixel-height",
1017continuation glyph. */) 1099 Fwindow_old_body_pixel_height,
1018 (Lisp_Object window, Lisp_Object pixelwise) 1100 Swindow_old_body_pixel_height, 0, 1, 0,
1101 doc: /* Return old height of WINDOW's text area in pixels.
1102WINDOW must be a live window and defaults to the selected one.
1103
1104The return value is the pixel height of WINDOW's text area after the
1105last time window change functions found WINDOW live on its frame. It
1106is zero if WINDOW was created after that. */)
1107 (Lisp_Object window)
1019{ 1108{
1020 return make_fixnum (window_body_width (decode_live_window (window), 1109 return (make_fixnum
1021 !NILP (pixelwise))); 1110 (decode_live_window (window)->old_body_pixel_height));
1022} 1111}
1023 1112
1024DEFUN ("window-mode-line-height", Fwindow_mode_line_height, 1113DEFUN ("window-mode-line-height", Fwindow_mode_line_height,
@@ -3264,7 +3353,7 @@ window-start value is reasonable when this function is called. */)
3264 adjust_frame_glyphs (f); 3353 adjust_frame_glyphs (f);
3265 unblock_input (); 3354 unblock_input ();
3266 3355
3267 run_window_configuration_change_hook (f); 3356 FRAME_WINDOW_CHANGE (f) = true;
3268 3357
3269 return Qnil; 3358 return Qnil;
3270} 3359}
@@ -3318,6 +3407,15 @@ select_frame_norecord (Lisp_Object frame)
3318 Fselect_frame (frame, Qt); 3407 Fselect_frame (frame, Qt);
3319} 3408}
3320 3409
3410/**
3411 * run_window_configuration_change_hook:
3412 *
3413 * Run any functions on 'window-configuration-change-hook' for the
3414 * frame specified by F. The buffer-local values are run with the
3415 * window showing the buffer selected. The default value is run with
3416 * the frame specified by F selected. All functions are called with
3417 * the selected window's buffer current.
3418 */
3321static void 3419static void
3322run_window_configuration_change_hook (struct frame *f) 3420run_window_configuration_change_hook (struct frame *f)
3323{ 3421{
@@ -3371,7 +3469,10 @@ run_window_configuration_change_hook (struct frame *f)
3371DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook, 3469DEFUN ("run-window-configuration-change-hook", Frun_window_configuration_change_hook,
3372 Srun_window_configuration_change_hook, 0, 1, 0, 3470 Srun_window_configuration_change_hook, 0, 1, 0,
3373 doc: /* Run `window-configuration-change-hook' for FRAME. 3471 doc: /* Run `window-configuration-change-hook' for FRAME.
3374If FRAME is omitted or nil, it defaults to the selected frame. */) 3472If FRAME is omitted or nil, it defaults to the selected frame.
3473
3474This function should not be needed any more and will be therefore
3475considered obsolete. */)
3375 (Lisp_Object frame) 3476 (Lisp_Object frame)
3376{ 3477{
3377 run_window_configuration_change_hook (decode_live_frame (frame)); 3478 run_window_configuration_change_hook (decode_live_frame (frame));
@@ -3381,130 +3482,381 @@ If FRAME is omitted or nil, it defaults to the selected frame. */)
3381DEFUN ("run-window-scroll-functions", Frun_window_scroll_functions, 3482DEFUN ("run-window-scroll-functions", Frun_window_scroll_functions,
3382 Srun_window_scroll_functions, 0, 1, 0, 3483 Srun_window_scroll_functions, 0, 1, 0,
3383 doc: /* Run `window-scroll-functions' for WINDOW. 3484 doc: /* Run `window-scroll-functions' for WINDOW.
3384If WINDOW is omitted or nil, it defaults to the selected window. */) 3485If WINDOW is omitted or nil, it defaults to the selected window.
3486
3487This function is curently only called by 'split-window' for the new
3488window after it has established the size of the new window. */)
3385 (Lisp_Object window) 3489 (Lisp_Object window)
3386{ 3490{
3387 if (! NILP (Vwindow_scroll_functions)) 3491 struct window *w = decode_live_window (window);
3492 ptrdiff_t count = SPECPDL_INDEX ();
3493
3494 record_unwind_current_buffer ();
3495 Fset_buffer (w->contents);
3496 if (!NILP (Vwindow_scroll_functions))
3388 run_hook_with_args_2 (Qwindow_scroll_functions, window, 3497 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3389 Fmarker_position (decode_live_window (window)->start)); 3498 Fmarker_position (w->start));
3499 unbind_to (count, Qnil);
3500
3390 return Qnil; 3501 return Qnil;
3391} 3502}
3392 3503
3393 3504
3394/* Compare old and present pixel sizes of windows in tree rooted at W. 3505/**
3395 Return true iff any of these windows differs in size. */ 3506 * window_sub_list:
3396 3507 *
3397static bool 3508 * Return list of live windows constructed by traversing any window
3398window_size_changed (struct window *w) 3509 * sub-tree rooted at WINDOW in preorder followed by right siblings of
3510 * WINDOW. Called from outside with second argument WINDOWS nil. The
3511 * returned list is in reverse order.
3512 */
3513static Lisp_Object
3514window_sub_list (Lisp_Object window, Lisp_Object windows)
3399{ 3515{
3400 if (w->pixel_width != w->pixel_width_before_size_change
3401 || w->pixel_height != w->pixel_height_before_size_change)
3402 return true;
3403 3516
3404 if (WINDOW_INTERNAL_P (w)) 3517 struct window *w = XWINDOW (window);
3518
3519 while (w)
3405 { 3520 {
3406 w = XWINDOW (w->contents); 3521 if (WINDOW_INTERNAL_P (w))
3407 while (w) 3522 windows = window_sub_list (w->contents, windows);
3408 { 3523 else
3409 if (window_size_changed (w)) 3524 windows = Fcons (window, windows);
3410 return true;
3411 3525
3412 w = NILP (w->next) ? 0 : XWINDOW (w->next); 3526 window = w->next;
3413 } 3527 w = NILP (window) ? 0 : XWINDOW (window);
3414 } 3528 }
3415 3529
3416 return false; 3530 return windows;
3417} 3531}
3418 3532
3419/* Set before size change pixel sizes of windows in tree rooted at W to
3420 their present pixel sizes. */
3421 3533
3422static void 3534/**
3423window_set_before_size_change_sizes (struct window *w) 3535 * window_change_record_windows:
3536 *
3537 * Record changes for all live windows found by traversing any window
3538 * sub-tree rooted at WINDOW in preorder followed by any right
3539 * siblings of WINDOW. This sets the old buffer, old pixel and old
3540 * body pixel sizes of each live window found to the respective
3541 * current values. It also sets the change stamp of each window found
3542 * to STAMP. Return the number of live windows found.
3543 *
3544 * When not called by itself recursively, WINDOW is its frame's root
3545 * window, STAMP is the current change stamp of WINDOW's frame and
3546 * NUMBER is 0.
3547 */
3548static ptrdiff_t
3549window_change_record_windows (Lisp_Object window, int stamp, ptrdiff_t number)
3424{ 3550{
3425 w->pixel_width_before_size_change = w->pixel_width; 3551 struct window *w = XWINDOW (window);
3426 w->pixel_height_before_size_change = w->pixel_height;
3427 3552
3428 if (WINDOW_INTERNAL_P (w)) 3553 while (w)
3429 { 3554 {
3430 w = XWINDOW (w->contents); 3555 if (WINDOW_INTERNAL_P (w))
3431 while (w) 3556 number = window_change_record_windows (w->contents, stamp, number);
3557 else
3432 { 3558 {
3433 window_set_before_size_change_sizes (w); 3559 number += 1;
3434 w = NILP (w->next) ? 0 : XWINDOW (w->next); 3560 w->change_stamp = stamp;
3561 wset_old_buffer (w, w->contents);
3562 w->old_pixel_width = w->pixel_width;
3563 w->old_pixel_height = w->pixel_height;
3564 w->old_body_pixel_width = window_body_width (w, true);
3565 w->old_body_pixel_height = window_body_height (w, true);
3435 } 3566 }
3567
3568 w = NILP (w->next) ? 0 : XWINDOW (w->next);
3436 } 3569 }
3570
3571 return number;
3437} 3572}
3438 3573
3439 3574
3440void 3575/**
3441run_window_size_change_functions (Lisp_Object frame) 3576 * window_change_record_frame:
3577 *
3578 * Record changes for FRAME. This records FRAME's selected window,
3579 * updates FRAME's change stamp, records the states of all live
3580 * windows of FRAME via window_change_record_windows and resets
3581 * FRAME's window_change flag.
3582 */
3583static void
3584window_change_record_frame (Lisp_Object frame)
3442{ 3585{
3443 struct frame *f = XFRAME (frame); 3586 struct frame *f = XFRAME (frame);
3444 struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f));
3445 3587
3446 if (NILP (Vrun_hooks) 3588 /* Record selected window. */
3447 || !(f->can_x_set_window_size) 3589 fset_old_selected_window (f, FRAME_SELECTED_WINDOW (f));
3448 || !(f->after_make_frame))
3449 return;
3450 3590
3451 if (FRAME_WINDOW_CONFIGURATION_CHANGED (f) 3591 /* Bump up FRAME's change stamp. If this wraps, make it 1 to avoid
3452 /* Here we implicitly exclude the possibility that the height of 3592 that a new window (whose change stamp is always set to 0) gets
3453 FRAME and its minibuffer window both change leaving the height 3593 reported as "existing before". */
3454 of FRAME's root window alone. */ 3594 f->change_stamp += 1;
3455 || window_size_changed (r)) 3595 if (f->change_stamp == 0)
3456 { 3596 f->change_stamp = 1;
3457 Lisp_Object globals = Fdefault_value (Qwindow_size_change_functions);
3458 Lisp_Object windows = Fwindow_list (frame, Qlambda, Qnil);
3459 /* The buffers for which the local hook was already run. */
3460 Lisp_Object buffers = Qnil;
3461 3597
3462 for (; CONSP (windows); windows = XCDR (windows)) 3598 /* Bump up the change stamps of all live windows on this frame so
3463 { 3599 the next call of this function can tell whether any of them
3464 Lisp_Object window = XCAR (windows); 3600 "existed before" and record state for each of these windows. */
3465 Lisp_Object buffer = Fwindow_buffer (window); 3601 f->number_of_windows
3466 3602 = window_change_record_windows (f->root_window, f->change_stamp, 0);
3467 /* Run a buffer-local value only once for that buffer and
3468 only if at least one window showing that buffer on FRAME
3469 actually changed its size. Note that the function is run
3470 with FRAME as its argument and as such oblivious to the
3471 window checked below. */
3472 if (window_size_changed (XWINDOW (window))
3473 && !NILP (Flocal_variable_p (Qwindow_size_change_functions, buffer))
3474 && NILP (Fmemq (buffer, buffers)))
3475 {
3476 Lisp_Object locals
3477 = Fbuffer_local_value (Qwindow_size_change_functions, buffer);
3478 3603
3479 while (CONSP (locals)) 3604 /* Reset our flag. */
3480 { 3605 FRAME_WINDOW_CHANGE (f) = false;
3481 if (!EQ (XCAR (locals), Qt)) 3606}
3482 safe_call1 (XCAR (locals), frame);
3483 locals = XCDR (locals);
3484 }
3485 3607
3486 buffers = Fcons (buffer, buffers);
3487 }
3488 }
3489 3608
3490 while (CONSP (globals)) 3609/**
3610 * window_change_record:
3611 *
3612 * Record selected window in old_selected_window and selected frame in
3613 * old_selected_frame.
3614 */
3615static void
3616window_change_record (void)
3617{
3618 /* Strictly spoken we don't need old_selected_window at all - its
3619 value is the old selected window of old_selected_frame. */
3620 old_selected_window = selected_window;
3621 old_selected_frame = selected_frame;
3622}
3623
3624
3625/**
3626 * run_window_change_functions_1:
3627 *
3628 * Run window change functions specified by SYMBOL with argument
3629 * WINDOW_OR_FRAME. If BUFFER is nil, WINDOW_OR_FRAME specifies a
3630 * frame. In this case, run the default value of SYMBOL. Otherwise,
3631 * WINDOW_OR_FRAME denotes a window showing BUFFER. In this case, run
3632 * the buffer local value of SYMBOL in BUFFER, if any.
3633 */
3634static void
3635run_window_change_functions_1 (Lisp_Object symbol, Lisp_Object buffer,
3636 Lisp_Object window_or_frame)
3637{
3638 Lisp_Object funs = Qnil;
3639
3640 if (NILP (buffer))
3641 funs = Fdefault_value (symbol);
3642 else if (!NILP (Fassoc (symbol, BVAR (XBUFFER (buffer), local_var_alist),
3643 Qnil)))
3644 /* Don't run global value buffer-locally. */
3645 funs = buffer_local_value (symbol, buffer);
3646
3647 while (CONSP (funs))
3648 {
3649 if (!EQ (XCAR (funs), Qt))
3650 safe_call1 (XCAR (funs), window_or_frame);
3651 funs = XCDR (funs);
3652 }
3653}
3654
3655
3656/**
3657 * run_window_change_functions:
3658 *
3659 * Run window change functions for each live frame. This function
3660 * must be called from a "safe" position in redisplay_internal.
3661 *
3662 * Do not run any functions for a frame whose window_change flag is
3663 * nil and where no window selection happened since the last time this
3664 * function was called. Also, skip any tooltip frame.
3665 *
3666 * The change functions run are, in this order:
3667 *
3668 * 'window-buffer-change-functions' which are run for a window that
3669 * changed its buffer or that was not shown the last time window
3670 * change functions were run. The default value is also run when a
3671 * window was deleted since the last time window change functions were
3672 * run.
3673 *
3674 * `window-size-change-functions' run for a window that changed its
3675 * body or total size, a window that changed its buffer or a window
3676 * that was not shown the last time window change functions were run.
3677 *
3678 * `window-selected-change-functions' run for a window that was
3679 * (de-)selected since the last time window change functions were run.
3680 *
3681 * A buffer-local value of these functions is run if and only if the
3682 * window for which the functions are run, currently shows the buffer.
3683 * Each call gets one argument - the window showing the buffer. This
3684 * means that the buffer-local value of these functions may be called
3685 * as many times at the buffer is shown on the frame.
3686 *
3687 * The default value of these functions is called only after all
3688 * buffer-local values for all of these functions have been run. Each
3689 * such call receives one argument - the frame for which this function
3690 * is run.
3691 *
3692 * After the three change functions cited above have been run in the
3693 * indicated way, functions on 'window-configuration-change-hook' are
3694 * run. A buffer-local value is run if a window shows that buffer and
3695 * has either changed its buffer or its body or total size or did not
3696 * appear on this frame since the last time window change functions
3697 * were run. The functions are called without argument and the
3698 * buffer's window selected. The default value is run without
3699 * argument and the frame for which the function is run selected.
3700 *
3701 * This function does not save and restore match data. Any functions
3702 * it calls are responsible for doing that themselves.
3703 */
3704void
3705run_window_change_functions (void)
3706{
3707 Lisp_Object tail, frame;
3708 bool selected_frame_change = !EQ (selected_frame, old_selected_frame);
3709 ptrdiff_t count_outer = SPECPDL_INDEX ();
3710
3711 record_unwind_protect_void (window_change_record);
3712
3713 FOR_EACH_FRAME (tail, frame)
3714 {
3715 struct frame *f = XFRAME (frame);
3716 Lisp_Object root = FRAME_ROOT_WINDOW (f);
3717 bool frame_window_change = FRAME_WINDOW_CHANGE (f);
3718 bool window_buffer_change, window_size_change;
3719 bool frame_buffer_change = false, frame_size_change = false;
3720 bool frame_selected_change
3721 = (selected_frame_change
3722 && (EQ (frame, old_selected_frame)
3723 || EQ (frame, selected_frame)));
3724 bool frame_selected_window_change
3725 = !EQ (FRAME_OLD_SELECTED_WINDOW (f), FRAME_SELECTED_WINDOW (f));
3726 bool window_deleted = false;
3727 Lisp_Object windows;
3728 ptrdiff_t number_of_windows;
3729 ptrdiff_t count_inner = SPECPDL_INDEX ();
3730
3731 if (!f->can_x_set_window_size
3732 || !f->after_make_frame
3733 || FRAME_TOOLTIP_P (f)
3734 || !(frame_window_change
3735 || frame_selected_change
3736 || frame_selected_window_change))
3737 /* Either we cannot run hooks for this frame yet or no window
3738 change has been reported for this frame since the last time
3739 we ran window change functions on it. */
3740 continue;
3741
3742 /* Analyze windows and run buffer locals hooks in pre-order. */
3743 windows = Fnreverse (window_sub_list (root, Qnil));
3744 number_of_windows = 0;
3745
3746 record_unwind_protect (window_change_record_frame, frame);
3747
3748 /* The following loop collects all data needed to tell whether
3749 the default value of a hook shall be run and runs any buffer
3750 local hooks right away. */
3751 for (; CONSP (windows); windows = XCDR (windows))
3491 { 3752 {
3492 if (!EQ (XCAR (globals), Qt)) 3753 Lisp_Object window = XCAR (windows);
3493 safe_call1 (XCAR (globals), frame); 3754 struct window *w = XWINDOW (window);
3494 globals = XCDR (globals); 3755 Lisp_Object buffer = WINDOW_BUFFER (w);
3756
3757 /* Count this window even if it has been deleted while
3758 running a hook. */
3759 number_of_windows += 1;
3760
3761 if (!WINDOW_LIVE_P (window))
3762 continue;
3763
3764 /* A "buffer change" means either the window's buffer
3765 changed or the window was not part of this frame the last
3766 time window change functions were run for it. */
3767 window_buffer_change =
3768 (frame_window_change
3769 && (!EQ (buffer, w->old_buffer)
3770 || w->change_stamp != f->change_stamp));
3771 /* A "size change" means either a buffer change or that the
3772 total or body size of the window has changed.
3773
3774 Note: A buffer change implies a size change because either
3775 this window didn't show the buffer before or this window
3776 didn't show the buffer the last time the window change
3777 functions were run. In either case, an application
3778 tracing size changes in a buffer-locally fashion might
3779 want to be informed about that change. */
3780 window_size_change =
3781 (frame_window_change
3782 && (window_buffer_change
3783 || w->pixel_width != w->old_pixel_width
3784 || w->pixel_height != w->old_pixel_height
3785 || window_body_width (w, true) != w->old_body_pixel_width
3786 || window_body_height (w, true) != w->old_body_pixel_height));
3787
3788 /* The following two are needed when running the default
3789 values for this frame below. */
3790 frame_buffer_change = frame_buffer_change || window_buffer_change;
3791 frame_size_change = frame_size_change || window_size_change;
3792
3793 if (window_buffer_change)
3794 run_window_change_functions_1
3795 (Qwindow_buffer_change_functions, buffer, window);
3796
3797 if (window_size_change && WINDOW_LIVE_P (window))
3798 run_window_change_functions_1
3799 (Qwindow_size_change_functions, buffer, window);
3800
3801 /* This window's selection has changed when it it was
3802 (de-)selected as its frame's or the globally selected
3803 window. */
3804 if (((frame_selected_change
3805 && (EQ (window, old_selected_window)
3806 || EQ (window, selected_window)))
3807 || (frame_selected_window_change
3808 && (EQ (window, FRAME_OLD_SELECTED_WINDOW (f))
3809 || EQ (window, FRAME_SELECTED_WINDOW (f)))))
3810 && WINDOW_LIVE_P (window))
3811 run_window_change_functions_1
3812 (Qwindow_selection_change_functions, buffer, window);
3495 } 3813 }
3496 3814
3497 window_set_before_size_change_sizes (r); 3815 /* When the number of windows on a frame has decreased, at least
3816 one window of that frame was deleted. In that case, we want
3817 to run the default buffer and configuration change hooks. The
3818 default size change hook is not necessarily run in that case,
3819 but usually will be unless the deletion was "compensated" by
3820 a reduction of the frame size or an increase of a minibuffer
3821 window size. */
3822 window_deleted = number_of_windows < f->number_of_windows;
3823 /* A frame changed buffers when one of its windows has changed
3824 its buffer or at least one window was deleted. */
3825 if ((frame_buffer_change || window_deleted) && FRAME_LIVE_P (f))
3826 run_window_change_functions_1
3827 (Qwindow_buffer_change_functions, Qnil, frame);
3828
3829 /* A size change occurred when at least one of the frame's
3830 windows has changed size. */
3831 if (frame_size_change && FRAME_LIVE_P (f))
3832 run_window_change_functions_1
3833 (Qwindow_size_change_functions, Qnil, frame);
3834
3835 /* A frame has changed its window selection when its selected
3836 window has changed or when it was (de-)selected. */
3837 if ((frame_selected_change || frame_selected_window_change)
3838 && FRAME_LIVE_P (f))
3839 run_window_change_functions_1
3840 (Qwindow_selection_change_functions, Qnil, frame);
3841
3842 /* A frame's configuration changed when one of its windows has
3843 changed buffer or size or at least one window was deleted. */
3844 if ((frame_size_change || window_deleted) && FRAME_LIVE_P (f))
3845 /* This will run any buffer local window configuration change
3846 hook as well. */
3847 run_window_configuration_change_hook (f);
3498 3848
3499 if (FRAME_HAS_MINIBUF_P (f) && !FRAME_MINIBUF_ONLY_P (f)) 3849 if (!FRAME_LIVE_P (f))
3500 /* Record size of FRAME's minibuffer window too. */ 3850 continue;
3501 window_set_before_size_change_sizes
3502 (XWINDOW (FRAME_MINIBUF_WINDOW (f)));
3503 3851
3504 FRAME_WINDOW_CONFIGURATION_CHANGED (f) = false; 3852 /* Record changes (via window_change_record_frame) for this
3853 frame, even when an unhandled error occurred. */
3854 unbind_to (count_inner, Qnil);
3505 } 3855 }
3506}
3507 3856
3857 /* Record selected window and frame. */
3858 unbind_to (count_outer, Qnil);
3859}
3508 3860
3509/* Make WINDOW display BUFFER. RUN_HOOKS_P means it's allowed 3861/* Make WINDOW display BUFFER. RUN_HOOKS_P means it's allowed
3510 to run hooks. See make_frame for a case where it's not allowed. 3862 to run hooks. See make_frame for a case where it's not allowed.
@@ -3581,14 +3933,18 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer,
3581 apply_window_adjustment (w); 3933 apply_window_adjustment (w);
3582 } 3934 }
3583 3935
3584 if (run_hooks_p) 3936 if (run_hooks_p && !NILP (Vwindow_scroll_functions))
3585 { 3937 run_hook_with_args_2 (Qwindow_scroll_functions, window,
3586 if (!NILP (Vwindow_scroll_functions)) 3938 Fmarker_position (w->start));
3587 run_hook_with_args_2 (Qwindow_scroll_functions, window, 3939
3588 Fmarker_position (w->start)); 3940 /* Ensure that window change functions are run later if the buffer
3589 if (!samebuf) 3941 differs and the window is neither a mini nor a pseudo window.
3590 run_window_configuration_change_hook (XFRAME (WINDOW_FRAME (w))); 3942
3591 } 3943 Note: Running window change functions for the minibuffer is noisy
3944 and was generally suppressed in the past. Is there any reason we
3945 should run them? */
3946 if (!samebuf && !MINI_WINDOW_P (w) && !WINDOW_PSEUDO_P (w))
3947 FRAME_WINDOW_CHANGE (XFRAME (w->frame)) = true;
3592 3948
3593 unbind_to (count, Qnil); 3949 unbind_to (count, Qnil);
3594} 3950}
@@ -3828,8 +4184,6 @@ make_window (void)
3828 w->phys_cursor_width = -1; 4184 w->phys_cursor_width = -1;
3829#endif 4185#endif
3830 w->sequence_number = ++sequence_number; 4186 w->sequence_number = ++sequence_number;
3831 w->pixel_width_before_size_change = 0;
3832 w->pixel_height_before_size_change = 0;
3833 w->scroll_bar_width = -1; 4187 w->scroll_bar_width = -1;
3834 w->scroll_bar_height = -1; 4188 w->scroll_bar_height = -1;
3835 w->column_number_displayed = -1; 4189 w->column_number_displayed = -1;
@@ -4095,6 +4449,9 @@ window_resize_apply (struct window *w, bool horflag)
4095 else 4449 else
4096 /* Bug#15957. */ 4450 /* Bug#15957. */
4097 w->window_end_valid = false; 4451 w->window_end_valid = false;
4452
4453 if (!WINDOW_PSEUDO_P (w))
4454 FRAME_WINDOW_CHANGE (WINDOW_XFRAME (w)) = true;
4098} 4455}
4099 4456
4100 4457
@@ -4559,17 +4916,11 @@ set correctly. See the code of `split-window' for how this is done. */)
4559 block_input (); 4916 block_input ();
4560 window_resize_apply (p, horflag); 4917 window_resize_apply (p, horflag);
4561 adjust_frame_glyphs (f); 4918 adjust_frame_glyphs (f);
4562 /* Set buffer of NEW to buffer of reference window. Don't run 4919 /* Set buffer of NEW to buffer of reference window. */
4563 any hooks. */ 4920 set_window_buffer (new, r->contents, true, true);
4564 set_window_buffer (new, r->contents, false, true); 4921 FRAME_WINDOW_CHANGE (f) = true;
4565 unblock_input (); 4922 unblock_input ();
4566 4923
4567 /* Maybe we should run the scroll functions in Elisp (which already
4568 runs the configuration change hook). */
4569 if (! NILP (Vwindow_scroll_functions))
4570 run_hook_with_args_2 (Qwindow_scroll_functions, new,
4571 Fmarker_position (n->start));
4572 /* Return NEW. */
4573 return new; 4924 return new;
4574} 4925}
4575 4926
@@ -4720,6 +5071,8 @@ Signal an error when WINDOW is the only window on its frame. */)
4720 } 5071 }
4721 else 5072 else
4722 unblock_input (); 5073 unblock_input ();
5074
5075 FRAME_WINDOW_CHANGE (f) = true;
4723 } 5076 }
4724 else 5077 else
4725 /* We failed: Relink WINDOW into window tree. */ 5078 /* We failed: Relink WINDOW into window tree. */
@@ -6310,7 +6663,6 @@ struct saved_window
6310 6663
6311 Lisp_Object window, buffer, start, pointm, old_pointm; 6664 Lisp_Object window, buffer, start, pointm, old_pointm;
6312 Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width; 6665 Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width;
6313 Lisp_Object pixel_height_before_size_change, pixel_width_before_size_change;
6314 Lisp_Object left_col, top_line, total_cols, total_lines; 6666 Lisp_Object left_col, top_line, total_cols, total_lines;
6315 Lisp_Object normal_cols, normal_lines; 6667 Lisp_Object normal_cols, normal_lines;
6316 Lisp_Object hscroll, min_hscroll, hscroll_whole, suspend_auto_hscroll; 6668 Lisp_Object hscroll, min_hscroll, hscroll_whole, suspend_auto_hscroll;
@@ -6426,12 +6778,6 @@ the return value is nil. Otherwise the value is t. */)
6426 struct window *root_window; 6778 struct window *root_window;
6427 struct window **leaf_windows; 6779 struct window **leaf_windows;
6428 ptrdiff_t i, k, n_leaf_windows; 6780 ptrdiff_t i, k, n_leaf_windows;
6429 /* Records whether a window has been added or removed wrt the
6430 original configuration. */
6431 bool window_changed = false;
6432 /* Records whether a window has changed its buffer wrt the
6433 original configuration. */
6434 bool buffer_changed = false;
6435 6781
6436 /* Don't do this within the main loop below: This may call Lisp 6782 /* Don't do this within the main loop below: This may call Lisp
6437 code and is thus potentially unsafe while input is blocked. */ 6783 code and is thus potentially unsafe while input is blocked. */
@@ -6441,11 +6787,6 @@ the return value is nil. Otherwise the value is t. */)
6441 window = p->window; 6787 window = p->window;
6442 w = XWINDOW (window); 6788 w = XWINDOW (window);
6443 6789
6444 if (NILP (w->contents))
6445 /* A dead window that will be resurrected, the window
6446 configuration will change. */
6447 window_changed = true;
6448
6449 if (BUFFERP (w->contents) 6790 if (BUFFERP (w->contents)
6450 && !EQ (w->contents, p->buffer) 6791 && !EQ (w->contents, p->buffer)
6451 && BUFFER_LIVE_P (XBUFFER (p->buffer))) 6792 && BUFFER_LIVE_P (XBUFFER (p->buffer)))
@@ -6530,10 +6871,6 @@ the return value is nil. Otherwise the value is t. */)
6530 w->pixel_top = XFIXNAT (p->pixel_top); 6871 w->pixel_top = XFIXNAT (p->pixel_top);
6531 w->pixel_width = XFIXNAT (p->pixel_width); 6872 w->pixel_width = XFIXNAT (p->pixel_width);
6532 w->pixel_height = XFIXNAT (p->pixel_height); 6873 w->pixel_height = XFIXNAT (p->pixel_height);
6533 w->pixel_width_before_size_change
6534 = XFIXNAT (p->pixel_width_before_size_change);
6535 w->pixel_height_before_size_change
6536 = XFIXNAT (p->pixel_height_before_size_change);
6537 w->left_col = XFIXNAT (p->left_col); 6874 w->left_col = XFIXNAT (p->left_col);
6538 w->top_line = XFIXNAT (p->top_line); 6875 w->top_line = XFIXNAT (p->top_line);
6539 w->total_cols = XFIXNAT (p->total_cols); 6876 w->total_cols = XFIXNAT (p->total_cols);
@@ -6581,9 +6918,6 @@ the return value is nil. Otherwise the value is t. */)
6581 if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer))) 6918 if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer)))
6582 /* If saved buffer is alive, install it. */ 6919 /* If saved buffer is alive, install it. */
6583 { 6920 {
6584 if (!EQ (w->contents, p->buffer))
6585 /* Record buffer configuration change. */
6586 buffer_changed = true;
6587 wset_buffer (w, p->buffer); 6921 wset_buffer (w, p->buffer);
6588 w->start_at_line_beg = !NILP (p->start_at_line_beg); 6922 w->start_at_line_beg = !NILP (p->start_at_line_beg);
6589 set_marker_restricted (w->start, p->start, w->contents); 6923 set_marker_restricted (w->start, p->start, w->contents);
@@ -6617,8 +6951,6 @@ the return value is nil. Otherwise the value is t. */)
6617 else if (!NILP (w->start)) 6951 else if (!NILP (w->start))
6618 /* Leaf window has no live buffer, get one. */ 6952 /* Leaf window has no live buffer, get one. */
6619 { 6953 {
6620 /* Record buffer configuration change. */
6621 buffer_changed = true;
6622 /* Get the buffer via other_buffer_safely in order to 6954 /* Get the buffer via other_buffer_safely in order to
6623 avoid showing an unimportant buffer and, if necessary, to 6955 avoid showing an unimportant buffer and, if necessary, to
6624 recreate *scratch* in the course (part of Juanma's bs-show 6956 recreate *scratch* in the course (part of Juanma's bs-show
@@ -6666,10 +6998,7 @@ the return value is nil. Otherwise the value is t. */)
6666 /* Now, free glyph matrices in windows that were not reused. */ 6998 /* Now, free glyph matrices in windows that were not reused. */
6667 for (i = 0; i < n_leaf_windows; i++) 6999 for (i = 0; i < n_leaf_windows; i++)
6668 if (NILP (leaf_windows[i]->contents)) 7000 if (NILP (leaf_windows[i]->contents))
6669 { 7001 free_window_matrices (leaf_windows[i]);
6670 free_window_matrices (leaf_windows[i]);
6671 window_changed = true;
6672 }
6673 7002
6674 /* Allow x_set_window_size again and apply frame size changes if 7003 /* Allow x_set_window_size again and apply frame size changes if
6675 needed. */ 7004 needed. */
@@ -6699,35 +7028,10 @@ the return value is nil. Otherwise the value is t. */)
6699 selected window. */ 7028 selected window. */
6700 if (FRAME_LIVE_P (XFRAME (data->selected_frame))) 7029 if (FRAME_LIVE_P (XFRAME (data->selected_frame)))
6701 do_switch_frame (data->selected_frame, 0, 0, Qnil); 7030 do_switch_frame (data->selected_frame, 0, 0, Qnil);
6702
6703 if (window_changed)
6704 /* At least one window has been added or removed. Run
6705 `window-configuration-change-hook' and make sure
6706 `window-size-change-functions' get run later.
6707
6708 We have to do this in order to capture the following
6709 scenario: Suppose our frame contains two live windows W1 and
6710 W2 and 'set-window-configuration' replaces them by two
6711 windows W3 and W4 that were dead the last time
6712 run_window_size_change_functions was run. If W3 and W4 have
6713 the same values for their old and new pixel sizes but these
6714 values differ from those of W1 and W2, the sizes of our
6715 frame's two live windows changed but window_size_changed has
6716 no means to detect that fact.
6717
6718 Obviously, this will get us false positives, for example,
6719 when we restore the original configuration with W1 and W2
6720 before run_window_size_change_functions gets called. */
6721 {
6722 run_window_configuration_change_hook (f);
6723 FRAME_WINDOW_CONFIGURATION_CHANGED (f) = true;
6724 }
6725 else if (buffer_changed)
6726 /* At least one window has changed its buffer. Run
6727 `window-configuration-change-hook' only. */
6728 run_window_configuration_change_hook (f);
6729 } 7031 }
6730 7032
7033 FRAME_WINDOW_CHANGE (f) = true;
7034
6731 if (!NILP (new_current_buffer)) 7035 if (!NILP (new_current_buffer))
6732 { 7036 {
6733 Fset_buffer (new_current_buffer); 7037 Fset_buffer (new_current_buffer);
@@ -6889,10 +7193,6 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, ptrdiff_t i)
6889 p->pixel_top = make_fixnum (w->pixel_top); 7193 p->pixel_top = make_fixnum (w->pixel_top);
6890 p->pixel_width = make_fixnum (w->pixel_width); 7194 p->pixel_width = make_fixnum (w->pixel_width);
6891 p->pixel_height = make_fixnum (w->pixel_height); 7195 p->pixel_height = make_fixnum (w->pixel_height);
6892 p->pixel_width_before_size_change
6893 = make_fixnum (w->pixel_width_before_size_change);
6894 p->pixel_height_before_size_change
6895 = make_fixnum (w->pixel_height_before_size_change);
6896 p->left_col = make_fixnum (w->left_col); 7196 p->left_col = make_fixnum (w->left_col);
6897 p->top_line = make_fixnum (w->top_line); 7197 p->top_line = make_fixnum (w->top_line);
6898 p->total_cols = make_fixnum (w->total_cols); 7198 p->total_cols = make_fixnum (w->total_cols);
@@ -7581,9 +7881,9 @@ init_window_once (void)
7581{ 7881{
7582 struct frame *f = make_initial_frame (); 7882 struct frame *f = make_initial_frame ();
7583 XSETFRAME (selected_frame, f); 7883 XSETFRAME (selected_frame, f);
7584 Vterminal_frame = selected_frame; 7884 old_selected_frame = Vterminal_frame = selected_frame;
7585 minibuf_window = f->minibuffer_window; 7885 minibuf_window = f->minibuffer_window;
7586 selected_window = f->selected_window; 7886 old_selected_window = selected_window = f->selected_window;
7587} 7887}
7588 7888
7589void 7889void
@@ -7604,6 +7904,8 @@ syms_of_window (void)
7604 7904
7605 DEFSYM (Qwindow_configuration_change_hook, "window-configuration-change-hook"); 7905 DEFSYM (Qwindow_configuration_change_hook, "window-configuration-change-hook");
7606 DEFSYM (Qwindow_size_change_functions, "window-size-change-functions"); 7906 DEFSYM (Qwindow_size_change_functions, "window-size-change-functions");
7907 DEFSYM (Qwindow_buffer_change_functions, "window-buffer-change-functions");
7908 DEFSYM (Qwindow_selection_change_functions, "window-selection-change-functions");
7607 DEFSYM (Qwindowp, "windowp"); 7909 DEFSYM (Qwindowp, "windowp");
7608 DEFSYM (Qwindow_configuration_p, "window-configuration-p"); 7910 DEFSYM (Qwindow_configuration_p, "window-configuration-p");
7609 DEFSYM (Qwindow_live_p, "window-live-p"); 7911 DEFSYM (Qwindow_live_p, "window-live-p");
@@ -7688,24 +7990,66 @@ on their symbols to be controlled by this variable. */);
7688 Vwindow_point_insertion_type = Qnil; 7990 Vwindow_point_insertion_type = Qnil;
7689 DEFSYM (Qwindow_point_insertion_type, "window-point-insertion-type"); 7991 DEFSYM (Qwindow_point_insertion_type, "window-point-insertion-type");
7690 7992
7691 DEFVAR_LISP ("window-configuration-change-hook", 7993 DEFVAR_LISP ("window-buffer-change-functions", Vwindow_buffer_change_functions,
7692 Vwindow_configuration_change_hook, 7994 doc: /* Functions called during redisplay when window buffers have changed.
7693 doc: /* Functions to call when window configuration changes. 7995The value should be a list of functions that take one argument.
7694The buffer-local value is run once per window, with the relevant window 7996
7695selected; while the global value is run only once for the modified frame, 7997Functions specified buffer-locally are called for each window showing
7696with the relevant frame selected. */); 7998the corresponding buffer if and only if that window has been added or
7697 Vwindow_configuration_change_hook = Qnil; 7999changed its buffer since the last redisplay. In this case the window
8000is passed as argument.
8001
8002Functions specified by the default value are called for each frame if
8003at least one window on that frame has been added, deleted or changed
8004its buffer since the last redisplay. In this case the frame is passed
8005as argument. */);
8006 Vwindow_buffer_change_functions = Qnil;
7698 8007
7699 DEFVAR_LISP ("window-size-change-functions", Vwindow_size_change_functions, 8008 DEFVAR_LISP ("window-size-change-functions", Vwindow_size_change_functions,
7700 doc: /* Functions called during redisplay, if window sizes have changed. 8009 doc: /* Functions called during redisplay when window sizes have changed.
7701The value should be a list of functions that take one argument. 8010The value should be a list of functions that take one argument.
7702During the first part of redisplay, for each frame, if any of its windows 8011
7703have changed size since the last redisplay, or have been split or deleted, 8012Functions specified buffer-locally are called for each window showing
7704all the functions in the list are called, with the frame as argument. 8013the corresponding buffer if and only if that window has been added or
7705If redisplay decides to resize the minibuffer window, it calls these 8014changed its buffer or its total or body size since the last redisplay.
7706functions on behalf of that as well. */); 8015In this case the window is passed as argument.
8016
8017Functions specified by the default value are called for each frame if
8018at least one window on that frame has been added or changed its buffer
8019or its total or body size since the last redisplay. In this case the
8020frame is passed as argument. */);
7707 Vwindow_size_change_functions = Qnil; 8021 Vwindow_size_change_functions = Qnil;
7708 8022
8023 DEFVAR_LISP ("window-selection-change-functions", Vwindow_selection_change_functions,
8024 doc: /* Functions called during redisplay when the selected window has changed.
8025The value should be a list of functions that take one argument.
8026
8027Functions specified buffer-locally are called for each window showing
8028the corresponding buffer if and only if that window has been selected
8029or deselected since the last redisplay. In this case the window is
8030passed as argument.
8031
8032Functions specified by the default value are called for each frame if
8033the frame's selected window has changed since the last redisplay. In
8034this case the frame is passed as argument. */);
8035 Vwindow_selection_change_functions = Qnil;
8036
8037 DEFVAR_LISP ("window-configuration-change-hook", Vwindow_configuration_change_hook,
8038 doc: /* Functions called during redisplay when window configuration has changed.
8039The value should be a list of functions that take no argument.
8040
8041Functions specified buffer-locally are called for each window showing
8042the corresponding buffer if at least one window on that frame has been
8043added, deleted or changed its buffer or its total or body size since
8044the last redisplay. Each call is performed with the window showing
8045the buffer temporarily selected.
8046
8047Functions specified by the default value are called for each frame if
8048at least one window on that frame has been added, deleted or changed
8049its buffer or its total or body size since the last redisplay. Each
8050call is performed with the frame temporarily selected. */);
8051 Vwindow_configuration_change_hook = Qnil;
8052
7709 DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay, 8053 DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay,
7710 doc: /* Non-nil means `recenter' redraws entire frame. 8054 doc: /* Non-nil means `recenter' redraws entire frame.
7711If this option is non-nil, then the `recenter' command with a nil 8055If this option is non-nil, then the `recenter' command with a nil
@@ -7817,6 +8161,7 @@ displayed after a scrolling operation to be somewhat inaccurate. */);
7817 Vfast_but_imprecise_scrolling = false; 8161 Vfast_but_imprecise_scrolling = false;
7818 8162
7819 defsubr (&Sselected_window); 8163 defsubr (&Sselected_window);
8164 defsubr (&Sold_selected_window);
7820 defsubr (&Sminibuffer_window); 8165 defsubr (&Sminibuffer_window);
7821 defsubr (&Swindow_minibuffer_p); 8166 defsubr (&Swindow_minibuffer_p);
7822 defsubr (&Swindowp); 8167 defsubr (&Swindowp);
@@ -7826,10 +8171,12 @@ displayed after a scrolling operation to be somewhat inaccurate. */);
7826 defsubr (&Sframe_root_window); 8171 defsubr (&Sframe_root_window);
7827 defsubr (&Sframe_first_window); 8172 defsubr (&Sframe_first_window);
7828 defsubr (&Sframe_selected_window); 8173 defsubr (&Sframe_selected_window);
8174 defsubr (&Sframe_old_selected_window);
7829 defsubr (&Sset_frame_selected_window); 8175 defsubr (&Sset_frame_selected_window);
7830 defsubr (&Spos_visible_in_window_p); 8176 defsubr (&Spos_visible_in_window_p);
7831 defsubr (&Swindow_line_height); 8177 defsubr (&Swindow_line_height);
7832 defsubr (&Swindow_buffer); 8178 defsubr (&Swindow_buffer);
8179 defsubr (&Swindow_old_buffer);
7833 defsubr (&Swindow_parent); 8180 defsubr (&Swindow_parent);
7834 defsubr (&Swindow_top_child); 8181 defsubr (&Swindow_top_child);
7835 defsubr (&Swindow_left_child); 8182 defsubr (&Swindow_left_child);
@@ -7840,8 +8187,10 @@ displayed after a scrolling operation to be somewhat inaccurate. */);
7840 defsubr (&Swindow_use_time); 8187 defsubr (&Swindow_use_time);
7841 defsubr (&Swindow_pixel_width); 8188 defsubr (&Swindow_pixel_width);
7842 defsubr (&Swindow_pixel_height); 8189 defsubr (&Swindow_pixel_height);
7843 defsubr (&Swindow_pixel_width_before_size_change); 8190 defsubr (&Swindow_old_pixel_width);
7844 defsubr (&Swindow_pixel_height_before_size_change); 8191 defsubr (&Swindow_old_pixel_height);
8192 defsubr (&Swindow_old_body_pixel_width);
8193 defsubr (&Swindow_old_body_pixel_height);
7845 defsubr (&Swindow_total_width); 8194 defsubr (&Swindow_total_width);
7846 defsubr (&Swindow_total_height); 8195 defsubr (&Swindow_total_height);
7847 defsubr (&Swindow_normal_size); 8196 defsubr (&Swindow_normal_size);
diff --git a/src/window.h b/src/window.h
index ee6ec3bb19a..9c4aea85ea6 100644
--- a/src/window.h
+++ b/src/window.h
@@ -142,6 +142,11 @@ struct window
142 as well. */ 142 as well. */
143 Lisp_Object contents; 143 Lisp_Object contents;
144 144
145 /* The old buffer of this window, set to this window's buffer by
146 run_window_change_functions every time it sees this window.
147 Unused for internal windows. */
148 Lisp_Object old_buffer;
149
145 /* A marker pointing to where in the text to start displaying. 150 /* A marker pointing to where in the text to start displaying.
146 BIDI Note: This is the _logical-order_ start, i.e. the smallest 151 BIDI Note: This is the _logical-order_ start, i.e. the smallest
147 buffer position visible in the window, not necessarily the 152 buffer position visible in the window, not necessarily the
@@ -229,6 +234,14 @@ struct window
229 /* Unique number of window assigned when it was created. */ 234 /* Unique number of window assigned when it was created. */
230 EMACS_INT sequence_number; 235 EMACS_INT sequence_number;
231 236
237 /* The change stamp of this window. Set to 0 when the window is
238 created, it is set to its frame's change stamp every time
239 run_window_change_functions is run on that frame with this
240 window live. It is left alone when the window exists only
241 within a window configuration. Not useful for internal
242 windows. */
243 int change_stamp;
244
232 /* The upper left corner pixel coordinates of this window, as 245 /* The upper left corner pixel coordinates of this window, as
233 integers relative to upper left corner of frame = 0, 0. */ 246 integers relative to upper left corner of frame = 0, 0. */
234 int pixel_left; 247 int pixel_left;
@@ -243,10 +256,13 @@ struct window
243 int pixel_width; 256 int pixel_width;
244 int pixel_height; 257 int pixel_height;
245 258
246 /* The pixel sizes of the window at the last time 259 /* The pixel and pixel body sizes of the window at the last time
247 `window-size-change-functions' was run. */ 260 run_window_change_functions was run with this window live. Not
248 int pixel_width_before_size_change; 261 useful for internal windows. */
249 int pixel_height_before_size_change; 262 int old_pixel_width;
263 int old_pixel_height;
264 int old_body_pixel_width;
265 int old_body_pixel_height;
250 266
251 /* The size of the window. */ 267 /* The size of the window. */
252 int total_cols; 268 int total_cols;
@@ -1023,6 +1039,7 @@ wset_next_buffers (struct window *w, Lisp_Object val)
1023 This value is always the same as FRAME_SELECTED_WINDOW (selected_frame). */ 1039 This value is always the same as FRAME_SELECTED_WINDOW (selected_frame). */
1024 1040
1025extern Lisp_Object selected_window; 1041extern Lisp_Object selected_window;
1042extern Lisp_Object old_selected_window;
1026 1043
1027/* This is a time stamp for window selection, so we can find the least 1044/* This is a time stamp for window selection, so we can find the least
1028 recently used window. Its only users are Fselect_window, 1045 recently used window. Its only users are Fselect_window,
@@ -1051,7 +1068,7 @@ extern void grow_mini_window (struct window *, int, bool);
1051extern void shrink_mini_window (struct window *, bool); 1068extern void shrink_mini_window (struct window *, bool);
1052extern int window_relative_x_coord (struct window *, enum window_part, int); 1069extern int window_relative_x_coord (struct window *, enum window_part, int);
1053 1070
1054void run_window_size_change_functions (Lisp_Object); 1071void run_window_change_functions (void);
1055 1072
1056/* Make WINDOW display BUFFER. RUN_HOOKS_P means it's allowed 1073/* Make WINDOW display BUFFER. RUN_HOOKS_P means it's allowed
1057 to run hooks. See make_frame for a case where it's not allowed. */ 1074 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 7725570ced3..86495078fb6 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -2786,6 +2786,7 @@ init_iterator (struct it *it, struct window *w,
2786 struct glyph_row *row, enum face_id base_face_id) 2786 struct glyph_row *row, enum face_id base_face_id)
2787{ 2787{
2788 enum face_id remapped_base_face_id = base_face_id; 2788 enum face_id remapped_base_face_id = base_face_id;
2789 int body_width = 0, body_height = 0;
2789 2790
2790 /* Some precondition checks. */ 2791 /* Some precondition checks. */
2791 eassert (w != NULL && it != NULL); 2792 eassert (w != NULL && it != NULL);
@@ -2962,7 +2963,7 @@ init_iterator (struct it *it, struct window *w,
2962 { 2963 {
2963 /* Mode lines, menu bar in terminal frames. */ 2964 /* Mode lines, menu bar in terminal frames. */
2964 it->first_visible_x = 0; 2965 it->first_visible_x = 0;
2965 it->last_visible_x = WINDOW_PIXEL_WIDTH (w); 2966 it->last_visible_x = body_width = WINDOW_PIXEL_WIDTH (w);
2966 } 2967 }
2967 else 2968 else
2968 { 2969 {
@@ -2982,8 +2983,12 @@ init_iterator (struct it *it, struct window *w,
2982 else 2983 else
2983 it->first_visible_x = 2984 it->first_visible_x =
2984 window_hscroll_limited (w, it->f) * FRAME_COLUMN_WIDTH (it->f); 2985 window_hscroll_limited (w, it->f) * FRAME_COLUMN_WIDTH (it->f);
2985 it->last_visible_x = (it->first_visible_x 2986
2986 + window_box_width (w, TEXT_AREA)); 2987 body_width = window_box_width (w, TEXT_AREA);
2988 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
2989 && body_width != w->old_body_pixel_width)
2990 FRAME_WINDOW_CHANGE (it->f) = true;
2991 it->last_visible_x = it->first_visible_x + body_width;
2987 2992
2988 /* If we truncate lines, leave room for the truncation glyph(s) at 2993 /* If we truncate lines, leave room for the truncation glyph(s) at
2989 the right margin. Otherwise, leave room for the continuation 2994 the right margin. Otherwise, leave room for the continuation
@@ -2997,7 +3002,8 @@ init_iterator (struct it *it, struct window *w,
2997 } 3002 }
2998 3003
2999 it->header_line_p = window_wants_header_line (w); 3004 it->header_line_p = window_wants_header_line (w);
3000 it->current_y = WINDOW_HEADER_LINE_HEIGHT (w) + w->vscroll; 3005 body_height = WINDOW_HEADER_LINE_HEIGHT (w);
3006 it->current_y = body_height + w->vscroll;
3001 } 3007 }
3002 3008
3003 /* Leave room for a border glyph. */ 3009 /* Leave room for a border glyph. */
@@ -3006,6 +3012,10 @@ init_iterator (struct it *it, struct window *w,
3006 it->last_visible_x -= 1; 3012 it->last_visible_x -= 1;
3007 3013
3008 it->last_visible_y = window_text_bottom_y (w); 3014 it->last_visible_y = window_text_bottom_y (w);
3015 body_height += it->last_visible_y;
3016 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3017 && body_height != w->old_body_pixel_height)
3018 FRAME_WINDOW_CHANGE (it->f) = true;
3009 3019
3010 /* For mode lines and alike, arrange for the first glyph having a 3020 /* For mode lines and alike, arrange for the first glyph having a
3011 left box line if the face specifies a box. */ 3021 left box line if the face specifies a box. */
@@ -12200,8 +12210,6 @@ prepare_menu_bars (void)
12200 && !XBUFFER (w->contents)->text->redisplay) 12210 && !XBUFFER (w->contents)->text->redisplay)
12201 continue; 12211 continue;
12202 12212
12203 run_window_size_change_functions (frame);
12204
12205 if (FRAME_PARENT_FRAME (f)) 12213 if (FRAME_PARENT_FRAME (f))
12206 continue; 12214 continue;
12207 12215
@@ -14119,20 +14127,6 @@ redisplay_internal (void)
14119 { 14127 {
14120 echo_area_display (false); 14128 echo_area_display (false);
14121 14129
14122 /* If echo_area_display resizes the mini-window, the redisplay and
14123 window_sizes_changed flags of the selected frame are set, but
14124 it's too late for the hooks in window-size-change-functions,
14125 which have been examined already in prepare_menu_bars. So in
14126 that case we call the hooks here only for the selected frame. */
14127 if (sf->redisplay)
14128 {
14129 ptrdiff_t count1 = SPECPDL_INDEX ();
14130
14131 record_unwind_save_match_data ();
14132 run_window_size_change_functions (selected_frame);
14133 unbind_to (count1, Qnil);
14134 }
14135
14136 if (message_cleared_p) 14130 if (message_cleared_p)
14137 update_miniwindow_p = true; 14131 update_miniwindow_p = true;
14138 14132
@@ -14149,15 +14143,6 @@ redisplay_internal (void)
14149 && (current_buffer->clip_changed || window_outdated (w)) 14143 && (current_buffer->clip_changed || window_outdated (w))
14150 && resize_mini_window (w, false)) 14144 && resize_mini_window (w, false))
14151 { 14145 {
14152 if (sf->redisplay)
14153 {
14154 ptrdiff_t count1 = SPECPDL_INDEX ();
14155
14156 record_unwind_save_match_data ();
14157 run_window_size_change_functions (selected_frame);
14158 unbind_to (count1, Qnil);
14159 }
14160
14161 /* Resized active mini-window to fit the size of what it is 14146 /* Resized active mini-window to fit the size of what it is
14162 showing if its contents might have changed. */ 14147 showing if its contents might have changed. */
14163 must_finish = true; 14148 must_finish = true;
@@ -14347,7 +14332,19 @@ redisplay_internal (void)
14347 && (w = XWINDOW (selected_window)) != sw) 14332 && (w = XWINDOW (selected_window)) != sw)
14348 goto retry; 14333 goto retry;
14349 14334
14350 /* We used to always goto end_of_redisplay here, but this 14335 if (!NILP (Vrun_hooks))
14336 {
14337 run_window_change_functions ();
14338
14339 /* If windows or buffers changed or selected_window
14340 changed, redisplay again. */
14341 if ((windows_or_buffers_changed)
14342 || (WINDOWP (selected_window)
14343 && (w = XWINDOW (selected_window)) != sw))
14344 goto retry;
14345 }
14346
14347 /* We used to always goto end_of_redisplay here, but this
14351 isn't enough if we have a blinking cursor. */ 14348 isn't enough if we have a blinking cursor. */
14352 if (w->cursor_off_p == w->last_cursor_off_p) 14349 if (w->cursor_off_p == w->last_cursor_off_p)
14353 goto end_of_redisplay; 14350 goto end_of_redisplay;
@@ -14706,9 +14703,22 @@ redisplay_internal (void)
14706 /* If we just did a pending size change, or have additional 14703 /* If we just did a pending size change, or have additional
14707 visible frames, or selected_window changed, redisplay again. */ 14704 visible frames, or selected_window changed, redisplay again. */
14708 if ((windows_or_buffers_changed && !pending) 14705 if ((windows_or_buffers_changed && !pending)
14709 || (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw)) 14706 || (WINDOWP (selected_window)
14707 && (w = XWINDOW (selected_window)) != sw))
14710 goto retry; 14708 goto retry;
14711 14709
14710 if (!NILP (Vrun_hooks))
14711 {
14712 run_window_change_functions ();
14713
14714 /* If windows or buffers changed or selected_window changed,
14715 redisplay again. */
14716 if ((windows_or_buffers_changed)
14717 || (WINDOWP (selected_window)
14718 && (w = XWINDOW (selected_window)) != sw))
14719 goto retry;
14720 }
14721
14712 /* Clear the face and image caches. 14722 /* Clear the face and image caches.
14713 14723
14714 We used to do this only if consider_all_windows_p. But the cache 14724 We used to do this only if consider_all_windows_p. But the cache