aboutsummaryrefslogtreecommitdiff
path: root/src/app/input/clipboard.rs
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-08-01 04:27:50 +0300
committerGitHub <noreply@github.com>2026-08-01 04:27:50 +0300
commitb76adc155d979705a353fd6dc87c702f9dfc6c22 (patch)
treef613254e0cfbfd2b4450a6a5f3ee7c0ba8136976 /src/app/input/clipboard.rs
parent8d190eddda2c74afa3dc043f8ec8020ffd7b5a94 (diff)
fix(input): preserve native key lifecycle across routing (#2142)
refs #2077 Co-authored-by: Jonathan Liebig <jonathan.liebig@gmail.com>
Diffstat (limited to 'src/app/input/clipboard.rs')
-rw-r--r--src/app/input/clipboard.rs45
1 files changed, 34 insertions, 11 deletions
diff --git a/src/app/input/clipboard.rs b/src/app/input/clipboard.rs
index db3fa9f2..62ac1ca9 100644
--- a/src/app/input/clipboard.rs
+++ b/src/app/input/clipboard.rs
@@ -5,7 +5,9 @@ use crate::{
input::TerminalKey,
};
-fn is_retained_selection_copy_key(key: TerminalKey) -> bool {
+use super::{ConsumedInputLease, InputLeaseKey};
+
+fn is_retained_selection_copy_key(key: &TerminalKey) -> bool {
matches!(key.code, KeyCode::Char('c' | 'C'))
&& matches!(key.modifiers, KeyModifiers::CONTROL | KeyModifiers::SUPER)
}
@@ -31,7 +33,7 @@ impl App {
key: TerminalKey,
) -> bool {
if self.state.copy_on_select
- || !is_retained_selection_copy_key(key)
+ || !is_retained_selection_copy_key(&key)
|| !self
.state
.selection
@@ -46,7 +48,10 @@ impl App {
return false;
}
- self.suppressed_repeat_keys.insert((source_id, key.code));
+ self.input_leases.insert_consumed(
+ InputLeaseKey::new(source_id, &key),
+ ConsumedInputLease::SuppressRepeats,
+ );
true
}
}
@@ -132,11 +137,19 @@ mod tests {
assert_visible_selection(&app);
assert!(app.event_rx.try_recv().is_err());
- let ctrl_c = TerminalKey::new(KeyCode::Char('c'), KeyModifiers::CONTROL);
+ let ctrl_c = TerminalKey::new(KeyCode::Char('c'), KeyModifiers::CONTROL)
+ .with_windows_record(crate::input::WindowsKeyRecord {
+ key_down: true,
+ repeat_count: 1,
+ virtual_key_code: 0x43,
+ virtual_scan_code: 0x2e,
+ unicode: 'c' as u16,
+ control_key_state: 0x0008,
+ });
let source_id = 41;
app.route_client_events_from(
source_id,
- vec![crate::raw_input::RawInputEvent::Key(ctrl_c)],
+ vec![crate::raw_input::RawInputEvent::Key(ctrl_c.clone())],
false,
);
@@ -156,29 +169,39 @@ mod tests {
app.route_client_events_from(
source_id,
- vec![crate::raw_input::RawInputEvent::Key(
- ctrl_c.with_kind(KeyEventKind::Repeat),
- )],
+ vec![
+ crate::raw_input::RawInputEvent::Key(ctrl_c.clone()),
+ crate::raw_input::RawInputEvent::Key(
+ ctrl_c.clone().with_kind(KeyEventKind::Repeat),
+ ),
+ ],
false,
);
+ assert_eq!(app.input_leases.len(), 1);
assert!(app.event_rx.try_recv().is_err());
assert!(input_rx.try_recv().is_err());
app.route_client_events_from(
source_id,
vec![crate::raw_input::RawInputEvent::Key(
- ctrl_c.with_kind(KeyEventKind::Release),
+ ctrl_c.clone().with_kind(KeyEventKind::Release),
)],
false,
);
+ assert!(app.input_leases.is_empty());
app.route_client_events_from(
source_id,
- vec![crate::raw_input::RawInputEvent::Key(ctrl_c)],
+ vec![crate::raw_input::RawInputEvent::Key(ctrl_c.clone())],
false,
);
+ let expected = if cfg!(windows) {
+ b"\x1b[67;46;99;1;8;1_".as_slice()
+ } else {
+ b"\x03".as_slice()
+ };
assert_eq!(
input_rx.try_recv().expect("forwarded Ctrl-C").as_ref(),
- b"\x03"
+ expected
);
assert!(app.event_rx.try_recv().is_err());
}