aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-09-15 17:24:35 +0300
committerGitHub <noreply@github.com>2026-09-15 17:24:35 +0300
commitee064a0c798dd5617d253be7d26aa41f924bab96 (patch)
treeac63fa4f16002c83f3931fc8085bb80923778f96 /src
parent963f78f46c8f10d0bfc869f0ea13223892a1f0ef (diff)
fix(windows): preserve sgr mouse encoding after native capture (#4195)
refs #4155
Diffstat (limited to 'src')
-rw-r--r--src/client/terminal_setup.rs50
-rw-r--r--src/terminal_modes.rs12
2 files changed, 54 insertions, 8 deletions
diff --git a/src/client/terminal_setup.rs b/src/client/terminal_setup.rs
index cc13bcdd..44f6fbaa 100644
--- a/src/client/terminal_setup.rs
+++ b/src/client/terminal_setup.rs
@@ -476,6 +476,54 @@ impl Drop for TerminalGuard {
mod tests {
use super::*;
+ #[derive(Clone, Default)]
+ struct SharedOutput(std::rc::Rc<std::cell::RefCell<Vec<u8>>>);
+
+ impl io::Write for SharedOutput {
+ fn write(&mut self, bytes: &[u8]) -> io::Result<usize> {
+ self.0.borrow_mut().extend_from_slice(bytes);
+ Ok(bytes.len())
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ Ok(())
+ }
+ }
+
+ #[test]
+ fn windows_native_mouse_capture_never_resets_encoding_after_native_enable() {
+ let mut output = SharedOutput::default();
+ for sgr_pixels in [false, false, true, false] {
+ let start = output.0.borrow().len();
+ let native_output = output.clone();
+ let native_boundary = std::cell::Cell::new(0);
+ set_windows_native_mouse_capture(&mut output, true, sgr_pixels, |enabled| {
+ assert!(enabled);
+ // ConPTY enables host SGR during native capture, before our VT requests.
+ native_output
+ .0
+ .borrow_mut()
+ .extend_from_slice(b"\x1b[?1003h\x1b[?1006h");
+ native_boundary.set(native_output.0.borrow().len());
+ Ok(())
+ })
+ .unwrap();
+
+ let bytes = output.0.borrow();
+ let before = std::str::from_utf8(&bytes[start..native_boundary.get()]).unwrap();
+ let after = std::str::from_utf8(&bytes[native_boundary.get()..]).unwrap();
+ assert!(before.contains("\x1b[?1016l"));
+ for reset in ["\x1b[?1005l", "\x1b[?1006l", "\x1b[?1016l"] {
+ assert!(
+ !after.contains(reset),
+ "mouse format reset after native capture (sgr_pixels={sgr_pixels}): {after:?}"
+ );
+ }
+ assert!(after.contains("\x1b[?1003h\x1b[?1006h"));
+ assert_eq!(after.contains("\x1b[?1016h"), sgr_pixels);
+ }
+ }
+
#[test]
fn windows_native_mouse_capture_restores_reporting_after_reset() {
let mut output = Vec::new();
@@ -488,7 +536,7 @@ mod tests {
assert_eq!(
output,
- b"\x1b[?1006l\x1b[?1016l\x1b[?1015l\x1b[?1005l\x1b[?1003l\x1b[?1002l\x1b[?1000l\x1b[?9l\x1b[?1000h\x1b[?1002h\x1b[?1003h\x1b[?1006h\x1b[?1016l"
+ b"\x1b[?1006l\x1b[?1016l\x1b[?1015l\x1b[?1005l\x1b[?1003l\x1b[?1002l\x1b[?1000l\x1b[?9l\x1b[?1000h\x1b[?1002h\x1b[?1003h\x1b[?1006h"
);
}
}
diff --git a/src/terminal_modes.rs b/src/terminal_modes.rs
index 810fa871..11bf56fc 100644
--- a/src/terminal_modes.rs
+++ b/src/terminal_modes.rs
@@ -26,12 +26,10 @@ pub(crate) fn set_windows_mouse_reporting<W: Write>(
} else {
WINDOWS_MOUSE_REPORTING_DISABLE_SEQUENCE
})?;
- if enabled {
- writer.write_all(if sgr_pixels {
- b"\x1b[?1016h"
- } else {
- b"\x1b[?1016l"
- })?;
+ // The caller clears modes before native capture. Resetting 1016 here can
+ // undo the SGR encoding that ConPTY has already enabled on the host.
+ if enabled && sgr_pixels {
+ writer.write_all(b"\x1b[?1016h")?;
}
writer.flush()
}
@@ -197,7 +195,7 @@ mod tests {
assert_eq!(
output,
- b"\x1b[?1000h\x1b[?1002h\x1b[?1003h\x1b[?1006h\x1b[?1016h\x1b[?1000h\x1b[?1002h\x1b[?1003h\x1b[?1006h\x1b[?1016l\x1b[?1016l\x1b[?1006l\x1b[?1003l\x1b[?1002l\x1b[?1000l"
+ b"\x1b[?1000h\x1b[?1002h\x1b[?1003h\x1b[?1006h\x1b[?1016h\x1b[?1000h\x1b[?1002h\x1b[?1003h\x1b[?1006h\x1b[?1016l\x1b[?1006l\x1b[?1003l\x1b[?1002l\x1b[?1000l"
);
}
}