# HG changeset patch # User Christian Brabandt # Date 1718459105 -7200 # Node ID ad79859e2780e7416fdf9eeeaeff8351317fcd32 # Parent d12077aaf8208ea6f47ad67e21a8f930b3c8dba6 patch 9.1.0491: Cmdline pum doesn't work properly with 'rightleft' Commit: https://github.com/vim/vim/commit/883018feff43413813770dd1e13d4f950aa38524 Author: zeertzjq Date: Sat Jun 15 15:37:11 2024 +0200 patch 9.1.0491: Cmdline pum doesn't work properly with 'rightleft' 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: #15005 Signed-off-by: zeertzjq Signed-off-by: Christian Brabandt diff --git a/src/popupmenu.c b/src/popupmenu.c --- a/src/popupmenu.c +++ b/src/popupmenu.c @@ -26,6 +26,9 @@ static int pum_base_width; // width of static int pum_kind_width; // width of pum items kind column static int pum_extra_width; // width of extra stuff static int pum_scrollbar; // TRUE when scrollbar present +#ifdef FEAT_RIGHTLEFT +static int pum_rl; // TRUE when pum is drawn 'rightleft' +#endif static int pum_row; // top row of pum static int pum_col; // left column of pum @@ -101,8 +104,9 @@ pum_display( #if defined(FEAT_QUICKFIX) win_T *pvwin; #endif + #ifdef FEAT_RIGHTLEFT - int right_left = State == MODE_CMDLINE ? FALSE : curwin->w_p_rl; + pum_rl = State != MODE_CMDLINE && curwin->w_p_rl; #endif do @@ -243,7 +247,7 @@ pum_display( // w_wcol includes virtual text "above" int wcol = curwin->w_wcol % curwin->w_width; #ifdef FEAT_RIGHTLEFT - if (right_left) + if (pum_rl) cursor_col = curwin->w_wincol + curwin->w_width - wcol - 1; else #endif @@ -264,8 +268,8 @@ pum_display( if (((cursor_col < Columns - p_pw || cursor_col < Columns - max_width) #ifdef FEAT_RIGHTLEFT - && !right_left) - || (right_left && (cursor_col > p_pw || cursor_col > max_width) + && !pum_rl) + || (pum_rl && (cursor_col > p_pw || cursor_col > max_width) #endif )) { @@ -274,7 +278,7 @@ pum_display( // start with the maximum space available #ifdef FEAT_RIGHTLEFT - if (right_left) + if (pum_rl) pum_width = pum_col - pum_scrollbar + 1; else #endif @@ -291,22 +295,22 @@ pum_display( } else if (((cursor_col > p_pw || cursor_col > max_width) #ifdef FEAT_RIGHTLEFT - && !right_left) - || (right_left && (cursor_col < Columns - p_pw + && !pum_rl) + || (pum_rl && (cursor_col < Columns - p_pw || cursor_col < Columns - max_width) #endif )) { // align pum edge with "cursor_col" #ifdef FEAT_RIGHTLEFT - if (right_left + if (pum_rl && W_ENDCOL(curwin) < max_width + pum_scrollbar + 1) { pum_col = cursor_col + max_width + pum_scrollbar + 1; if (pum_col >= Columns) pum_col = Columns - 1; } - else if (!right_left) + else if (!pum_rl) #endif { if (curwin->w_wincol > Columns - max_width - pum_scrollbar @@ -320,7 +324,7 @@ pum_display( } #ifdef FEAT_RIGHTLEFT - if (right_left) + if (pum_rl) pum_width = pum_col - pum_scrollbar + 1; else #endif @@ -330,7 +334,7 @@ pum_display( { pum_width = p_pw; #ifdef FEAT_RIGHTLEFT - if (right_left) + if (pum_rl) { if (pum_width > pum_col) pum_width = pum_col; @@ -358,7 +362,7 @@ pum_display( { // not enough room, will use what we have #ifdef FEAT_RIGHTLEFT - if (right_left) + if (pum_rl) pum_col = Columns - 1; else #endif @@ -370,7 +374,7 @@ pum_display( if (max_width > p_pw) max_width = p_pw; // truncate #ifdef FEAT_RIGHTLEFT - if (right_left) + if (pum_rl) pum_col = max_width - 1; else #endif @@ -443,7 +447,7 @@ pum_screen_put_with_attr(int row, int co } #ifdef FEAT_RIGHTLEFT - if (curwin->w_p_rl) + if (pum_rl) rt_leader = reverse_text(leader); #endif match_leader = rt_leader != NULL ? rt_leader : leader; @@ -572,7 +576,7 @@ pum_redraw(void) // prepend a space if there is room #ifdef FEAT_RIGHTLEFT - if (curwin->w_p_rl) + if (pum_rl) { if (pum_col < curwin->w_wincol + curwin->w_width - 1) screen_putchar(' ', row, pum_col + 1, attr); @@ -620,7 +624,7 @@ pum_redraw(void) if (saved != NUL) *p = saved; #ifdef FEAT_RIGHTLEFT - if (curwin->w_p_rl) + if (pum_rl) { if (st != NULL) { @@ -691,7 +695,7 @@ pum_redraw(void) // Display two spaces for a Tab. #ifdef FEAT_RIGHTLEFT - if (curwin->w_p_rl) + if (pum_rl) { screen_puts_len((char_u *)" ", 2, row, col - 1, attr); @@ -724,7 +728,7 @@ pum_redraw(void) || pum_base_width + n >= pum_width) break; #ifdef FEAT_RIGHTLEFT - if (curwin->w_p_rl) + if (pum_rl) { screen_fill(row, row + 1, pum_col - pum_base_width - n + 1, col + 1, ' ', ' ', attr); @@ -741,7 +745,7 @@ pum_redraw(void) } #ifdef FEAT_RIGHTLEFT - if (curwin->w_p_rl) + if (pum_rl) screen_fill(row, row + 1, pum_col - pum_width + 1, col + 1, ' ', ' ', attr); else @@ -751,7 +755,7 @@ pum_redraw(void) if (pum_scrollbar > 0) { #ifdef FEAT_RIGHTLEFT - if (curwin->w_p_rl) + if (pum_rl) screen_putchar(' ', row, pum_col - pum_width, i >= thumb_pos && i < thumb_pos + thumb_height ? attr_thumb : attr_scroll); @@ -1296,16 +1300,34 @@ pum_position_at_mouse(int min_width) pum_row = 0; } } - if (Columns - mouse_col >= pum_base_width - || Columns - mouse_col > min_width) - // Enough space to show at mouse column. - pum_col = mouse_col; + +# ifdef FEAT_RIGHTLEFT + if (pum_rl) + { + if (mouse_col + 1 >= pum_base_width + || mouse_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 = (pum_base_width > min_width + ? min_width : pum_base_width) - 1; + pum_width = pum_col + 1; + } else - // Not enough space, right align with window. - pum_col = Columns - (pum_base_width > min_width +# endif + { + if (Columns - mouse_col >= pum_base_width + || Columns - 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 = Columns - (pum_base_width > min_width ? min_width : pum_base_width); + pum_width = Columns - pum_col; + } - pum_width = Columns - pum_col; if (pum_width > pum_base_width + 1) pum_width = pum_base_width + 1; @@ -1529,6 +1551,9 @@ ui_post_balloon(char_u *mesg, list_T *li pum_compute_size(); pum_scrollbar = 0; pum_height = balloon_arraysize; +# ifdef FEAT_RIGHTLEFT + pum_rl = curwin->w_p_rl; +# endif pum_position_at_mouse(BALLOON_MIN_WIDTH); pum_selected = -1; @@ -1639,6 +1664,9 @@ pum_show_popupmenu(vimmenu_T *menu) pum_compute_size(); pum_scrollbar = 0; pum_height = pum_size; +# ifdef FEAT_RIGHTLEFT + pum_rl = curwin->w_p_rl; +# endif pum_position_at_mouse(20); pum_selected = -1; @@ -1734,7 +1762,11 @@ pum_make_popup(char_u *path_name, int us // Hack: set mouse position at the cursor so that the menu pops up // around there. mouse_row = W_WINROW(curwin) + curwin->w_wrow; - mouse_col = curwin->w_wincol + curwin->w_wcol; + mouse_col = +# ifdef FEAT_RIGHTLEFT + curwin->w_p_rl ? W_ENDCOL(curwin) - curwin->w_wcol - 1 : +# endif + curwin->w_wincol + curwin->w_wcol; } menu = gui_find_menu(path_name); diff --git a/src/testdir/dumps/Test_balloon_eval_term_03.dump b/src/testdir/dumps/Test_balloon_eval_term_03.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_balloon_eval_term_03.dump @@ -0,0 +1,10 @@ +| +0&#ffffff0@38|e|n|o| |e|n|o| |e|n>o +| @38|o|w|t| |o|X|t| |o|w|t +| @27| +0#0000001#ffd7ff255@17|e+0#0000000#ffffff0|r|h|t +| +0#4040ff13&@27| +0#0000001#ffd7ff255|:|6| |n|m|u|l|o|c| |2| |e|n|i|l| | +0#4040ff13#ffffff0@2|~ +| @27| +0#0000001#ffd7ff255@12|<|o|X|t| | +0#4040ff13#ffffff0@2|~ +| @27| +0#0000001#ffd7ff255@17| +0#4040ff13#ffffff0@2|~ +| @48|~ +| @48|~ +| @48|~ +|:+0#0000000&|c|a|l@1| |T|r|i|g@1|e|r|(|)| @16|1|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_mouse_popup_position_01.dump b/src/testdir/dumps/Test_mouse_popup_position_01.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_mouse_popup_position_01.dump @@ -0,0 +1,20 @@ +|0+0&#ffffff0| |1| |2| |3| |4| |5| |6| |7| |8| |9| |1|0| |1@1| |1|2| |1|3| |1|4| |1|5| |1|6| |1|7| >1|8| |1|9| +|~+0#4040ff13&| @31| +0#0000001#ffd7ff255|U|n|d|o| @11 +|~+0#4040ff13#ffffff0| @31| +0#0000001#ffd7ff255@16 +|~+0#4040ff13#ffffff0| @31| +0#0000001#ffd7ff255|P|a|s|t|e| @10 +|~+0#4040ff13#ffffff0| @31| +0#0000001#ffd7ff255@16 +|~+0#4040ff13#ffffff0| @31| +0#0000001#ffd7ff255|S|e|l|e|c|t| |W|o|r|d| @4 +|~+0#4040ff13#ffffff0| @31| +0#0000001#ffd7ff255|S|e|l|e|c|t| |S|e|n|t|e|n|c|e| +|~+0#4040ff13#ffffff0| @31| +0#0000001#ffd7ff255|S|e|l|e|c|t| |P|a|r|a|g|r|a|p|h +|~+0#4040ff13#ffffff0| @31| +0#0000001#ffd7ff255|S|e|l|e|c|t| |L|i|n|e| @4 +|~+0#4040ff13#ffffff0| @31| +0#0000001#ffd7ff255|S|e|l|e|c|t| |B|l|o|c|k| @3 +|~+0#4040ff13#ffffff0| @31| +0#0000001#ffd7ff255|S|e|l|e|c|t| |A|l@1| @5 +|~+0#4040ff13#ffffff0| @48 +|~| @48 +|~| @48 +|~| @48 +|~| @48 +|~| @48 +|~| @48 +|~| @48 +|:+0#0000000&|c|a|l@1| |T|r|i|g@1|e|r|(|4|5|)| @14|1|,|1| @10|A|l@1| diff --git a/src/testdir/dumps/Test_mouse_popup_position_02.dump b/src/testdir/dumps/Test_mouse_popup_position_02.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_mouse_popup_position_02.dump @@ -0,0 +1,20 @@ +| +0&#ffffff0|9|1| |8>1| |7|1| |6|1| |5|1| |4|1| |3|1| |2|1| |1@1| |0|1| |9| |8| |7| |6| |5| |4| |3| |2| |1| |0 +| +0#0000001#ffd7ff255@11|o|d|n|U| | +0#4040ff13#ffffff0@31|~ +| +0#0000001#ffd7ff255@16| +0#4040ff13#ffffff0@31|~ +| +0#0000001#ffd7ff255@10|e|t|s|a|P| | +0#4040ff13#ffffff0@31|~ +| +0#0000001#ffd7ff255@16| +0#4040ff13#ffffff0@31|~ +| +0#0000001#ffd7ff255@4|d|r|o|W| |t|c|e|l|e|S| | +0#4040ff13#ffffff0@31|~ +| +0#0000001#ffd7ff255|e|c|n|e|t|n|e|S| |t|c|e|l|e|S| | +0#4040ff13#ffffff0@31|~ +|h+0#0000001#ffd7ff255|p|a|r|g|a|r|a|P| |t|c|e|l|e|S| | +0#4040ff13#ffffff0@31|~ +| +0#0000001#ffd7ff255@4|e|n|i|L| |t|c|e|l|e|S| | +0#4040ff13#ffffff0@31|~ +| +0#0000001#ffd7ff255@3|k|c|o|l|B| |t|c|e|l|e|S| | +0#4040ff13#ffffff0@31|~ +| +0#0000001#ffd7ff255@5|l@1|A| |t|c|e|l|e|S| | +0#4040ff13#ffffff0@31|~ +| @48|~ +| @48|~ +| @48|~ +| @48|~ +| @48|~ +| @48|~ +| @48|~ +| @48|~ +|:+0#0000000&|c|a|l@1| |T|r|i|g@1|e|r|(|5|0| |+| |1| |-| |4|5|)| @5|1|,|4|5| @9|A|l@1| diff --git a/src/testdir/dumps/Test_popup_command_rl.dump b/src/testdir/dumps/Test_popup_command_rl.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_popup_command_rl.dump @@ -0,0 +1,20 @@ +| +0&#ffffff0@51|e|v|i|f| |r|u|o|f| |e@1|r|h|t| |o|w|t| |e|n|o +| @46|e|v|i|f| |r|u|o|f| |e@1|r|h|t>X| |o|w|t| |e|n|o| |d|n|a +| @45| +0#0000001#ffd7ff255@12|o|d|n|U| |w+0#0000000#ffffff0|t| |e|r|o|m| |e|n|o +| +0#4040ff13&@45| +0#0000001#ffd7ff255@17| +0#4040ff13#ffffff0@9|~ +| @45| +0#0000001#ffd7ff255@11|e|t|s|a|P| | +0#4040ff13#ffffff0@9|~ +| @45| +0#0000001#ffd7ff255@17| +0#4040ff13#ffffff0@9|~ +| @45| +0#0000001#ffd7ff255@5|d|r|o|W| |t|c|e|l|e|S| | +0#4040ff13#ffffff0@9|~ +| @45| +0#0000001#ffd7ff255@1|e|c|n|e|t|n|e|S| |t|c|e|l|e|S| | +0#4040ff13#ffffff0@9|~ +| @45| +0#0000001#ffd7ff255|h|p|a|r|g|a|r|a|P| |t|c|e|l|e|S| | +0#4040ff13#ffffff0@9|~ +| @45| +0#0000001#ffd7ff255@5|e|n|i|L| |t|c|e|l|e|S| | +0#4040ff13#ffffff0@9|~ +| @45| +0#0000001#ffd7ff255@4|k|c|o|l|B| |t|c|e|l|e|S| | +0#4040ff13#ffffff0@9|~ +| @45| +0#0000001#ffd7ff255@6|l@1|A| |t|c|e|l|e|S| | +0#4040ff13#ffffff0@9|~ +| @73|~ +| @73|~ +| @73|~ +| @73|~ +| @73|~ +| @73|~ +| @73|~ +|:+0#0000000&|p|o|p|u|p| |P|o|p|U|p| @62 diff --git a/src/testdir/dumps/Test_wildmenu_pum_rl.dump b/src/testdir/dumps/Test_wildmenu_pum_rl.dump new file mode 100644 --- /dev/null +++ b/src/testdir/dumps/Test_wildmenu_pum_rl.dump @@ -0,0 +1,10 @@ +| +0&#ffffff0@49 +| +0#4040ff13&@48|~ +| @48|~ +| @4| +0#0000001#e0e0e08|d|e|f|i|n|e| @8| +0#4040ff13#ffffff0@27|~ +| @4| +0#0000001#ffd7ff255|j|u|m|p| @10| +0#4040ff13#ffffff0@27|~ +| @4| +0#0000001#ffd7ff255|l|i|s|t| @10| +0#4040ff13#ffffff0@27|~ +| @4| +0#0000001#ffd7ff255|p|l|a|c|e| @9| +0#4040ff13#ffffff0@27|~ +| @4| +0#0000001#ffd7ff255|u|n|d|e|f|i|n|e| @6| +0#4040ff13#ffffff0@27|~ +| @4| +0#0000001#ffd7ff255|u|n|p|l|a|c|e| @7| +0#4040ff13#ffffff0@27|~ +|:+0#0000000&|s|i|g|n| |d|e|f|i|n|e> @37 diff --git a/src/testdir/test_balloon.vim b/src/testdir/test_balloon.vim --- a/src/testdir/test_balloon.vim +++ b/src/testdir/test_balloon.vim @@ -64,4 +64,29 @@ func Test_balloon_eval_term_visual() call StopVimInTerminal(buf) endfunc +func Test_balloon_eval_term_rightleft() + CheckFeature rightleft + + " Use after to return from vgetc() without removing + " the balloon. + let xtra_lines =<< trim [CODE] + set rightleft + func Trigger() + call test_setmouse(2, 50 + 1 - 6) + call feedkeys("\\", "xt") + endfunc + [CODE] + call writefile(s:common_script + xtra_lines, 'XTest_beval_rl', 'D') + + " Check that the balloon shows up after a mouse move + let buf = RunVimInTerminal('-S XTest_beval_rl', {'rows': 10, 'cols': 50}) + call TermWait(buf, 50) + call term_sendkeys(buf, 'll') + call term_sendkeys(buf, ":call Trigger()\") + call VerifyScreenDump(buf, 'Test_balloon_eval_term_03', {}) + + " clean up + call StopVimInTerminal(buf) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -2741,6 +2741,24 @@ func Test_wildmenu_pum_odd_wildchar() call StopVimInTerminal(buf) 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 \") + call VerifyScreenDump(buf, 'Test_wildmenu_pum_rl', {}) + + call StopVimInTerminal(buf) +endfunc + " Test for completion after a :substitute command followed by a pipe (|) " character func Test_cmdline_complete_substitute() diff --git a/src/testdir/test_popup.vim b/src/testdir/test_popup.vim --- a/src/testdir/test_popup.vim +++ b/src/testdir/test_popup.vim @@ -908,6 +908,13 @@ func Test_popup_command_dump() call term_sendkeys(buf, "\") + if has('rightleft') + call term_sendkeys(buf, ":set rightleft\") + call term_sendkeys(buf, "/X\:popup PopUp\") + call VerifyScreenDump(buf, 'Test_popup_command_rl', {}) + call term_sendkeys(buf, "\:set norightleft\") + endif + " 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 " "changed" shows up, which means the timer triggered. @@ -930,6 +937,37 @@ func Test_popup_command_dump() call StopVimInTerminal(buf) 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("\", 't') + endfunc + END + call writefile(script, 'XmousePopupPosition', 'D') + let buf = RunVimInTerminal('-S XmousePopupPosition', #{rows: 20, cols: 50}) + + call term_sendkeys(buf, ":call Trigger(45)\") + call VerifyScreenDump(buf, 'Test_mouse_popup_position_01', {}) + call term_sendkeys(buf, "\") + + if has('rightleft') + call term_sendkeys(buf, ":set rightleft\") + call term_sendkeys(buf, ":call Trigger(50 + 1 - 45)\") + call VerifyScreenDump(buf, 'Test_mouse_popup_position_02', {}) + call term_sendkeys(buf, "\:set norightleft\") + endif + + call StopVimInTerminal(buf) +endfunc + func Test_popup_complete_backwards() new call setline(1, ['Post', 'Port', 'Po']) diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -705,6 +705,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 491, +/**/ 490, /**/ 489,