diff options
| author | Martin Rudalics | 2016-02-23 12:08:55 +0100 |
|---|---|---|
| committer | Martin Rudalics | 2016-02-23 12:08:55 +0100 |
| commit | 8e7712c7afc47a8a861a9f4d6a10be1f78a2dac6 (patch) | |
| tree | 46b7a58fae8aa09fc316cec8231697f84282a319 /src | |
| parent | ef52e66efd78aac4c4e5bd5e11870e5ba3b37a1e (diff) | |
| download | emacs-8e7712c7afc47a8a861a9f4d6a10be1f78a2dac6.tar.gz emacs-8e7712c7afc47a8a861a9f4d6a10be1f78a2dac6.zip | |
Fix `window-configuration-change-hook' and `window-size-change-functions'
(1) Run `window-configuration-change-hook' if and only if at least
one window was deleted or created or shows another buffer since
last redisplay.
(2) Run `window-size-change-functions' if and only if at least
one window changed its size since last redisplay (in a few cases
`window-size-change-functions' will also run when no window
changed its size).
(3) Provide two functions `window-pixel-height-before-size-change'
and `window-pixel-width-before-size-change' that allow to easily
detect which window changed size.
* src/frame.h (struct frame): New boolean member
window_configuration_changed.
(FRAME_WINDOW_SIZES_CHANGED): Remove macro.
(FRAME_WINDOW_CONFIGURATION_CHANGED): New macro.
* src/frame.c (adjust_frame_size): Don't run
`window-configuration-change-hook'.
* src/window.h (struct window): New fields
pixel_width_before_size_change and pixel_height_before_size_change.
(WINDOW_INTERNAL_P): New macro.
* src/window.c (Fwindow_pixel_width_before_size_change)
(Fwindow_pixel_height_before_size_change): New functions.
(Fdelete_other_windows_internal, Fwindow_resize_apply)
(resize_frame_windows, Fsplit_window_internal)
(Fdelete_window_internal, grow_mini_window)
(shrink_mini_window, Fresize_mini_window_internal): Don't call
FRAME_WINDOW_SIZES_CHANGED.
(window_size_changed, window_set_before_size_change_sizes)
(run_window_size_change_functions): New functions.
(make_window): Initialize pixel_width_before_size_change and
pixel_height_before_size_change.
(Fdelete_window_internal): Don't call
run_window_configuration_change_hook.
(struct saved_window): Add pixel_height_before_size_change and
pixel_width_before_size_change.
(Fset_window_configuration): Try to identify window configuration
changes correctly so run_window_configuration_change_hook and
run_window_size_change_functions run only if configuration and size
really changed.
(save_window_save): Set the pixel_height_before_size_change and
pixel_width_before_size_change fields.
(Vwindow_size_change_functions): Move here definiton from xdisp.c.
* src/xdisp.c (prepare_menu_bars, redisplay_internal): Call
run_window_size_change_functions.
(Vwindow_size_change_functions): Move definition to window.c.
* src/xfns.c (x_set_menu_bar_lines): Don't call
run_window_configuration_change_hook.
* doc/lispref/windows.texi (Window Sizes): Document new
functions `window-pixel-height-before-size-change' and
`window-pixel-width-before-size-change'.
(Window Configurations): Mention that this may trigger
execution of `window-size-change-functions' although no window
changed size.
(Window Hooks): Update descriptions of `window-size-change-functions'
and `window-configuration-change-hook'.
Diffstat (limited to 'src')
| -rw-r--r-- | src/frame.c | 2 | ||||
| -rw-r--r-- | src/frame.h | 13 | ||||
| -rw-r--r-- | src/window.c | 205 | ||||
| -rw-r--r-- | src/window.h | 16 | ||||
| -rw-r--r-- | src/xdisp.c | 59 | ||||
| -rw-r--r-- | src/xfns.c | 1 |
6 files changed, 199 insertions, 97 deletions
diff --git a/src/frame.c b/src/frame.c index 8c86afe4efb..df473aebc21 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, | |||
| 591 | || new_pixel_height != old_pixel_height); | 591 | || new_pixel_height != old_pixel_height); |
| 592 | 592 | ||
| 593 | unblock_input (); | 593 | unblock_input (); |
| 594 | |||
| 595 | run_window_configuration_change_hook (f); | ||
| 596 | } | 594 | } |
| 597 | 595 | ||
| 598 | /* Allocate basically initialized frame. */ | 596 | /* Allocate basically initialized frame. */ |
diff --git a/src/frame.h b/src/frame.h index 71dab4b1cb1..d9424ab5965 100644 --- a/src/frame.h +++ b/src/frame.h | |||
| @@ -288,8 +288,9 @@ struct frame | |||
| 288 | cleared. */ | 288 | cleared. */ |
| 289 | bool_bf explicit_name : 1; | 289 | bool_bf explicit_name : 1; |
| 290 | 290 | ||
| 291 | /* True if size of some window on this frame has changed. */ | 291 | /* True if configuration of windows on this frame has changed since |
| 292 | bool_bf window_sizes_changed : 1; | 292 | last call of run_window_size_change_functions. */ |
| 293 | bool_bf window_configuration_changed : 1; | ||
| 293 | 294 | ||
| 294 | /* True if the mouse has moved on this display device | 295 | /* True if the mouse has moved on this display device |
| 295 | since the last time we checked. */ | 296 | since the last time we checked. */ |
| @@ -828,10 +829,10 @@ default_pixels_per_inch_y (void) | |||
| 828 | are frozen on frame F. */ | 829 | are frozen on frame F. */ |
| 829 | #define FRAME_WINDOWS_FROZEN(f) (f)->frozen_window_starts | 830 | #define FRAME_WINDOWS_FROZEN(f) (f)->frozen_window_starts |
| 830 | 831 | ||
| 831 | /* True if a size change has been requested for frame F | 832 | /* True if the frame's window configuration has changed since last call |
| 832 | but not yet really put into effect. This can be true temporarily | 833 | of run_window_size_change_functions. */ |
| 833 | when an X event comes in at a bad time. */ | 834 | #define FRAME_WINDOW_CONFIGURATION_CHANGED(f) \ |
| 834 | #define FRAME_WINDOW_SIZES_CHANGED(f) (f)->window_sizes_changed | 835 | ((f)->window_configuration_changed) |
| 835 | 836 | ||
| 836 | /* The minibuffer window of frame F, if it has one; otherwise nil. */ | 837 | /* The minibuffer window of frame F, if it has one; otherwise nil. */ |
| 837 | #define FRAME_MINIBUF_WINDOW(f) f->minibuffer_window | 838 | #define FRAME_MINIBUF_WINDOW(f) f->minibuffer_window |
diff --git a/src/window.c b/src/window.c index e1a30ee5714..29c35875039 100644 --- a/src/window.c +++ b/src/window.c | |||
| @@ -720,6 +720,34 @@ the height of the screen areas spanned by its children. */) | |||
| 720 | return make_number (decode_valid_window (window)->pixel_height); | 720 | return make_number (decode_valid_window (window)->pixel_height); |
| 721 | } | 721 | } |
| 722 | 722 | ||
| 723 | DEFUN ("window-pixel-width-before-size-change", Fwindow_pixel_width_before_size_change, | ||
| 724 | Swindow_pixel_width_before_size_change, 0, 1, 0, | ||
| 725 | doc: /* Return pixel width of window WINDOW before last size changes. | ||
| 726 | WINDOW must be a valid window and defaults to the selected one. | ||
| 727 | |||
| 728 | The return value is the pixel width of WINDOW at the last time | ||
| 729 | `window-size-change-functions' was run. It's zero if WINDOW was made | ||
| 730 | after that. */) | ||
| 731 | (Lisp_Object window) | ||
| 732 | { | ||
| 733 | return (make_number | ||
| 734 | (decode_valid_window (window)->pixel_width_before_size_change)); | ||
| 735 | } | ||
| 736 | |||
| 737 | DEFUN ("window-pixel-height-before-size-change", Fwindow_pixel_height_before_size_change, | ||
| 738 | Swindow_pixel_height_before_size_change, 0, 1, 0, | ||
| 739 | doc: /* Return pixel height of window WINDOW before last size changes. | ||
| 740 | WINDOW must be a valid window and defaults to the selected one. | ||
| 741 | |||
| 742 | The return value is the pixel height of WINDOW at the last time | ||
| 743 | `window-size-change-functions' was run. It's zero if WINDOW was made | ||
| 744 | after that. */) | ||
| 745 | (Lisp_Object window) | ||
| 746 | { | ||
| 747 | return (make_number | ||
| 748 | (decode_valid_window (window)->pixel_height_before_size_change)); | ||
| 749 | } | ||
| 750 | |||
| 723 | DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 2, 0, | 751 | DEFUN ("window-total-height", Fwindow_total_height, Swindow_total_height, 0, 2, 0, |
| 724 | doc: /* Return the height of window WINDOW in lines. | 752 | doc: /* Return the height of window WINDOW in lines. |
| 725 | WINDOW must be a valid window and defaults to the selected one. | 753 | WINDOW must be a valid window and defaults to the selected one. |
| @@ -2879,6 +2907,7 @@ window-start value is reasonable when this function is called. */) | |||
| 2879 | Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta; | 2907 | Lisp_Object sibling, pwindow, swindow IF_LINT (= Qnil), delta; |
| 2880 | ptrdiff_t startpos IF_LINT (= 0), startbyte IF_LINT (= 0); | 2908 | ptrdiff_t startpos IF_LINT (= 0), startbyte IF_LINT (= 0); |
| 2881 | int top IF_LINT (= 0), new_top; | 2909 | int top IF_LINT (= 0), new_top; |
| 2910 | bool resize_failed = false; | ||
| 2882 | 2911 | ||
| 2883 | w = decode_valid_window (window); | 2912 | w = decode_valid_window (window); |
| 2884 | XSETWINDOW (window, w); | 2913 | XSETWINDOW (window, w); |
| @@ -2978,8 +3007,6 @@ window-start value is reasonable when this function is called. */) | |||
| 2978 | 3007 | ||
| 2979 | fset_redisplay (f); | 3008 | fset_redisplay (f); |
| 2980 | Vwindow_list = Qnil; | 3009 | Vwindow_list = Qnil; |
| 2981 | FRAME_WINDOW_SIZES_CHANGED (f) = true; | ||
| 2982 | bool resize_failed = false; | ||
| 2983 | 3010 | ||
| 2984 | if (!WINDOW_LEAF_P (w)) | 3011 | if (!WINDOW_LEAF_P (w)) |
| 2985 | { | 3012 | { |
| @@ -3229,6 +3256,76 @@ If WINDOW is omitted or nil, it defaults to the selected window. */) | |||
| 3229 | return Qnil; | 3256 | return Qnil; |
| 3230 | } | 3257 | } |
| 3231 | 3258 | ||
| 3259 | |||
| 3260 | /* Compare old and present pixel sizes of windows in tree rooted at W. | ||
| 3261 | Return true iff any of these windows differs in size. */ | ||
| 3262 | |||
| 3263 | static bool | ||
| 3264 | window_size_changed (struct window *w) | ||
| 3265 | { | ||
| 3266 | if (w->pixel_width != w->pixel_width_before_size_change | ||
| 3267 | || w->pixel_height != w->pixel_height_before_size_change) | ||
| 3268 | return true; | ||
| 3269 | |||
| 3270 | if (WINDOW_INTERNAL_P (w)) | ||
| 3271 | { | ||
| 3272 | w = XWINDOW (w->contents); | ||
| 3273 | while (w) | ||
| 3274 | { | ||
| 3275 | if (window_size_changed (w)) | ||
| 3276 | return true; | ||
| 3277 | |||
| 3278 | w = NILP (w->next) ? 0 : XWINDOW (w->next); | ||
| 3279 | } | ||
| 3280 | } | ||
| 3281 | |||
| 3282 | return false; | ||
| 3283 | } | ||
| 3284 | |||
| 3285 | /* Set before size change pixel sizes of windows in tree rooted at W to | ||
| 3286 | their present pixel sizes. */ | ||
| 3287 | |||
| 3288 | static void | ||
| 3289 | window_set_before_size_change_sizes (struct window *w) | ||
| 3290 | { | ||
| 3291 | w->pixel_width_before_size_change = w->pixel_width; | ||
| 3292 | w->pixel_height_before_size_change = w->pixel_height; | ||
| 3293 | |||
| 3294 | if (WINDOW_INTERNAL_P (w)) | ||
| 3295 | { | ||
| 3296 | w = XWINDOW (w->contents); | ||
| 3297 | while (w) | ||
| 3298 | { | ||
| 3299 | window_set_before_size_change_sizes (w); | ||
| 3300 | w = NILP (w->next) ? 0 : XWINDOW (w->next); | ||
| 3301 | } | ||
| 3302 | } | ||
| 3303 | } | ||
| 3304 | |||
| 3305 | |||
| 3306 | void | ||
| 3307 | run_window_size_change_functions (Lisp_Object frame) | ||
| 3308 | { | ||
| 3309 | struct frame *f = XFRAME (frame); | ||
| 3310 | struct window *r = XWINDOW (FRAME_ROOT_WINDOW (f)); | ||
| 3311 | Lisp_Object functions = Vwindow_size_change_functions; | ||
| 3312 | |||
| 3313 | if (FRAME_WINDOW_CONFIGURATION_CHANGED (f) || | ||
| 3314 | window_size_changed (r)) | ||
| 3315 | { | ||
| 3316 | while (CONSP (functions)) | ||
| 3317 | { | ||
| 3318 | if (!EQ (XCAR (functions), Qt)) | ||
| 3319 | call1 (XCAR (functions), frame); | ||
| 3320 | functions = XCDR (functions); | ||
| 3321 | } | ||
| 3322 | |||
| 3323 | window_set_before_size_change_sizes (r); | ||
| 3324 | FRAME_WINDOW_CONFIGURATION_CHANGED (f) = false; | ||
| 3325 | } | ||
| 3326 | } | ||
| 3327 | |||
| 3328 | |||
| 3232 | /* Make WINDOW display BUFFER. RUN_HOOKS_P means it's allowed | 3329 | /* Make WINDOW display BUFFER. RUN_HOOKS_P means it's allowed |
| 3233 | to run hooks. See make_frame for a case where it's not allowed. | 3330 | to run hooks. See make_frame for a case where it's not allowed. |
| 3234 | KEEP_MARGINS_P means that the current margins, fringes, and | 3331 | KEEP_MARGINS_P means that the current margins, fringes, and |
| @@ -3263,15 +3360,9 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, | |||
| 3263 | 3360 | ||
| 3264 | if (!(keep_margins_p && samebuf)) | 3361 | if (!(keep_margins_p && samebuf)) |
| 3265 | { /* If we're not actually changing the buffer, don't reset hscroll | 3362 | { /* If we're not actually changing the buffer, don't reset hscroll |
| 3266 | and vscroll. This case happens for example when called from | 3363 | and vscroll. Resetting hscroll and vscroll here is problematic |
| 3267 | change_frame_size_1, where we use a dummy call to | 3364 | for things like image-mode and doc-view-mode since it resets |
| 3268 | Fset_window_buffer on the frame's selected window (and no | 3365 | the image's position whenever we resize the frame. */ |
| 3269 | other) just in order to run window-configuration-change-hook | ||
| 3270 | (no longer true since change_frame_size_1 directly calls | ||
| 3271 | run_window_configuration_change_hook). Resetting hscroll and | ||
| 3272 | vscroll here is problematic for things like image-mode and | ||
| 3273 | doc-view-mode since it resets the image's position whenever we | ||
| 3274 | resize the frame. */ | ||
| 3275 | w->hscroll = w->min_hscroll = w->hscroll_whole = 0; | 3366 | w->hscroll = w->min_hscroll = w->hscroll_whole = 0; |
| 3276 | w->suspend_auto_hscroll = false; | 3367 | w->suspend_auto_hscroll = false; |
| 3277 | w->vscroll = 0; | 3368 | w->vscroll = 0; |
| @@ -3283,10 +3374,8 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, | |||
| 3283 | w->start_at_line_beg = false; | 3374 | w->start_at_line_beg = false; |
| 3284 | w->force_start = false; | 3375 | w->force_start = false; |
| 3285 | } | 3376 | } |
| 3286 | /* Maybe we could move this into the `if' but it's not obviously safe and | ||
| 3287 | I doubt it's worth the trouble. */ | ||
| 3288 | wset_redisplay (w); | ||
| 3289 | 3377 | ||
| 3378 | wset_redisplay (w); | ||
| 3290 | wset_update_mode_line (w); | 3379 | wset_update_mode_line (w); |
| 3291 | 3380 | ||
| 3292 | /* We must select BUFFER to run the window-scroll-functions and to look up | 3381 | /* We must select BUFFER to run the window-scroll-functions and to look up |
| @@ -3314,7 +3403,7 @@ set_window_buffer (Lisp_Object window, Lisp_Object buffer, | |||
| 3314 | 3403 | ||
| 3315 | if (run_hooks_p) | 3404 | if (run_hooks_p) |
| 3316 | { | 3405 | { |
| 3317 | if (! NILP (Vwindow_scroll_functions)) | 3406 | if (!NILP (Vwindow_scroll_functions)) |
| 3318 | run_hook_with_args_2 (Qwindow_scroll_functions, window, | 3407 | run_hook_with_args_2 (Qwindow_scroll_functions, window, |
| 3319 | Fmarker_position (w->start)); | 3408 | Fmarker_position (w->start)); |
| 3320 | if (!samebuf) | 3409 | if (!samebuf) |
| @@ -3559,6 +3648,8 @@ make_window (void) | |||
| 3559 | w->phys_cursor_width = -1; | 3648 | w->phys_cursor_width = -1; |
| 3560 | #endif | 3649 | #endif |
| 3561 | w->sequence_number = ++sequence_number; | 3650 | w->sequence_number = ++sequence_number; |
| 3651 | w->pixel_width_before_size_change = 0; | ||
| 3652 | w->pixel_height_before_size_change = 0; | ||
| 3562 | w->scroll_bar_width = -1; | 3653 | w->scroll_bar_width = -1; |
| 3563 | w->scroll_bar_height = -1; | 3654 | w->scroll_bar_height = -1; |
| 3564 | w->column_number_displayed = -1; | 3655 | w->column_number_displayed = -1; |
| @@ -3922,7 +4013,6 @@ be applied on the Elisp level. */) | |||
| 3922 | window_resize_apply (r, horflag); | 4013 | window_resize_apply (r, horflag); |
| 3923 | 4014 | ||
| 3924 | fset_redisplay (f); | 4015 | fset_redisplay (f); |
| 3925 | FRAME_WINDOW_SIZES_CHANGED (f) = true; | ||
| 3926 | 4016 | ||
| 3927 | adjust_frame_glyphs (f); | 4017 | adjust_frame_glyphs (f); |
| 3928 | unblock_input (); | 4018 | unblock_input (); |
| @@ -4087,7 +4177,6 @@ resize_frame_windows (struct frame *f, int size, bool horflag, bool pixelwise) | |||
| 4087 | } | 4177 | } |
| 4088 | } | 4178 | } |
| 4089 | 4179 | ||
| 4090 | FRAME_WINDOW_SIZES_CHANGED (f) = true; | ||
| 4091 | fset_redisplay (f); | 4180 | fset_redisplay (f); |
| 4092 | } | 4181 | } |
| 4093 | 4182 | ||
| @@ -4214,7 +4303,6 @@ set correctly. See the code of `split-window' for how this is done. */) | |||
| 4214 | p = XWINDOW (o->parent); | 4303 | p = XWINDOW (o->parent); |
| 4215 | 4304 | ||
| 4216 | fset_redisplay (f); | 4305 | fset_redisplay (f); |
| 4217 | FRAME_WINDOW_SIZES_CHANGED (f) = true; | ||
| 4218 | new = make_window (); | 4306 | new = make_window (); |
| 4219 | n = XWINDOW (new); | 4307 | n = XWINDOW (new); |
| 4220 | wset_frame (n, frame); | 4308 | wset_frame (n, frame); |
| @@ -4383,7 +4471,6 @@ Signal an error when WINDOW is the only window on its frame. */) | |||
| 4383 | 4471 | ||
| 4384 | fset_redisplay (f); | 4472 | fset_redisplay (f); |
| 4385 | Vwindow_list = Qnil; | 4473 | Vwindow_list = Qnil; |
| 4386 | FRAME_WINDOW_SIZES_CHANGED (f) = true; | ||
| 4387 | 4474 | ||
| 4388 | wset_next (w, Qnil); /* Don't delete w->next too. */ | 4475 | wset_next (w, Qnil); /* Don't delete w->next too. */ |
| 4389 | free_window_matrices (w); | 4476 | free_window_matrices (w); |
| @@ -4451,9 +4538,6 @@ Signal an error when WINDOW is the only window on its frame. */) | |||
| 4451 | } | 4538 | } |
| 4452 | else | 4539 | else |
| 4453 | unblock_input (); | 4540 | unblock_input (); |
| 4454 | |||
| 4455 | /* Must be run by the caller: | ||
| 4456 | run_window_configuration_change_hook (f); */ | ||
| 4457 | } | 4541 | } |
| 4458 | else | 4542 | else |
| 4459 | /* We failed: Relink WINDOW into window tree. */ | 4543 | /* We failed: Relink WINDOW into window tree. */ |
| @@ -4527,7 +4611,6 @@ grow_mini_window (struct window *w, int delta, bool pixelwise) | |||
| 4527 | /* Enforce full redisplay of the frame. */ | 4611 | /* Enforce full redisplay of the frame. */ |
| 4528 | /* FIXME: Shouldn't window--resize-root-window-vertically do it? */ | 4612 | /* FIXME: Shouldn't window--resize-root-window-vertically do it? */ |
| 4529 | fset_redisplay (f); | 4613 | fset_redisplay (f); |
| 4530 | FRAME_WINDOW_SIZES_CHANGED (f) = true; | ||
| 4531 | adjust_frame_glyphs (f); | 4614 | adjust_frame_glyphs (f); |
| 4532 | unblock_input (); | 4615 | unblock_input (); |
| 4533 | } | 4616 | } |
| @@ -4567,7 +4650,6 @@ shrink_mini_window (struct window *w, bool pixelwise) | |||
| 4567 | /* Enforce full redisplay of the frame. */ | 4650 | /* Enforce full redisplay of the frame. */ |
| 4568 | /* FIXME: Shouldn't window--resize-root-window-vertically do it? */ | 4651 | /* FIXME: Shouldn't window--resize-root-window-vertically do it? */ |
| 4569 | fset_redisplay (f); | 4652 | fset_redisplay (f); |
| 4570 | FRAME_WINDOW_SIZES_CHANGED (f) = true; | ||
| 4571 | adjust_frame_glyphs (f); | 4653 | adjust_frame_glyphs (f); |
| 4572 | unblock_input (); | 4654 | unblock_input (); |
| 4573 | } | 4655 | } |
| @@ -4610,7 +4692,6 @@ DEFUN ("resize-mini-window-internal", Fresize_mini_window_internal, Sresize_mini | |||
| 4610 | w->top_line = r->top_line + r->total_lines; | 4692 | w->top_line = r->top_line + r->total_lines; |
| 4611 | 4693 | ||
| 4612 | fset_redisplay (f); | 4694 | fset_redisplay (f); |
| 4613 | FRAME_WINDOW_SIZES_CHANGED (f) = true; | ||
| 4614 | adjust_frame_glyphs (f); | 4695 | adjust_frame_glyphs (f); |
| 4615 | unblock_input (); | 4696 | unblock_input (); |
| 4616 | return Qt; | 4697 | return Qt; |
| @@ -5948,6 +6029,7 @@ struct saved_window | |||
| 5948 | 6029 | ||
| 5949 | Lisp_Object window, buffer, start, pointm, old_pointm; | 6030 | Lisp_Object window, buffer, start, pointm, old_pointm; |
| 5950 | Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width; | 6031 | Lisp_Object pixel_left, pixel_top, pixel_height, pixel_width; |
| 6032 | Lisp_Object pixel_height_before_size_change, pixel_width_before_size_change; | ||
| 5951 | Lisp_Object left_col, top_line, total_cols, total_lines; | 6033 | Lisp_Object left_col, top_line, total_cols, total_lines; |
| 5952 | Lisp_Object normal_cols, normal_lines; | 6034 | Lisp_Object normal_cols, normal_lines; |
| 5953 | Lisp_Object hscroll, min_hscroll, hscroll_whole, suspend_auto_hscroll; | 6035 | Lisp_Object hscroll, min_hscroll, hscroll_whole, suspend_auto_hscroll; |
| @@ -6063,6 +6145,12 @@ the return value is nil. Otherwise the value is t. */) | |||
| 6063 | struct window *root_window; | 6145 | struct window *root_window; |
| 6064 | struct window **leaf_windows; | 6146 | struct window **leaf_windows; |
| 6065 | ptrdiff_t i, k, n_leaf_windows; | 6147 | ptrdiff_t i, k, n_leaf_windows; |
| 6148 | /* Records whether a window has been added or removed wrt the | ||
| 6149 | original configuration. */ | ||
| 6150 | bool window_changed = false; | ||
| 6151 | /* Records whether a window has changed its buffer wrt the | ||
| 6152 | original configuration. */ | ||
| 6153 | bool buffer_changed = false; | ||
| 6066 | 6154 | ||
| 6067 | /* Don't do this within the main loop below: This may call Lisp | 6155 | /* Don't do this within the main loop below: This may call Lisp |
| 6068 | code and is thus potentially unsafe while input is blocked. */ | 6156 | code and is thus potentially unsafe while input is blocked. */ |
| @@ -6071,6 +6159,12 @@ the return value is nil. Otherwise the value is t. */) | |||
| 6071 | p = SAVED_WINDOW_N (saved_windows, k); | 6159 | p = SAVED_WINDOW_N (saved_windows, k); |
| 6072 | window = p->window; | 6160 | window = p->window; |
| 6073 | w = XWINDOW (window); | 6161 | w = XWINDOW (window); |
| 6162 | |||
| 6163 | if (NILP (w->contents)) | ||
| 6164 | /* A dead window that will be resurrected, the window | ||
| 6165 | configuration will change. */ | ||
| 6166 | window_changed = true; | ||
| 6167 | |||
| 6074 | if (BUFFERP (w->contents) | 6168 | if (BUFFERP (w->contents) |
| 6075 | && !EQ (w->contents, p->buffer) | 6169 | && !EQ (w->contents, p->buffer) |
| 6076 | && BUFFER_LIVE_P (XBUFFER (p->buffer))) | 6170 | && BUFFER_LIVE_P (XBUFFER (p->buffer))) |
| @@ -6100,7 +6194,6 @@ the return value is nil. Otherwise the value is t. */) | |||
| 6100 | } | 6194 | } |
| 6101 | 6195 | ||
| 6102 | fset_redisplay (f); | 6196 | fset_redisplay (f); |
| 6103 | FRAME_WINDOW_SIZES_CHANGED (f) = true; | ||
| 6104 | 6197 | ||
| 6105 | /* Problem: Freeing all matrices and later allocating them again | 6198 | /* Problem: Freeing all matrices and later allocating them again |
| 6106 | is a serious redisplay flickering problem. What we would | 6199 | is a serious redisplay flickering problem. What we would |
| @@ -6156,6 +6249,10 @@ the return value is nil. Otherwise the value is t. */) | |||
| 6156 | w->pixel_top = XFASTINT (p->pixel_top); | 6249 | w->pixel_top = XFASTINT (p->pixel_top); |
| 6157 | w->pixel_width = XFASTINT (p->pixel_width); | 6250 | w->pixel_width = XFASTINT (p->pixel_width); |
| 6158 | w->pixel_height = XFASTINT (p->pixel_height); | 6251 | w->pixel_height = XFASTINT (p->pixel_height); |
| 6252 | w->pixel_width_before_size_change | ||
| 6253 | = XFASTINT (p->pixel_width_before_size_change); | ||
| 6254 | w->pixel_height_before_size_change | ||
| 6255 | = XFASTINT (p->pixel_height_before_size_change); | ||
| 6159 | w->left_col = XFASTINT (p->left_col); | 6256 | w->left_col = XFASTINT (p->left_col); |
| 6160 | w->top_line = XFASTINT (p->top_line); | 6257 | w->top_line = XFASTINT (p->top_line); |
| 6161 | w->total_cols = XFASTINT (p->total_cols); | 6258 | w->total_cols = XFASTINT (p->total_cols); |
| @@ -6203,6 +6300,9 @@ the return value is nil. Otherwise the value is t. */) | |||
| 6203 | if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer))) | 6300 | if (BUFFERP (p->buffer) && BUFFER_LIVE_P (XBUFFER (p->buffer))) |
| 6204 | /* If saved buffer is alive, install it. */ | 6301 | /* If saved buffer is alive, install it. */ |
| 6205 | { | 6302 | { |
| 6303 | if (!EQ (w->contents, p->buffer)) | ||
| 6304 | /* Record buffer configuration change. */ | ||
| 6305 | buffer_changed = true; | ||
| 6206 | wset_buffer (w, p->buffer); | 6306 | wset_buffer (w, p->buffer); |
| 6207 | w->start_at_line_beg = !NILP (p->start_at_line_beg); | 6307 | w->start_at_line_beg = !NILP (p->start_at_line_beg); |
| 6208 | set_marker_restricted (w->start, p->start, w->contents); | 6308 | set_marker_restricted (w->start, p->start, w->contents); |
| @@ -6236,6 +6336,8 @@ the return value is nil. Otherwise the value is t. */) | |||
| 6236 | else if (!NILP (w->start)) | 6336 | else if (!NILP (w->start)) |
| 6237 | /* Leaf window has no live buffer, get one. */ | 6337 | /* Leaf window has no live buffer, get one. */ |
| 6238 | { | 6338 | { |
| 6339 | /* Record buffer configuration change. */ | ||
| 6340 | buffer_changed = true; | ||
| 6239 | /* Get the buffer via other_buffer_safely in order to | 6341 | /* Get the buffer via other_buffer_safely in order to |
| 6240 | avoid showing an unimportant buffer and, if necessary, to | 6342 | avoid showing an unimportant buffer and, if necessary, to |
| 6241 | recreate *scratch* in the course (part of Juanma's bs-show | 6343 | recreate *scratch* in the course (part of Juanma's bs-show |
| @@ -6283,7 +6385,10 @@ the return value is nil. Otherwise the value is t. */) | |||
| 6283 | /* Now, free glyph matrices in windows that were not reused. */ | 6385 | /* Now, free glyph matrices in windows that were not reused. */ |
| 6284 | for (i = 0; i < n_leaf_windows; i++) | 6386 | for (i = 0; i < n_leaf_windows; i++) |
| 6285 | if (NILP (leaf_windows[i]->contents)) | 6387 | if (NILP (leaf_windows[i]->contents)) |
| 6286 | free_window_matrices (leaf_windows[i]); | 6388 | { |
| 6389 | free_window_matrices (leaf_windows[i]); | ||
| 6390 | window_changed = true; | ||
| 6391 | } | ||
| 6287 | 6392 | ||
| 6288 | /* Allow x_set_window_size again and apply frame size changes if | 6393 | /* Allow x_set_window_size again and apply frame size changes if |
| 6289 | needed. */ | 6394 | needed. */ |
| @@ -6303,7 +6408,8 @@ the return value is nil. Otherwise the value is t. */) | |||
| 6303 | 6408 | ||
| 6304 | /* Record the selected window's buffer here. The window should | 6409 | /* Record the selected window's buffer here. The window should |
| 6305 | already be the selected one from the call above. */ | 6410 | already be the selected one from the call above. */ |
| 6306 | select_window (data->current_window, Qnil, false); | 6411 | if (WINDOW_LIVE_P (data->current_window)) |
| 6412 | select_window (data->current_window, Qnil, false); | ||
| 6307 | 6413 | ||
| 6308 | /* Fselect_window will have made f the selected frame, so we | 6414 | /* Fselect_window will have made f the selected frame, so we |
| 6309 | reselect the proper frame here. Fhandle_switch_frame will change the | 6415 | reselect the proper frame here. Fhandle_switch_frame will change the |
| @@ -6313,7 +6419,32 @@ the return value is nil. Otherwise the value is t. */) | |||
| 6313 | if (FRAME_LIVE_P (XFRAME (data->selected_frame))) | 6419 | if (FRAME_LIVE_P (XFRAME (data->selected_frame))) |
| 6314 | do_switch_frame (data->selected_frame, 0, 0, Qnil); | 6420 | do_switch_frame (data->selected_frame, 0, 0, Qnil); |
| 6315 | 6421 | ||
| 6316 | run_window_configuration_change_hook (f); | 6422 | if (window_changed) |
| 6423 | /* At least one window has been added or removed. Run | ||
| 6424 | `window-configuration-change-hook' and make sure | ||
| 6425 | `window-size-change-functions' get run later. | ||
| 6426 | |||
| 6427 | We have to do this in order to capture the following | ||
| 6428 | scenario: Suppose our frame contains two live windows W1 and | ||
| 6429 | W2 and ‘set-window-configuration’ replaces them by two | ||
| 6430 | windows W3 and W4 that were dead the last time | ||
| 6431 | run_window_size_change_functions was run. If W3 and W4 have | ||
| 6432 | the same values for their old and new pixel sizes but these | ||
| 6433 | values differ from those of W1 and W2, the sizes of our | ||
| 6434 | frame's two live windows changed but window_size_changed has | ||
| 6435 | no means to detect that fact. | ||
| 6436 | |||
| 6437 | Obviously, this will get us false positives, for example, | ||
| 6438 | when we restore the original configuration with W1 and W2 | ||
| 6439 | before run_window_size_change_functions gets called. */ | ||
| 6440 | { | ||
| 6441 | run_window_configuration_change_hook (f); | ||
| 6442 | FRAME_WINDOW_CONFIGURATION_CHANGED (f) = true; | ||
| 6443 | } | ||
| 6444 | else if (buffer_changed) | ||
| 6445 | /* At least one window has changed its buffer. Run | ||
| 6446 | `window-configuration-change-hook' only. */ | ||
| 6447 | run_window_configuration_change_hook (f); | ||
| 6317 | } | 6448 | } |
| 6318 | 6449 | ||
| 6319 | if (!NILP (new_current_buffer)) | 6450 | if (!NILP (new_current_buffer)) |
| @@ -6464,6 +6595,10 @@ save_window_save (Lisp_Object window, struct Lisp_Vector *vector, ptrdiff_t i) | |||
| 6464 | p->pixel_top = make_number (w->pixel_top); | 6595 | p->pixel_top = make_number (w->pixel_top); |
| 6465 | p->pixel_width = make_number (w->pixel_width); | 6596 | p->pixel_width = make_number (w->pixel_width); |
| 6466 | p->pixel_height = make_number (w->pixel_height); | 6597 | p->pixel_height = make_number (w->pixel_height); |
| 6598 | p->pixel_width_before_size_change | ||
| 6599 | = make_number (w->pixel_width_before_size_change); | ||
| 6600 | p->pixel_height_before_size_change | ||
| 6601 | = make_number (w->pixel_height_before_size_change); | ||
| 6467 | p->left_col = make_number (w->left_col); | 6602 | p->left_col = make_number (w->left_col); |
| 6468 | p->top_line = make_number (w->top_line); | 6603 | p->top_line = make_number (w->top_line); |
| 6469 | p->total_cols = make_number (w->total_cols); | 6604 | p->total_cols = make_number (w->total_cols); |
| @@ -7246,6 +7381,16 @@ selected; while the global part is run only once for the modified frame, | |||
| 7246 | with the relevant frame selected. */); | 7381 | with the relevant frame selected. */); |
| 7247 | Vwindow_configuration_change_hook = Qnil; | 7382 | Vwindow_configuration_change_hook = Qnil; |
| 7248 | 7383 | ||
| 7384 | DEFVAR_LISP ("window-size-change-functions", Vwindow_size_change_functions, | ||
| 7385 | doc: /* Functions called during redisplay, if window sizes have changed. | ||
| 7386 | The value should be a list of functions that take one argument. | ||
| 7387 | During the first part of redisplay, for each frame, if any of its windows | ||
| 7388 | have changed size since the last redisplay, or have been split or deleted, | ||
| 7389 | all the functions in the list are called, with the frame as argument. | ||
| 7390 | If redisplay decides to resize the minibuffer window, it calls these | ||
| 7391 | functions on behalf of that as well. */); | ||
| 7392 | Vwindow_size_change_functions = Qnil; | ||
| 7393 | |||
| 7249 | DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay, | 7394 | DEFVAR_LISP ("recenter-redisplay", Vrecenter_redisplay, |
| 7250 | doc: /* Non-nil means `recenter' redraws entire frame. | 7395 | doc: /* Non-nil means `recenter' redraws entire frame. |
| 7251 | If this option is non-nil, then the `recenter' command with a nil | 7396 | If this option is non-nil, then the `recenter' command with a nil |
| @@ -7374,6 +7519,8 @@ displayed after a scrolling operation to be somewhat inaccurate. */); | |||
| 7374 | defsubr (&Swindow_use_time); | 7519 | defsubr (&Swindow_use_time); |
| 7375 | defsubr (&Swindow_pixel_width); | 7520 | defsubr (&Swindow_pixel_width); |
| 7376 | defsubr (&Swindow_pixel_height); | 7521 | defsubr (&Swindow_pixel_height); |
| 7522 | defsubr (&Swindow_pixel_width_before_size_change); | ||
| 7523 | defsubr (&Swindow_pixel_height_before_size_change); | ||
| 7377 | defsubr (&Swindow_total_width); | 7524 | defsubr (&Swindow_total_width); |
| 7378 | defsubr (&Swindow_total_height); | 7525 | defsubr (&Swindow_total_height); |
| 7379 | defsubr (&Swindow_normal_size); | 7526 | defsubr (&Swindow_normal_size); |
diff --git a/src/window.h b/src/window.h index c29207d6356..a4d4dfe3ff4 100644 --- a/src/window.h +++ b/src/window.h | |||
| @@ -214,6 +214,11 @@ struct window | |||
| 214 | int pixel_width; | 214 | int pixel_width; |
| 215 | int pixel_height; | 215 | int pixel_height; |
| 216 | 216 | ||
| 217 | /* The pixel sizes of the window at the last time | ||
| 218 | `window-size-change-functions' was run. */ | ||
| 219 | int pixel_width_before_size_change; | ||
| 220 | int pixel_height_before_size_change; | ||
| 221 | |||
| 217 | /* The size of the window. */ | 222 | /* The size of the window. */ |
| 218 | int total_cols; | 223 | int total_cols; |
| 219 | int total_lines; | 224 | int total_lines; |
| @@ -499,15 +504,17 @@ wset_next_buffers (struct window *w, Lisp_Object val) | |||
| 499 | #define WINDOW_LEAF_P(W) \ | 504 | #define WINDOW_LEAF_P(W) \ |
| 500 | (BUFFERP ((W)->contents)) | 505 | (BUFFERP ((W)->contents)) |
| 501 | 506 | ||
| 502 | /* True if W is a member of horizontal combination. */ | 507 | /* Non-nil if W is internal. */ |
| 508 | #define WINDOW_INTERNAL_P(W) \ | ||
| 509 | (WINDOWP ((W)->contents)) | ||
| 503 | 510 | ||
| 511 | /* True if W is a member of horizontal combination. */ | ||
| 504 | #define WINDOW_HORIZONTAL_COMBINATION_P(W) \ | 512 | #define WINDOW_HORIZONTAL_COMBINATION_P(W) \ |
| 505 | (WINDOWP ((W)->contents) && (W)->horizontal) | 513 | (WINDOW_INTERNAL_P (W) && (W)->horizontal) |
| 506 | 514 | ||
| 507 | /* True if W is a member of vertical combination. */ | 515 | /* True if W is a member of vertical combination. */ |
| 508 | |||
| 509 | #define WINDOW_VERTICAL_COMBINATION_P(W) \ | 516 | #define WINDOW_VERTICAL_COMBINATION_P(W) \ |
| 510 | (WINDOWP ((W)->contents) && !(W)->horizontal) | 517 | (WINDOW_INTERNAL_P (W) && !(W)->horizontal) |
| 511 | 518 | ||
| 512 | /* WINDOW's XFRAME. */ | 519 | /* WINDOW's XFRAME. */ |
| 513 | #define WINDOW_XFRAME(W) (XFRAME (WINDOW_FRAME ((W)))) | 520 | #define WINDOW_XFRAME(W) (XFRAME (WINDOW_FRAME ((W)))) |
| @@ -1014,6 +1021,7 @@ extern void shrink_mini_window (struct window *, bool); | |||
| 1014 | extern int window_relative_x_coord (struct window *, enum window_part, int); | 1021 | extern int window_relative_x_coord (struct window *, enum window_part, int); |
| 1015 | 1022 | ||
| 1016 | void run_window_configuration_change_hook (struct frame *f); | 1023 | void run_window_configuration_change_hook (struct frame *f); |
| 1024 | void run_window_size_change_functions (Lisp_Object); | ||
| 1017 | 1025 | ||
| 1018 | /* Make WINDOW display BUFFER. RUN_HOOKS_P means it's allowed | 1026 | /* Make WINDOW display BUFFER. RUN_HOOKS_P means it's allowed |
| 1019 | to run hooks. See make_frame for a case where it's not allowed. */ | 1027 | 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 fed58799eaa..4330f106002 100644 --- a/src/xdisp.c +++ b/src/xdisp.c | |||
| @@ -11786,24 +11786,7 @@ prepare_menu_bars (void) | |||
| 11786 | && !XBUFFER (w->contents)->text->redisplay) | 11786 | && !XBUFFER (w->contents)->text->redisplay) |
| 11787 | continue; | 11787 | continue; |
| 11788 | 11788 | ||
| 11789 | /* If a window on this frame changed size, report that to | 11789 | run_window_size_change_functions (frame); |
| 11790 | the user and clear the size-change flag. */ | ||
| 11791 | if (FRAME_WINDOW_SIZES_CHANGED (f)) | ||
| 11792 | { | ||
| 11793 | Lisp_Object functions; | ||
| 11794 | |||
| 11795 | /* Clear flag first in case we get an error below. */ | ||
| 11796 | FRAME_WINDOW_SIZES_CHANGED (f) = false; | ||
| 11797 | functions = Vwindow_size_change_functions; | ||
| 11798 | |||
| 11799 | while (CONSP (functions)) | ||
| 11800 | { | ||
| 11801 | if (!EQ (XCAR (functions), Qt)) | ||
| 11802 | call1 (XCAR (functions), frame); | ||
| 11803 | functions = XCDR (functions); | ||
| 11804 | } | ||
| 11805 | } | ||
| 11806 | |||
| 11807 | menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run); | 11790 | menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run); |
| 11808 | #ifdef HAVE_WINDOW_SYSTEM | 11791 | #ifdef HAVE_WINDOW_SYSTEM |
| 11809 | update_tool_bar (f, false); | 11792 | update_tool_bar (f, false); |
| @@ -13599,24 +13582,12 @@ redisplay_internal (void) | |||
| 13599 | it's too late for the hooks in window-size-change-functions, | 13582 | it's too late for the hooks in window-size-change-functions, |
| 13600 | which have been examined already in prepare_menu_bars. So in | 13583 | which have been examined already in prepare_menu_bars. So in |
| 13601 | that case we call the hooks here only for the selected frame. */ | 13584 | that case we call the hooks here only for the selected frame. */ |
| 13602 | if (sf->redisplay && FRAME_WINDOW_SIZES_CHANGED (sf)) | 13585 | if (sf->redisplay) |
| 13603 | { | 13586 | { |
| 13604 | Lisp_Object functions; | ||
| 13605 | ptrdiff_t count1 = SPECPDL_INDEX (); | 13587 | ptrdiff_t count1 = SPECPDL_INDEX (); |
| 13606 | 13588 | ||
| 13607 | record_unwind_save_match_data (); | 13589 | record_unwind_save_match_data (); |
| 13608 | 13590 | run_window_size_change_functions (selected_frame); | |
| 13609 | /* Clear flag first in case we get an error below. */ | ||
| 13610 | FRAME_WINDOW_SIZES_CHANGED (sf) = false; | ||
| 13611 | functions = Vwindow_size_change_functions; | ||
| 13612 | |||
| 13613 | while (CONSP (functions)) | ||
| 13614 | { | ||
| 13615 | if (!EQ (XCAR (functions), Qt)) | ||
| 13616 | call1 (XCAR (functions), selected_frame); | ||
| 13617 | functions = XCDR (functions); | ||
| 13618 | } | ||
| 13619 | |||
| 13620 | unbind_to (count1, Qnil); | 13591 | unbind_to (count1, Qnil); |
| 13621 | } | 13592 | } |
| 13622 | 13593 | ||
| @@ -13638,22 +13609,10 @@ redisplay_internal (void) | |||
| 13638 | { | 13609 | { |
| 13639 | if (sf->redisplay) | 13610 | if (sf->redisplay) |
| 13640 | { | 13611 | { |
| 13641 | Lisp_Object functions; | ||
| 13642 | ptrdiff_t count1 = SPECPDL_INDEX (); | 13612 | ptrdiff_t count1 = SPECPDL_INDEX (); |
| 13643 | 13613 | ||
| 13644 | record_unwind_save_match_data (); | 13614 | record_unwind_save_match_data (); |
| 13645 | 13615 | run_window_size_change_functions (selected_frame); | |
| 13646 | /* Clear flag first in case we get an error below. */ | ||
| 13647 | FRAME_WINDOW_SIZES_CHANGED (sf) = false; | ||
| 13648 | functions = Vwindow_size_change_functions; | ||
| 13649 | |||
| 13650 | while (CONSP (functions)) | ||
| 13651 | { | ||
| 13652 | if (!EQ (XCAR (functions), Qt)) | ||
| 13653 | call1 (XCAR (functions), selected_frame); | ||
| 13654 | functions = XCDR (functions); | ||
| 13655 | } | ||
| 13656 | |||
| 13657 | unbind_to (count1, Qnil); | 13616 | unbind_to (count1, Qnil); |
| 13658 | } | 13617 | } |
| 13659 | 13618 | ||
| @@ -31447,16 +31406,6 @@ If nil, disable message logging. If t, log messages but don't truncate | |||
| 31447 | the buffer when it becomes large. */); | 31406 | the buffer when it becomes large. */); |
| 31448 | Vmessage_log_max = make_number (1000); | 31407 | Vmessage_log_max = make_number (1000); |
| 31449 | 31408 | ||
| 31450 | DEFVAR_LISP ("window-size-change-functions", Vwindow_size_change_functions, | ||
| 31451 | doc: /* Functions called during redisplay, if window sizes have changed. | ||
| 31452 | The value should be a list of functions that take one argument. | ||
| 31453 | During the first part of redisplay, for each frame, if any of its windows | ||
| 31454 | have changed size since the last redisplay, or have been split or deleted, | ||
| 31455 | all the functions in the list are called, with the frame as argument. | ||
| 31456 | If redisplay decides to resize the minibuffer window, it calls these | ||
| 31457 | functions on behalf of that as well. */); | ||
| 31458 | Vwindow_size_change_functions = Qnil; | ||
| 31459 | |||
| 31460 | DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions, | 31409 | DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions, |
| 31461 | doc: /* List of functions to call before redisplaying a window with scrolling. | 31410 | doc: /* List of functions to call before redisplaying a window with scrolling. |
| 31462 | Each function is called with two arguments, the window and its new | 31411 | Each function is called with two arguments, the window and its new |
diff --git a/src/xfns.c b/src/xfns.c index 20ac6271715..2a50a5a5f99 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) | |||
| 1313 | } | 1313 | } |
| 1314 | #endif /* not USE_X_TOOLKIT && not USE_GTK */ | 1314 | #endif /* not USE_X_TOOLKIT && not USE_GTK */ |
| 1315 | adjust_frame_glyphs (f); | 1315 | adjust_frame_glyphs (f); |
| 1316 | run_window_configuration_change_hook (f); | ||
| 1317 | } | 1316 | } |
| 1318 | 1317 | ||
| 1319 | 1318 | ||