mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
Support xterm any-event mouse tracking
From https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Any-event-tracking:
Any-event mode is the same as button-event mode, except that all motion
events are reported, even if no mouse button is down. It is enabled by
specifying 1003 to DECSET.
Normally the front ends only report mouse events when buttons are
pressed, so we introduce a MA_MOVE event with MBT_NOTHING set to
indicate such a mouse movement.
(cherry picked from commit 3cfbd3df0f
)
This commit is contained in:
parent
4eb089f601
commit
0112167f98
2
putty.h
2
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 */
|
||||
|
@ -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;
|
||||
@ -3068,6 +3070,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;
|
||||
@ -7055,6 +7061,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)
|
||||
@ -7141,6 +7154,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;
|
||||
}
|
||||
@ -7155,7 +7173,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 */
|
||||
|
@ -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;
|
||||
|
||||
|
@ -495,6 +495,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 */
|
||||
}
|
||||
|
||||
@ -2298,7 +2300,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;
|
||||
@ -2318,12 +2322,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;
|
||||
|
@ -2754,6 +2754,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(term, MBT_NOTHING, MBT_NOTHING, MA_MOVE,
|
||||
TO_CHR_X(X_POS(lParam)),
|
||||
TO_CHR_Y(Y_POS(lParam)), false,
|
||||
false, false);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user