Skip to content

Commit aef8c3d

Browse files
committed
patch 8.0.1558: no right-click menu in a terminal
Problem: No right-click menu in a terminal. Solution: Implement the right click menu for the terminal.
1 parent c71807d commit aef8c3d

File tree

7 files changed

+344
-152
lines changed

7 files changed

+344
-152
lines changed

src/feature.h

+7
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,13 @@
726726
# endif
727727
#endif
728728

729+
/*
730+
* popup menu in a terminal
731+
*/
732+
#if defined(FEAT_MENU) && !defined(ALWAYS_USE_GUI) && defined(FEAT_INS_EXPAND)
733+
# define FEAT_TERM_POPUP_MENU
734+
#endif
735+
729736
/* There are two ways to use XPM. */
730737
#if (defined(HAVE_XM_XPMP_H) && defined(FEAT_GUI_MOTIF)) \
731738
|| defined(HAVE_X11_XPM_H)

src/menu.c

+67-57
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,6 @@ static int menu_namecmp(char_u *name, char_u *mname);
3434
static int get_menu_cmd_modes(char_u *, int, int *, int *);
3535
static char_u *popup_mode_name(char_u *name, int idx);
3636
static char_u *menu_text(char_u *text, int *mnemonic, char_u **actext);
37-
#ifdef FEAT_GUI
38-
static int get_menu_mode(void);
39-
static void gui_update_menus_recurse(vimmenu_T *, int);
40-
#endif
4137

4238
#if defined(FEAT_GUI_W32) && defined(FEAT_TEAROFF)
4339
static void gui_create_tearoffs_recurse(vimmenu_T *menu, const char_u *pname, int *pri_tab, int pri_idx);
@@ -1871,7 +1867,7 @@ menu_is_tearoff(char_u *name UNUSED)
18711867
}
18721868
#endif
18731869

1874-
#ifdef FEAT_GUI
1870+
#if defined(FEAT_GUI) || defined(FEAT_TERM_POPUP_MENU) || defined(PROTO)
18751871

18761872
static int
18771873
get_menu_mode(void)
@@ -1895,6 +1891,60 @@ get_menu_mode(void)
18951891
return MENU_INDEX_INVALID;
18961892
}
18971893

