mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	fix(window): skip unfocusable and hidden floats with "{count}<C-W>w" #33810
Problem: Using `<C-W>w`, `<C-W>W` or the ":wincmd" variants with a count can
enter unfocusable or hidden floating windows. This is especially problematic
when using the new in-development extui, which creates many unfocusable floats
for various UI elements.
Solution: Skip unfocusable and hidden floating windows. Instead, skip to the
next focusable, non-hidden window in the current tabpage's window list. Reword
the documentation a bit (hopefully an improvement?)
(cherry picked from commit 403fcacfc1)
			
			
This commit is contained in:
		 Sean Dewar
					Sean Dewar
				
			
				
					committed by
					
						![github-actions[bot]](/assets/img/avatar_default.png) github-actions[bot]
						github-actions[bot]
					
				
			
			
				
	
			
			
			![github-actions[bot]](/assets/img/avatar_default.png) github-actions[bot]
						github-actions[bot]
					
				
			
						parent
						
							4e43264cd3
						
					
				
				
					commit
					9b3426691c
				
			| @@ -439,18 +439,17 @@ CTRL-W l	Move cursor to Nth window right of current one.  Uses the | |||||||
|  |  | ||||||
| CTRL-W w					*CTRL-W_w* *CTRL-W_CTRL-W* | CTRL-W w					*CTRL-W_w* *CTRL-W_CTRL-W* | ||||||
| CTRL-W CTRL-W	Without count: move cursor to the |focusable| window | CTRL-W CTRL-W	Without count: move cursor to the |focusable| window | ||||||
| 		below/right of the current one.  If there is no (focusable) | 		below/right of the current one.  If none, go to the top-left | ||||||
| 		window below or right, go to top-left window. With count: go | 		window.  With count: go to Nth window (numbered top-left to | ||||||
| 		to Nth window (windows are numbered from top-left to | 		bottom-right), skipping unfocusable windows.  To obtain the | ||||||
| 		bottom-right).  To obtain the window number see |bufwinnr()| | 		window number see |bufwinnr()| and |winnr()|.  When N is | ||||||
| 		and |winnr()|.  When N is larger than the number of windows go | 		larger than the number of windows go to the last focusable | ||||||
| 		to the last window. | 		window. | ||||||
|  |  | ||||||
| 						*CTRL-W_W* | 						*CTRL-W_W* | ||||||
| CTRL-W W	Without count: move cursor to the |focusable| window | CTRL-W W	Without count: move cursor to the |focusable| window | ||||||
| 		above/left of current one.  If there is no window above or | 		above/left of current one.  If none, go to the bottom-right | ||||||
| 		left, go to bottom-right window.  With count: go to Nth | 		window.  With count: go to Nth window, like CTRL-W w. | ||||||
| 		window, like with CTRL-W w. |  | ||||||
|  |  | ||||||
| CTRL-W t					*CTRL-W_t* *CTRL-W_CTRL-T* | CTRL-W t					*CTRL-W_t* *CTRL-W_CTRL-T* | ||||||
| CTRL-W CTRL-T	Move cursor to top-left window. | CTRL-W CTRL-T	Move cursor to top-left window. | ||||||
|   | |||||||
| @@ -347,12 +347,23 @@ newwindow: | |||||||
|     } else { |     } else { | ||||||
|       win_T *wp; |       win_T *wp; | ||||||
|       if (Prenum) {  // go to specified window |       if (Prenum) {  // go to specified window | ||||||
|  |         win_T *last_focusable = firstwin; | ||||||
|         for (wp = firstwin; --Prenum > 0;) { |         for (wp = firstwin; --Prenum > 0;) { | ||||||
|  |           if (!wp->w_floating || (!wp->w_config.hide && wp->w_config.focusable)) { | ||||||
|  |             last_focusable = wp; | ||||||
|  |           } | ||||||
|           if (wp->w_next == NULL) { |           if (wp->w_next == NULL) { | ||||||
|             break; |             break; | ||||||
|           } |           } | ||||||
|           wp = wp->w_next; |           wp = wp->w_next; | ||||||
|         } |         } | ||||||
|  |         while (wp != NULL && wp->w_floating | ||||||
|  |                && (wp->w_config.hide || !wp->w_config.focusable)) { | ||||||
|  |           wp = wp->w_next; | ||||||
|  |         } | ||||||
|  |         if (wp == NULL) {  // went past the last focusable window | ||||||
|  |           wp = last_focusable; | ||||||
|  |         } | ||||||
|       } else { |       } else { | ||||||
|         if (nchar == 'W') {  // go to previous window |         if (nchar == 'W') {  // go to previous window | ||||||
|           wp = curwin->w_prev; |           wp = curwin->w_prev; | ||||||
|   | |||||||
| @@ -5632,6 +5632,59 @@ describe('float window', function() | |||||||
|                                                     | |                                                     | | ||||||
|           ]]) |           ]]) | ||||||
|         end |         end | ||||||
|  |  | ||||||
|  |         api.nvim_open_win( | ||||||
|  |           0, | ||||||
|  |           false, | ||||||
|  |           { relative = "editor", width = 1, height = 1, row = 0, col = 0 } | ||||||
|  |         ) | ||||||
|  |         api.nvim_open_win( | ||||||
|  |           0, | ||||||
|  |           false, | ||||||
|  |           { relative = "editor", width = 1, height = 1, row = 0, col = 0, focusable = false } | ||||||
|  |         ) | ||||||
|  |         api.nvim_open_win( | ||||||
|  |           0, | ||||||
|  |           false, | ||||||
|  |           { relative = "editor", width = 1, height = 1, row = 0, col = 0, focusable = false } | ||||||
|  |         ) | ||||||
|  |         api.nvim_open_win( | ||||||
|  |           0, | ||||||
|  |           false, | ||||||
|  |           { relative = "editor", width = 1, height = 1, row = 0, col = 0, focusable = true } | ||||||
|  |         ) | ||||||
|  |         api.nvim_open_win( | ||||||
|  |           0, | ||||||
|  |           false, | ||||||
|  |           { relative = "editor", width = 1, height = 1, row = 0, col = 0, focusable = false } | ||||||
|  |         ) | ||||||
|  |         local nr_focusable = {} | ||||||
|  |         for nr = 1, fn.winnr("$") do | ||||||
|  |           table.insert(nr_focusable, api.nvim_win_get_config(fn.win_getid(nr)).focusable) | ||||||
|  |         end | ||||||
|  |         eq({true, false, true, false, false, true, false}, nr_focusable) | ||||||
|  |  | ||||||
|  |         command("1wincmd w") | ||||||
|  |         eq(1, fn.winnr()) | ||||||
|  |         command("2wincmd w") | ||||||
|  |         eq(3, fn.winnr()) | ||||||
|  |         command("3wincmd w") | ||||||
|  |         eq(3, fn.winnr()) | ||||||
|  |         command("4wincmd w") | ||||||
|  |         eq(6, fn.winnr()) | ||||||
|  |         command("5wincmd w") | ||||||
|  |         eq(6, fn.winnr()) | ||||||
|  |         command("6wincmd w") | ||||||
|  |         eq(6, fn.winnr()) | ||||||
|  |         command("7wincmd w") | ||||||
|  |         eq(6, fn.winnr()) | ||||||
|  |  | ||||||
|  |         feed("1<c-w>w") | ||||||
|  |         eq(1, fn.winnr()) | ||||||
|  |         feed("2<c-w>w") | ||||||
|  |         eq(3, fn.winnr()) | ||||||
|  |         feed("999<c-w>w") | ||||||
|  |         eq(6, fn.winnr()) | ||||||
|       end) |       end) | ||||||
|  |  | ||||||
|       it("W", function() |       it("W", function() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user