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