Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
brammool committed Mar 3, 2018
1 parent c71807d commit aef8c3d
Show file tree
Hide file tree
Showing 7 changed files with 344 additions and 152 deletions.
7 changes: 7 additions & 0 deletions src/feature.h
Expand Up @@ -726,6 +726,13 @@
# endif
#endif

/*
* popup menu in a terminal
*/
#if defined(FEAT_MENU) && !defined(ALWAYS_USE_GUI) && defined(FEAT_INS_EXPAND)
# define FEAT_TERM_POPUP_MENU
#endif

/* There are two ways to use XPM. */
#if (defined(HAVE_XM_XPMP_H) && defined(FEAT_GUI_MOTIF)) \
|| defined(HAVE_X11_XPM_H)
Expand Down
124 changes: 67 additions & 57 deletions src/menu.c
Expand Up @@ -34,10 +34,6 @@ static int menu_namecmp(char_u *name, char_u *mname);
static int get_menu_cmd_modes(char_u *, int, int *, int *);
static char_u *popup_mode_name(char_u *name, int idx);
static char_u *menu_text(char_u *text, int *mnemonic, char_u **actext);
#ifdef FEAT_GUI
static int get_menu_mode(void);
static void gui_update_menus_recurse(vimmenu_T *, int);
#endif

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

#ifdef FEAT_GUI
#if defined(FEAT_GUI) || defined(FEAT_TERM_POPUP_MENU) || defined(PROTO)

static int
get_menu_mode(void)
Expand All @@ -1895,6 +1891,60 @@ get_menu_mode(void)
return MENU_INDEX_INVALID;
}

/*
* Display the Special "PopUp" menu as a pop-up at the current mouse
* position. The "PopUpn" menu is for Normal mode, "PopUpi" for Insert mode,
* etc.
*/
void
show_popupmenu(void)
{
vimmenu_T *menu;
int mode;

mode = get_menu_mode();
if (mode == MENU_INDEX_INVALID)
return;
mode = menu_mode_chars[mode];

# ifdef FEAT_AUTOCMD
{
char_u ename[2];

ename[0] = mode;
ename[1] = NUL;
apply_autocmds(EVENT_MENUPOPUP, ename, NULL, FALSE, curbuf);
}
# endif

for (menu = root_menu; menu != NULL; menu = menu->next)
if (STRNCMP("PopUp", menu->name, 5) == 0 && menu->name[5] == mode)
break;

/* Only show a popup when it is defined and has entries */
if (menu != NULL && menu->children != NULL)
{
# if defined(FEAT_GUI)
if (gui.in_use)
{
/* Update the menus now, in case the MenuPopup autocommand did
* anything. */
gui_update_menus(0);
gui_mch_show_popupmenu(menu);
}
# endif
# if defined(FEAT_GUI) && defined(FEAT_TERM_POPUP_MENU)
else
# endif
# if defined(FEAT_TERM_POPUP_MENU)
pum_show_popupmenu(menu);
# endif
}
}
#endif

#if defined(FEAT_GUI) || defined(PROTO)

/*
* Check that a pointer appears in the menu tree. Used to protect from using
* a menu that was deleted after it was selected but before the event was
Expand Down Expand Up @@ -1955,28 +2005,28 @@ gui_update_menus_recurse(vimmenu_T *menu, int mode)
while (menu)
{
if ((menu->modes & menu->enabled & mode)
#if defined(FEAT_GUI_W32) && defined(FEAT_TEAROFF)
# if defined(FEAT_GUI_W32) && defined(FEAT_TEAROFF)
|| menu_is_tearoff(menu->dname)
#endif
# endif
)
grey = FALSE;
else
grey = TRUE;
#ifdef FEAT_GUI_ATHENA
# ifdef FEAT_GUI_ATHENA
/* Hiding menus doesn't work for Athena, it can cause a crash. */
gui_mch_menu_grey(menu, grey);
#else
# else
/* Never hide a toplevel menu, it may make the menubar resize or
* disappear. Same problem for ToolBar items. */
if (vim_strchr(p_go, GO_GREY) != NULL || menu->parent == NULL
# ifdef FEAT_TOOLBAR
# ifdef FEAT_TOOLBAR
|| menu_is_toolbar(menu->parent->name)
# endif
# endif
)
gui_mch_menu_grey(menu, grey);
else
gui_mch_menu_hidden(menu, grey);
#endif
# endif
gui_update_menus_recurse(menu->children, mode);
menu = menu->next;
}
Expand Down Expand Up @@ -2010,15 +2060,15 @@ gui_update_menus(int modes)
gui_mch_draw_menubar();
prev_mode = mode;
force_menu_update = FALSE;
#ifdef FEAT_GUI_W32
# ifdef FEAT_GUI_W32
/* This can leave a tearoff as active window - make sure we
* have the focus <negri>*/
gui_mch_activate_window();
#endif
# endif
}
}

