diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-26 18:26:12 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-05-26 18:26:12 +0300 |
| commit | af399094f5d24f157e35aaa657ed5ad5c44e5325 (patch) | |
| tree | 2f44cc902312fbe8c405a972b9a438ca6bead27c /src/app/input/mod.rs | |
| parent | 3750e0bae21c54da3947d337584f180a21d0bc67 (diff) | |
feat: open pane links with ctrl-click
refs #307
Diffstat (limited to 'src/app/input/mod.rs')
| -rw-r--r-- | src/app/input/mod.rs | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/src/app/input/mod.rs b/src/app/input/mod.rs index e145e628..8ba8e4bd 100644 --- a/src/app/input/mod.rs +++ b/src/app/input/mod.rs @@ -1,6 +1,6 @@ //! Input handling — translates crossterm key/mouse events into state mutations. -use crossterm::event::{KeyCode, KeyEvent, MouseButton, MouseEvent, MouseEventKind}; +use crossterm::event::{KeyCode, KeyEvent, KeyModifiers, MouseButton, MouseEvent, MouseEventKind}; use crate::app::PaneClickState; use crate::input::TerminalKey; @@ -195,6 +195,10 @@ impl App { } } + if self.handle_modified_url_click(mouse) { + return; + } + let handled_pane_double_click = self.handle_pane_double_click(mouse); let previous_agent_panel_scope = self.state.agent_panel_scope; @@ -248,6 +252,33 @@ impl App { } } + fn handle_modified_url_click(&mut self, mouse: MouseEvent) -> bool { + if self.state.mode != Mode::Terminal + || !matches!(mouse.kind, MouseEventKind::Down(MouseButton::Left)) + || !mouse.modifiers.contains(KeyModifiers::CONTROL) + { + return false; + } + + let Some(info) = self.state.pane_at(mouse.column, mouse.row).cloned() else { + return false; + }; + let viewport_row = mouse.row.saturating_sub(info.inner_rect.y); + let col = mouse.column.saturating_sub(info.inner_rect.x); + let Some(url) = + self.state + .url_at_pane_cell(&self.terminal_runtimes, info.id, viewport_row, col) + else { + return false; + }; + + self.last_pane_click = None; + if let Err(err) = crate::platform::open_url(&url) { + tracing::warn!(err = %err, url = %url, "failed to open pane URL"); + } + true + } + fn handle_pane_double_click(&mut self, mouse: MouseEvent) -> bool { // A pane press stops being a double-click candidate once it becomes // a drag or completes as a real text selection. @@ -291,6 +322,11 @@ impl App { return None; } + if !mouse.modifiers.is_empty() { + self.last_pane_click = None; + return None; + } + if self.state.mode != Mode::Terminal { self.last_pane_click = None; return None; |