1894+
/*
1895+
* Display the Special "PopUp" menu as a pop-up at the current mouse
1896+
* position. The "PopUpn" menu is for Normal mode, "PopUpi" for Insert mode,
1897+
* etc.
1898+
*/
1899+
void
1900+
show_popupmenu(void)
1901+
{
1902+
vimmenu_T *menu;
1903+
int mode;
1904+
1905+
mode = get_menu_mode();
1906+
if (mode == MENU_INDEX_INVALID)
1907+
return;
1908+
mode = menu_mode_chars[mode];
1909+
1910+
# ifdef FEAT_AUTOCMD
1911+
{
1912+
char_u ename[2];
1913+
1914+
ename[0] = mode;
1915+
ename[1] = NUL;
1916+
apply_autocmds(EVENT_MENUPOPUP, ename, NULL, FALSE, curbuf);
1917+
}
1918+
# endif
1919+
1920+
for (menu = root_menu; menu != NULL; menu = menu->next)
1921+
if (STRNCMP("PopUp", menu->name, 5) == 0 && menu->name[5] == mode)
1922+
break;
1923+
1924+
/* Only show a popup when it is defined and has entries */
1925+
if (menu != NULL && menu->children != NULL)
1926+
{
1927+
# if defined(FEAT_GUI)
1928+
if (gui.in_use)
1929+
{
1930+
/* Update the menus now, in case the MenuPopup autocommand did
1931+
* anything. */
1932+
gui_update_menus(0);
1933+
gui_mch_show_popupmenu(menu);
1934+
}
1935+
# endif
1936+
# if defined(FEAT_GUI) && defined(FEAT_TERM_POPUP_MENU)
1937+
else
1938+
# endif
1939+
# if defined(FEAT_TERM_POPUP_MENU)
1940+
pum_show_popupmenu(menu);
1941+
# endif
1942+
}
1943+
}
1944+
#endif
1945+
1946+
#if defined(FEAT_GUI) || defined(PROTO)
1947+
18981948
/*
18991949
* Check that a pointer appears in the menu tree. Used to protect from using
19001950
* a menu that was deleted after it was selected but before the event was
@@ -1955,28 +2005,28 @@ gui_update_menus_recurse(vimmenu_T *menu, int mode)
19552005
while (menu)
19562006
{
19572007
if ((menu->modes & menu->enabled & mode)
1958-
#if defined(FEAT_GUI_W32) && defined(FEAT_TEAROFF)
2008+
# if defined(FEAT_GUI_W32) && defined(FEAT_TEAROFF)
19592009
|| menu_is_tearoff(menu->dname)
1960-
#endif
2010+
# endif
19612011
)
19622012
grey = FALSE;
19632013
else
19642014
grey = TRUE;
1965-
#ifdef FEAT_GUI_ATHENA
2015+
# ifdef FEAT_GUI_ATHENA
19662016
/* Hiding menus doesn't work for Athena, it can cause a crash. */
19672017
gui_mch_menu_grey(menu, grey);
1968-
#else
2018+
# else
19692019
/* Never hide a toplevel menu, it may make the menubar resize or
19702020
* disappear. Same problem for ToolBar items. */
19712021
if (vim_strchr(p_go, GO_GREY) != NULL || menu->parent == NULL
1972-
# ifdef FEAT_TOOLBAR
2022+
# ifdef FEAT_TOOLBAR
19732023
|| menu_is_toolbar(menu->parent->name)
1974-
# endif
2024+
# endif
19752025
)
19762026
gui_mch_menu_grey(menu, grey);
19772027
else
19782028
gui_mch_menu_hidden(menu, grey);
1979-
#endif
2029+
# endif
19802030
gui_update_menus_recurse(menu->children, mode);
19812031
menu = menu->next;
19822032
}
@@ -2010,15 +2060,15 @@ gui_update_menus(int modes)
20102060
gui_mch_draw_menubar();
20112061
prev_mode = mode;
20122062
force_menu_update = FALSE;
2013-
#ifdef FEAT_GUI_W32
2063+
# ifdef FEAT_GUI_W32
20142064
/* This can leave a tearoff as active window - make sure we
20152065
* have the focus <negri>*/
20162066
gui_mch_activate_window();
2017-
#endif
2067+
# endif
20182068
}
20192069
}
20202070

2021-
#if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) \
2071+
# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) \
20222072
|| defined(FEAT_GUI_GTK) || defined(FEAT_GUI_PHOTON) || defined(PROTO)
20232073
/*
20242074
* Check if a key is used as a mnemonic for a toplevel menu.
@@ -2037,47 +2087,7 @@ gui_is_menu_shortcut(int key)
20372087
return TRUE;
20382088
return FALSE;
20392089
}
2040-
#endif
2041-
2042-
/*
2043-
* Display the Special "PopUp" menu as a pop-up at the current mouse
2044-
* position. The "PopUpn" menu is for Normal mode, "PopUpi" for Insert mode,
2045-
* etc.
2046-
*/
2047-
void
2048-
gui_show_popupmenu(void)
2049-
{
2050-
vimmenu_T *menu;
2051-
int mode;
2052-
2053-
mode = get_menu_mode();
2054-
if (mode == MENU_INDEX_INVALID)
2055-
return;
2056-
mode = menu_mode_chars[mode];
2057-
2058-
#ifdef FEAT_AUTOCMD
2059-
{
2060-
char_u ename[2];
2061-
2062-
ename[0] = mode;
2063-
ename[1] = NUL;
2064-
apply_autocmds(EVENT_MENUPOPUP, ename, NULL, FALSE, curbuf);
2065-
}
2066-
#endif
2067-
2068-
for (menu = root_menu; menu != NULL; menu = menu->next)
2069-
if (STRNCMP("PopUp", menu->name, 5) == 0 && menu->name[5] == mode)
2070-
break;
2071-
2072-
/* Only show a popup when it is defined and has entries */
2073-
if (menu != NULL && menu->children != NULL)
2074-
{
2075-
/* Update the menus now, in case the MenuPopup autocommand did
2076-
* anything. */
2077-
gui_update_menus(0);
2078-
gui_mch_show_popupmenu(menu);
2079-
}
2080-
}
2090+
# endif
20812091
#endif /* FEAT_GUI */
20822092

