Mercurial > vim
diff src/popupwin.c @ 17292:8a095d343c59 v8.1.1645
patch 8.1.1645: cannot use a popup window for a balloon
commit https://github.com/vim/vim/commit/b3d17a20d243f65bcfe23de08b7afd948c5132c2
Author: Bram Moolenaar <Bram@vim.org>
Date: Sun Jul 7 18:28:14 2019 +0200
patch 8.1.1645: cannot use a popup window for a balloon
Problem: Cannot use a popup window for a balloon.
Solution: Add popup_beval(). Add the "mousemoved" property. Add the
screenpos() function.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sun, 07 Jul 2019 18:30:05 +0200 |
parents | 6a7ba68d448e |
children | 0dff534a0807 |
line wrap: on
line diff
--- a/src/popupwin.c +++ b/src/popupwin.c @@ -168,6 +168,35 @@ set_moved_columns(win_T *wp, int flags) } /* + * Used when popup options contain "mousemoved": set default moved values. + */ + static void +set_mousemoved_values(win_T *wp) +{ + wp->w_popup_mouse_row = mouse_row; + wp->w_popup_mouse_mincol = mouse_col; + wp->w_popup_mouse_maxcol = mouse_col; +} + +/* + * Used when popup options contain "moved" with "word" or "WORD". + */ + static void +set_mousemoved_columns(win_T *wp, int flags) +{ + char_u *text; + int col; + + if (find_word_under_cursor(mouse_row, mouse_col, TRUE, flags, + NULL, NULL, &text, &col) == OK) + { + wp->w_popup_mouse_mincol = col; + wp->w_popup_mouse_maxcol = col + STRLEN(text) - 1; + vim_free(text); + } +} + +/* * Return TRUE if "row"/"col" is on the border of the popup. * The values are relative to the top-left corner. */ @@ -336,6 +365,53 @@ apply_move_options(win_T *wp, dict_T *d) } static void +handle_moved_argument(win_T *wp, dictitem_T *di, int mousemoved) +{ + if (di->di_tv.v_type == VAR_STRING && di->di_tv.vval.v_string != NULL) + { + char_u *s = di->di_tv.vval.v_string; + int flags = 0; + + if (STRCMP(s, "word") == 0) + flags = FIND_IDENT | FIND_STRING; + else if (STRCMP(s, "WORD") == 0) + flags = FIND_STRING; + else if (STRCMP(s, "expr") == 0) + flags = FIND_IDENT | FIND_STRING | FIND_EVAL; + else if (STRCMP(s, "any") != 0) + semsg(_(e_invarg2), s); + if (flags != 0) + { + if (mousemoved) + set_mousemoved_columns(wp, flags); + else + set_moved_columns(wp, flags); + } + } + else if (di->di_tv.v_type == VAR_LIST + && di->di_tv.vval.v_list != NULL + && di->di_tv.vval.v_list->lv_len == 2) + { + list_T *l = di->di_tv.vval.v_list; + int mincol = tv_get_number(&l->lv_first->li_tv); + int maxcol = tv_get_number(&l->lv_first->li_next->li_tv); + + if (mousemoved) + { + wp->w_popup_mouse_mincol = mincol; + wp->w_popup_mouse_maxcol = maxcol; + } + else + { + wp->w_popup_mincol = mincol; + wp->w_popup_maxcol = maxcol; + } + } + else + semsg(_(e_invarg2), tv_get_string(&di->di_tv)); +} + + static void check_highlight(dict_T *dict, char *name, char_u **pval) { dictitem_T *di; @@ -541,31 +617,14 @@ apply_general_options(win_T *wp, dict_T if (di != NULL) { set_moved_values(wp); - if (di->di_tv.v_type == VAR_STRING && di->di_tv.vval.v_string != NULL) - { - char_u *s = di->di_tv.vval.v_string; - int flags = 0; + handle_moved_argument(wp, di, FALSE); + } - if (STRCMP(s, "word") == 0) - flags = FIND_IDENT | FIND_STRING; - else if (STRCMP(s, "WORD") == 0) - flags = FIND_STRING; - else if (STRCMP(s, "any") != 0) - semsg(_(e_invarg2), s); - if (flags != 0) - set_moved_columns(wp, flags); - } - else if (di->di_tv.v_type == VAR_LIST - && di->di_tv.vval.v_list != NULL - && di->di_tv.vval.v_list->lv_len == 2) - { - list_T *l = di->di_tv.vval.v_list; - - wp->w_popup_mincol = tv_get_number(&l->lv_first->li_tv); - wp->w_popup_maxcol = tv_get_number(&l->lv_first->li_next->li_tv); - } - else - semsg(_(e_invarg2), tv_get_string(&di->di_tv)); + di = dict_find(dict, (char_u *)"mousemoved", -1); + if (di != NULL) + { + set_mousemoved_values(wp); + handle_moved_argument(wp, di, TRUE); } di = dict_find(dict, (char_u *)"filter", -1); @@ -956,6 +1015,7 @@ typedef enum { TYPE_NORMAL, TYPE_ATCURSOR, + TYPE_BEVAL, TYPE_NOTIFICATION, TYPE_DIALOG, TYPE_MENU @@ -1137,17 +1197,33 @@ popup_create(typval_T *argvars, typval_T { wp->w_popup_pos = POPPOS_BOTLEFT; setcursor_mayforce(TRUE); - wp->w_wantline = screen_screenrow(); + wp->w_wantline = curwin->w_winrow + curwin->w_wrow; if (wp->w_wantline == 0) // cursor in first line { wp->w_wantline = 2; wp->w_popup_pos = POPPOS_TOPLEFT; } - wp->w_wantcol = screen_screencol() + 1; + wp->w_wantcol = curwin->w_wincol + curwin->w_wcol + 1; set_moved_values(wp); set_moved_columns(wp, FIND_STRING); } + if (type == TYPE_BEVAL) + { + wp->w_popup_pos = POPPOS_BOTLEFT; + + // by default use the mouse position + wp->w_wantline = mouse_row; + if (wp->w_wantline <= 0) // mouse on first line + { + wp->w_wantline = 2; + wp->w_popup_pos = POPPOS_TOPLEFT; + } + wp->w_wantcol = mouse_col + 1; + set_mousemoved_values(wp); + set_mousemoved_columns(wp, FIND_IDENT + FIND_STRING + FIND_EVAL); + } + // set default values wp->w_zindex = POPUPWIN_DEFAULT_ZINDEX; wp->w_popup_close = POPCLOSE_NONE; @@ -1276,6 +1352,15 @@ f_popup_atcursor(typval_T *argvars, typv } /* + * popup_beval({text}, {options}) + */ + void +f_popup_beval(typval_T *argvars, typval_T *rettv) +{ + popup_create(argvars, rettv, TYPE_BEVAL); +} + +/* * Invoke the close callback for window "wp" with value "result". * Careful: The callback may make "wp" invalid! */ @@ -1334,6 +1419,48 @@ popup_close_for_mouse_click(win_T *wp) popup_close_and_callback(wp, &res); } + static void +check_mouse_moved(win_T *wp, win_T *mouse_wp) +{ + // Close the popup when all if these are true: + // - the mouse is not on this popup + // - "mousemoved" was used + // - the mouse is no longer on the same screen row or the mouse column is + // outside of the relevant text + if (wp != mouse_wp + && wp->w_popup_mouse_row != 0 + && (wp->w_popup_mouse_row != mouse_row + || mouse_col < wp->w_popup_mouse_mincol + || mouse_col > wp->w_popup_mouse_maxcol)) + { + typval_T res; + + res.v_type = VAR_NUMBER; + res.vval.v_number = -2; + popup_close_and_callback(wp, &res); + } +} + +/* + * Called when the mouse moved: may close a popup with "mousemoved". + */ + void +popup_handle_mouse_moved(void) +{ + win_T *wp; + win_T *mouse_wp; + int row = mouse_row; + int col = mouse_col; + + // find the window where the mouse is in + mouse_wp = mouse_find_win(&row, &col, FIND_POPUP); + + for (wp = first_popupwin; wp != NULL; wp = wp->w_next) + check_mouse_moved(wp, mouse_wp); + for (wp = curtab->tp_first_popupwin; wp != NULL; wp = wp->w_next) + check_mouse_moved(wp, mouse_wp); +} + /* * In a filter: check if the typed key is a mouse event that is used for * dragging the popup. @@ -1821,7 +1948,7 @@ get_borderchars(dict_T *dict, win_T *wp) } /* - * For popup_getoptions(): add a "moved" entry to "dict". + * For popup_getoptions(): add a "moved" and "mousemoved" entry to "dict". */ static void get_moved_list(dict_T *dict, win_T *wp) @@ -1832,9 +1959,18 @@ get_moved_list(dict_T *dict, win_T *wp) if (list != NULL) { dict_add_list(dict, "moved", list); + list_append_number(list, wp->w_popup_lnum); list_append_number(list, wp->w_popup_mincol); list_append_number(list, wp->w_popup_maxcol); } + list = list_alloc(); + if (list != NULL) + { + dict_add_list(dict, "mousemoved", list); + list_append_number(list, wp->w_popup_mouse_row); + list_append_number(list, wp->w_popup_mouse_mincol); + list_append_number(list, wp->w_popup_mouse_maxcol); + } } /*