diff options
| author | akbash <akbash@herdr.dev> | 2026-08-22 01:52:03 +0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-08-22 01:52:03 +0300 |
| commit | 1c76079f8b9494ec1c971c80fda34c116ecb89dd (patch) | |
| tree | 9c1ec01b870215cf6b2e7fbaeeb33a4d84376762 /src/app | |
| parent | 25e35f079e5147b52a696e72e87df92108febf93 (diff) | |
fix: copy selections before delayed mouse release (#3102)
refs #3100
Co-authored-by: akbash-bot <300245827+akbash-bot@users.noreply.github.com>
Diffstat (limited to 'src/app')
| -rw-r--r-- | src/app/input/clipboard.rs | 80 |
1 files changed, 79 insertions, 1 deletions
diff --git a/src/app/input/clipboard.rs b/src/app/input/clipboard.rs index 62ac1ca9..095b944d 100644 --- a/src/app/input/clipboard.rs +++ b/src/app/input/clipboard.rs @@ -38,12 +38,13 @@ impl App { .state .selection .as_ref() - .is_some_and(crate::selection::Selection::is_finalized) + .is_some_and(crate::selection::Selection::is_visible) { return false; } self.state.copy_selection(&self.terminal_runtimes); + self.selection_autoscroll_deadline = None; if !self.dispatch_pending_clipboard_write() { return false; } @@ -220,6 +221,83 @@ mod tests { } #[tokio::test] + async fn copy_shortcut_before_delayed_mouse_up_copies_in_progress_selection() { + let (mut app, info, mut input_rx) = app_with_screen_bytes_and_input(b"alpha beta"); + app.state.copy_on_select = false; + let source_id = 41; + let row = info.inner_rect.y; + let start_col = info.inner_rect.x; + let end_col = info.inner_rect.x + 4; + app.route_client_events_from( + source_id, + vec![ + crate::raw_input::RawInputEvent::Mouse(mouse( + MouseEventKind::Down(MouseButton::Left), + start_col, + row, + )), + crate::raw_input::RawInputEvent::Mouse(mouse( + MouseEventKind::Drag(MouseButton::Left), + end_col, + row, + )), + ], + false, + ); + assert_visible_selection(&app); + assert!(app + .state + .selection + .as_ref() + .is_some_and(crate::selection::Selection::is_in_progress)); + assert!(app.state.selection_autoscroll.is_some()); + assert!(app.selection_autoscroll_deadline.is_some()); + + let cmd_c = TerminalKey::new(KeyCode::Char('c'), KeyModifiers::SUPER); + app.route_client_events_from( + source_id, + vec![crate::raw_input::RawInputEvent::Key(cmd_c.clone())], + false, + ); + + assert_eq!(clipboard_write_content(&mut app), b"alpha"); + assert!(app.event_rx.try_recv().is_err()); + assert!(app.state.selection.is_none()); + assert!(app.state.selection_autoscroll.is_none()); + assert!(app.selection_autoscroll_deadline.is_none()); + assert!(app.selection_highlight_clear_deadline.is_none()); + assert_eq!(app.input_leases.len(), 1); + assert!(input_rx.try_recv().is_err()); + + app.route_client_events_from( + source_id, + vec![crate::raw_input::RawInputEvent::Key( + cmd_c.with_kind(KeyEventKind::Release), + )], + false, + ); + assert!(app.input_leases.is_empty()); + + app.route_client_events_from( + source_id, + vec![crate::raw_input::RawInputEvent::Mouse(mouse( + MouseEventKind::Up(MouseButton::Left), + end_col, + row, + ))], + false, + ); + + assert!(app.state.selection.is_none()); + assert!(app.state.selection_autoscroll.is_none()); + assert!(app.selection_autoscroll_deadline.is_none()); + assert!(app.selection_highlight_clear_deadline.is_none()); + assert!(app.input_leases.is_empty()); + assert!(app.event_rx.try_recv().is_err()); + assert!(input_rx.try_recv().is_err()); + } + + #[tokio::test] async fn retained_selection_copy_shortcut_is_disabled_with_copy_on_select() { let (mut app, _info, mut input_rx) = app_with_screen_bytes_and_input(b"alpha beta"); let pane_id = app.state.workspaces[0].tabs[0].root_pane; |