#if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) \
# if defined(FEAT_GUI_MSWIN) || defined(FEAT_GUI_MOTIF) \
|| defined(FEAT_GUI_GTK) || defined(FEAT_GUI_PHOTON) || defined(PROTO)
/*
* Check if a key is used as a mnemonic for a toplevel menu.
Expand All @@ -2037,47 +2087,7 @@ gui_is_menu_shortcut(int key)
return TRUE;
return FALSE;
}
#endif

/*
* Display the Special "PopUp" menu as a pop-up at the current mouse
* position. The "PopUpn" menu is for Normal mode, "PopUpi" for Insert mode,
* etc.
*/
void
gui_show_popupmenu(void)
{
vimmenu_T *menu;
int mode;

mode = get_menu_mode();
if (mode == MENU_INDEX_INVALID)
return;
mode = menu_mode_chars[mode];

#ifdef FEAT_AUTOCMD
{
char_u ename[2];

ename[0] = mode;
ename[1] = NUL;
apply_autocmds(EVENT_MENUPOPUP, ename, NULL, FALSE, curbuf);
}
#endif

for (menu = root_menu; menu != NULL; menu = menu->next)
if (STRNCMP("PopUp", menu->name, 5) == 0 && menu->name[5] == mode)
break;

/* Only show a popup when it is defined and has entries */
if (menu != NULL && menu->children != NULL)
{
/* Update the menus now, in case the MenuPopup autocommand did
* anything. */
gui_update_menus(0);
gui_mch_show_popupmenu(menu);
}
}
# endif
#endif /* FEAT_GUI */

