mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	vim-patch:9.1.0491: Cmdline pum doesn't work properly with 'rightleft' (#29355)
Problem:  Cmdline pum doesn't work properly with 'rightleft'.
Solution: Don't use curwin->w_p_rl in cmdline mode in pum_redraw().  Use
          a static variable since pum_may_redraw() may be called in any
          mode.  Also correct position of other popups with 'rightleft'.
          (zeertzjq)
closes: vim/vim#15005
883018feff
			
			
This commit is contained in:
		| @@ -143,7 +143,7 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i | |||||||
|                    || (State == MODE_CMDLINE && ui_has(kUIWildmenu)); |                    || (State == MODE_CMDLINE && ui_has(kUIWildmenu)); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   pum_rl = (curwin->w_p_rl && State != MODE_CMDLINE); |   pum_rl = State != MODE_CMDLINE && curwin->w_p_rl; | ||||||
|  |  | ||||||
|   do { |   do { | ||||||
|     // Mark the pum as visible already here, |     // Mark the pum as visible already here, | ||||||
| @@ -450,7 +450,7 @@ static void pum_puts_with_attr(int col, char *text, hlf_T hlf) | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   char *rt_leader = NULL; |   char *rt_leader = NULL; | ||||||
|   if (curwin->w_p_rl) { |   if (pum_rl) { | ||||||
|     rt_leader = reverse_text(leader); |     rt_leader = reverse_text(leader); | ||||||
|   } |   } | ||||||
|   char *match_leader = rt_leader != NULL ? rt_leader : leader; |   char *match_leader = rt_leader != NULL ? rt_leader : leader; | ||||||
| @@ -1212,12 +1212,14 @@ void pum_set_event_info(dict_T *dict) | |||||||
| static void pum_position_at_mouse(int min_width) | static void pum_position_at_mouse(int min_width) | ||||||
| { | { | ||||||
|   int min_row = 0; |   int min_row = 0; | ||||||
|  |   int min_col = 0; | ||||||
|   int max_row = Rows; |   int max_row = Rows; | ||||||
|   int max_col = Columns; |   int max_col = Columns; | ||||||
|   if (mouse_grid > 1) { |   if (mouse_grid > 1) { | ||||||
|     win_T *wp = get_win_by_grid_handle(mouse_grid); |     win_T *wp = get_win_by_grid_handle(mouse_grid); | ||||||
|     if (wp != NULL) { |     if (wp != NULL) { | ||||||
|       min_row = -wp->w_winrow; |       min_row = -wp->w_winrow; | ||||||
|  |       min_col = -wp->w_wincol; | ||||||
|       max_row = MAX(Rows - wp->w_winrow, wp->w_grid.rows); |       max_row = MAX(Rows - wp->w_winrow, wp->w_grid.rows); | ||||||
|       max_col = MAX(Columns - wp->w_wincol, wp->w_grid.cols); |       max_col = MAX(Columns - wp->w_wincol, wp->w_grid.cols); | ||||||
|     } |     } | ||||||
| @@ -1230,6 +1232,7 @@ static void pum_position_at_mouse(int min_width) | |||||||
|   } else { |   } else { | ||||||
|     pum_anchor_grid = mouse_grid; |     pum_anchor_grid = mouse_grid; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (max_row - mouse_row > pum_size) { |   if (max_row - mouse_row > pum_size) { | ||||||
|     // Enough space below the mouse row. |     // Enough space below the mouse row. | ||||||
|     pum_above = false; |     pum_above = false; | ||||||
| @@ -1246,16 +1249,29 @@ static void pum_position_at_mouse(int min_width) | |||||||
|       pum_row = min_row; |       pum_row = min_row; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   if (max_col - mouse_col >= pum_base_width |  | ||||||
|       || max_col - mouse_col > min_width) { |   if (pum_rl) { | ||||||
|     // Enough space to show at mouse column. |     if (mouse_col - min_col + 1 >= pum_base_width | ||||||
|     pum_col = mouse_col; |         || mouse_col - min_col + 1 > min_width) { | ||||||
|  |       // Enough space to show at mouse column. | ||||||
|  |       pum_col = mouse_col; | ||||||
|  |     } else { | ||||||
|  |       // Not enough space, left align with window. | ||||||
|  |       pum_col = min_col + MIN(pum_base_width, min_width) - 1; | ||||||
|  |     } | ||||||
|  |     pum_width = pum_col - min_col + 1; | ||||||
|   } else { |   } else { | ||||||
|     // Not enough space, right align with window. |     if (max_col - mouse_col >= pum_base_width | ||||||
|     pum_col = max_col - (pum_base_width > min_width ? min_width : pum_base_width); |         || max_col - mouse_col > min_width) { | ||||||
|  |       // Enough space to show at mouse column. | ||||||
|  |       pum_col = mouse_col; | ||||||
|  |     } else { | ||||||
|  |       // Not enough space, right align with window. | ||||||
|  |       pum_col = max_col - MIN(pum_base_width, min_width); | ||||||
|  |     } | ||||||
|  |     pum_width = max_col - pum_col; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   pum_width = max_col - pum_col; |  | ||||||
|   if (pum_width > pum_base_width + 1) { |   if (pum_width > pum_base_width + 1) { | ||||||
|     pum_width = pum_base_width + 1; |     pum_width = pum_base_width + 1; | ||||||
|   } |   } | ||||||
| @@ -1337,6 +1353,7 @@ void pum_show_popupmenu(vimmenu_T *menu) | |||||||
|   pum_compute_size(); |   pum_compute_size(); | ||||||
|   pum_scrollbar = 0; |   pum_scrollbar = 0; | ||||||
|   pum_height = pum_size; |   pum_height = pum_size; | ||||||
|  |   pum_rl = curwin->w_p_rl; | ||||||
|   pum_position_at_mouse(20); |   pum_position_at_mouse(20); | ||||||
|  |  | ||||||
|   pum_selected = -1; |   pum_selected = -1; | ||||||
| @@ -1416,7 +1433,9 @@ void pum_make_popup(const char *path_name, int use_mouse_pos) | |||||||
|     // Hack: set mouse position at the cursor so that the menu pops up |     // Hack: set mouse position at the cursor so that the menu pops up | ||||||
|     // around there. |     // around there. | ||||||
|     mouse_row = curwin->w_grid.row_offset + curwin->w_wrow; |     mouse_row = curwin->w_grid.row_offset + curwin->w_wrow; | ||||||
|     mouse_col = curwin->w_grid.col_offset + curwin->w_wcol; |     mouse_col = curwin->w_grid.col_offset | ||||||
|  |                 + (curwin->w_p_rl ? curwin->w_width_inner - curwin->w_wcol - 1 | ||||||
|  |                                   : curwin->w_wcol); | ||||||
|     if (ui_has(kUIMultigrid)) { |     if (ui_has(kUIMultigrid)) { | ||||||
|       mouse_grid = curwin->w_grid.target->handle; |       mouse_grid = curwin->w_grid.target->handle; | ||||||
|     } else if (curwin->w_grid.target != &default_grid) { |     } else if (curwin->w_grid.target != &default_grid) { | ||||||
|   | |||||||
| @@ -2530,6 +2530,7 @@ describe('builtin popupmenu', function() | |||||||
|         ]], |         ]], | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         -- oldtest: Test_wildmenu_pum_rightleft() | ||||||
|         feed('<tab>') |         feed('<tab>') | ||||||
|         screen:expect { |         screen:expect { | ||||||
|           grid = [[ |           grid = [[ | ||||||
| @@ -4479,6 +4480,27 @@ describe('builtin popupmenu', function() | |||||||
|  |  | ||||||
|         feed('<Esc>') |         feed('<Esc>') | ||||||
|  |  | ||||||
|  |         command('set rightleft') | ||||||
|  |         feed('/X<CR>:popup PopUp<CR>') | ||||||
|  |         screen:expect([[ | ||||||
|  |                    evif ruof eerht owt eno| | ||||||
|  |               evif ruof eerht{7:^X} owt eno dna| | ||||||
|  |              {n:             odnU }wt erom eno| | ||||||
|  |           {1:   }{n:                  }{1:          ~}| | ||||||
|  |           {1:   }{n:            etsaP }{1:          ~}| | ||||||
|  |           {1:   }{n:                  }{1:          ~}| | ||||||
|  |           {1:   }{n:      droW tceleS }{1:          ~}| | ||||||
|  |           {1:   }{n:  ecnetneS tceleS }{1:          ~}| | ||||||
|  |           {1:   }{n: hpargaraP tceleS }{1:          ~}| | ||||||
|  |           {1:   }{n:      eniL tceleS }{1:          ~}| | ||||||
|  |           {1:   }{n:     kcolB tceleS }{1:          ~}| | ||||||
|  |           {1:   }{n:       llA tceleS }{1:          ~}| | ||||||
|  |           {1:                               ~}|*7 | ||||||
|  |           :popup PopUp                    | | ||||||
|  |         ]]) | ||||||
|  |         feed('<Esc>') | ||||||
|  |         command('set norightleft') | ||||||
|  |  | ||||||
|         -- Set an <expr> mapping to change a menu entry while it's displayed. |         -- Set an <expr> mapping to change a menu entry while it's displayed. | ||||||
|         -- The text should not change but the command does. |         -- The text should not change but the command does. | ||||||
|         -- Also verify that "changed" shows up, which means the mapping triggered. |         -- Also verify that "changed" shows up, which means the mapping triggered. | ||||||
| @@ -4535,6 +4557,55 @@ describe('builtin popupmenu', function() | |||||||
|         feed('<Esc>') |         feed('<Esc>') | ||||||
|       end) |       end) | ||||||
|  |  | ||||||
|  |       -- oldtest: Test_mouse_popup_position() | ||||||
|  |       it('position of right-click menu when clicking near edge', function() | ||||||
|  |         screen:try_resize(50, 20) | ||||||
|  |         exec([[ | ||||||
|  |           set mousemodel=popup_setpos | ||||||
|  |           aunmenu * | ||||||
|  |           source $VIMRUNTIME/menu.vim | ||||||
|  |           call setline(1, join(range(20))) | ||||||
|  |         ]]) | ||||||
|  |  | ||||||
|  |         api.nvim_input_mouse('right', 'press', '', 0, 0, 45 - 1) | ||||||
|  |         screen:expect([[ | ||||||
|  |           0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ^18 19 | | ||||||
|  |           {1:~                                }{n: Undo            }| | ||||||
|  |           {1:~                                }{n:                 }| | ||||||
|  |           {1:~                                }{n: Paste           }| | ||||||
|  |           {1:~                                }{n:                 }| | ||||||
|  |           {1:~                                }{n: Select Word     }| | ||||||
|  |           {1:~                                }{n: Select Sentence }| | ||||||
|  |           {1:~                                }{n: Select Paragraph}| | ||||||
|  |           {1:~                                }{n: Select Line     }| | ||||||
|  |           {1:~                                }{n: Select Block    }| | ||||||
|  |           {1:~                                }{n: Select All      }| | ||||||
|  |           {1:~                                                 }|*8 | ||||||
|  |                                                             | | ||||||
|  |         ]]) | ||||||
|  |         feed('<Esc>') | ||||||
|  |  | ||||||
|  |         command('set rightleft') | ||||||
|  |         api.nvim_input_mouse('right', 'press', '', 0, 0, 50 - 45) | ||||||
|  |         screen:expect([[ | ||||||
|  |            91 8^1 71 61 51 41 31 21 11 01 9 8 7 6 5 4 3 2 1 0| | ||||||
|  |           {n:            odnU }{1:                                ~}| | ||||||
|  |           {n:                 }{1:                                ~}| | ||||||
|  |           {n:           etsaP }{1:                                ~}| | ||||||
|  |           {n:                 }{1:                                ~}| | ||||||
|  |           {n:     droW tceleS }{1:                                ~}| | ||||||
|  |           {n: ecnetneS tceleS }{1:                                ~}| | ||||||
|  |           {n:hpargaraP tceleS }{1:                                ~}| | ||||||
|  |           {n:     eniL tceleS }{1:                                ~}| | ||||||
|  |           {n:    kcolB tceleS }{1:                                ~}| | ||||||
|  |           {n:      llA tceleS }{1:                                ~}| | ||||||
|  |           {1:                                                 ~}|*8 | ||||||
|  |                                                             | | ||||||
|  |         ]]) | ||||||
|  |         feed('<Esc>') | ||||||
|  |         command('set norightleft') | ||||||
|  |       end) | ||||||
|  |  | ||||||
|       describe('"kind" and "menu"', function() |       describe('"kind" and "menu"', function() | ||||||
|         before_each(function() |         before_each(function() | ||||||
|           screen:try_resize(30, 8) |           screen:try_resize(30, 8) | ||||||
|   | |||||||
| @@ -2905,6 +2905,24 @@ func Test_wildmenu_pum_odd_wildchar() | |||||||
|   call StopVimInTerminal(buf) |   call StopVimInTerminal(buf) | ||||||
| endfunc | endfunc | ||||||
|  |  | ||||||
|  | " Test that 'rightleft' should not affect cmdline completion popup menu. | ||||||
|  | func Test_wildmenu_pum_rightleft() | ||||||
|  |   CheckFeature rightleft | ||||||
|  |   CheckScreendump | ||||||
|  |  | ||||||
|  |   let lines =<< trim END | ||||||
|  |     set wildoptions=pum | ||||||
|  |     set rightleft | ||||||
|  |   END | ||||||
|  |   call writefile(lines, 'Xwildmenu_pum_rl', 'D') | ||||||
|  |   let buf = RunVimInTerminal('-S Xwildmenu_pum_rl', #{rows: 10, cols: 50}) | ||||||
|  |  | ||||||
|  |   call term_sendkeys(buf, ":sign \<Tab>") | ||||||
|  |   call VerifyScreenDump(buf, 'Test_wildmenu_pum_rl', {}) | ||||||
|  |  | ||||||
|  |   call StopVimInTerminal(buf) | ||||||
|  | endfunc | ||||||
|  |  | ||||||
| " Test for completion after a :substitute command followed by a pipe (|) | " Test for completion after a :substitute command followed by a pipe (|) | ||||||
| " character | " character | ||||||
| func Test_cmdline_complete_substitute() | func Test_cmdline_complete_substitute() | ||||||
|   | |||||||
| @@ -910,6 +910,13 @@ func Test_popup_command_dump() | |||||||
|  |  | ||||||
|   call term_sendkeys(buf, "\<Esc>") |   call term_sendkeys(buf, "\<Esc>") | ||||||
|  |  | ||||||
|  |   if has('rightleft') | ||||||
|  |     call term_sendkeys(buf, ":set rightleft\<CR>") | ||||||
|  |     call term_sendkeys(buf, "/X\<CR>:popup PopUp\<CR>") | ||||||
|  |     call VerifyScreenDump(buf, 'Test_popup_command_rl', {}) | ||||||
|  |     call term_sendkeys(buf, "\<Esc>:set norightleft\<CR>") | ||||||
|  |   endif | ||||||
|  |  | ||||||
|   " Set a timer to change a menu entry while it's displayed.  The text should |   " Set a timer to change a menu entry while it's displayed.  The text should | ||||||
|   " not change but the command does.  Making the screendump also verifies that |   " not change but the command does.  Making the screendump also verifies that | ||||||
|   " "changed" shows up, which means the timer triggered. |   " "changed" shows up, which means the timer triggered. | ||||||
| @@ -932,6 +939,37 @@ func Test_popup_command_dump() | |||||||
|   call StopVimInTerminal(buf) |   call StopVimInTerminal(buf) | ||||||
| endfunc | endfunc | ||||||
|  |  | ||||||
|  | " Test position of right-click menu when clicking near window edge. | ||||||
|  | func Test_mouse_popup_position() | ||||||
|  |   CheckFeature menu | ||||||
|  |   CheckScreendump | ||||||
|  |  | ||||||
|  |   let script =<< trim END | ||||||
|  |     set mousemodel=popup_setpos | ||||||
|  |     source $VIMRUNTIME/menu.vim | ||||||
|  |     call setline(1, join(range(20))) | ||||||
|  |     func Trigger(col) | ||||||
|  |       call test_setmouse(1, a:col) | ||||||
|  |       call feedkeys("\<RightMouse>", 't') | ||||||
|  |     endfunc | ||||||
|  |   END | ||||||
|  |   call writefile(script, 'XmousePopupPosition', 'D') | ||||||
|  |   let buf = RunVimInTerminal('-S XmousePopupPosition', #{rows: 20, cols: 50}) | ||||||
|  |  | ||||||
|  |   call term_sendkeys(buf, ":call Trigger(45)\<CR>") | ||||||
|  |   call VerifyScreenDump(buf, 'Test_mouse_popup_position_01', {}) | ||||||
|  |   call term_sendkeys(buf, "\<Esc>") | ||||||
|  |  | ||||||
|  |   if has('rightleft') | ||||||
|  |     call term_sendkeys(buf, ":set rightleft\<CR>") | ||||||
|  |     call term_sendkeys(buf, ":call Trigger(50 + 1 - 45)\<CR>") | ||||||
|  |     call VerifyScreenDump(buf, 'Test_mouse_popup_position_02', {}) | ||||||
|  |     call term_sendkeys(buf, "\<Esc>:set norightleft\<CR>") | ||||||
|  |   endif | ||||||
|  |  | ||||||
|  |   call StopVimInTerminal(buf) | ||||||
|  | endfunc | ||||||
|  |  | ||||||
| func Test_popup_complete_backwards() | func Test_popup_complete_backwards() | ||||||
|   new |   new | ||||||
|   call setline(1, ['Post', 'Port', 'Po']) |   call setline(1, ['Post', 'Port', 'Po']) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 zeertzjq
					zeertzjq