1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

Cancel drag-select when the context menu pops up.

I got a pterm into a stuck state this morning by an accidental mouse
action. I'd intended to press Ctrl + right-click to pop up the context
menu, but I accidentally pressed down the left button first, starting
a selection drag, and then while the left button was still held down,
pressed down the right button as well, triggering the menu.

The effect was that the context menu appeared while term->selstate was
set to DRAGGING, in which state terminal output is suppressed, and
which is only unset by a mouse-button release event. But then that
release event went to the popup menu, and the terminal window never
got it. So the terminal stayed stuck forever - or rather, until I
guessed the cause and did another selection drag to reset it.

This happened to me on GTK, but once I knew how I'd done it, I found I
could reproduce the same misbehaviour on Windows by the same method.
Added a simplistic fix, on both platforms, that cancels a selection
drag if the popup menu is summoned part way through it.
This commit is contained in:
Simon Tatham 2022-03-29 18:05:11 +01:00
parent 5d58931b51
commit bdab00341b
4 changed files with 23 additions and 0 deletions

View File

@ -2137,6 +2137,7 @@ void term_pwron(Terminal *, bool);
void term_clrsb(Terminal *);
void term_mouse(Terminal *, Mouse_Button, Mouse_Button, Mouse_Action,
int, int, bool, bool, bool);
void term_cancel_selection_drag(Terminal *);
void term_key(Terminal *, Key_Sym, wchar_t *, size_t, unsigned int,
unsigned int);
void term_lost_clipboard_ownership(Terminal *, int clipboard);

View File

@ -7299,6 +7299,23 @@ void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked,
term_schedule_update(term);
}
void term_cancel_selection_drag(Terminal *term)
{
/*
* In unusual circumstances, a mouse drag might be interrupted by
* something that steals the rest of the mouse gesture. An example
* is the GTK popup menu appearing. In that situation, we'll never
* receive the MA_RELEASE that finishes the DRAGGING state, which
* means terminal output could be suppressed indefinitely. Call
* this function from the front end in such situations to restore
* sensibleness.
*/
if (term->selstate == DRAGGING)
term->selstate = NO_SELECTION;
term_out(term, false);
term_schedule_update(term);
}
static int shift_bitmap(bool shift, bool ctrl, bool alt, bool *consumed_alt)
{
int bitmap = (shift ? 1 : 0) + (alt ? 2 : 0) + (ctrl ? 4 : 0);

View File

@ -2162,6 +2162,8 @@ static gboolean button_internal(GtkFrontend *inst, GdkEventButton *event)
}
if (event->button == 3 && ctrl) {
/* Just in case this happened in mid-select */
term_cancel_selection_drag(inst->term);
#if GTK_CHECK_VERSION(3,22,0)
gtk_menu_popup_at_pointer(GTK_MENU(inst->menu), (GdkEvent *)event);
#else

View File

@ -2641,6 +2641,9 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
(conf_get_int(conf, CONF_mouse_is_xterm) == 2))) {
POINT cursorpos;
/* Just in case this happened in mid-select */
term_cancel_selection_drag(term);
show_mouseptr(true); /* make sure pointer is visible */
GetCursorPos(&cursorpos);
TrackPopupMenu(popup_menus[CTXMENU].menu,