|
@@ -517,6 +517,8 @@ static int *seq_append = NULL;
|
|
|
|
|
|
static int *pending_keys = NULL;
|
|
|
|
|
|
+static int mouse_btn, mouse_x, mouse_y;
|
|
|
+
|
|
|
#ifdef __QNXNTO__
|
|
|
ph_dv_f ph_attach;
|
|
|
ph_ov_f ph_input_group;
|
|
@@ -707,18 +709,14 @@ getch_with_delay (void)
|
|
|
static void
|
|
|
xmouse_get_event (Gpm_Event * ev)
|
|
|
{
|
|
|
- int btn;
|
|
|
static struct timeval tv1 = { 0, 0 }; /* Force first click as single */
|
|
|
static struct timeval tv2;
|
|
|
static int clicks = 0;
|
|
|
static int last_btn = 0;
|
|
|
+ int btn = mouse_btn;
|
|
|
|
|
|
/* Decode Xterm mouse information to a GPM style event */
|
|
|
|
|
|
- /* Variable btn has following meaning: */
|
|
|
- /* 0 = btn1 dn, 1 = btn2 dn, 2 = btn3 dn, 3 = btn up */
|
|
|
- btn = tty_lowlevel_getch () - 32;
|
|
|
-
|
|
|
/* There seems to be no way of knowing which button was released */
|
|
|
/* So we assume all the buttons were released */
|
|
|
|
|
@@ -796,10 +794,8 @@ xmouse_get_event (Gpm_Event * ev)
|
|
|
}
|
|
|
last_btn = ev->buttons;
|
|
|
}
|
|
|
- /* Coordinates are 33-based */
|
|
|
- /* Transform them to 1-based */
|
|
|
- ev->x = tty_lowlevel_getch () - 32;
|
|
|
- ev->y = tty_lowlevel_getch () - 32;
|
|
|
+ ev->x = mouse_x;
|
|
|
+ ev->y = mouse_y;
|
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------- */
|
|
@@ -933,6 +929,134 @@ push_char (int c)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+/* --------------------------------------------------------------------------------------------- */
|
|
|
+/* Parse extended mouse coordinates.
|
|
|
+ Returns -1 if pending_keys cannot be a prefix of extended mouse coordinates.
|
|
|
+ Returns 0 if pending_keys 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 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 231,
|
|
|
+ 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 231.
|
|
|
+ + 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.
|
|
|
+*/
|
|
|
+
|
|
|
+static int
|
|
|
+parse_extended_mouse_coordinates (void)
|
|
|
+{
|
|
|
+ int c, btn = 0, x = 0, y = 0;
|
|
|
+ const int *p = pending_keys;
|
|
|
+
|
|
|
+ c = *p++;
|
|
|
+ if (c == 0)
|
|
|
+ return 0;
|
|
|
+ if (c != ESC_CHAR)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ c = *p++;
|
|
|
+ if (c == 0)
|
|
|
+ return 0;
|
|
|
+ if (c != '[')
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ while (TRUE)
|
|
|
+ {
|
|
|
+ c = *p++;
|
|
|
+ if (c == 0)
|
|
|
+ return 0;
|
|
|
+ if (c == ';')
|
|
|
+ break;
|
|
|
+ if (c < '0' || c > '9')
|
|
|
+ return -1;
|
|
|
+ btn = 10 * btn + c - '0';
|
|
|
+ }
|
|
|
+ if (btn < 32)
|
|
|
+ return -1;
|
|
|
+ btn -= 32;
|
|
|
+
|
|
|
+ while (TRUE)
|
|
|
+ {
|
|
|
+ c = *p++;
|
|
|
+ if (c == 0)
|
|
|
+ return 0;
|
|
|
+ if (c == ';')
|
|
|
+ break;
|
|
|
+ if (c < '0' || c > '9')
|
|
|
+ return -1;
|
|
|
+ x = 10 * x + c - '0';
|
|
|
+ }
|
|
|
+ if (x < 1)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ while (TRUE)
|
|
|
+ {
|
|
|
+ c = *p++;
|
|
|
+ if (c == 0)
|
|
|
+ return 0;
|
|
|
+ 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() */
|
|
|
|
|
@@ -1692,22 +1816,35 @@ get_key_code (int no_delay)
|
|
|
pend_send:
|
|
|
if (pending_keys != NULL)
|
|
|
{
|
|
|
- int d = *pending_keys++;
|
|
|
- check_pend:
|
|
|
- if (*pending_keys == 0)
|
|
|
+ int m;
|
|
|
+
|
|
|
+ m = parse_extended_mouse_coordinates ();
|
|
|
+ if (m == 1)
|
|
|
{
|
|
|
- pending_keys = NULL;
|
|
|
- seq_append = NULL;
|
|
|
+ pending_keys = seq_append = NULL;
|
|
|
+ this = NULL;
|
|
|
+ return MCKEY_EXTENDED_MOUSE;
|
|
|
}
|
|
|
- if ((d == ESC_CHAR) && (pending_keys != NULL))
|
|
|
+ if (m == -1)
|
|
|
{
|
|
|
- d = ALT (*pending_keys++);
|
|
|
- goto check_pend;
|
|
|
+ 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++);
|
|
|
+ goto check_pend;
|
|
|
+ }
|
|
|
+ if ((d > 127 && d < 256) && use_8th_bit_as_meta)
|
|
|
+ d = ALT (d & 0x7f);
|
|
|
+ this = NULL;
|
|
|
+ return correct_key_code (d);
|
|
|
}
|
|
|
- if ((d > 127 && d < 256) && use_8th_bit_as_meta)
|
|
|
- d = ALT (d & 0x7f);
|
|
|
- this = NULL;
|
|
|
- return correct_key_code (d);
|
|
|
+ /* else if (m == 0), just let it continue */
|
|
|
}
|
|
|
|
|
|
nodelay_try_again:
|
|
@@ -2014,9 +2151,21 @@ tty_get_event (struct Gpm_Event *event, gboolean redo_event, gboolean block)
|
|
|
#ifdef KEY_MOUSE
|
|
|
|| c == KEY_MOUSE
|
|
|
#endif /* KEY_MOUSE */
|
|
|
+ || c == MCKEY_EXTENDED_MOUSE
|
|
|
))
|
|
|
{
|
|
|
/* Mouse event */
|
|
|
+ /* In case of extended coordinates, mouse_btn, mouse_x and mouse_y are already filled in. */
|
|
|
+ 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;
|
|
|
}
|