diff --git a/putty.h b/putty.h index 606ff178..fc5c2941 100644 --- a/putty.h +++ b/putty.h @@ -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); diff --git a/terminal/terminal.c b/terminal/terminal.c index 923ed03e..ae5e4144 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -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); diff --git a/unix/window.c b/unix/window.c index a8e73789..d9d007b4 100644 --- a/unix/window.c +++ b/unix/window.c @@ -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 diff --git a/windows/window.c b/windows/window.c index c81755f2..cb9d5b1c 100644 --- a/windows/window.c +++ b/windows/window.c @@ -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,