]> granicus.if.org Git - vim/commitdiff
patch 8.1.1799: cannot avoid mapping for a popup window v8.1.1799
authorBram Moolenaar <Bram@vim.org>
Sat, 3 Aug 2019 14:18:07 +0000 (16:18 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 3 Aug 2019 14:18:07 +0000 (16:18 +0200)
Problem:    Cannot avoid mapping for a popup window.
Solution:   Add the "mapping" property, default TRUE.

runtime/doc/popup.txt
src/getchar.c
src/popupwin.c
src/proto/popupwin.pro
src/testdir/test_popupwin.vim
src/version.c
src/vim.h

index b58ade69d260123c73f4db2cf60feb147d95ad28..bac34331f86fdb5255c08eda9777f48cc0ca03be 100644 (file)
@@ -246,6 +246,7 @@ popup_dialog({what}, {options})                             *popup_dialog()*
                                \ drag: 1,
                                \ border: [],
                                \ padding: [],
+                               \ mapping: 0,
                                \})
 <              Use {options} to change the properties. E.g. add a 'filter'
                option with value 'popup_filter_yesno'.  Example: >
@@ -369,12 +370,20 @@ popup_menu({what}, {options})                              *popup_menu()*
                                \ cursorline: 1,
                                \ padding: [0,1,0,1],
                                \ filter: 'popup_filter_menu',
+                               \ mapping: 0,
                                \ })
 <              The current line is highlighted with a match using
                "PopupSelected", or "PmenuSel" if that is not defined.
 
                Use {options} to change the properties.  Should at least set
                "callback" to a function that handles the selected item.
+               Example: >
+                       func ColorSelected(id, result)
+                          " use a:result
+                       endfunc
+                       call popup_menu(['red', 'green', 'blue'], #{
+                               \ callback: 'ColorSelected',
+                               \ })
 
 
 popup_move({id}, {options})                                    *popup_move()*
@@ -433,16 +442,17 @@ popup_setoptions({id}, {options})                 *popup_setoptions()*
                        borderhighlight
                        callback
                        close
-                       drag
-                       resize
                        cursorline
+                       drag
                        filter
                        firstline
                        flip
                        highlight
+                       mapping
                        mask
                        moved
                        padding
+                       resize
                        scrollbar
                        scrollbarhighlight
                        thumbhighlight
@@ -615,6 +625,9 @@ The second argument of |popup_create()| is a dictionary with options:
                        Default is zero, except for |popup_menu()|.
        filter          A callback that can filter typed characters, see
                        |popup-filter|.
+       mapping         Allow for key mapping.  When FALSE and the popup is
+                       visible and has a filter callback key mapping is
+                       disabled.  Default value is TRUE.
        callback        A callback that is called when the popup closes, e.g.
                        when using |popup_filter_menu()|, see |popup-callback|.
 
@@ -671,8 +684,11 @@ key as a string, e.g.: >
          endif
          return 0
        endfunc
-
-Currently the key is what results after any mapping.  This may change...
+<                                                      *popup-mapping*
+Normally the key is what results after any mapping, since the keys pass on as
+normal input if the filter does not use it.  If the filter consumes all the
+keys, set the "mapping" property to zero so that mappings do not get in the
+way.  This is default for |popup_menu()| and |popup_dialog()|.
 
 Some common key actions:
        x               close the popup (see note below)
@@ -703,6 +719,11 @@ the second argument of `popup_close()`.
 If the popup is force-closed, e.g. because the cursor moved or CTRL-C was
 pressed, the number -1 is passed to the callback.
 
+Example: >
+       func SelectedColor(id, result)
+          echo 'choice made: ' .. a:result
+       endfunc
+
 
 POPUP SCROLLBAR                                                *popup-scrollbar*
 
index fe1cc7e2ef214948ed66b8051e392d50bc89aabc..4a3587c3f27d4dad7650cf1404d7597f1a148676 100644 (file)
@@ -1574,6 +1574,9 @@ vgetc(void)
            if (mod_mask
 #if defined(FEAT_XIM) && defined(FEAT_GUI_GTK)
                    || im_is_preediting()
+#endif
+#if defined(FEAT_TEXT_PROP)
+                   || popup_no_mapping()
 #endif
                    )
            {
index 4ca6d9fdf1a4a80aa4db6d2f7882f7e07b3c3379..28ad48cfc850526f7ac6394d83a7a1b85ad2b887 100644 (file)
@@ -800,6 +800,15 @@ apply_general_options(win_T *wp, dict_T *dict)
            set_callback(&wp->w_filter_cb, &callback);
        }
     }
+    di = dict_find(dict, (char_u *)"mapping", -1);
+    if (di != NULL)
+    {
+       nr = dict_get_number(dict, (char_u *)"mapping");
+       if (nr)
+           wp->w_popup_flags |= POPF_MAPPING;
+       else
+           wp->w_popup_flags &= ~POPF_MAPPING;
+    }
 
     di = dict_find(dict, (char_u *)"callback", -1);
     if (di != NULL)
