//! Windows conhost mouse capture helpers, used by RetainedRenderer to
//! set/clear `ENABLE_MOUSE_INPUT` while preserving the pre-enter console
//! mode.
#![cfg(windows)]
/// Enable `ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS | ENABLE_WINDOW_INPUT`
/// on STD_INPUT_HANDLE, clear `ENABLE_QUICK_EDIT_MODE` so the user can't
/// accidentally drag-select and freeze the terminal, and write the result
/// back. Returns the original mode on success so the caller can restore it
/// byte-for-byte; returns `None` if either GetConsoleMode or SetConsoleMode
/// fails (typically: stdin was redirected and isn't a console handle, e.g.
/// running under a pipe).
///
/// All results are mirrored to `tuix_trace!` (gated on
/// `ATOMCODE_TUIX_LOG`) so a "wheel still doesn't work" report shows
/// exactly which syscall returned what mask.
pub fn enable_conhost_mouse_capture() -> Option<u32> {
use windows_sys::Win32::System::Console::{
GetConsoleMode, GetStdHandle, SetConsoleMode, ENABLE_EXTENDED_FLAGS,
ENABLE_MOUSE_INPUT, ENABLE_QUICK_EDIT_MODE, ENABLE_WINDOW_INPUT, STD_INPUT_HANDLE,
};
unsafe {
let h = GetStdHandle(STD_INPUT_HANDLE);
// GetStdHandle returns INVALID_HANDLE_VALUE (`!0 as HANDLE`) on
// failure; on Windows that's `-1isize as *mut c_void`. Treat
// null and "all bits set" as failure shapes.
if h.is_null() || h as isize == -1 {
crate::tuix_trace!("REN", "conhost-mouse: GetStdHandle returned invalid");
return None;
}
let mut original: u32 = 0;
if GetConsoleMode(h, &mut original) == 0 {
let err = std::io::Error::last_os_error();
crate::tuix_trace!("REN", "conhost-mouse: GetConsoleMode failed: {}", err);
return None;
}
let new_mode = (original | ENABLE_MOUSE_INPUT | ENABLE_EXTENDED_FLAGS | ENABLE_WINDOW_INPUT)
& !ENABLE_QUICK_EDIT_MODE;
if SetConsoleMode(h, new_mode) == 0 {
let err = std::io::Error::last_os_error();
crate::tuix_trace!(
"REN",
"conhost-mouse: SetConsoleMode(0x{:08x}) failed: {}",
new_mode,
err
);
return None;
}
crate::tuix_trace!(
"REN",
"conhost-mouse: ok prev=0x{:08x} new=0x{:08x}",
original,
new_mode
);
Some(original)
}
}
/// Restore STD_INPUT_HANDLE's console mode to the value `enable_conhost_
/// mouse_capture` returned. Best-effort — failure here just means the
/// shell mode bits drift slightly on exit; better than aborting.
pub fn restore_conhost_console_in_mode(prior: u32) {
use windows_sys::Win32::System::Console::{GetStdHandle, SetConsoleMode, STD_INPUT_HANDLE};
unsafe {
let h = GetStdHandle(STD_INPUT_HANDLE);
if h.is_null() || h as isize == -1 {
return;
}
let _ = SetConsoleMode(h, prior);
}
}