summaryrefslogtreecommitdiff
path: root/src/client/input.rs
diff options
context:
space:
mode:
authorakbash <akbash@herdr.dev>2026-09-20 17:10:16 +0300
committerGitHub <noreply@github.com>2026-09-20 16:10:16 +0200
commitc00a62dda169beb472fc2f386d0f673ca100dfa4 (patch)
treeff0822ed7bb848e2e340dc382920da7c519f2458 /src/client/input.rs
parent29f9f4056f344af60f411004fc89c7eb5f357c48 (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.rs85
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()
}
// ---------------------------------------------------------------------------