Merge branch '2956_mouse_protocol_1006'
* 2956_mouse_protocol_1006: Code refactoring: removed unneeded 'go to' label. Ticket #2956: Newer protocol for extended mouse clicks.
Этот коммит содержится в:
Коммит
424e71fac1
231
lib/tty/key.c
231
lib/tty/key.c
@ -521,8 +521,6 @@ static int *seq_append = NULL;
|
|||||||
|
|
||||||
static int *pending_keys = NULL;
|
static int *pending_keys = NULL;
|
||||||
|
|
||||||
static int mouse_btn, mouse_x, mouse_y;
|
|
||||||
|
|
||||||
#ifdef __QNXNTO__
|
#ifdef __QNXNTO__
|
||||||
ph_dv_f ph_attach;
|
ph_dv_f ph_attach;
|
||||||
ph_ov_f ph_input_group;
|
ph_ov_f ph_input_group;
|
||||||
@ -711,16 +709,63 @@ getch_with_delay (void)
|
|||||||
/* --------------------------------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
xmouse_get_event (Gpm_Event * ev)
|
xmouse_get_event (Gpm_Event * ev, gboolean extended)
|
||||||
{
|
{
|
||||||
static struct timeval tv1 = { 0, 0 }; /* Force first click as single */
|
static struct timeval tv1 = { 0, 0 }; /* Force first click as single */
|
||||||
static struct timeval tv2;
|
static struct timeval tv2;
|
||||||
static int clicks = 0;
|
static int clicks = 0;
|
||||||
static int last_btn = 0;
|
static int last_btn = 0;
|
||||||
int btn = mouse_btn;
|
int btn;
|
||||||
|
|
||||||
/* Decode Xterm mouse information to a GPM style event */
|
/* Decode Xterm mouse information to a GPM style event */
|
||||||
|
|
||||||
|
if (!extended)
|
||||||
|
{
|
||||||
|
/* Variable btn has following meaning: */
|
||||||
|
/* 0 = btn1 dn, 1 = btn2 dn, 2 = btn3 dn, 3 = btn up */
|
||||||
|
btn = tty_lowlevel_getch () - 32;
|
||||||
|
/* Coordinates are 33-based */
|
||||||
|
/* Transform them to 1-based */
|
||||||
|
ev->x = tty_lowlevel_getch () - 32;
|
||||||
|
ev->y = tty_lowlevel_getch () - 32;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* SGR 1006 extension (e.g. "\e[<0;12;300M"):
|
||||||
|
- Numbers are encoded in decimal to make it ASCII-safe
|
||||||
|
and to overcome the limit of 223 columns/rows.
|
||||||
|
- Mouse release is encoded by trailing 'm' rather than 'M'
|
||||||
|
so that the released button can be reported.
|
||||||
|
- Numbers are no longer offset by 32. */
|
||||||
|
char c;
|
||||||
|
btn = ev->x = ev->y = 0;
|
||||||
|
ev->type = 0; /* In case we return on an invalid sequence */
|
||||||
|
while ((c = tty_lowlevel_getch ()) != ';')
|
||||||
|
{
|
||||||
|
if (c < '0' || c > '9')
|
||||||
|
return;
|
||||||
|
btn = 10 * btn + (c - '0');
|
||||||
|
}
|
||||||
|
while ((c = tty_lowlevel_getch ()) != ';')
|
||||||
|
{
|
||||||
|
if (c < '0' || c > '9')
|
||||||
|
return;
|
||||||
|
ev->x = 10 * ev->x + (c - '0');
|
||||||
|
}
|
||||||
|
while ((c = tty_lowlevel_getch ()) != 'M' && c != 'm')
|
||||||
|
{
|
||||||
|
if (c < '0' || c > '9')
|
||||||
|
return;
|
||||||
|
ev->y = 10 * ev->y + (c - '0');
|
||||||
|
}
|
||||||
|
/* Legacy mouse protocol doesn't tell which button was released,
|
||||||
|
conveniently all of mc's widgets are written not to rely on this
|
||||||
|
information. With the SGR extension the released button becomes
|
||||||
|
known, but for the sake of simplicity we just ignore it. */
|
||||||
|
if (c == 'm')
|
||||||
|
btn = 3;
|
||||||
|
}
|
||||||
|
|
||||||
/* There seems to be no way of knowing which button was released */
|
/* There seems to be no way of knowing which button was released */
|
||||||
/* So we assume all the buttons were released */
|
/* So we assume all the buttons were released */
|
||||||
|
|
||||||
@ -798,8 +843,6 @@ xmouse_get_event (Gpm_Event * ev)
|
|||||||
}
|
}
|
||||||
last_btn = ev->buttons;
|
last_btn = ev->buttons;
|
||||||
}
|
}
|
||||||
ev->x = mouse_x;
|
|
||||||
ev->y = mouse_y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
@ -933,136 +976,6 @@ push_char (int c)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------- */
|
|
||||||
/* Parse extended mouse coordinates.
|
|
||||||
Returns -1 if pending_keys (up to seq_append) cannot be a prefix of extended mouse coordinates.
|
|
||||||
Returns 0 if pending_keys (up to seq_append) is a valid (but still incomplete) prefix for
|
|
||||||
extended mouse coordinates, e.g. "^[[32;4".
|
|
||||||
Returns 1 and fills the mouse_btn, mouse_x, mouse_y values if pending_keys (up to seq_append) is
|
|
||||||
a complete extended mouse sequence, e.g. "^[[32;42;5M"
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Technical info (Egmont Koblinger <egmont@gmail.com>):
|
|
||||||
|
|
||||||
The ancient way of reporting mouse coordinates only supports coordinates up to 223,
|
|
||||||
so if your terminal is wider (or taller, but that's unlikely), you cannot use your mouse
|
|
||||||
in the rightmost columns.
|
|
||||||
|
|
||||||
* The old way of reporting mouse coordinates is the following:
|
|
||||||
+ Output DECSET 1000 to enable mouse
|
|
||||||
+ Expect escape sequences in the format \e[M<action+32><x+32><y+32> whereas <action+32>,
|
|
||||||
<x+32> and <y+32> are single bytes. (Action is 0 for left click, 1 for middle click,
|
|
||||||
2 for right click, 3 for release, or something like this.)
|
|
||||||
+ Disadvantages of this format:
|
|
||||||
+ x and y can only go up to 223.
|
|
||||||
+ Coordinates above 95 are not ascii-compatible, so any character set converting
|
|
||||||
layer (e.g. luit) messes them up.
|
|
||||||
+ The stream is not valid UTF-8, even if everything else is.
|
|
||||||
|
|
||||||
* The first new extension, introduced by xterm-262, is the following:
|
|
||||||
+ Output DECSET 1000 to enable mouse, followed by DECSET 1005 to activate extended mode.
|
|
||||||
+ Expect escape sequences in the format \e[M<action+32><<x+32>><<y+32>> whereas <<x+32>>
|
|
||||||
and <<y+32>> each can be up to two bytes long: coordinate+32 is encoded in UTF-8.
|
|
||||||
+ Disadvantates of this format:
|
|
||||||
+ There's still a limit of 2015 rows/columns (okay, it's not a real life problem).
|
|
||||||
+ Doesn't solve the luit issue.
|
|
||||||
+ It is "horribly broken" (quoting urxvt's changelog) in terms of compatibility
|
|
||||||
with the previous standard. There is no way for an application to tell whether
|
|
||||||
the underlying terminal supports this new mode (whether DECSET 1005 did actually change
|
|
||||||
the behavior or not), but depending on this a completely different user action might
|
|
||||||
generate the same input. Example:
|
|
||||||
+ If the terminal doesn't support this extension, then clicking at (162, 129)
|
|
||||||
generates \e[M<32><194><161>.
|
|
||||||
+ If the terminal supports this extension, then clicking at (129, 1) [bit of math:
|
|
||||||
129+32 = 161, U+0161 in UTF-8 is 194 161] generates \e[M<32><194><161><33>.
|
|
||||||
+ so there's no way to tell whether the terminal ignored the 1005 escape sequence,
|
|
||||||
the user clicked on (162, 129) and then typed an exclamation mark; or whether
|
|
||||||
the terminal recognized the escape, and the user clicked on (129, 1).
|
|
||||||
+ Due to this horrible brokenness, there's no way to implement support it without
|
|
||||||
explicitly asking the user (via a setting) if the terminal can speak this extension.
|
|
||||||
|
|
||||||
* The second new extension, introduced by rxvt-unicode-9.10, is the following:
|
|
||||||
+ Output DECSET 1000 to enable mouse, followed by DECSET 1015 to activate this extended mode.
|
|
||||||
+ Expect escape sequences in the format \e[{action+32};{x};{y}M where this time I used
|
|
||||||
the braces to denote spelling out the numbers in decimal, rather than using raw bytes.
|
|
||||||
+ The only thing I don't understand is why they kept the offset of 32 at action, but other
|
|
||||||
than that, this format is totally okay, and solves all the weaknesses of the previous ones.
|
|
||||||
|
|
||||||
Currently, at least the following terminal emulators have support for these:
|
|
||||||
* xterm supports the xterm extension
|
|
||||||
* rxvt-unicode >= 9.10 supports both extensions
|
|
||||||
* iterm2 supports both extensions
|
|
||||||
* vte >= 0.31 supports the urxvt extension
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int
|
|
||||||
parse_extended_mouse_coordinates (void)
|
|
||||||
{
|
|
||||||
int c, btn = 0, x = 0, y = 0;
|
|
||||||
const int *p = pending_keys;
|
|
||||||
const int *endp = seq_append;
|
|
||||||
|
|
||||||
if (p == endp)
|
|
||||||
return 0;
|
|
||||||
c = *p++;
|
|
||||||
if (c != ESC_CHAR)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (p == endp)
|
|
||||||
return 0;
|
|
||||||
c = *p++;
|
|
||||||
if (c != '[')
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
while (TRUE)
|
|
||||||
{
|
|
||||||
if (p == endp)
|
|
||||||
return 0;
|
|
||||||
c = *p++;
|
|
||||||
if (c == ';')
|
|
||||||
break;
|
|
||||||
if (c < '0' || c > '9')
|
|
||||||
return -1;
|
|
||||||
btn = 10 * btn + c - '0';
|
|
||||||
}
|
|
||||||
if (btn < 32)
|
|
||||||
return -1;
|
|
||||||
btn -= 32;
|
|
||||||
|
|
||||||
while (TRUE)
|
|
||||||
{
|
|
||||||
if (p == endp)
|
|
||||||
return 0;
|
|
||||||
c = *p++;
|
|
||||||
if (c == ';')
|
|
||||||
break;
|
|
||||||
if (c < '0' || c > '9')
|
|
||||||
return -1;
|
|
||||||
x = 10 * x + c - '0';
|
|
||||||
}
|
|
||||||
if (x < 1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
while (TRUE)
|
|
||||||
{
|
|
||||||
if (p == endp)
|
|
||||||
return 0;
|
|
||||||
c = *p++;
|
|
||||||
if (c == 'M')
|
|
||||||
break;
|
|
||||||
if (c < '0' || c > '9')
|
|
||||||
return -1;
|
|
||||||
y = 10 * y + c - '0';
|
|
||||||
}
|
|
||||||
if (y < 1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
mouse_btn = btn;
|
|
||||||
mouse_x = x;
|
|
||||||
mouse_y = y;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
/* Apply corrections for the keycode generated in get_key_code() */
|
/* Apply corrections for the keycode generated in get_key_code() */
|
||||||
|
|
||||||
@ -1831,36 +1744,21 @@ get_key_code (int no_delay)
|
|||||||
pend_send:
|
pend_send:
|
||||||
if (pending_keys != NULL)
|
if (pending_keys != NULL)
|
||||||
{
|
{
|
||||||
int m;
|
int d;
|
||||||
|
|
||||||
m = parse_extended_mouse_coordinates ();
|
d = *pending_keys++;
|
||||||
if (m == 1)
|
while (d == ESC_CHAR && *pending_keys != '\0')
|
||||||
{
|
|
||||||
pending_keys = seq_append = NULL;
|
|
||||||
this = NULL;
|
|
||||||
return MCKEY_EXTENDED_MOUSE;
|
|
||||||
}
|
|
||||||
if (m == -1)
|
|
||||||
{
|
|
||||||
int d = *pending_keys++;
|
|
||||||
check_pend:
|
|
||||||
if (*pending_keys == 0)
|
|
||||||
{
|
|
||||||
pending_keys = NULL;
|
|
||||||
seq_append = NULL;
|
|
||||||
}
|
|
||||||
if ((d == ESC_CHAR) && (pending_keys != NULL))
|
|
||||||
{
|
|
||||||
d = ALT (*pending_keys++);
|
d = ALT (*pending_keys++);
|
||||||
goto check_pend;
|
|
||||||
}
|
if (*pending_keys == '\0')
|
||||||
if ((d > 127 && d < 256) && use_8th_bit_as_meta)
|
pending_keys = seq_append = NULL;
|
||||||
|
|
||||||
|
if (d > 127 && d < 256 && use_8th_bit_as_meta)
|
||||||
d = ALT (d & 0x7f);
|
d = ALT (d & 0x7f);
|
||||||
|
|
||||||
this = NULL;
|
this = NULL;
|
||||||
return correct_key_code (d);
|
return correct_key_code (d);
|
||||||
}
|
}
|
||||||
/* else if (m == 0), just let it continue */
|
|
||||||
}
|
|
||||||
|
|
||||||
nodelay_try_again:
|
nodelay_try_again:
|
||||||
if (no_delay)
|
if (no_delay)
|
||||||
@ -2169,18 +2067,7 @@ tty_get_event (struct Gpm_Event *event, gboolean redo_event, gboolean block)
|
|||||||
|| c == MCKEY_EXTENDED_MOUSE))
|
|| c == MCKEY_EXTENDED_MOUSE))
|
||||||
{
|
{
|
||||||
/* Mouse event */
|
/* Mouse event */
|
||||||
/* In case of extended coordinates, mouse_btn, mouse_x and mouse_y are already filled in. */
|
xmouse_get_event (event, c == MCKEY_EXTENDED_MOUSE);
|
||||||
if (c != MCKEY_EXTENDED_MOUSE)
|
|
||||||
{
|
|
||||||
/* Variable btn has following meaning: */
|
|
||||||
/* 0 = btn1 dn, 1 = btn2 dn, 2 = btn3 dn, 3 = btn up */
|
|
||||||
mouse_btn = tty_lowlevel_getch () - 32;
|
|
||||||
/* Coordinates are 33-based */
|
|
||||||
/* Transform them to 1-based */
|
|
||||||
mouse_x = tty_lowlevel_getch () - 32;
|
|
||||||
mouse_y = tty_lowlevel_getch () - 32;
|
|
||||||
}
|
|
||||||
xmouse_get_event (event);
|
|
||||||
return (event->type != 0) ? EV_MOUSE : EV_NONE;
|
return (event->type != 0) ? EV_MOUSE : EV_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
Mouse_Type use_mouse_p = MOUSE_NONE;
|
Mouse_Type use_mouse_p = MOUSE_NONE;
|
||||||
gboolean mouse_enabled = FALSE;
|
gboolean mouse_enabled = FALSE;
|
||||||
const char *xmouse_seq;
|
const char *xmouse_seq;
|
||||||
|
const char *xmouse_extended_seq;
|
||||||
|
|
||||||
/*** file scope macro definitions ****************************************************************/
|
/*** file scope macro definitions ****************************************************************/
|
||||||
|
|
||||||
@ -90,6 +91,7 @@ init_mouse (void)
|
|||||||
case MOUSE_XTERM_NORMAL_TRACKING:
|
case MOUSE_XTERM_NORMAL_TRACKING:
|
||||||
case MOUSE_XTERM_BUTTON_EVENT_TRACKING:
|
case MOUSE_XTERM_BUTTON_EVENT_TRACKING:
|
||||||
define_sequence (MCKEY_MOUSE, xmouse_seq, MCKEY_NOACTION);
|
define_sequence (MCKEY_MOUSE, xmouse_seq, MCKEY_NOACTION);
|
||||||
|
define_sequence (MCKEY_EXTENDED_MOUSE, xmouse_extended_seq, MCKEY_NOACTION);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -138,8 +140,8 @@ enable_mouse (void)
|
|||||||
/* enable mouse tracking */
|
/* enable mouse tracking */
|
||||||
printf (ESC_STR "[?1000h");
|
printf (ESC_STR "[?1000h");
|
||||||
|
|
||||||
/* enable urxvt extended mouse coordinate reporting */
|
/* enable SGR extended mouse reporting */
|
||||||
printf (ESC_STR "[?1015h");
|
printf (ESC_STR "[?1006h");
|
||||||
|
|
||||||
fflush (stdout);
|
fflush (stdout);
|
||||||
mouse_enabled = TRUE;
|
mouse_enabled = TRUE;
|
||||||
@ -152,8 +154,8 @@ enable_mouse (void)
|
|||||||
/* enable mouse tracking */
|
/* enable mouse tracking */
|
||||||
printf (ESC_STR "[?1002h");
|
printf (ESC_STR "[?1002h");
|
||||||
|
|
||||||
/* enable urxvt extended mouse coordinate reporting */
|
/* enable SGR extended mouse reporting */
|
||||||
printf (ESC_STR "[?1015h");
|
printf (ESC_STR "[?1006h");
|
||||||
|
|
||||||
fflush (stdout);
|
fflush (stdout);
|
||||||
mouse_enabled = TRUE;
|
mouse_enabled = TRUE;
|
||||||
@ -182,8 +184,8 @@ disable_mouse (void)
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case MOUSE_XTERM_NORMAL_TRACKING:
|
case MOUSE_XTERM_NORMAL_TRACKING:
|
||||||
/* disable urxvt extended mouse coordinate reporting */
|
/* disable SGR extended mouse reporting */
|
||||||
printf (ESC_STR "[?1015l");
|
printf (ESC_STR "[?1006l");
|
||||||
|
|
||||||
/* disable mouse tracking */
|
/* disable mouse tracking */
|
||||||
printf (ESC_STR "[?1000l");
|
printf (ESC_STR "[?1000l");
|
||||||
@ -194,8 +196,8 @@ disable_mouse (void)
|
|||||||
fflush (stdout);
|
fflush (stdout);
|
||||||
break;
|
break;
|
||||||
case MOUSE_XTERM_BUTTON_EVENT_TRACKING:
|
case MOUSE_XTERM_BUTTON_EVENT_TRACKING:
|
||||||
/* disable urxvt extended mouse coordinate reporting */
|
/* disable SGR extended mouse reporting */
|
||||||
printf (ESC_STR "[?1015l");
|
printf (ESC_STR "[?1006l");
|
||||||
|
|
||||||
/* disable mouse tracking */
|
/* disable mouse tracking */
|
||||||
printf (ESC_STR "[?1002l");
|
printf (ESC_STR "[?1002l");
|
||||||
|
@ -97,9 +97,12 @@ typedef int (*mouse_h) (Gpm_Event *, void *);
|
|||||||
/* Type of the currently used mouse */
|
/* Type of the currently used mouse */
|
||||||
extern Mouse_Type use_mouse_p;
|
extern Mouse_Type use_mouse_p;
|
||||||
|
|
||||||
/* String indicating that a mouse event has occured, usually "\E[M" */
|
/* String indicating that a mouse event has occurred, usually "\E[M" */
|
||||||
extern const char *xmouse_seq;
|
extern const char *xmouse_seq;
|
||||||
|
|
||||||
|
/* String indicating that an SGR extended mouse event has occurred, namely "\E[<" */
|
||||||
|
extern const char *xmouse_extended_seq;
|
||||||
|
|
||||||
/*** declarations of public functions ************************************************************/
|
/*** declarations of public functions ************************************************************/
|
||||||
|
|
||||||
/* General (i.e. both for xterm and gpm) mouse support definitions */
|
/* General (i.e. both for xterm and gpm) mouse support definitions */
|
||||||
|
@ -303,6 +303,10 @@ tty_init_xterm_support (gboolean is_xterm)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* No termcap for SGR extended mouse (yet), hardcode it for now */
|
||||||
|
if (xmouse_seq != NULL)
|
||||||
|
xmouse_extended_seq = ESC_STR "[<";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user