20832093
#if (defined(FEAT_GUI_W32) && defined(FEAT_TEAROFF)) || defined(PROTO)
@@ -2238,7 +2248,7 @@ gui_destroy_tearoffs_recurse(vimmenu_T *menu)
22382248
* Execute "menu". Use by ":emenu" and the window toolbar.
22392249
* "eap" is NULL for the window toolbar.
22402250
*/
2241-
static void
2251+
void
22422252
execute_menu(exarg_T *eap, vimmenu_T *menu)
22432253
{
22442254
char_u *mode;

src/normal.c

+74-62
Original file line numberDiff line numberDiff line change
@@ -2286,12 +2286,12 @@ op_function(oparg_T *oap UNUSED)
22862286
* Do the appropriate action for the current mouse click in the current mode.
22872287
* Not used for Command-line mode.
22882288
*
2289-
* Normal Mode:
2289+
* Normal and Visual Mode:
22902290
* event modi- position visual change action
22912291
* fier cursor window
22922292
* left press - yes end yes
22932293
* left press C yes end yes "^]" (2)
2294-
* left press S yes end yes "*" (2)
2294+
* left press S yes end (popup: extend) yes "*" (2)
22952295
* left drag - yes start if moved no
22962296
* left relse - yes start if moved no
22972297
* middle press - yes if not active no put register
@@ -2670,82 +2670,94 @@ do_mouse(
26702670
if (which_button == MOUSE_RIGHT
26712671
&& !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)))
26722672
{
2673-
/*
2674-
* NOTE: Ignore right button down and drag mouse events.
2675-
* Windows only shows the popup menu on the button up event.
2676-
*/
26772673
#if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \
2674+
|| defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \
2675+
|| defined(FEAT_GUI_MAC) || defined(FEAT_GUI_PHOTON) \
2676+
|| defined(FEAT_TERM_POPUP_MENU)
2677+
# ifdef FEAT_GUI
2678+
if (gui.in_use)
2679+
{
2680+
# if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \
26782681
|| defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC)
2682+
if (!is_click)
2683+
/* Ignore right button release events, only shows the popup
2684+
* menu on the button down event. */
2685+
return FALSE;
2686+
# endif
2687+
# if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN)
2688+
if (is_click || is_drag)
2689+
/* Ignore right button down and drag mouse events. Windows
2690+
* only shows the popup menu on the button up event. */
2691+
return FALSE;
2692+
# endif
2693+
}
2694+
# endif
2695+
# if defined(FEAT_GUI) && defined(FEAT_TERM_POPUP_MENU)
2696+
else
2697+
# endif
2698+
# if defined(FEAT_TERM_POPUP_MENU)
26792699
if (!is_click)
2700+
/* Ignore right button release events, only shows the popup
2701+
* menu on the button down event. */
26802702
return FALSE;
26812703
#endif
2682-
#if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN)
2683-
if (is_click || is_drag)
2684-
return FALSE;
2685-
#endif
2686-
#if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \
2687-
|| defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \
2688-
|| defined(FEAT_GUI_MAC) || defined(FEAT_GUI_PHOTON)
2689-
if (gui.in_use)
2704+
2705+
jump_flags = 0;
2706+
if (STRCMP(p_mousem, "popup_setpos") == 0)
26902707
{
2691-
jump_flags = 0;
2692-
if (STRCMP(p_mousem, "popup_setpos") == 0)
2708+
/* First set the cursor position before showing the popup
2709+
* menu. */
2710+
if (VIsual_active)
26932711
{
2694-
/* First set the cursor position before showing the popup
2695-
* menu. */
2696-
if (VIsual_active)
2712+
pos_T m_pos;
2713+
2714+
/*
2715+
* set MOUSE_MAY_STOP_VIS if we are outside the
2716+
* selection or the current window (might have false
2717+
* negative here)
2718+
*/
2719+
if (mouse_row < curwin->w_winrow
2720+
|| mouse_row
2721+
> (curwin->w_winrow + curwin->w_height))
2722+
jump_flags = MOUSE_MAY_STOP_VIS;
2723+
else if (get_fpos_of_mouse(&m_pos) != IN_BUFFER)
2724+
jump_flags = MOUSE_MAY_STOP_VIS;
2725+
else
26972726
{
2698-
pos_T m_pos;
2699-
2700-
/*
2701-
* set MOUSE_MAY_STOP_VIS if we are outside the
2702-
* selection or the current window (might have false
2703-
* negative here)
2704-
*/
2705-
if (mouse_row < curwin->w_winrow
2706-
|| mouse_row
2707-
> (curwin->w_winrow + curwin->w_height))
2708-
jump_flags = MOUSE_MAY_STOP_VIS;
2709-
else if (get_fpos_of_mouse(&m_pos) != IN_BUFFER)
2727+
if ((LT_POS(curwin->w_cursor, VIsual)
2728+
&& (LT_POS(m_pos, curwin->w_cursor)
2729+
|| LT_POS(VIsual, m_pos)))
2730+
|| (LT_POS(VIsual, curwin->w_cursor)
2731+
&& (LT_POS(m_pos, VIsual)
2732+
|| LT_POS(curwin->w_cursor, m_pos))))
2733+
{
27102734
jump_flags = MOUSE_MAY_STOP_VIS;
2711-
else
2735+
}
2736+
else if (VIsual_mode == Ctrl_V)
27122737
{
2713-
if ((LT_POS(curwin->w_cursor, VIsual)
2714-
&& (LT_POS(m_pos, curwin->w_cursor)
2715-
|| LT_POS(VIsual, m_pos)))
2716-
|| (LT_POS(VIsual, curwin->w_cursor)
2717-
&& (LT_POS(m_pos, VIsual)
2718-
|| LT_POS(curwin->w_cursor, m_pos))))
2719-
{
2738+
getvcols(curwin, &curwin->w_cursor, &VIsual,
2739+
&leftcol, &rightcol);
2740+
getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL);
2741+
if (m_pos.col < leftcol || m_pos.col > rightcol)
27202742
jump_flags = MOUSE_MAY_STOP_VIS;
2721-
}
2722-
else if (VIsual_mode == Ctrl_V)
2723-
{
2724-
getvcols(curwin, &curwin->w_cursor, &VIsual,
2725-
&leftcol, &rightcol);
2726-
getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL);
2727-
if (m_pos.col < leftcol || m_pos.col > rightcol)
2728-
jump_flags = MOUSE_MAY_STOP_VIS;
2729-
}
27302743
}
27312744
}
2732-
else
2733-
jump_flags = MOUSE_MAY_STOP_VIS;
2734-
}
2735-
if (jump_flags)
2736-
{
2737-
jump_flags = jump_to_mouse(jump_flags, NULL, which_button);
2738-
update_curbuf(VIsual_active ? INVERTED : VALID);
2739-
setcursor();
2740-
out_flush(); /* Update before showing popup menu */
27412745
}
2746+
else
2747+
jump_flags = MOUSE_MAY_STOP_VIS;
2748+
}
2749+
if (jump_flags)
2750+
{
2751+
jump_flags = jump_to_mouse(jump_flags, NULL, which_button);
2752+
update_curbuf(VIsual_active ? INVERTED : VALID);
2753+
setcursor();
2754+
out_flush(); /* Update before showing popup menu */
2755+
}
27422756
# ifdef FEAT_MENU
2743-
gui_show_popupmenu();
2757+
show_popupmenu();
2758+
got_click = FALSE; /* ignore release events */
27442759
# endif
2745-
return (jump_flags & CURSOR_MOVED) != 0;
2746-
}
2747-
else
2748-
return FALSE;
2760+
return (jump_flags & CURSOR_MOVED) != 0;
27492761
#else
27502762
return FALSE;
27512763
#endif

0 commit comments

Comments
 (0)