fix(windows): restore mouse reporting when reattaching

This commit is contained in:
Jonathan Liebig
2026-09-14 00:48:20 +02:00
parent 3b478e69dc
commit 1ae26d2938
2 changed files with 62 additions and 13 deletions
+53 -4
View File
@@ -265,16 +265,46 @@ pub(super) fn effective_sgr_pixel_mouse(
enabled && requested && exact_geometry
}
#[cfg(any(windows, test))]
fn set_windows_native_mouse_capture<W: io::Write>(
writer: &mut W,
enabled: bool,
sgr_pixels: bool,
set_console_capture: impl FnOnce(bool) -> io::Result<()>,
) -> io::Result<()> {
crate::terminal_modes::clear_host_mouse_reporting(writer)?;
set_console_capture(enabled)?;
if enabled {
crate::terminal_modes::set_windows_mouse_reporting(writer, true, sgr_pixels)?;
}
Ok(())
}
pub(super) fn set_mouse_capture(enabled: bool, sgr_pixels: bool) -> io::Result<()> {
crate::terminal_modes::clear_host_mouse_reporting(&mut io::stdout())?;
#[cfg(windows)]
if is_ssh_session() && windows_vti_input_backend_enabled() {
return crate::terminal_modes::set_windows_ssh_mouse_reporting(
crate::terminal_modes::clear_host_mouse_reporting(&mut io::stdout())?;
return crate::terminal_modes::set_windows_mouse_reporting(
&mut io::stdout(),
enabled,
sgr_pixels,
);
}
#[cfg(windows)]
return set_windows_native_mouse_capture(&mut io::stdout(), enabled, sgr_pixels, |enabled| {
if enabled {
execute!(io::stdout(), EnableMouseCapture)
} else {
match execute!(io::stdout(), DisableMouseCapture) {
Ok(()) => Ok(()),
Err(err) if err.to_string() == "Initial console modes not set" => Ok(()),
Err(err) => Err(err),
}
}
});
#[cfg(not(windows))]
crate::terminal_modes::clear_host_mouse_reporting(&mut io::stdout())?;
#[cfg(not(windows))]
if enabled {
execute!(io::stdout(), EnableMouseCapture)?;
if sgr_pixels {
@@ -285,8 +315,6 @@ pub(super) fn set_mouse_capture(enabled: bool, sgr_pixels: bool) -> io::Result<(
} else {
match execute!(io::stdout(), DisableMouseCapture) {
Ok(()) => Ok(()),
#[cfg(windows)]
Err(err) if err.to_string() == "Initial console modes not set" => Ok(()),
Err(err) => Err(err),
}
}
@@ -443,3 +471,24 @@ impl Drop for TerminalGuard {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn windows_native_mouse_capture_restores_reporting_after_reset() {
let mut output = Vec::new();
set_windows_native_mouse_capture(&mut output, true, false, |enabled| {
assert!(enabled);
Ok(())
})
.unwrap();
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"
);
}
}
+9 -9
View File
@@ -4,10 +4,10 @@ const DISABLE_HOST_MOUSE_REPORTING_SEQUENCE: &[u8] =
b"\x1b[?1006l\x1b[?1016l\x1b[?1015l\x1b[?1005l\x1b[?1003l\x1b[?1002l\x1b[?1000l\x1b[?9l";
#[cfg(any(windows, test))]
const WINDOWS_SSH_MOUSE_REPORTING_ENABLE_SEQUENCE: &[u8] =
const WINDOWS_MOUSE_REPORTING_ENABLE_SEQUENCE: &[u8] =
b"\x1b[?1000h\x1b[?1002h\x1b[?1003h\x1b[?1006h";
#[cfg(any(windows, test))]
const WINDOWS_SSH_MOUSE_REPORTING_DISABLE_SEQUENCE: &[u8] =
const WINDOWS_MOUSE_REPORTING_DISABLE_SEQUENCE: &[u8] =
b"\x1b[?1016l\x1b[?1006l\x1b[?1003l\x1b[?1002l\x1b[?1000l";
pub(crate) fn clear_host_mouse_reporting<W: Write>(writer: &mut W) -> io::Result<()> {
@@ -16,15 +16,15 @@ pub(crate) fn clear_host_mouse_reporting<W: Write>(writer: &mut W) -> io::Result
}
#[cfg(any(windows, test))]
pub(crate) fn set_windows_ssh_mouse_reporting<W: Write>(
pub(crate) fn set_windows_mouse_reporting<W: Write>(
writer: &mut W,
enabled: bool,
sgr_pixels: bool,
) -> io::Result<()> {
writer.write_all(if enabled {
WINDOWS_SSH_MOUSE_REPORTING_ENABLE_SEQUENCE
WINDOWS_MOUSE_REPORTING_ENABLE_SEQUENCE
} else {
WINDOWS_SSH_MOUSE_REPORTING_DISABLE_SEQUENCE
WINDOWS_MOUSE_REPORTING_DISABLE_SEQUENCE
})?;
if enabled {
writer.write_all(if sgr_pixels {
@@ -188,12 +188,12 @@ mod tests {
}
#[test]
fn windows_ssh_mouse_reporting_setup_and_teardown_request_required_modes() {
fn windows_mouse_reporting_setup_and_teardown_request_required_modes() {
let mut output = Vec::new();
set_windows_ssh_mouse_reporting(&mut output, true, true).unwrap();
set_windows_ssh_mouse_reporting(&mut output, true, false).unwrap();
set_windows_ssh_mouse_reporting(&mut output, false, false).unwrap();
set_windows_mouse_reporting(&mut output, true, true).unwrap();
set_windows_mouse_reporting(&mut output, true, false).unwrap();
set_windows_mouse_reporting(&mut output, false, false).unwrap();
assert_eq!(
output,