]> granicus.if.org Git - vim/commitdiff
patch 8.1.1525: cannot move a popup window with the mouse v8.1.1525
authorBram Moolenaar <Bram@vim.org>
Thu, 13 Jun 2019 21:59:52 +0000 (23:59 +0200)
committerBram Moolenaar <Bram@vim.org>
Thu, 13 Jun 2019 21:59:52 +0000 (23:59 +0200)
Problem:    Cannot move a popup window with the mouse.
Solution:   Add the "drag" property and make it possible to drag a popup
            window by its border.

runtime/doc/popup.txt
src/popupwin.c
src/proto/popupwin.pro
src/proto/window.pro
src/structs.h
src/ui.c
src/version.c
src/window.c

index 7e56d35b9beafeb44187b3ea6412c38f5f6a35c6..7da0d1689605a5a7151f16340a9083d71e31346f 100644 (file)
@@ -95,7 +95,7 @@ IMPLEMENTATION:
 - For the "moved" property also include mouse movement?
 - When selecting text in the popup with modeless selection, do not select
   outside of the popup and don't select the border or padding.
-- Allow the user to drag the popup window when the "dragging" property is set.
+- Add test for dragging the popup window.
 - Make redrawing more efficient and avoid flicker:
     - put popup menu also put in popup_mask?
 - Invoke filter with character before mapping?
@@ -277,7 +277,7 @@ popup_menu({text}, {options})                                *popup_menu()*
 
 
 popup_move({id}, {options})                                    *popup_move()*
-               Move popup {id} to the position speficied with {options}.
+               Move popup {id} to the position specified with {options}.
                {options} may contain the items from |popup_create()| that
                specify the popup position: "line", "col", "pos", "maxheight",
                "minheight", "maxwidth" and "minwidth".
@@ -293,6 +293,7 @@ popup_notification({text}, {options})                        *popup_notification()*
                                \ 'time': 3000,
                                \ 'tab': -1,
                                \ 'zindex': 200,
+                               \ 'drag': 1,
                                \ 'highlight': 'WarningMsg',
                                \ 'border': [],
                                \ 'padding': [0,1,0,1],
@@ -409,9 +410,13 @@ The second argument of |popup_create()| is a dictionary with options:
                        {only -1 and 0 are implemented}
        title           Text to be displayed above the first item in the
                        popup, on top of any border.  If there is no top
-                       border on line of padding is added to put the title on.
+                       border one line of padding is added to put the title
+                       on.
                        {not implemented yet}
        wrap            TRUE to make the lines wrap (default TRUE).
+       drag            TRUE to allow the popup to be dragged with the mouse
+                       by grabbing at at the border.  Has no effect if the
+                       popup does not have a border.
        highlight       Highlight group name to use for the text, stored in
                        the 'wincolor' option.
        padding         List with numbers, defining the padding
@@ -442,7 +447,7 @@ The second argument of |popup_create()| is a dictionary with options:
                        By default a double line is used all around when
                        'encoding' is "utf-8", otherwise ASCII characters are
                        used.
-       zindex          Priority for the popup, default 50.  Mininum value is
+       zindex          Priority for the popup, default 50.  Minimum value is
                        1, maximum value is 32000.
        time            Time in milliseconds after which the popup will close.
                        When omitted |popup_close()| must be used.
index 5e444aee038e387240c85026b2b5612cca639b00..f773958bee1c19ef3ff31de0fb2d99c95340a9c4 100644 (file)
@@ -164,6 +164,68 @@ set_moved_columns(win_T *wp, int flags)
     }
 }
 
