aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client/mod.rs28
-rw-r--r--src/client/shell/input.rs4
-rw-r--r--src/raw_input.rs17
3 files changed, 46 insertions, 3 deletions
diff --git a/src/client/mod.rs b/src/client/mod.rs
index 8775ac19..59ff94c1 100644
--- a/src/client/mod.rs
+++ b/src/client/mod.rs
@@ -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);
diff --git a/src/client/shell/input.rs b/src/client/shell/input.rs
index 60202d1d..eb1f8f2f 100644
--- a/src/client/shell/input.rs
+++ b/src/client/shell/input.rs
@@ -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;
diff --git a/src/raw_input.rs b/src/raw_input.rs
index fc6ff52e..147d6e39 100644
--- a/src/raw_input.rs
+++ b/src/raw_input.rs
@@ -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
@@ -1356,6 +1363,16 @@ mod tests {
}
#[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");
let lost = parse_raw_input_bytes_sync(b"\x1b[O");