@@ -1413,7 +1422,7 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
     if (rettv != NULL)
        rettv->vval.v_number = wp->w_id;
     wp->w_popup_pos = POPPOS_TOPLEFT;
-    wp->w_popup_flags = POPF_IS_POPUP;
+    wp->w_popup_flags = POPF_IS_POPUP | POPF_MAPPING;
 
     if (buf != NULL)
     {
@@ -1561,6 +1570,7 @@ popup_create(typval_T *argvars, typval_T *rettv, create_type_T type)
        wp->w_popup_pos = POPPOS_CENTER;
        wp->w_zindex = POPUPWIN_DIALOG_ZINDEX;
        wp->w_popup_flags |= POPF_DRAG;
+       wp->w_popup_flags &= ~POPF_MAPPING;
        for (i = 0; i < 4; ++i)
        {
            wp->w_popup_border[i] = 1;
@@ -2501,6 +2511,25 @@ popup_do_filter(int c)
     return res;
 }
 
+/*
+ * Return TRUE if there is a popup visible with a filter callback and the
+ * "mapping" property off.
+ */
+    int
+popup_no_mapping(void)
+{
+    int            round;
+    win_T   *wp;
+
+    for (round = 1; round <= 2; ++round)
+       for (wp = round == 1 ? first_popupwin : curtab->tp_first_popupwin;
+                                                  wp != NULL; wp = wp->w_next)
+           if (wp->w_filter_cb.cb_name != NULL
+                   && (wp->w_popup_flags & (POPF_HIDDEN | POPF_MAPPING)) == 0)
+               return TRUE;
+    return FALSE;
+}
+
 /*
  * Called when the cursor moved: check if any popup needs to be closed if the
  * cursor moved far enough.
index b964fc0dd02a921e711ddefb2aa8f27709db7388..f1d0d2b5233ba3cb1ac4aa652fd67990a52874bf 100644 (file)
@@ -38,6 +38,7 @@ int error_if_popup_window(void);
 void popup_reset_handled(void);
 win_T *find_next_popup(int lowest);
 int popup_do_filter(int c);
+int popup_no_mapping(void);
 void popup_check_cursor_pos(void);
 void may_update_popup_mask(int type);
 void update_popups(void (*win_update)(win_T *wp));
index d4b98aee7be43d95550fdfbde80dabf3be868091..e5d16314bc4e3a8f6f63d878be1e919ad4cd69df 100644 (file)
@@ -657,6 +657,7 @@ func Test_popup_invalid_arguments()
   call assert_fails('call popup_create("text", #{mask: ["asdf"]})', 'E475:')
   call popup_clear()
   call assert_fails('call popup_create("text", #{mask: test_null_list()})', 'E475:')
+  call assert_fails('call popup_create("text", #{mapping: []})', 'E745:')
   call popup_clear()
 endfunc
 
@@ -1203,6 +1204,8 @@ func Test_popup_menu()
     let s:cb_winid = a:id
     let s:cb_res = a:res
   endfunc
+  " mapping won't be used in popup
+  map j k
 
   let winid = ShowMenu(" ", 1)
   let winid = ShowMenu("j \<CR>", 2)
@@ -1215,6 +1218,7 @@ func Test_popup_menu()
   let winid = ShowMenu("\<C-C>", -1)
 
   delfunc QuitCallback
+  unmap j
 endfunc
 
 func Test_popup_menu_screenshot()
@@ -2194,6 +2198,9 @@ func Test_previewpopup()
   call term_sendkeys(buf, "/another\<CR>\<C-W>}")
   call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_4', {})
 
+  call term_sendkeys(buf, ":cd ..\<CR>:\<CR>")
+  call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_5', {})
+
   call StopVimInTerminal(buf)
   call delete('Xtags')
   call delete('Xtagfile')
index ec67fe406026c22f3234b3032066d7485eedb315..b2c4416ae3de4fd9bc5139e630097d054dd1a24d 100644 (file)
@@ -773,6 +773,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1799,
 /**/
     1798,
 /**/
index 02b4c03bc65d6d5143f70046132d1de680ecc62b..70fcf3a12cece1be9ebc62ddbc8dafa4e69cb699 100644 (file)
--- a/src/vim.h
+++ b/src/vim.h
@@ -621,6 +621,7 @@ extern int (*dyn_libintl_wputenv)(const wchar_t *envstring);
 #define POPF_ON_CMDLINE        0x10    // popup overlaps command line
 #define POPF_DRAG      0x20    // popup can be moved by dragging
 #define POPF_RESIZE    0x40    // popup can be resized by dragging
+#define POPF_MAPPING   0x80    // mapping keys
 
 #ifdef FEAT_TEXT_PROP
 # define WIN_IS_POPUP(wp) ((wp)->w_popup_flags != 0)