+/*
+ * Return TRUE if "row"/"col" is on the border of the popup.
+ * The values are relative to the top-left corner.
+ */
+    int
+popup_on_border(win_T *wp, int row, int col)
+{
+    return (row == 0 && wp->w_popup_border[0] > 0)
+           || (row == popup_height(wp) - 1 && wp->w_popup_border[2] > 0)
+           || (col == 0 && wp->w_popup_border[3] > 0)
+           || (col == popup_width(wp) - 1 && wp->w_popup_border[1] > 0);
+}
+
+// Values set when dragging a popup window starts.
+static int drag_start_row;
+static int drag_start_col;
+static int drag_start_wantline;
+static int drag_start_wantcol;
+
+/*
+ * Mouse down on border of popup window: start dragging it.
+ * Uses mouse_col and mouse_row.
+ */
+    void
+popup_start_drag(win_T *wp)
+{
+    drag_start_row = mouse_row;
+    drag_start_col = mouse_col;
+    // TODO: handle using different corner
+    if (wp->w_wantline == 0)
+       drag_start_wantline = wp->w_winrow + 1;
+    else
+       drag_start_wantline = wp->w_wantline;
+    if (wp->w_wantcol == 0)
+       drag_start_wantcol = wp->w_wincol + 1;
+    else
+       drag_start_wantcol = wp->w_wantcol;
+}
+
+/*
+ * Mouse moved while dragging a popup window: adjust the window popup position.
+ */
+    void
+popup_drag(win_T *wp)
+{
+    // The popup may be closed before dragging stops.
+    if (!win_valid_popup(wp))
+       return;
+
+    wp->w_wantline = drag_start_wantline + (mouse_row - drag_start_row);
+    if (wp->w_wantline < 1)
+       wp->w_wantline = 1;
+    if (wp->w_wantline > Rows)
+       wp->w_wantline = Rows;
+    wp->w_wantcol = drag_start_wantcol + (mouse_col - drag_start_col);
+    if (wp->w_wantcol < 1)
+       wp->w_wantcol = 1;
+    if (wp->w_wantcol > Columns)
+       wp->w_wantcol = Columns;
+
+    popup_adjust_position(wp);
+}
 
 #if defined(FEAT_TIMERS)
     static void
@@ -237,6 +299,8 @@ apply_options(win_T *wp, buf_T *buf UNUSED, dict_T *dict)
        wp->w_p_wrap = nr != 0;
     }
 
+    wp->w_popup_drag = dict_get_number(dict, (char_u *)"drag");
+
     di = dict_find(dict, (char_u *)"callback", -1);
     if (di != NULL)
     {
@@ -798,6 +862,7 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
        wp->w_popup_padding[3] = 1;
        set_string_option_direct_in_win(wp, (char_u *)"wincolor", -1,
                                (char_u *)"WarningMsg", OPT_FREE|OPT_LOCAL, 0);
+       wp->w_popup_drag = 1;
     }
 
     // Deal with options.
index 03d3729ed04e087c4957f11f7c4ae8e84cab3a97..eeabafa9a6c6f1c707b97589ec819e1f80e30a30 100644 (file)
@@ -1,4 +1,7 @@
 /* popupwin.c */
+int popup_on_border(win_T *wp, int row, int col);
+void popup_start_drag(win_T *wp);
+void popup_drag(win_T *wp);
 int popup_height(win_T *wp);
 int popup_width(win_T *wp);
 void popup_adjust_position(win_T *wp);
index 1424c3de5aa3752f7505025a4fdac1b8106b41cc..94b9f083a1ca6445b483f6c98f9979c21f659b93 100644 (file)
@@ -3,6 +3,7 @@ void do_window(int nchar, long Prenum, int xchar);
 void get_wincmd_addr_type(char_u *arg, exarg_T *eap);
 int win_split(int size, int flags);
 int win_split_ins(int size, int flags, win_T *new_wp, int dir);
+int win_valid_popup(win_T *win);
 int win_valid(win_T *win);
 int win_valid_any_tab(win_T *win);
 int win_count(void);
index da5ed2e53aae8c7c5e9a56ab2dd446dfbf86fa71..04e21a106ce4b4510c1dbcc89204e9a8e76b65af 100644 (file)
@@ -2909,6 +2909,7 @@ struct window_S
     linenr_T   w_popup_lnum;       // close popup if cursor not on this line
     colnr_T    w_popup_mincol;     // close popup if cursor before this col
     colnr_T    w_popup_maxcol;     // close popup if cursor after this col
+    int                w_popup_drag;       // allow moving the popup with the mouse
 
 # if defined(FEAT_TIMERS)
     timer_T    *w_popup_timer;     // timer for closing popup window
