mirror of
https://github.com/vim/vim.git
synced 2025-07-26 11:04:33 -04:00
patch 8.1.2265: when popup with "botleft" does not fit it flips incorrectly
Problem: When popup with "botleft" does not fit it flips incorrectly. Solution: Only flip when there is more space on the other side. Add the "posinvert" option to disable flipping and do it in both directions if enabled. (closes #5151)
This commit is contained in:
parent
fcf8a8743b
commit
638a4a7508
@ -673,6 +673,16 @@ apply_general_options(win_T *wp, dict_T *dict)
|
|||||||
wp->w_popup_flags &= ~POPF_DRAG;
|
wp->w_popup_flags &= ~POPF_DRAG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
di = dict_find(dict, (char_u *)"posinvert", -1);
|
||||||
|
if (di != NULL)
|
||||||
|
{
|
||||||
|
nr = dict_get_number(dict, (char_u *)"posinvert");
|
||||||
|
if (nr)
|
||||||
|
wp->w_popup_flags |= POPF_POSINVERT;
|
||||||
|
else
|
||||||
|
wp->w_popup_flags &= ~POPF_POSINVERT;
|
||||||
|
}
|
||||||
|
|
||||||
di = dict_find(dict, (char_u *)"resize", -1);
|
di = dict_find(dict, (char_u *)"resize", -1);
|
||||||
if (di != NULL)
|
if (di != NULL)
|
||||||
{
|
{
|
||||||
@ -1383,15 +1393,35 @@ popup_adjust_position(win_T *wp)
|
|||||||
wp->w_winrow = 0;
|
wp->w_winrow = 0;
|
||||||
}
|
}
|
||||||
else if (wp->w_popup_pos == POPPOS_BOTRIGHT
|
else if (wp->w_popup_pos == POPPOS_BOTRIGHT
|
||||||
|| wp->w_popup_pos == POPPOS_BOTLEFT)
|
|| wp->w_popup_pos == POPPOS_BOTLEFT)
|
||||||
{
|
{
|
||||||
if ((wp->w_height + extra_height) <= wantline)
|
if ((wp->w_height + extra_height) <= wantline)
|
||||||
// bottom aligned: may move down
|
// bottom aligned: may move down
|
||||||
wp->w_winrow = wantline - (wp->w_height + extra_height);
|
wp->w_winrow = wantline - (wp->w_height + extra_height);
|
||||||
|
else if (wantline * 2 >= Rows || !(wp->w_popup_flags & POPF_POSINVERT))
|
||||||
|
{
|
||||||
|
// Bottom aligned but does not fit, and less space on the other
|
||||||
|
// side or "posinvert" is off: reduce height.
|
||||||
|
wp->w_winrow = 0;
|
||||||
|
wp->w_height = wantline - extra_height;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
// Not enough space, make top aligned.
|
// Not enough space and more space on the other side: make top
|
||||||
|
// aligned.
|
||||||
wp->w_winrow = (wantline < 0 ? 0 : wantline) + 1;
|
wp->w_winrow = (wantline < 0 ? 0 : wantline) + 1;
|
||||||
}
|
}
|
||||||
|
else if (wp->w_popup_pos == POPPOS_TOPRIGHT
|
||||||
|
|| wp->w_popup_pos == POPPOS_TOPLEFT)
|
||||||
|
{
|
||||||
|
if (wantline + (wp->w_height + extra_height) - 1 > Rows
|
||||||
|
&& wantline * 2 > Rows
|
||||||
|
&& (wp->w_popup_flags & POPF_POSINVERT))
|
||||||
|
// top aligned and not enough space below but there is space above:
|
||||||
|
// make bottom aligned
|
||||||
|
wp->w_winrow = wantline - 2 - wp->w_height - extra_height;
|
||||||
|
else
|
||||||
|
wp->w_winrow = wantline - 1;
|
||||||
|
}
|
||||||
if (wp->w_winrow >= Rows)
|
if (wp->w_winrow >= Rows)
|
||||||
wp->w_winrow = Rows - 1;
|
wp->w_winrow = Rows - 1;
|
||||||
else if (wp->w_winrow < 0)
|
else if (wp->w_winrow < 0)
|
||||||
@ -1730,7 +1760,7 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
|
|||||||
if (rettv != NULL)
|
if (rettv != NULL)
|
||||||
rettv->vval.v_number = wp->w_id;
|
rettv->vval.v_number = wp->w_id;
|
||||||
wp->w_popup_pos = POPPOS_TOPLEFT;
|
wp->w_popup_pos = POPPOS_TOPLEFT;
|
||||||
wp->w_popup_flags = POPF_IS_POPUP | POPF_MAPPING;
|
wp->w_popup_flags = POPF_IS_POPUP | POPF_MAPPING | POPF_POSINVERT;
|
||||||
|
|
||||||
if (buf != NULL)
|
if (buf != NULL)
|
||||||
{
|
{
|
||||||
@ -2670,6 +2700,8 @@ f_popup_getoptions(typval_T *argvars, typval_T *rettv)
|
|||||||
dict_add_number(dict, "mapping",
|
dict_add_number(dict, "mapping",
|
||||||
(wp->w_popup_flags & POPF_MAPPING) != 0);
|
(wp->w_popup_flags & POPF_MAPPING) != 0);
|
||||||
dict_add_number(dict, "resize", (wp->w_popup_flags & POPF_RESIZE) != 0);
|
dict_add_number(dict, "resize", (wp->w_popup_flags & POPF_RESIZE) != 0);
|
||||||
|
dict_add_number(dict, "posinvert",
|
||||||
|
(wp->w_popup_flags & POPF_POSINVERT) != 0);
|
||||||
dict_add_number(dict, "cursorline",
|
dict_add_number(dict, "cursorline",
|
||||||
(wp->w_popup_flags & POPF_CURSORLINE) != 0);
|
(wp->w_popup_flags & POPF_CURSORLINE) != 0);
|
||||||
dict_add_string(dict, "highlight", wp->w_p_wcr);
|
dict_add_string(dict, "highlight", wp->w_p_wcr);
|
||||||
@ -2830,7 +2862,7 @@ invoke_popup_filter(win_T *wp, int c)
|
|||||||
|
|
||||||
argv[2].v_type = VAR_UNKNOWN;
|
argv[2].v_type = VAR_UNKNOWN;
|
||||||
|
|
||||||
// NOTE: The callback might close the popup, thus make "wp" invalid.
|
// NOTE: The callback might close the popup and make "wp" invalid.
|
||||||
call_callback(&wp->w_filter_cb, -1, &rettv, 2, argv);
|
call_callback(&wp->w_filter_cb, -1, &rettv, 2, argv);
|
||||||
if (win_valid_popup(wp) && old_lnum != wp->w_cursor.lnum)
|
if (win_valid_popup(wp) && old_lnum != wp->w_cursor.lnum)
|
||||||
popup_highlight_curline(wp);
|
popup_highlight_curline(wp);
|
||||||
|
12
src/testdir/dumps/Test_popupwin_nospace.dump
Normal file
12
src/testdir/dumps/Test_popupwin_nospace.dump
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
|-+0&#ffffff0|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@1|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@8|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@32| @14
|
||||||
|
|-|║+0#0000001#ffd7ff255|o|n|e|║|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|o|n|e|║|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|a@2|║|-+0#0000000#ffffff0@32| @14
|
||||||
|
|-|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|b@2|║|-+0#0000000#ffffff0@15|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@11| @14
|
||||||
|
|-|╚+0#0000001#ffd7ff255|═@2|╝|-+0#0000000#ffffff0@1|╚+0#0000001#ffd7ff255|═@2|╝|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|c@2|║|-+0#0000000#ffffff0@15|║+0#0000001#ffd7ff255|o|n|e|║|-+0#0000000#ffffff0@11| @14
|
||||||
|
|-|@|-@5|#|-@5|%|-@5|║+0#0000001#ffd7ff255|d@2|║|-+0#0000000#ffffff0@15|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@1>*|-@8| @14
|
||||||
|
|-@14|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|e@2|║|-+0#0000000#ffffff0@15|║+0#0000001#ffd7ff255|t|e@1|║|-+0#0000000#ffffff0@1|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@4| @14
|
||||||
|
|-@14|║+0#0000001#ffd7ff255|o|n|e|║|-+0#0000000#ffffff0@1|╚+0#0000001#ffd7ff255|═@2|╝|-+0#0000000#ffffff0@15|╚+0#0000001#ffd7ff255|═@2|╝|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|a@2|║|-+0#0000000#ffffff0@4| @14
|
||||||
|
|-@14|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@1|*|-@5|@|-@5|#|-@5|%|-@5|║+0#0000001#ffd7ff255|b@2|║|-+0#0000000#ffffff0@4| @14
|
||||||
|
|-@14|║+0#0000001#ffd7ff255|t|e@1|║|-+0#0000000#ffffff0@8|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@1|╔+0#0000001#ffd7ff255|═@2|╗|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|c@2|║|-+0#0000000#ffffff0@4| @14
|
||||||
|
|-@14|╚+0#0000001#ffd7ff255|═@2|╝|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|o|n|e|║|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|o|n|e|║|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|d@2|║|-+0#0000000#ffffff0@4| @14
|
||||||
|
|-@28|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|t|w|o|║|-+0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|e@2|║|-+0#0000000#ffffff0@4| @14
|
||||||
|
@29|╚+0#0000001#ffd7ff255|═@2|╝| +0#0000000#ffffff0@1|║+0#0000001#ffd7ff255|t|e@1|║| +0#0000000#ffffff0@8|║+0#0000001#ffd7ff255|f@2|║| +0#0000000#ffffff0@1|5|,|5|1| @9|T|o|p|
|
@ -323,6 +323,98 @@ func Test_popup_all_corners()
|
|||||||
call delete('XtestPopupCorners')
|
call delete('XtestPopupCorners')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_popup_nospace()
|
||||||
|
CheckScreendump
|
||||||
|
|
||||||
|
let lines =<< trim END
|
||||||
|
call setline(1, repeat([repeat('-', 60)], 15))
|
||||||
|
set so=0
|
||||||
|
|
||||||
|
" cursor in a line in top half, using "botleft" with popup that
|
||||||
|
" does fit
|
||||||
|
normal 5G2|r@
|
||||||
|
let winid1 = popup_create(['one', 'two'], #{
|
||||||
|
\ line: 'cursor-1',
|
||||||
|
\ col: 'cursor',
|
||||||
|
\ pos: 'botleft',
|
||||||
|
\ border: [],
|
||||||
|
\ })
|
||||||
|
" cursor in a line in top half, using "botleft" with popup that
|
||||||
|
" doesn't fit: gets truncated
|
||||||
|
normal 5G9|r#
|
||||||
|
let winid1 = popup_create(['one', 'two', 'tee'], #{
|
||||||
|
\ line: 'cursor-1',
|
||||||
|
\ col: 'cursor',
|
||||||
|
\ pos: 'botleft',
|
||||||
|
\ posinvert: 0,
|
||||||
|
\ border: [],
|
||||||
|
\ })
|
||||||
|
" cursor in a line in top half, using "botleft" with popup that
|
||||||
|
" doesn't fit and 'posinvert' set: flips to below.
|
||||||
|
normal 5G16|r%
|
||||||
|
let winid1 = popup_create(['one', 'two', 'tee'], #{
|
||||||
|
\ line: 'cursor-1',
|
||||||
|
\ col: 'cursor',
|
||||||
|
\ pos: 'botleft',
|
||||||
|
\ border: [],
|
||||||
|
\ })
|
||||||
|
" cursor in a line in bottom half, using "botleft" with popup that
|
||||||
|
" doesn't fit: does not flip.
|
||||||
|
normal 8G23|r*
|
||||||
|
let winid1 = popup_create(['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff'], #{
|
||||||
|
\ line: 'cursor-1',
|
||||||
|
\ col: 'cursor',
|
||||||
|
\ pos: 'botleft',
|
||||||
|
\ border: [],
|
||||||
|
\ })
|
||||||
|
|
||||||
|
" cursor in a line in bottom half, using "topleft" with popup that
|
||||||
|
" does fit
|
||||||
|
normal 8G30|r@
|
||||||
|
let winid1 = popup_create(['one', 'two'], #{
|
||||||
|
\ line: 'cursor+1',
|
||||||
|
\ col: 'cursor',
|
||||||
|
\ pos: 'topleft',
|
||||||
|
\ border: [],
|
||||||
|
\ })
|
||||||
|
" cursor in a line in top half, using "topleft" with popup that
|
||||||
|
" doesn't fit: truncated
|
||||||
|
normal 8G37|r#
|
||||||
|
let winid1 = popup_create(['one', 'two', 'tee'], #{
|
||||||
|
\ line: 'cursor+1',
|
||||||
|
\ col: 'cursor',
|
||||||
|
\ pos: 'topleft',
|
||||||
|
\ posinvert: 0,
|
||||||
|
\ border: [],
|
||||||
|
\ })
|
||||||
|
" cursor in a line in top half, using "topleft" with popup that
|
||||||
|
" doesn't fit and "posinvert" set: flips to below.
|
||||||
|
normal 8G44|r%
|
||||||
|
let winid1 = popup_create(['one', 'two', 'tee'], #{
|
||||||
|
\ line: 'cursor+1',
|
||||||
|
\ col: 'cursor',
|
||||||
|
\ pos: 'topleft',
|
||||||
|
\ border: [],
|
||||||
|
\ })
|
||||||
|
" cursor in a line in top half, using "topleft" with popup that
|
||||||
|
" doesn't fit: does not flip.
|
||||||
|
normal 5G51|r*
|
||||||
|
let winid1 = popup_create(['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff'], #{
|
||||||
|
\ line: 'cursor+1',
|
||||||
|
\ col: 'cursor',
|
||||||
|
\ pos: 'topleft',
|
||||||
|
\ border: [],
|
||||||
|
\ })
|
||||||
|
END
|
||||||
|
call writefile(lines, 'XtestPopupNospace')
|
||||||
|
let buf = RunVimInTerminal('-S XtestPopupNospace', #{rows: 12})
|
||||||
|
call VerifyScreenDump(buf, 'Test_popupwin_nospace', {})
|
||||||
|
|
||||||
|
" clean up
|
||||||
|
call StopVimInTerminal(buf)
|
||||||
|
call delete('XtestPopupNospace')
|
||||||
|
endfunc
|
||||||
|
|
||||||
func Test_popup_firstline()
|
func Test_popup_firstline()
|
||||||
CheckScreendump
|
CheckScreendump
|
||||||
|
|
||||||
@ -586,6 +678,7 @@ func Test_popup_with_mask()
|
|||||||
\], #{
|
\], #{
|
||||||
\ line: 1,
|
\ line: 1,
|
||||||
\ col: 10,
|
\ col: 10,
|
||||||
|
\ posinvert: 0,
|
||||||
\ wrap: 0,
|
\ wrap: 0,
|
||||||
\ fixed: 1,
|
\ fixed: 1,
|
||||||
\ zindex: 90,
|
\ zindex: 90,
|
||||||
@ -604,6 +697,7 @@ func Test_popup_with_mask()
|
|||||||
\], #{
|
\], #{
|
||||||
\ line: 7,
|
\ line: 7,
|
||||||
\ col: 10,
|
\ col: 10,
|
||||||
|
\ posinvert: 0,
|
||||||
\ wrap: 0,
|
\ wrap: 0,
|
||||||
\ fixed: 1,
|
\ fixed: 1,
|
||||||
\ close: 'button',
|
\ close: 'button',
|
||||||
|
@ -741,6 +741,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2265,
|
||||||
/**/
|
/**/
|
||||||
2264,
|
2264,
|
||||||
/**/
|
/**/
|
||||||
|
@ -632,6 +632,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
|
|||||||
#define POPF_MAPPING 0x80 // mapping keys
|
#define POPF_MAPPING 0x80 // mapping keys
|
||||||
#define POPF_INFO 0x100 // used for info of popup menu
|
#define POPF_INFO 0x100 // used for info of popup menu
|
||||||
#define POPF_INFO_MENU 0x200 // align info popup with popup menu
|
#define POPF_INFO_MENU 0x200 // align info popup with popup menu
|
||||||
|
#define POPF_POSINVERT 0x400 // vertical position can be inverted
|
||||||
|
|
||||||
#ifdef FEAT_TEXT_PROP
|
#ifdef FEAT_TEXT_PROP
|
||||||
# define WIN_IS_POPUP(wp) ((wp)->w_popup_flags != 0)
|
# define WIN_IS_POPUP(wp) ((wp)->w_popup_flags != 0)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user