Mercurial > vim
comparison src/window.c @ 31146:f6d4c6a3b41c v9.0.0907
patch 9.0.0907: restoring window after WinScrolled may fail
Commit: https://github.com/vim/vim/commit/d63a85592cef0ee4f0fec5efe2f8d66b31f01f05
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Nov 19 11:41:30 2022 +0000
patch 9.0.0907: restoring window after WinScrolled may fail
Problem: Restoring window after WinScrolled may fail.
Solution: Lock the window layout when triggering WinScrolled.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 19 Nov 2022 12:45:04 +0100 |
parents | eb51299c4bfc |
children | bcda71c89776 |
comparison
equal
deleted
inserted
replaced
31145:500ebbee148d | 31146:f6d4c6a3b41c |
---|---|
81 static char *m_onlyone = N_("Already only one window"); | 81 static char *m_onlyone = N_("Already only one window"); |
82 | 82 |
83 // When non-zero splitting a window is forbidden. Used to avoid that nasty | 83 // When non-zero splitting a window is forbidden. Used to avoid that nasty |
84 // autocommands mess up the window structure. | 84 // autocommands mess up the window structure. |
85 static int split_disallowed = 0; | 85 static int split_disallowed = 0; |
86 | |
87 // When non-zero closing a window is forbidden. Used to avoid that nasty | |
88 // autocommands mess up the window structure. | |
89 static int close_disallowed = 0; | |
90 | |
91 /* | |
92 * Disallow changing the window layout (split window, close window, move | |
93 * window). Resizing is still allowed. | |
94 * Used for autocommands that temporarily use another window and need to | |
95 * make sure the previously selected window is still there. | |
96 * Must be matched with exactly one call to window_layout_unlock()! | |
97 */ | |
98 static void | |
99 window_layout_lock(void) | |
100 { | |
101 ++split_disallowed; | |
102 ++close_disallowed; | |
103 } | |
104 | |
105 static void | |
106 window_layout_unlock(void) | |
107 { | |
108 --split_disallowed; | |
109 --close_disallowed; | |
110 } | |
111 | |
112 /* | |
113 * When the window layout cannot be changed give an error and return TRUE. | |
114 */ | |
115 int | |
116 window_layout_locked(void) | |
117 { | |
118 if (split_disallowed > 0 || close_disallowed > 0) | |
119 { | |
120 if (close_disallowed == 0) | |
121 emsg(_(e_cannot_split_window_when_closing_buffer)); | |
122 else | |
123 emsg(_(e_not_allowed_to_change_window_layout_in_this_autocmd)); | |
124 return TRUE; | |
125 } | |
126 return FALSE; | |
127 } | |
86 | 128 |
87 // #define WIN_DEBUG | 129 // #define WIN_DEBUG |
88 #ifdef WIN_DEBUG | 130 #ifdef WIN_DEBUG |
89 /* | 131 /* |
90 * Call this method to log the current window layout. | 132 * Call this method to log the current window layout. |
2529 if (last_window()) | 2571 if (last_window()) |
2530 { | 2572 { |
2531 emsg(_(e_cannot_close_last_window)); | 2573 emsg(_(e_cannot_close_last_window)); |
2532 return FAIL; | 2574 return FAIL; |
2533 } | 2575 } |
2576 if (window_layout_locked()) | |
2577 return FAIL; | |
2534 | 2578 |
2535 if (win->w_closing || (win->w_buffer != NULL | 2579 if (win->w_closing || (win->w_buffer != NULL |
2536 && win->w_buffer->b_locked > 0)) | 2580 && win->w_buffer->b_locked > 0)) |
2537 return FAIL; // window is already being closed | 2581 return FAIL; // window is already being closed |
2538 if (win_unlisted(win)) | 2582 if (win_unlisted(win)) |
2800 * Trigger WinScrolled for "curwin" if needed. | 2844 * Trigger WinScrolled for "curwin" if needed. |
2801 */ | 2845 */ |
2802 void | 2846 void |
2803 may_trigger_winscrolled(void) | 2847 may_trigger_winscrolled(void) |
2804 { | 2848 { |
2805 win_T *wp = curwin; | |
2806 static int recursive = FALSE; | 2849 static int recursive = FALSE; |
2807 char_u winid[NUMBUFLEN]; | |
2808 | 2850 |
2809 if (recursive || !has_winscrolled()) | 2851 if (recursive || !has_winscrolled()) |
2810 return; | 2852 return; |
2811 | 2853 |
2854 win_T *wp = curwin; | |
2812 if (wp->w_last_topline != wp->w_topline | 2855 if (wp->w_last_topline != wp->w_topline |
2813 || wp->w_last_leftcol != wp->w_leftcol | 2856 || wp->w_last_leftcol != wp->w_leftcol |
2814 || wp->w_last_skipcol != wp->w_skipcol | 2857 || wp->w_last_skipcol != wp->w_skipcol |
2815 || wp->w_last_width != wp->w_width | 2858 || wp->w_last_width != wp->w_width |
2816 || wp->w_last_height != wp->w_height) | 2859 || wp->w_last_height != wp->w_height) |
2817 { | 2860 { |
2861 // "curwin" may be different from the actual current window, make sure | |
2862 // it can be restored. | |
2863 window_layout_lock(); | |
2864 | |
2865 recursive = TRUE; | |
2866 char_u winid[NUMBUFLEN]; | |
2818 vim_snprintf((char *)winid, sizeof(winid), "%d", wp->w_id); | 2867 vim_snprintf((char *)winid, sizeof(winid), "%d", wp->w_id); |
2819 | |
2820 recursive = TRUE; | |
2821 apply_autocmds(EVENT_WINSCROLLED, winid, winid, FALSE, wp->w_buffer); | 2868 apply_autocmds(EVENT_WINSCROLLED, winid, winid, FALSE, wp->w_buffer); |
2822 recursive = FALSE; | 2869 recursive = FALSE; |
2870 window_layout_unlock(); | |
2823 | 2871 |
2824 // an autocmd may close the window, "wp" may be invalid now | 2872 // an autocmd may close the window, "wp" may be invalid now |
2825 if (win_valid_any_tab(wp)) | 2873 if (win_valid_any_tab(wp)) |
2826 { | 2874 { |
2827 wp->w_last_topline = wp->w_topline; | 2875 wp->w_last_topline = wp->w_topline; |
4012 if (cmdwin_type != 0) | 4060 if (cmdwin_type != 0) |
4013 { | 4061 { |
4014 emsg(_(e_invalid_in_cmdline_window)); | 4062 emsg(_(e_invalid_in_cmdline_window)); |
4015 return FAIL; | 4063 return FAIL; |
4016 } | 4064 } |
4065 if (window_layout_locked()) | |
4066 return FAIL; | |
4017 | 4067 |
4018 newtp = alloc_tabpage(); | 4068 newtp = alloc_tabpage(); |
4019 if (newtp == NULL) | 4069 if (newtp == NULL) |
4020 return FAIL; | 4070 return FAIL; |
4021 | 4071 |