diff --git a/putty.h b/putty.h index 9eb6c0b5..c7088644 100644 --- a/putty.h +++ b/putty.h @@ -367,7 +367,7 @@ typedef enum { } Mouse_Button; typedef enum { - MA_NOTHING, MA_CLICK, MA_2CLK, MA_3CLK, MA_DRAG, MA_RELEASE + MA_NOTHING, MA_CLICK, MA_2CLK, MA_3CLK, MA_DRAG, MA_RELEASE, MA_MOVE } Mouse_Action; /* Keyboard modifiers -- keys the user is actually holding down */ diff --git a/terminal/terminal.c b/terminal/terminal.c index cf658710..fd57a5af 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -1374,6 +1374,8 @@ static void power_on(Terminal *term, bool clear) term->xterm_mouse = 0; term->xterm_extended_mouse = false; term->urxvt_extended_mouse = false; + term->raw_mouse_reported_x = 0; + term->raw_mouse_reported_y = 0; win_set_raw_mouse_mode(term->win, false); term->win_pointer_shape_pending = true; term->win_pointer_shape_raw = false; @@ -3067,6 +3069,10 @@ static void toggle_mode(Terminal *term, int mode, int query, bool state) term->xterm_mouse = state ? 2 : 0; term_update_raw_mouse_mode(term); break; + case 1003: /* xterm mouse any-event tracking */ + term->xterm_mouse = state ? 3 : 0; + term_update_raw_mouse_mode(term); + break; case 1006: /* xterm extended mouse */ term->xterm_extended_mouse = state; break; @@ -7053,6 +7059,13 @@ void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked, !(term->mouse_override && shift)); int default_seltype; + // Don't do anything if mouse movement events weren't requested; + // Note: return early to avoid doing all of this code on every mouse move + // event only to throw it away. + if (a == MA_MOVE && (!raw_mouse || term->xterm_mouse < 3)) { + return; + } + if (y < 0) { y = 0; if (a == MA_DRAG && !raw_mouse) @@ -7139,6 +7152,11 @@ void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked, encstate = 0x41; wheel = true; break; + case MBT_NOTHING: + assert( a == MA_MOVE ); + encstate = 0x03; // release; no buttons pressed + wheel = false; + break; default: return; } @@ -7153,7 +7171,21 @@ void term_mouse(Terminal *term, Mouse_Button braw, Mouse_Button bcooked, case MA_DRAG: if (term->xterm_mouse == 1) return; - encstate += 0x20; + encstate += 0x20; // motion indicator + break; + case MA_MOVE: // mouse move without buttons + assert( braw == MBT_NOTHING && bcooked == MBT_NOTHING ); + if (term->xterm_mouse < 3) + return; + + if (selpoint.x == term->raw_mouse_reported_x && + selpoint.y == term->raw_mouse_reported_y) + return; + + term->raw_mouse_reported_x = x; + term->raw_mouse_reported_y = y; + + encstate += 0x20; // motion indicator break; case MA_RELEASE: /* If multiple extensions are enabled, the xterm 1006 is used, so it's okay to check for only that */ diff --git a/terminal/terminal.h b/terminal/terminal.h index c9d93342..66d57d8b 100644 --- a/terminal/terminal.h +++ b/terminal/terminal.h @@ -155,6 +155,8 @@ struct terminal_tag { bool xterm_extended_mouse; bool urxvt_extended_mouse; int mouse_is_down; /* used while tracking mouse buttons */ + int raw_mouse_reported_x; + int raw_mouse_reported_y; bool bracketed_paste, bracketed_paste_active; diff --git a/unix/window.c b/unix/window.c index 64efb968..5460bb52 100644 --- a/unix/window.c +++ b/unix/window.c @@ -502,6 +502,8 @@ static Mouse_Button translate_button(Mouse_Button button) return MBT_PASTE; if (button == MBT_RIGHT) return MBT_EXTEND; + if (button == MBT_NOTHING) + return MBT_NOTHING; return 0; /* shouldn't happen */ } @@ -2305,7 +2307,9 @@ gint motion_event(GtkWidget *widget, GdkEventMotion *event, gpointer data) { GtkFrontend *inst = (GtkFrontend *)data; bool shift, ctrl, alt; - int x, y, button; + Mouse_Action action = MA_DRAG; + Mouse_Button button = MBT_NOTHING; + int x, y; /* Remember the timestamp. */ inst->input_event_time = event->time; @@ -2325,12 +2329,12 @@ gint motion_event(GtkWidget *widget, GdkEventMotion *event, gpointer data) else if (event->state & GDK_BUTTON3_MASK) button = MBT_RIGHT; else - return false; /* don't even know what button! */ + action = MA_MOVE; x = (event->x - inst->window_border) / inst->font_width; y = (event->y - inst->window_border) / inst->font_height; - term_mouse(inst->term, button, translate_button(button), MA_DRAG, + term_mouse(inst->term, button, translate_button(button), action, x, y, shift, ctrl, alt); return true; diff --git a/windows/window.c b/windows/window.c index 3f052c79..7f2271bb 100644 --- a/windows/window.c +++ b/windows/window.c @@ -2729,6 +2729,11 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, TO_CHR_X(X_POS(lParam)), TO_CHR_Y(Y_POS(lParam)), wParam & MK_SHIFT, wParam & MK_CONTROL, is_alt_pressed()); + } else { + term_mouse(wgs->term, MBT_NOTHING, MBT_NOTHING, MA_MOVE, + TO_CHR_X(X_POS(lParam)), + TO_CHR_Y(Y_POS(lParam)), false, + false, false); } return 0; }