Keep terminal focus reports local
This commit is contained in:
+39
-3
@@ -4401,8 +4401,9 @@ async fn run_terminal(
|
|||||||
if input_matches_escape(&bytes, escape_key.as_deref()) {
|
if input_matches_escape(&bytes, escape_key.as_deref()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
let saw_focus_in = input_contains_focus_in(&bytes);
|
||||||
if !forward_only
|
if !forward_only
|
||||||
&& input_contains_focus_in(&bytes)
|
&& saw_focus_in
|
||||||
&& last_focus_repaint_at.elapsed() >= FOCUS_REPAINT_COOLDOWN
|
&& last_focus_repaint_at.elapsed() >= FOCUS_REPAINT_COOLDOWN
|
||||||
{
|
{
|
||||||
last_focus_repaint_at = Instant::now();
|
last_focus_repaint_at = Instant::now();
|
||||||
@@ -4436,6 +4437,10 @@ async fn run_terminal(
|
|||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bytes = strip_terminal_focus_reports(&bytes);
|
||||||
|
if bytes.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if should_strip_stale_terminal_reports(
|
if should_strip_stale_terminal_reports(
|
||||||
last_packet_at.elapsed(),
|
last_packet_at.elapsed(),
|
||||||
stale_terminal_input_suppress_until,
|
stale_terminal_input_suppress_until,
|
||||||
@@ -5641,6 +5646,26 @@ fn input_contains_focus_in(bytes: &[u8]) -> bool {
|
|||||||
contains_bytes(bytes, b"\x1b[I") || contains_bytes(bytes, b"\x9bI")
|
contains_bytes(bytes, b"\x1b[I") || contains_bytes(bytes, b"\x9bI")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn strip_terminal_focus_reports(bytes: &[u8]) -> Vec<u8> {
|
||||||
|
let mut out = Vec::with_capacity(bytes.len());
|
||||||
|
let mut offset = 0;
|
||||||
|
while offset < bytes.len() {
|
||||||
|
match bytes.get(offset..) {
|
||||||
|
Some([0x1b, b'[', b'I' | b'O', ..]) => {
|
||||||
|
offset += 3;
|
||||||
|
}
|
||||||
|
Some([0x9b, b'I' | b'O', ..]) => {
|
||||||
|
offset += 2;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
out.push(bytes[offset]);
|
||||||
|
offset += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
fn should_repaint_idle_alternate_screen(
|
fn should_repaint_idle_alternate_screen(
|
||||||
alternate_screen: bool,
|
alternate_screen: bool,
|
||||||
last_terminal_frame_at: Instant,
|
last_terminal_frame_at: Instant,
|
||||||
@@ -7347,8 +7372,8 @@ mod tests {
|
|||||||
should_hold_during_startup_gate, should_hold_post_submit_input,
|
should_hold_during_startup_gate, should_hold_post_submit_input,
|
||||||
should_repaint_idle_alternate_screen, split_after_command_submit, ssh_destination_host,
|
should_repaint_idle_alternate_screen, split_after_command_submit, ssh_destination_host,
|
||||||
ssh_username, ssh_with_user, startup_command, status_ssh_target, strip_stale_mouse_reports,
|
ssh_username, ssh_with_user, startup_command, status_ssh_target, strip_stale_mouse_reports,
|
||||||
toml_bare_key_or_quoted, update_check_requested, update_version_status,
|
strip_terminal_focus_reports, toml_bare_key_or_quoted, update_check_requested,
|
||||||
upsert_managed_block, valid_forward_host, vscode_safe_alias,
|
update_version_status, upsert_managed_block, valid_forward_host, vscode_safe_alias,
|
||||||
};
|
};
|
||||||
use dosh::config::{ClientConfig, CommandExtension, HostConfig};
|
use dosh::config::{ClientConfig, CommandExtension, HostConfig};
|
||||||
use dosh::native::EnvVar;
|
use dosh::native::EnvVar;
|
||||||
@@ -8661,6 +8686,17 @@ mod tests {
|
|||||||
assert!(!input_contains_focus_in(b"\x1b[A"));
|
assert!(!input_contains_focus_in(b"\x1b[A"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn focus_reports_are_never_forwarded_as_user_input() {
|
||||||
|
assert_eq!(strip_terminal_focus_reports(b"\x1b[Ihello\x1b[O"), b"hello");
|
||||||
|
assert_eq!(strip_terminal_focus_reports(b"\x9bIhello\x9bO"), b"hello");
|
||||||
|
assert_eq!(strip_terminal_focus_reports(b"\x1b[A"), b"\x1b[A");
|
||||||
|
assert_eq!(
|
||||||
|
strip_terminal_focus_reports(b"before\x1b[Iafter"),
|
||||||
|
b"beforeafter"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn idle_repaint_only_runs_for_stale_alternate_screen() {
|
fn idle_repaint_only_runs_for_stale_alternate_screen() {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
|
|||||||
Reference in New Issue
Block a user