mirror of https://github.com/martanne/abduco
client: tighten CSI u detach key matching
Restrict the kitty keyboard protocol detach matcher to better mirror the legacy single-byte behavior: - Only match key press events (:1 or absent), not repeat (:2) or release (:3). In practice the press triggers detach before the release arrives, but this is more correct. - Reject if shift, alt, super, hyper, or meta are also held. The legacy byte for e.g. Ctrl-\ is distinct from Ctrl+Shift-\, so extra non-lock modifiers should not trigger detach. Lock keys (numlock, capslock) are still allowed since they do not affect key identity.
This commit is contained in:
parent
4d5cbf22c0
commit
d6551eb226
27
client.c
27
client.c
|
|
@ -86,8 +86,11 @@ static void init_csi_detach(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse a CSI u sequence: ESC [ <number> ; <number> [: <number>] u
|
/* Parse a CSI u sequence: ESC [ <number> ; <number> [: <number>] u
|
||||||
* Returns true if it encodes the detach key with ctrl modifier.
|
* Returns true if it encodes the detach key with only the ctrl modifier
|
||||||
* Accepts any additional modifiers (numlock, capslock, etc.). */
|
* (plus any lock keys like numlock/capslock).
|
||||||
|
*
|
||||||
|
* Does NOT match if shift, alt, or super are also held, mirroring the
|
||||||
|
* legacy behavior where only the exact control byte triggers detach. */
|
||||||
static bool is_csi_detach(const char *buf, ssize_t len) {
|
static bool is_csi_detach(const char *buf, ssize_t len) {
|
||||||
if (len < 6 || buf[0] != '\033' || buf[1] != '[')
|
if (len < 6 || buf[0] != '\033' || buf[1] != '[')
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -112,21 +115,33 @@ static bool is_csi_detach(const char *buf, ssize_t len) {
|
||||||
while (i < len && buf[i] >= '0' && buf[i] <= '9')
|
while (i < len && buf[i] >= '0' && buf[i] <= '9')
|
||||||
mod = mod * 10 + (buf[i++] - '0');
|
mod = mod * 10 + (buf[i++] - '0');
|
||||||
|
|
||||||
/* Skip optional event type (:1=press, :2=repeat, :3=release) */
|
/* Check optional event type — only match press (:1) or
|
||||||
|
* absent (implied press), not repeat (:2) or release (:3). */
|
||||||
if (i < len && buf[i] == ':') {
|
if (i < len && buf[i] == ':') {
|
||||||
i++;
|
i++;
|
||||||
|
unsigned int event = 0;
|
||||||
while (i < len && buf[i] >= '0' && buf[i] <= '9')
|
while (i < len && buf[i] >= '0' && buf[i] <= '9')
|
||||||
i++;
|
event = event * 10 + (buf[i++] - '0');
|
||||||
|
if (event != 1)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Must end with 'u' */
|
/* Must end with 'u' */
|
||||||
if (i != len - 1)
|
if (i != len - 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Check ctrl is set: modifier = 1 + bitmask, ctrl = bit 2 (value 4) */
|
/* Modifier = 1 + bitmask. Check ctrl (bit 2) is set and no
|
||||||
|
* other non-lock modifiers (shift=1, alt=2, super=8, hyper=16,
|
||||||
|
* meta=32) are present. Lock keys (capslock=64, numlock=128)
|
||||||
|
* are allowed since they don't affect the key identity. */
|
||||||
if (mod < 1)
|
if (mod < 1)
|
||||||
return false;
|
return false;
|
||||||
return ((mod - 1) & 4) != 0;
|
unsigned int bits = mod - 1;
|
||||||
|
if (!(bits & 4))
|
||||||
|
return false; /* ctrl not set */
|
||||||
|
if (bits & (1|2|8|16|32))
|
||||||
|
return false; /* shift, alt, super, hyper, or meta also held */
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int client_mainloop(void) {
|
static int client_mainloop(void) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue