diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-29 18:09:25 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-29 18:09:25 +0300 |
| commit | 1a4e94e57e181379e2ed42d63a49fbc56ed1dba4 (patch) | |
| tree | 0319544374f1149a405259070b90df9d62854789 /src/app/input/mouse.rs | |
| parent | a937f7e85bbf8780c6030c57f48dab2168bca932 (diff) | |
refactor: route tui mutations through runtime authority
Diffstat (limited to 'src/app/input/mouse.rs')
| -rw-r--r-- | src/app/input/mouse.rs | 133 |
1 files changed, 94 insertions, 39 deletions
diff --git a/src/app/input/mouse.rs b/src/app/input/mouse.rs index c8a03674..71c0cfbd 100644 --- a/src/app/input/mouse.rs +++ b/src/app/input/mouse.rs @@ -26,6 +26,40 @@ use super::{ ScrollbarClickTarget, TAB_DRAG_THRESHOLD, WORKSPACE_DRAG_THRESHOLD, }; +pub(super) enum MouseAction { + Settings(SettingsAction), + FocusWorkspace { + ws_idx: usize, + }, + FocusTab { + tab_idx: usize, + }, + FocusPane { + ws_idx: usize, + pane_id: crate::layout::PaneId, + }, + FocusToastTarget, + MoveWorkspace { + source_ws_idx: usize, + insert_idx: usize, + }, + MoveTab { + ws_idx: usize, + source_tab_idx: usize, + insert_idx: usize, + }, + SetSplitRatio { + path: Vec<bool>, + ratio: f32, + }, +} + +enum MobileMouseResult { + Ignored, + Consumed, + Action(MouseAction), +} + impl AppState { pub(crate) fn handle_pane_mouse_only( &mut self, @@ -59,7 +93,7 @@ impl AppState { &mut self, terminal_runtimes: &mut TerminalRuntimeRegistry, mouse: MouseEvent, - ) -> Option<SettingsAction> { + ) -> Option<MouseAction> { if self.mode == Mode::Onboarding { self.handle_onboarding_mouse(mouse); return None; @@ -69,8 +103,7 @@ impl AppState { && self.clickable_toast_at(mouse.column, mouse.row) && matches!(mouse.kind, MouseEventKind::Down(MouseButton::Left)) { - self.focus_toast_target(); - return None; + return Some(MouseAction::FocusToastTarget); } if self.mode == Mode::Terminal @@ -81,7 +114,7 @@ impl AppState { } if self.mode == Mode::Settings { - return self.handle_settings_mouse(mouse); + return self.handle_settings_mouse(mouse).map(MouseAction::Settings); } let launcher_enabled = self.view.layout != ViewLayout::Mobile @@ -134,8 +167,12 @@ impl AppState { return None; } - if self.view.layout == ViewLayout::Mobile && self.handle_mobile_mouse(mouse) { - return None; + if self.view.layout == ViewLayout::Mobile { + match self.handle_mobile_mouse(mouse) { + MobileMouseResult::Ignored => {} + MobileMouseResult::Consumed => return None, + MobileMouseResult::Action(action) => return Some(action), + } } let sidebar = self.view.sidebar_rect; @@ -473,16 +510,15 @@ impl AppState { if self.sidebar_collapsed { if let Some(idx) = self.collapsed_workspace_at_row(mouse.row) { - self.switch_workspace(idx); self.mode = Mode::Terminal; - return None; + return Some(MouseAction::FocusWorkspace { ws_idx: idx }); } if let Some((ws_idx, _tab_idx, pane_id)) = self.collapsed_agent_detail_target_at(mouse.row) { - self.focus_pane_in_workspace(ws_idx, pane_id); self.mode = Mode::Terminal; + return Some(MouseAction::FocusPane { ws_idx, pane_id }); } return None; } @@ -574,12 +610,10 @@ impl AppState { if let Some((ws_idx, _tab_idx, pane_id)) = self.agent_detail_target_at(mouse.row) { - self.focus_pane_in_workspace(ws_idx, pane_id); self.mode = Mode::Terminal; - return None; + return Some(MouseAction::FocusPane { ws_idx, pane_id }); } } else if let Some(info) = self.pane_at(mouse.column, mouse.row).cloned() { - self.focus_pane(info.id); if self.mode != Mode::Terminal { self.mode = Mode::Terminal; } @@ -587,6 +621,12 @@ impl AppState { if self.forward_pane_mouse_button(terminal_runtimes, &info, mouse) { self.selection = None; self.selection_autoscroll = None; + if let Some(ws_idx) = self.active { + return Some(MouseAction::FocusPane { + ws_idx, + pane_id: info.id, + }); + } return None; } @@ -600,6 +640,12 @@ impl AppState { col, self.pane_scroll_metrics(terminal_runtimes, info.id), )); + if let Some(ws_idx) = self.active { + return Some(MouseAction::FocusPane { + ws_idx, + pane_id: info.id, + }); + } } else if let Some(info) = self.view.pane_infos.iter().find(|p| { mouse.column >= p.rect.x && mouse.column < p.rect.x + p.rect.width @@ -607,10 +653,15 @@ impl AppState { && mouse.row < p.rect.y + p.rect.height }) { let id = info.id; - self.focus_pane(id); if self.mode != Mode::Terminal { self.mode = Mode::Terminal; } + if let Some(ws_idx) = self.active { + return Some(MouseAction::FocusPane { + ws_idx, + pane_id: id, + }); + } } } @@ -721,10 +772,7 @@ impl AppState { }; let ratio = ratio.clamp(0.1, 0.9); let path = path.clone(); - if let Some(ws) = self.active.and_then(|i| self.workspaces.get_mut(i)) { - ws.layout.set_ratio_at(&path, ratio); - self.mark_session_dirty(); - } + return Some(MouseAction::SetSplitRatio { path, ratio }); } DragTarget::PaneScrollbar { pane_id, @@ -798,7 +846,10 @@ impl AppState { insert_idx: Some(insert_idx), }, }) => { - self.move_workspace(source_ws_idx, insert_idx); + return Some(MouseAction::MoveWorkspace { + source_ws_idx, + insert_idx, + }); } Some(DragState { target: @@ -809,22 +860,28 @@ impl AppState { }, }) => { if self.active == Some(ws_idx) { - self.move_tab(source_tab_idx, insert_idx); self.mode = Mode::Terminal; + return Some(MouseAction::MoveTab { + ws_idx, + source_tab_idx, + insert_idx, + }); } } Some(_) => {} None => { if let Some(press) = workspace_press { - self.switch_workspace(press.ws_idx); self.mode = Mode::Terminal; - return None; + return Some(MouseAction::FocusWorkspace { + ws_idx: press.ws_idx, + }); } if let Some(press) = tab_press { if self.active == Some(press.ws_idx) { - self.switch_tab(press.tab_idx); self.mode = Mode::Terminal; - return None; + return Some(MouseAction::FocusTab { + tab_idx: press.tab_idx, + }); } } } @@ -1021,40 +1078,40 @@ impl AppState { None } - fn handle_mobile_mouse(&mut self, mouse: MouseEvent) -> bool { + fn handle_mobile_mouse(&mut self, mouse: MouseEvent) -> MobileMouseResult { if self.mode == Mode::Navigate { match mouse.kind { MouseEventKind::ScrollUp => { self.scroll_mobile_switcher_at(mouse.column, mouse.row, -1); - return true; + return MobileMouseResult::Consumed; } MouseEventKind::ScrollDown => { self.scroll_mobile_switcher_at(mouse.column, mouse.row, 1); - return true; + return MobileMouseResult::Consumed; } MouseEventKind::Down(MouseButton::Left) => {} - _ => return true, + _ => return MobileMouseResult::Consumed, } } else if !matches!(mouse.kind, MouseEventKind::Down(MouseButton::Left)) { - return false; + return MobileMouseResult::Ignored; } if self.mode != Mode::Navigate { if !matches!(self.mode, Mode::Terminal | Mode::Resize) { - return false; + return MobileMouseResult::Ignored; } if rect_contains(self.view.mobile_menu_hit_area, mouse.column, mouse.row) { self.mobile_switcher_scroll = 0; self.mode = Mode::Navigate; - return true; + return MobileMouseResult::Consumed; } - return false; + return MobileMouseResult::Ignored; } let areas = crate::ui::mobile_switcher_areas(self); if rect_contains(areas.close, mouse.column, mouse.row) { self.mode = Mode::Terminal; - return true; + return MobileMouseResult::Consumed; } match crate::ui::mobile_switcher_target_at(self, mouse.column, mouse.row) { @@ -1062,8 +1119,8 @@ impl AppState { self.request_new_workspace = true; } Some(crate::ui::MobileSwitcherTarget::Workspace(ws_idx)) => { - self.switch_workspace(ws_idx); self.mode = Mode::Terminal; + return MobileMouseResult::Action(MouseAction::FocusWorkspace { ws_idx }); } Some(crate::ui::MobileSwitcherTarget::NewTab) => { if self.prompt_new_tab_name { @@ -1074,16 +1131,16 @@ impl AppState { } } Some(crate::ui::MobileSwitcherTarget::Tab(tab_idx)) => { - self.switch_tab(tab_idx); self.mode = Mode::Terminal; + return MobileMouseResult::Action(MouseAction::FocusTab { tab_idx }); } Some(crate::ui::MobileSwitcherTarget::Agent { ws_idx, tab_idx: _, pane_id, }) => { - self.focus_pane_in_workspace(ws_idx, pane_id); self.mode = Mode::Terminal; + return MobileMouseResult::Action(MouseAction::FocusPane { ws_idx, pane_id }); } Some(crate::ui::MobileSwitcherTarget::Menu(action_idx)) => { let actions = global_menu_actions(self); @@ -1094,7 +1151,7 @@ impl AppState { None => {} } - true + MobileMouseResult::Consumed } fn scroll_mobile_switcher_at(&mut self, _col: u16, _row: u16, delta: i16) { @@ -1335,9 +1392,7 @@ impl AppState { } pub(super) fn focus_pane(&mut self, pane_id: crate::layout::PaneId) { - if let Some(ws_idx) = self.active { - self.focus_pane_in_workspace(ws_idx, pane_id); - } + let _ = pane_id; } fn clickable_toast_at(&self, col: u16, row: u16) -> bool { |