#if (defined(FEAT_GUI_W32) && defined(FEAT_TEAROFF)) || defined(PROTO)
Expand Down Expand Up @@ -2238,7 +2248,7 @@ gui_destroy_tearoffs_recurse(vimmenu_T *menu)
* Execute "menu". Use by ":emenu" and the window toolbar.
* "eap" is NULL for the window toolbar.
*/
static void
void
execute_menu(exarg_T *eap, vimmenu_T *menu)
{
char_u *mode;
Expand Down
136 changes: 74 additions & 62 deletions src/normal.c
Expand Up @@ -2286,12 +2286,12 @@ op_function(oparg_T *oap UNUSED)
* Do the appropriate action for the current mouse click in the current mode.
* Not used for Command-line mode.
*
* Normal Mode:
* Normal and Visual Mode:
* event modi- position visual change action
* fier cursor window
* left press - yes end yes
* left press C yes end yes "^]" (2)
* left press S yes end yes "*" (2)
* left press S yes end (popup: extend) yes "*" (2)
* left drag - yes start if moved no
* left relse - yes start if moved no
* middle press - yes if not active no put register
Expand Down Expand Up @@ -2670,82 +2670,94 @@ do_mouse(
if (which_button == MOUSE_RIGHT
&& !(mod_mask & (MOD_MASK_SHIFT | MOD_MASK_CTRL)))
{
/*
* NOTE: Ignore right button down and drag mouse events.
* Windows only shows the popup menu on the button up event.
*/
#if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \
|| defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \
|| defined(FEAT_GUI_MAC) || defined(FEAT_GUI_PHOTON) \
|| defined(FEAT_TERM_POPUP_MENU)
# ifdef FEAT_GUI
if (gui.in_use)
{
# if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \
|| defined(FEAT_GUI_PHOTON) || defined(FEAT_GUI_MAC)
if (!is_click)
/* Ignore right button release events, only shows the popup
* menu on the button down event. */
return FALSE;
# endif
# if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN)
if (is_click || is_drag)
/* Ignore right button down and drag mouse events. Windows
* only shows the popup menu on the button up event. */
return FALSE;
# endif
}
# endif
# if defined(FEAT_GUI) && defined(FEAT_TERM_POPUP_MENU)
else
# endif
# if defined(FEAT_TERM_POPUP_MENU)
if (!is_click)
/* Ignore right button release events, only shows the popup
* menu on the button down event. */
return FALSE;
#endif
#if defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN)
if (is_click || is_drag)
return FALSE;
#endif
#if defined(FEAT_GUI_MOTIF) || defined(FEAT_GUI_GTK) \
|| defined(FEAT_GUI_ATHENA) || defined(FEAT_GUI_MSWIN) \
|| defined(FEAT_GUI_MAC) || defined(FEAT_GUI_PHOTON)
if (gui.in_use)

jump_flags = 0;
if (STRCMP(p_mousem, "popup_setpos") == 0)
{
jump_flags = 0;
if (STRCMP(p_mousem, "popup_setpos") == 0)
/* First set the cursor position before showing the popup
* menu. */
if (VIsual_active)
{
/* First set the cursor position before showing the popup
* menu. */
if (VIsual_active)
pos_T m_pos;

/*
* set MOUSE_MAY_STOP_VIS if we are outside the
* selection or the current window (might have false
* negative here)
*/
if (mouse_row < curwin->w_winrow
|| mouse_row
> (curwin->w_winrow + curwin->w_height))
jump_flags = MOUSE_MAY_STOP_VIS;
else if (get_fpos_of_mouse(&m_pos) != IN_BUFFER)
jump_flags = MOUSE_MAY_STOP_VIS;
else
{
pos_T m_pos;

/*
* set MOUSE_MAY_STOP_VIS if we are outside the
* selection or the current window (might have false
* negative here)
*/
if (mouse_row < curwin->w_winrow
|| mouse_row
> (curwin->w_winrow + curwin->w_height))
jump_flags = MOUSE_MAY_STOP_VIS;
else if (get_fpos_of_mouse(&m_pos) != IN_BUFFER)
if ((LT_POS(curwin->w_cursor, VIsual)
&& (LT_POS(m_pos, curwin->w_cursor)
|| LT_POS(VIsual, m_pos)))
|| (LT_POS(VIsual, curwin->w_cursor)
&& (LT_POS(m_pos, VIsual)
|| LT_POS(curwin->w_cursor, m_pos))))
{
jump_flags = MOUSE_MAY_STOP_VIS;
else
}
else if (VIsual_mode == Ctrl_V)
{
if ((LT_POS(curwin->w_cursor, VIsual)
&& (LT_POS(m_pos, curwin->w_cursor)
|| LT_POS(VIsual, m_pos)))
|| (LT_POS(VIsual, curwin->w_cursor)
&& (LT_POS(m_pos, VIsual)
|| LT_POS(curwin->w_cursor, m_pos))))
{
getvcols(curwin, &curwin->w_cursor, &VIsual,
&leftcol, &rightcol);
getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL);
if (m_pos.col < leftcol || m_pos.col > rightcol)
jump_flags = MOUSE_MAY_STOP_VIS;
}
else if (VIsual_mode == Ctrl_V)
{
getvcols(curwin, &curwin->w_cursor, &VIsual,
&leftcol, &rightcol);
getvcol(curwin, &m_pos, NULL, &m_pos.col, NULL);
if (m_pos.col < leftcol || m_pos.col > rightcol)
jump_flags = MOUSE_MAY_STOP_VIS;
}
}
}
else
jump_flags = MOUSE_MAY_STOP_VIS;
}
if (jump_flags)
{
jump_flags = jump_to_mouse(jump_flags, NULL, which_button);
update_curbuf(VIsual_active ? INVERTED : VALID);
setcursor();
out_flush(); /* Update before showing popup menu */
}
else
jump_flags = MOUSE_MAY_STOP_VIS;
}
if (jump_flags)
{
jump_flags = jump_to_mouse(jump_flags, NULL, which_button);
update_curbuf(VIsual_active ? INVERTED : VALID);
setcursor();
out_flush(); /* Update before showing popup menu */
}
# ifdef FEAT_MENU
gui_show_popupmenu();
show_popupmenu();
got_click = FALSE; /* ignore release events */
# endif
return (jump_flags & CURSOR_MOVED) != 0;
}
else
return FALSE;
return (jump_flags & CURSOR_MOVED) != 0;
#else
return FALSE;
#endif
Expand Down

0 comments on commit aef8c3d

Please sign in to comment.