mirror of
https://github.com/herdrdev/herdr.git
synced 2026-09-21 16:01:04 +00:00
fix(client): re-assert host mouse modes after a terminal reconnect (#4079)
Co-authored-by: dengos <dengoswei@gmail.com>
This commit is contained in:
+27
-1
@@ -73,6 +73,12 @@ use terminal_setup::{
|
||||
effective_mouse_capture, effective_sgr_pixel_mouse, set_mouse_capture,
|
||||
setup_direct_attach_terminal, setup_terminal, should_draw_host_cursor,
|
||||
};
|
||||
|
||||
fn refresh_host_mouse_capture(enabled: bool, sgr_pixels: bool) {
|
||||
if let Err(err) = set_mouse_capture(enabled, sgr_pixels) {
|
||||
warn!(err = %err, "failed to re-assert host mouse capture");
|
||||
}
|
||||
}
|
||||
#[cfg(windows)]
|
||||
use terminal_setup::{
|
||||
enable_windows_virtual_terminal_input, is_ssh_session, windows_vti_input_backend_enabled,
|
||||
@@ -783,9 +789,16 @@ async fn run_client_loop(
|
||||
continue;
|
||||
}
|
||||
}
|
||||
let events = crate::raw_input::parse_raw_input_bytes_sync(&data);
|
||||
if crate::raw_input::events_require_host_mode_refresh(&events) {
|
||||
refresh_host_mouse_capture(
|
||||
state.mouse_capture_active,
|
||||
host_sgr_pixels_active.load(Ordering::Acquire),
|
||||
);
|
||||
}
|
||||
let (outcome, frame) = {
|
||||
let shell = state.shell.as_mut().expect("checked shell mode");
|
||||
let outcome = shell.handle_input_bytes(&data);
|
||||
let outcome = shell.handle_raw_events(events);
|
||||
let frame = outcome
|
||||
.repaint
|
||||
.then(|| shell.compose(state.reported_size.0, state.reported_size.1))
|
||||
@@ -1008,6 +1021,14 @@ async fn run_client_loop(
|
||||
write_stream.active_surface_available(),
|
||||
);
|
||||
if state.shell.is_some() {
|
||||
if events.iter().any(|event| {
|
||||
matches!(event, crate::protocol::ClientInputEvent::FocusGained)
|
||||
}) {
|
||||
refresh_host_mouse_capture(
|
||||
state.mouse_capture_active,
|
||||
host_sgr_pixels_active.load(Ordering::Acquire),
|
||||
);
|
||||
}
|
||||
let image_target = state
|
||||
.shell
|
||||
.as_ref()
|
||||
@@ -1084,6 +1105,11 @@ async fn run_client_loop(
|
||||
set_mouse_capture(state.mouse_capture_active, false)
|
||||
.map_err(ClientError::ConnectionFailed)?;
|
||||
host_sgr_pixels_active.store(false, Ordering::Release);
|
||||
} else {
|
||||
refresh_host_mouse_capture(
|
||||
state.mouse_capture_active,
|
||||
host_sgr_pixels_active.load(Ordering::Acquire),
|
||||
);
|
||||
}
|
||||
state.reported_size = (new_cols, new_rows);
|
||||
state.reported_cell_size = (cell_width_px, cell_height_px);
|
||||
|
||||
@@ -84,7 +84,7 @@ impl ClientShellState {
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(any(unix, test))]
|
||||
#[cfg(test)]
|
||||
pub(crate) fn handle_input_bytes(&mut self, data: &[u8]) -> ClientShellInput {
|
||||
self.handle_raw_events(crate::raw_input::parse_raw_input_bytes_sync(data))
|
||||
}
|
||||
@@ -155,7 +155,7 @@ impl ClientShellState {
|
||||
outcome
|
||||
}
|
||||
|
||||
pub(super) fn handle_raw_events(&mut self, events: Vec<RawInputEvent>) -> ClientShellInput {
|
||||
pub(crate) fn handle_raw_events(&mut self, events: Vec<RawInputEvent>) -> ClientShellInput {
|
||||
let mut outcome = ClientShellInput::default();
|
||||
if !events.is_empty() && self.endpoint_error.take().is_some() {
|
||||
self.endpoint_error_deadline = None;
|
||||
|
||||
@@ -543,6 +543,13 @@ pub(crate) fn events_require_host_surface_redraw(
|
||||
.any(|event| matches!(event, RawInputEvent::OuterFocusGained))
|
||||
}
|
||||
|
||||
#[cfg(any(unix, test))]
|
||||
pub(crate) fn events_require_host_mode_refresh(events: &[RawInputEvent]) -> bool {
|
||||
events
|
||||
.iter()
|
||||
.any(|event| matches!(event, RawInputEvent::OuterFocusGained))
|
||||
}
|
||||
|
||||
#[cfg(any(not(windows), test))]
|
||||
pub(crate) fn events_require_host_terminal_appearance_query(events: &[RawInputEvent]) -> bool {
|
||||
events
|
||||
@@ -1355,6 +1362,16 @@ mod tests {
|
||||
assert!(!events_require_host_surface_redraw(&events, true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn outer_focus_gained_requests_host_mode_refresh() {
|
||||
assert!(events_require_host_mode_refresh(
|
||||
&parse_raw_input_bytes_sync(b"\x1b[I")
|
||||
));
|
||||
assert!(!events_require_host_mode_refresh(
|
||||
&parse_raw_input_bytes_sync(b"\x1b[O")
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn outer_focus_gained_requests_host_appearance_query() {
|
||||
let gained = parse_raw_input_bytes_sync(b"\x1b[I");
|
||||
|
||||
Reference in New Issue
Block a user