diff options
| author | JJ Liebig <jonathan.liebig@gmail.com> | 2026-09-06 15:36:35 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-09-06 15:36:35 +0200 |
| commit | 5a64e8da4551990367dd26d77cf3b654dfa27a73 (patch) | |
| tree | d7eaf5f4143cb7b0d34bfe73dd3d1ea315fa6c1a /src/client | |
| parent | e366a05f03b6e37549c7a1744c3551553017c541 (diff) | |
fix: consume failed selection copies without interrupting agents (#3681)
Diffstat (limited to 'src/client')
| -rw-r--r-- | src/client/shell/actions.rs | 46 | ||||
| -rw-r--r-- | src/client/shell/input.rs | 2 | ||||
| -rw-r--r-- | src/client/shell/state.rs | 5 | ||||
| -rw-r--r-- | src/client/shell/tests/copy.rs | 25 | ||||
| -rw-r--r-- | src/client/shell/tests/endpoint_requests.rs | 10 | ||||
| -rw-r--r-- | src/client/shell/worktrees.rs | 2 | ||||
| -rw-r--r-- | src/client/shell_runtime.rs | 5 |
7 files changed, 14 insertions, 81 deletions
diff --git a/src/client/shell/actions.rs b/src/client/shell/actions.rs index f99d8f3a..e62d75ff 100644 --- a/src/client/shell/actions.rs +++ b/src/client/shell/actions.rs @@ -248,14 +248,6 @@ impl ClientShellState { } pub(super) fn request_selection_copy(&mut self, outcome: &mut ClientShellInput) { - self.request_selection_copy_with_fallback(outcome, None); - } - - pub(super) fn request_selection_copy_with_fallback( - &mut self, - outcome: &mut ClientShellInput, - fallback_key: Option<crate::input::TerminalKey>, - ) { let Some(selection) = self.selection.as_ref() else { return; }; @@ -266,27 +258,6 @@ impl ClientShellState { .and_then(|surface| surface.panes.iter().find(|pane| pane.pane_id == pane_id)) .map(|pane| pane.content_revision); let (anchor, cursor) = selection.ordered_cells(); - let fallback = fallback_key.and_then(|key| { - let press = ClientPaneInputEvent::from_terminal_key(key.clone())?; - let tracks_release = matches!( - &press, - ClientPaneInputEvent::Key { - tracks_release: true, - .. - } - ); - let mut message = - super::target_event_message(ClientInputTarget::Pane(pane_id.clone()), press); - if tracks_release { - let release = ClientPaneInputEvent::from_terminal_key( - key.with_kind(crossterm::event::KeyEventKind::Release), - )?; - if let ClientMessage::ClientShellPaneInput { events, .. } = &mut message { - events.push(release); - } - } - Some(message) - }); self.push_endpoint_method_with_kind( crate::api::schema::Method::PaneSelectionRead( crate::api::schema::PaneSelectionReadParams { @@ -302,7 +273,7 @@ impl ClientShellState { content_revision, }, ), - PendingEndpointKind::SelectionCopy { fallback }, + PendingEndpointKind::SelectionCopy, outcome, ); } @@ -654,13 +625,7 @@ impl ClientShellState { let repaint = self.complete_pane_scroll(pane_id, serial, result, &mut outcome); return (repaint, outcome.actions); } - PendingEndpointKind::SelectionCopy { fallback } => { - let fallback = || { - fallback - .map(ClientShellAction::Request) - .into_iter() - .collect::<Vec<_>>() - }; + PendingEndpointKind::SelectionCopy => { return match result { Ok(crate::api::schema::ResponseResult::PaneSelection { text, .. }) if !text.is_empty() => @@ -672,17 +637,14 @@ impl ClientShellState { ) } Ok(crate::api::schema::ResponseResult::PaneSelection { .. }) => { - (false, fallback()) + (false, Vec::new()) } Ok(_) => { self.endpoint_error = Some("endpoint returned an unexpected selection result".to_owned()); - (true, fallback()) - } - Err(error) if error.code.as_deref() == Some("endpoint_cancelled") => { (true, Vec::new()) } - Err(_) => (true, fallback()), + Err(_) => (true, Vec::new()), }; } PendingEndpointKind::WordSelection { diff --git a/src/client/shell/input.rs b/src/client/shell/input.rs index f8826136..539dec6e 100644 --- a/src/client/shell/input.rs +++ b/src/client/shell/input.rs @@ -523,7 +523,7 @@ impl ClientShellState { .as_ref() .is_some_and(crate::selection::Selection::is_visible) { - self.request_selection_copy_with_fallback(outcome, Some(key.clone())); + self.request_selection_copy(outcome); self.selection = None; self.stop_selection_autoscroll(); self.selection_highlight_clear_deadline = None; diff --git a/src/client/shell/state.rs b/src/client/shell/state.rs index 67bdff91..b30f57d0 100644 --- a/src/client/shell/state.rs +++ b/src/client/shell/state.rs @@ -298,7 +298,6 @@ pub(crate) enum ClientShellAction { request: Box<crate::api::schema::Request>, }, ClipboardWrite(Vec<u8>), - Request(ClientMessage), OpenSafeWebUrl(String), ActivateEndpoint { endpoint_id: ClientEndpointId, @@ -689,9 +688,7 @@ pub(super) enum PendingEndpointKind { WorktreeRemove { forced: bool, }, - SelectionCopy { - fallback: Option<ClientMessage>, - }, + SelectionCopy, PaneScroll { pane_id: String, serial: u64, diff --git a/src/client/shell/tests/copy.rs b/src/client/shell/tests/copy.rs index 7d71a981..7cc3241b 100644 --- a/src/client/shell/tests/copy.rs +++ b/src/client/shell/tests/copy.rs @@ -224,7 +224,7 @@ fn retained_mouse_selection_copies_only_on_exact_copy_shortcut() { ClientShellAction::Endpoint { request, .. } => request.id.clone(), _ => unreachable!(), }; - let (_, fallback) = state.handle_endpoint_result( + let (_, actions) = state.handle_endpoint_result( "boot-1", &request_id, Ok(crate::api::schema::ResponseResult::PaneSelection { @@ -232,25 +232,10 @@ fn retained_mouse_selection_copies_only_on_exact_copy_shortcut() { text: String::new(), }), ); - assert!(matches!( - &fallback[..], - [ClientShellAction::Request(ClientMessage::ClientShellPaneInput { - pane_id, - events, - })] if pane_id == "pane_1" - && matches!( - &events[..], - [ClientPaneInputEvent::Key { - code: crate::protocol::ClientKeyCode::Char('c'), - kind: crate::protocol::ClientKeyKind::Press, - .. - }, ClientPaneInputEvent::Key { - code: crate::protocol::ClientKeyCode::Char('c'), - kind: crate::protocol::ClientKeyKind::Release, - .. - }] - ) - )); + assert!( + actions.is_empty(), + "failed copy must not send terminal input" + ); } #[test] diff --git a/src/client/shell/tests/endpoint_requests.rs b/src/client/shell/tests/endpoint_requests.rs index 8149b530..ab5a3cb2 100644 --- a/src/client/shell/tests/endpoint_requests.rs +++ b/src/client/shell/tests/endpoint_requests.rs @@ -216,7 +216,7 @@ fn cancelled_integration_install_does_not_queue_a_refresh() { } #[test] -fn cancelled_selection_does_not_replay_its_fallback_key() { +fn cancelled_selection_does_not_send_terminal_input() { let mut state = ClientShellState::new(ClientShellConfig::from_config(&Config::default())); state.set_snapshot(Box::new(snapshot())); state.set_pane_surface(surface()); @@ -226,13 +226,7 @@ fn cancelled_selection_does_not_replay_its_fallback_key() { (0, 2), )); let mut outcome = ClientShellInput::default(); - state.request_selection_copy_with_fallback( - &mut outcome, - Some(crate::input::TerminalKey::new( - KeyCode::Char('c'), - KeyModifiers::CONTROL, - )), - ); + state.request_selection_copy(&mut outcome); let (_, actions) = state.handle_endpoint_result( "boot-1", request_id(&outcome.actions), diff --git a/src/client/shell/worktrees.rs b/src/client/shell/worktrees.rs index ea2e8f24..8218c0cc 100644 --- a/src/client/shell/worktrees.rs +++ b/src/client/shell/worktrees.rs @@ -540,7 +540,7 @@ impl ClientShellState { | PendingEndpointKind::ReloadConfig | PendingEndpointKind::IntegrationList | PendingEndpointKind::IntegrationInstall - | PendingEndpointKind::SelectionCopy { .. } + | PendingEndpointKind::SelectionCopy | PendingEndpointKind::PaneScroll { .. } | PendingEndpointKind::WordSelection { .. } | PendingEndpointKind::PaneLinkActivate { .. } diff --git a/src/client/shell_runtime.rs b/src/client/shell_runtime.rs index 8a4af0b7..00bb1406 100644 --- a/src/client/shell_runtime.rs +++ b/src/client/shell_runtime.rs @@ -28,11 +28,6 @@ pub(super) fn dispatch_client_shell_actions( shell::ClientShellAction::ClipboardWrite(bytes) => { crate::selection::write_osc52_bytes(&bytes); } - shell::ClientShellAction::Request(request) => { - if endpoints.active_surface_available() { - write_to_server(endpoints, &request).map_err(ClientError::ConnectionLost)?; - } - } shell::ClientShellAction::ActivateEndpoint { endpoint_id, target, |