index 62d8ae7d3ef456bb5457dba1b1ed4d08a5acdf76..08b3011c0e2a84003a7176a0b7ec9eb201bd4475 100644 (file)
--- a/src/ui.c
+++ b/src/ui.c
@@ -1002,7 +1002,7 @@ static void clip_update_modeless_selection(VimClipboard *, int, int,
 
 /*
  * Start, continue or end a modeless selection.  Used when editing the
- * command-line and in the cmdline window.
+ * command-line, in the cmdline window and when the mouse is in a popup window.
  */
     void
 clip_modeless(int button, int is_click, int is_drag)
@@ -2841,7 +2841,8 @@ jump_to_mouse(
     static int  in_winbar = FALSE;
 #endif
 #ifdef FEAT_TEXT_PROP
-    static int  in_popup_win = FALSE;
+    static int   in_popup_win = FALSE;
+    static win_T *popup_dragwin = NULL;
 #endif
     static int prev_row = -1;
     static int prev_col = -1;
@@ -2869,6 +2870,9 @@ jump_to_mouse(
            flags &= ~(MOUSE_FOCUS | MOUSE_DID_MOVE);
        dragwin = NULL;
        did_drag = FALSE;
+#ifdef FEAT_TEXT_PROP
+       popup_dragwin = NULL;
+#endif
     }
 
     if ((flags & MOUSE_DID_MOVE)
@@ -2910,7 +2914,15 @@ retnomove:
 #ifdef FEAT_TEXT_PROP
        // Continue a modeless selection in a popup window.
        if (in_popup_win)
+       {
+           if (popup_dragwin != NULL)
+           {
+               // dragging a popup window
+               popup_drag(popup_dragwin);
+               return IN_UNKNOWN;
+           }
            return IN_OTHER_WIN;
+       }
 #endif
        return IN_BUFFER;
     }
@@ -2936,29 +2948,36 @@ retnomove:
 
     if (!(flags & MOUSE_FOCUS))
     {
-       if (row < 0 || col < 0)                 /* check if it makes sense */
+       if (row < 0 || col < 0)                 // check if it makes sense
            return IN_UNKNOWN;
 
-       /* find the window where the row is in */
+       // find the window where the row is in
        wp = mouse_find_win(&row, &col, FIND_POPUP);
        if (wp == NULL)
            return IN_UNKNOWN;
        dragwin = NULL;
 
 #ifdef FEAT_TEXT_PROP
-       // Click in a popup window may start modeless selection, but not much
-       // else.
+       // Click in a popup window may start dragging or modeless selection,
+       // but not much else.
        if (bt_popup(wp->w_buffer))
        {
            on_sep_line = 0;
            in_popup_win = TRUE;
+           if (wp->w_popup_drag && popup_on_border(wp, row, col))
+           {
+               popup_dragwin = wp;
+               popup_start_drag(wp);
+               return IN_UNKNOWN;
+           }
 # ifdef FEAT_CLIPBOARD
            return IN_OTHER_WIN;
 # else
            return IN_UNKNOWN;
 # endif
        }
-           in_popup_win = FALSE;
+       in_popup_win = FALSE;
+       popup_dragwin = NULL;
 #endif
 #ifdef FEAT_MENU
        if (row == -1)
@@ -3127,9 +3146,17 @@ retnomove:
            return IN_OTHER_WIN;
 #endif
 #ifdef FEAT_TEXT_PROP
-       // Continue a modeless selection in a popup window.
        if (in_popup_win)
+       {
+           if (popup_dragwin != NULL)
+           {
+               // dragging a popup window
+               popup_drag(popup_dragwin);
+               return IN_UNKNOWN;
+           }
+           // continue a modeless selection in a popup window
            return IN_OTHER_WIN;
+       }
 #endif
 
        row -= W_WINROW(curwin);
index 9835fcc7e22190c8a234353731cd9edff2e8843c..058dbc702d6a98d23fd3ef52d471b89d2c4dae82 100644 (file)
@@ -777,6 +777,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1525,
 /**/
     1524,
 /**/
index c15a86111b7d730ba245a943d094160514290eba..436912934eee2a0ce0be5f41b5bf60a97a80dec1 100644 (file)
@@ -1371,7 +1371,7 @@ win_init_some(win_T *newp, win_T *oldp)
 /*
  * Return TRUE if "win" is a global popup or a popup in the current tab page.
  */
-    static int
+    int
 win_valid_popup(win_T *win UNUSED)
 {
 #ifdef FEAT_TEXT_PROP