From cd73c79d22365f080fd1168fbb1787ea758ecbf8 Mon Sep 17 00:00:00 2001 From: Daniel Arbuckle Date: Tue, 20 Dec 2022 16:54:02 -0800 Subject: [PATCH 1/6] improve support for kitty keyboard protocol --- src/event/sys/unix/parse.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/event/sys/unix/parse.rs b/src/event/sys/unix/parse.rs index ea2b1b468..873e995e5 100644 --- a/src/event/sys/unix/parse.rs +++ b/src/event/sys/unix/parse.rs @@ -170,6 +170,14 @@ pub(crate) fn parse_csi(buffer: &[u8]) -> Result> { b'I' => Some(Event::FocusGained), b'O' => Some(Event::FocusLost), b';' => return parse_csi_modifier_key_code(buffer), + // P, Q, R, and S for compatibility Kitty keyboard protocol, + // as the 1 in 'CSI 1 P' etc. must be omitted if there are no + // modifiers pressed: + // https://sw.kovidgoyal.net/kitty/keyboard-protocol/#legacy-functional-keys + b'P' => Some(Event::Key(KeyCode::F(1).into())), + b'Q' => Some(Event::Key(KeyCode::F(2).into())), + b'R' => Some(Event::Key(KeyCode::F(3).into())), + b'S' => Some(Event::Key(KeyCode::F(4).into())), b'0'..=b'9' => { // Numbered escape code. if buffer.len() == 3 { @@ -189,7 +197,13 @@ pub(crate) fn parse_csi(buffer: &[u8]) -> Result> { b'M' => return parse_csi_rxvt_mouse(buffer), b'~' => return parse_csi_special_key_code(buffer), b'u' => return parse_csi_u_encoded_key_code(buffer), - b'R' => return parse_csi_cursor_position(buffer), + // In the case of an R in the last byte, we + // need to check whether it's a Kitty keyboard + // protocol F3 event or a Report Cursor + // Position response. If it contains an event + // type, it's definitely not a cursor + // position. + b'R' if buffer[buffer.len() - 3] != b':' => return parse_csi_cursor_position(buffer), _ => return parse_csi_modifier_key_code(buffer), } } From 120329ec845aa5d350dcc9586e6527269fc1c738 Mon Sep 17 00:00:00 2001 From: Daniel Arbuckle Date: Tue, 20 Dec 2022 16:59:24 -0800 Subject: [PATCH 2/6] code style --- src/event/sys/unix/parse.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/event/sys/unix/parse.rs b/src/event/sys/unix/parse.rs index 873e995e5..90e64ecb4 100644 --- a/src/event/sys/unix/parse.rs +++ b/src/event/sys/unix/parse.rs @@ -203,7 +203,8 @@ pub(crate) fn parse_csi(buffer: &[u8]) -> Result> { // Position response. If it contains an event // type, it's definitely not a cursor // position. - b'R' if buffer[buffer.len() - 3] != b':' => return parse_csi_cursor_position(buffer), + b'R' if buffer[buffer.len() - 3] != b':' => + return parse_csi_cursor_position(buffer), _ => return parse_csi_modifier_key_code(buffer), } } From abd2d674ecea3c4ef2feece8836ebd5c61c89695 Mon Sep 17 00:00:00 2001 From: Daniel Arbuckle Date: Wed, 21 Dec 2022 08:21:28 -0800 Subject: [PATCH 3/6] handle F3 with modifiers pressed --- src/event/sys/unix/parse.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/event/sys/unix/parse.rs b/src/event/sys/unix/parse.rs index 90e64ecb4..b18fd724c 100644 --- a/src/event/sys/unix/parse.rs +++ b/src/event/sys/unix/parse.rs @@ -170,7 +170,7 @@ pub(crate) fn parse_csi(buffer: &[u8]) -> Result> { b'I' => Some(Event::FocusGained), b'O' => Some(Event::FocusLost), b';' => return parse_csi_modifier_key_code(buffer), - // P, Q, R, and S for compatibility Kitty keyboard protocol, + // P, Q, R, and S for compatibility with Kitty keyboard protocol, // as the 1 in 'CSI 1 P' etc. must be omitted if there are no // modifiers pressed: // https://sw.kovidgoyal.net/kitty/keyboard-protocol/#legacy-functional-keys @@ -200,11 +200,13 @@ pub(crate) fn parse_csi(buffer: &[u8]) -> Result> { // In the case of an R in the last byte, we // need to check whether it's a Kitty keyboard // protocol F3 event or a Report Cursor - // Position response. If it contains an event - // type, it's definitely not a cursor - // position. - b'R' if buffer[buffer.len() - 3] != b':' => - return parse_csi_cursor_position(buffer), + // Position response. The protocol + // specification states that when used as a + // key event, the bytes following the CSI must + // be '1;' so we check that. + b'R' if buffer.starts_with(b"\x1B[1;") => + return parse_csi_modifier_key_code(buffer), + b'R' => return parse_csi_cursor_position(buffer), _ => return parse_csi_modifier_key_code(buffer), } } From 855e25b4fe784a896f571965e2b176458f01fac8 Mon Sep 17 00:00:00 2001 From: Daniel Arbuckle Date: Fri, 23 Dec 2022 01:52:26 -0800 Subject: [PATCH 4/6] disambiguating with 1; is not satisfactory --- src/event/sys/unix/parse.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/event/sys/unix/parse.rs b/src/event/sys/unix/parse.rs index b18fd724c..51f9852c7 100644 --- a/src/event/sys/unix/parse.rs +++ b/src/event/sys/unix/parse.rs @@ -31,6 +31,14 @@ pub(crate) fn parse_event(buffer: &[u8], input_available: bool) -> Result