diff options
| author | akbash <akbash@herdr.dev> | 2026-09-20 17:10:16 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-09-20 16:10:16 +0200 |
| commit | c00a62dda169beb472fc2f386d0f673ca100dfa4 (patch) | |
| tree | ff0822ed7bb848e2e340dc382920da7c519f2458 /src/client/input.rs | |
| parent | 29f9f4056f344af60f411004fc89c7eb5f357c48 (diff) | |
fix: preserve delayed mouse reports with confirmed keyboard input (#4247)
* fix: preserve delayed mouse reports with confirmed keyboard input
refs #3480
* fix: capture geometry before replaying buffered mouse input
refs #3480
---------
Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Co-authored-by: JJ Liebig <jonathan.liebig@gmail.com>
Diffstat (limited to 'src/client/input.rs')
| -rw-r--r-- | src/client/input.rs | 85 |
1 files changed, 60 insertions, 25 deletions
diff --git a/src/client/input.rs b/src/client/input.rs index 41850f96..45656f84 100644 --- a/src/client/input.rs +++ b/src/client/input.rs @@ -42,6 +42,8 @@ pub fn stdin_reader_loop( host_cell_size_query_sent: bool, host_mouse_capture_active: Arc<AtomicBool>, host_sgr_pixels_active: Arc<AtomicBool>, + host_escape_disambiguation_active: bool, + initial_host_input: Vec<u8>, #[cfg(unix)] direct_response: Arc<std::sync::Mutex<super::direct_graphics::ResponseMatcher>>, #[cfg(unix)] direct_response_active: Arc<AtomicBool>, ) { @@ -53,6 +55,7 @@ pub fn stdin_reader_loop( host_mouse_capture_active, host_sgr_pixels_active, ); + let _ = (host_escape_disambiguation_active, initial_host_input); windows_stdin_reader_loop(event_tx, should_quit); } @@ -64,6 +67,8 @@ pub fn stdin_reader_loop( host_cell_size_query_sent, host_mouse_capture_active, host_sgr_pixels_active, + host_escape_disambiguation_active, + initial_host_input, direct_response, direct_response_active, ); @@ -77,6 +82,8 @@ fn unix_stdin_reader_loop( host_cell_size_query_sent: bool, host_mouse_capture_active: Arc<AtomicBool>, host_sgr_pixels_active: Arc<AtomicBool>, + host_escape_disambiguation_active: bool, + initial_host_input: Vec<u8>, direct_response: Arc<std::sync::Mutex<super::direct_graphics::ResponseMatcher>>, direct_response_active: Arc<AtomicBool>, ) { @@ -84,6 +91,7 @@ fn unix_stdin_reader_loop( let mut reader = stdin.lock(); let mut scratch = [0u8; 4096]; let mut framer = crate::raw_input::RawInputByteFramer::for_host_input(); + framer.set_host_escape_disambiguation_active(host_escape_disambiguation_active); if host_color_query_sent { framer.host_color_query_sent(); framer.enable_host_color_scheme_change_tracking(); @@ -97,6 +105,57 @@ fn unix_stdin_reader_loop( let mut last_geometry = None; let mut direct_filter = super::direct_graphics::InputFilter::default(); + if !initial_host_input.is_empty() { + let sgr_pixels = host_sgr_pixels_active.load(Ordering::Acquire); + if sgr_pixels { + last_geometry = crate::input::mouse::HostGeometry::current(); + } + let chunks = framer.push(&initial_host_input); + if !send_unix_input_chunks( + chunks, + &event_tx, + &mut pending_palette, + sgr_pixels, + last_geometry, + ) { + return; + } + if (framer.has_pending_input() || !pending_palette.is_empty()) + && stdin_read_ready( + &reader, + idle_flush_timeout_ms(&framer, host_mouse_capture_active.load(Ordering::Acquire)), + ) == Some(false) + { + let had_pending = framer.has_pending_input(); + let chunks = framer.flush_timeout(); + let held_escape = had_pending && chunks.is_empty(); + if !send_unix_input_chunks( + chunks, + &event_tx, + &mut pending_palette, + sgr_pixels, + last_geometry, + ) || !flush_unix_palette_input(&event_tx, &mut pending_palette) + { + return; + } + if held_escape + && stdin_read_ready(&reader, crate::raw_input::RAW_INPUT_IDLE_FLUSH_TIMEOUT_MS) + == Some(false) + && !send_unix_input_chunks( + framer.flush_timeout(), + &event_tx, + &mut pending_palette, + sgr_pixels, + last_geometry, + ) + { + return; + } + } + pending_mode = framer.has_pending_input().then_some(sgr_pixels); + } + while !should_quit.load(Ordering::Acquire) { if direct_filter.has_pending() && stdin_read_ready(&reader, crate::raw_input::RAW_INPUT_IDLE_FLUSH_TIMEOUT_MS) @@ -593,31 +652,7 @@ fn stdin_read_ready<R: AsRawFd>(reader: &R, timeout_ms: i32) -> Option<bool> { #[cfg(unix)] fn poll_read_ready(fd: i32, timeout_ms: i32) -> Option<bool> { - #[repr(C)] - struct PollFd { - fd: i32, - events: i16, - revents: i16, - } - - unsafe extern "C" { - fn poll(fds: *mut PollFd, nfds: usize, timeout: i32) -> i32; - } - - const POLLIN: i16 = 0x0001; - - let mut pfd = PollFd { - fd, - events: POLLIN, - revents: 0, - }; - - let result = unsafe { poll(&mut pfd as *mut PollFd, 1, timeout_ms) }; - if result < 0 { - None - } else { - Some(result > 0) - } + crate::platform::poll_fd_readable(fd, timeout_ms).ok() } // --------------------------------------------------------------------------- |
