@@ -517,6 +517,8 @@ static int *seq_append = NULL;
517
517
518
518
static int * pending_keys = NULL ;
519
519
520
+ static int mouse_btn , mouse_x , mouse_y ;
521
+
520
522
#ifdef __QNXNTO__
521
523
ph_dv_f ph_attach ;
522
524
ph_ov_f ph_input_group ;
@@ -707,18 +709,14 @@ getch_with_delay (void)
707
709
static void
708
710
xmouse_get_event (Gpm_Event * ev )
709
711
{
710
- int btn ;
711
712
static struct timeval tv1 = { 0 , 0 }; /* Force first click as single */
712
713
static struct timeval tv2 ;
713
714
static int clicks = 0 ;
714
715
static int last_btn = 0 ;
716
+ int btn = mouse_btn ;
715
717
716
718
/* Decode Xterm mouse information to a GPM style event */
717
719
718
- /* Variable btn has following meaning: */
719
- /* 0 = btn1 dn, 1 = btn2 dn, 2 = btn3 dn, 3 = btn up */
720
- btn = tty_lowlevel_getch () - 32 ;
721
-
722
720
/* There seems to be no way of knowing which button was released */
723
721
/* So we assume all the buttons were released */
724
722
@@ -796,10 +794,8 @@ xmouse_get_event (Gpm_Event * ev)
796
794
}
797
795
last_btn = ev -> buttons ;
798
796
}
799
- /* Coordinates are 33-based */
800
- /* Transform them to 1-based */
801
- ev -> x = tty_lowlevel_getch () - 32 ;
802
- ev -> y = tty_lowlevel_getch () - 32 ;
797
+ ev -> x = mouse_x ;
798
+ ev -> y = mouse_y ;
803
799
}
804
800
805
801
/* --------------------------------------------------------------------------------------------- */
@@ -933,6 +929,134 @@ push_char (int c)
933
929
return ret ;
934
930
}
935
931
932
+ /* --------------------------------------------------------------------------------------------- */
933
+ /* Parse extended mouse coordinates.
934
+ Returns -1 if pending_keys cannot be a prefix of extended mouse coordinates.
935
+ Returns 0 if pending_keys is a valid (but still incomplete) prefix for extended mouse
936
+ coordinates, e.g. "^[[32;4".
937
+ Returns 1 and fills the mouse_btn, mouse_x, mouse_y values if pending_keys is a complete extended
938
+ mouse sequence, e.g. "^[[32;42;5M"
939
+ */
940
+
941
+ /* Technical info (Egmont Koblinger <[email protected] >):
942
+
943
+ The ancient way of reporting mouse coordinates only supports coordinates up to 231,
944
+ so if your terminal is wider (or taller, but that's unlikely), you cannot use your mouse
945
+ in the rightmost columns.
946
+
947
+ * The old way of reporting mouse coordinates is the following:
948
+ + Output DECSET 1000 to enable mouse
949
+ + Expect escape sequences in the format \e[M<action+32><x+32><y+32> whereas <action+32>,
950
+ <x+32> and <y+32> are single bytes. (Action is 0 for left click, 1 for middle click,
951
+ 2 for right click, 3 for release, or something like this.)
952
+ + Disadvantages of this format:
953
+ + x and y can only go up to 231.
954
+ + Coordinates above 95 are not ascii-compatible, so any character set converting
955
+ layer (e.g. luit) messes them up.
956
+ + The stream is not valid UTF-8, even if everything else is.
957
+
958
+ * The first new extension, introduced by xterm-262, is the following:
959
+ + Output DECSET 1000 to enable mouse, followed by DECSET 1005 to activate extended mode.
960
+ + Expect escape sequences in the format \e[M<action+32><<x+32>><<y+32>> whereas <<x+32>>
961
+ and <<y+32>> each can be up to two bytes long: coordinate+32 is encoded in UTF-8.
962
+ + Disadvantates of this format:
963
+ + There's still a limit of 2015 rows/columns (okay, it's not a real life problem).
964
+ + Doesn't solve the luit issue.
965
+ + It is "horribly broken" (quoting urxvt's changelog) in terms of compatibility
966
+ with the previous standard. There is no way for an application to tell whether
967
+ the underlying terminal supports this new mode (whether DECSET 1005 did actually change
968
+ the behavior or not), but depending on this a completely different user action might
969
+ generate the same input. Example:
970
+ + If the terminal doesn't support this extension, then clicking at (162, 129)
971
+ generates \e[M<32><194><161>.
972
+ + If the terminal supports this extension, then clicking at (129, 1) [bit of math:
973
+ 129+32 = 161, U+0161 in UTF-8 is 194 161] generates \e[M<32><194><161><33>.
974
+ + so there's no way to tell whether the terminal ignored the 1005 escape sequence,
975
+ the user clicked on (162, 129) and then typed an exclamation mark; or whether
976
+ the terminal recognized the escape, and the user clicked on (129, 1).
977
+ + Due to this horrible brokenness, there's no way to implement support it without
978
+ explicitly asking the user (via a setting) if the terminal can speak this extension.
979
+
980
+ * The second new extension, introduced by rxvt-unicode-9.10, is the following:
981
+ + Output DECSET 1000 to enable mouse, followed by DECSET 1015 to activate this extended mode.
982
+ + Expect escape sequences in the format \e[{action+32};{x};{y}M where this time I used
983
+ the braces to denote spelling out the numbers in decimal, rather than using raw bytes.
984
+ + The only thing I don't understand is why they kept the offset of 32 at action, but other
985
+ than that, this format is totally okay, and solves all the weaknesses of the previous ones.
986
+
987
+ Currently, at least the following terminal emulators have support for these:
988
+ * xterm supports the xterm extension
989
+ * rxvt-unicode >= 9.10 supports both extensions
990
+ * iterm2 supports both extensions.
991
+ */
992
+
993
+ static int
994
+ parse_extended_mouse_coordinates (void )
995
+ {
996
+ int c , btn = 0 , x = 0 , y = 0 ;
997
+ const int * p = pending_keys ;
998
+
999
+ c = * p ++ ;
1000
+ if (c == 0 )
1001
+ return 0 ;
1002
+ if (c != ESC_CHAR )
1003
+ return -1 ;
1004
+
1005
+ c = * p ++ ;
1006
+ if (c == 0 )
1007
+ return 0 ;
1008
+ if (c != '[' )
1009
+ return -1 ;
1010
+
1011
+ while (TRUE)
1012
+ {
1013
+ c = * p ++ ;
1014
+ if (c == 0 )
1015
+ return 0 ;
1016
+ if (c == ';' )
1017
+ break ;
1018
+ if (c < '0' || c > '9' )
1019
+ return -1 ;
1020
+ btn = 10 * btn + c - '0' ;
1021
+ }
1022
+ if (btn < 32 )
1023
+ return -1 ;
1024
+ btn -= 32 ;
1025
+
1026
+ while (TRUE)
1027
+ {
1028
+ c = * p ++ ;
1029
+ if (c == 0 )
1030
+ return 0 ;
1031
+ if (c == ';' )
1032
+ break ;
1033
+ if (c < '0' || c > '9' )
1034
+ return -1 ;
1035
+ x = 10 * x + c - '0' ;
1036
+ }
1037
+ if (x < 1 )
1038
+ return -1 ;
1039
+
1040
+ while (TRUE)
1041
+ {
1042
+ c = * p ++ ;
1043
+ if (c == 0 )
1044
+ return 0 ;
1045
+ if (c == 'M' )
1046
+ break ;
1047
+ if (c < '0' || c > '9' )
1048
+ return -1 ;
1049
+ y = 10 * y + c - '0' ;
1050
+ }
1051
+ if (y < 1 )
1052
+ return -1 ;
1053
+
1054
+ mouse_btn = btn ;
1055
+ mouse_x = x ;
1056
+ mouse_y = y ;
1057
+ return 1 ;
1058
+ }
1059
+
936
1060
/* --------------------------------------------------------------------------------------------- */
937
1061
/* Apply corrections for the keycode generated in get_key_code() */
938
1062
@@ -1692,22 +1816,35 @@ get_key_code (int no_delay)
1692
1816
pend_send :
1693
1817
if (pending_keys != NULL )
1694
1818
{
1695
- int d = * pending_keys ++ ;
1696
- check_pend :
1697
- if (* pending_keys == 0 )
1819
+ int m ;
1820
+
1821
+ m = parse_extended_mouse_coordinates ();
1822
+ if (m == 1 )
1698
1823
{
1699
- pending_keys = NULL ;
1700
- seq_append = NULL ;
1824
+ pending_keys = seq_append = NULL ;
1825
+ this = NULL ;
1826
+ return MCKEY_EXTENDED_MOUSE ;
1701
1827
}
1702
- if (( d == ESC_CHAR ) && ( pending_keys != NULL ) )
1828
+ if (m == -1 )
1703
1829
{
1704
- d = ALT (* pending_keys ++ );
1705
- goto check_pend ;
1830
+ int d = * pending_keys ++ ;
1831
+ check_pend :
1832
+ if (* pending_keys == 0 )
1833
+ {
1834
+ pending_keys = NULL ;
1835
+ seq_append = NULL ;
1836
+ }
1837
+ if ((d == ESC_CHAR ) && (pending_keys != NULL ))
1838
+ {
1839
+ d = ALT (* pending_keys ++ );
1840
+ goto check_pend ;
1841
+ }
1842
+ if ((d > 127 && d < 256 ) && use_8th_bit_as_meta )
1843
+ d = ALT (d & 0x7f );
1844
+ this = NULL ;
1845
+ return correct_key_code (d );
1706
1846
}
1707
- if ((d > 127 && d < 256 ) && use_8th_bit_as_meta )
1708
- d = ALT (d & 0x7f );
1709
- this = NULL ;
1710
- return correct_key_code (d );
1847
+ /* else if (m == 0), just let it continue */
1711
1848
}
1712
1849
1713
1850
nodelay_try_again :
@@ -2014,9 +2151,21 @@ tty_get_event (struct Gpm_Event *event, gboolean redo_event, gboolean block)
2014
2151
#ifdef KEY_MOUSE
2015
2152
|| c == KEY_MOUSE
2016
2153
#endif /* KEY_MOUSE */
2154
+ || c == MCKEY_EXTENDED_MOUSE
2017
2155
))
2018
2156
{
2019
2157
/* Mouse event */
2158
+ /* In case of extended coordinates, mouse_btn, mouse_x and mouse_y are already filled in. */
2159
+ if (c != MCKEY_EXTENDED_MOUSE )
2160
+ {
2161
+ /* Variable btn has following meaning: */
2162
+ /* 0 = btn1 dn, 1 = btn2 dn, 2 = btn3 dn, 3 = btn up */
2163
+ mouse_btn = tty_lowlevel_getch () - 32 ;
2164
+ /* Coordinates are 33-based */
2165
+ /* Transform them to 1-based */
2166
+ mouse_x = tty_lowlevel_getch () - 32 ;
2167
+ mouse_y = tty_lowlevel_getch () - 32 ;
2168
+ }
2020
2169
xmouse_get_event (event );
2021
2170
return (event -> type != 0 ) ? EV_MOUSE : EV_NONE ;
2022
2171
}
0 commit comments