aboutsummaryrefslogtreecommitdiff
path: root/src/app/input/mouse.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/app/input/mouse.rs')
-rw-r--r--src/app/input/mouse.rs98
1 files changed, 88 insertions, 10 deletions
diff --git a/src/app/input/mouse.rs b/src/app/input/mouse.rs
index 71c0cfbd..7f9f9cde 100644
--- a/src/app/input/mouse.rs
+++ b/src/app/input/mouse.rs
@@ -18,8 +18,7 @@ use crate::{
use super::WheelRouting;
use super::{
modal::{
- apply_context_menu_action, apply_global_menu_action, apply_rename_action,
- confirm_close_accept, confirm_close_cancel, global_menu_actions, leave_modal,
+ apply_global_menu_action, confirm_close_cancel, global_menu_actions, leave_modal,
modal_action_from_buttons, open_global_menu, open_new_tab_dialog, ModalAction,
},
settings::SettingsAction,
@@ -52,6 +51,12 @@ pub(super) enum MouseAction {
path: Vec<bool>,
ratio: f32,
},
+ RenameModal(ModalAction),
+ ConfirmCloseAccept,
+ ContextMenu {
+ menu: ContextMenuState,
+ idx: usize,
+ },
}
enum MobileMouseResult {
@@ -234,7 +239,9 @@ impl AppState {
(cancel, ModalAction::Cancel),
],
) {
- Some(ModalAction::Confirm) => confirm_close_accept(self),
+ Some(ModalAction::Confirm) => {
+ return Some(MouseAction::ConfirmCloseAccept);
+ }
Some(ModalAction::Cancel) | None => confirm_close_cancel(self),
_ => {}
}
@@ -396,15 +403,14 @@ impl AppState {
)
})
.unwrap_or(ModalAction::Cancel);
- apply_rename_action(self, action);
- return None;
+ return Some(MouseAction::RenameModal(action));
}
if self.mode == Mode::ContextMenu {
let item_idx = self.context_menu_item_at(mouse.column, mouse.row);
if let Some(menu) = self.context_menu.take() {
if let Some(idx) = item_idx {
- apply_context_menu_action(self, terminal_runtimes, menu, idx);
+ return Some(MouseAction::ContextMenu { menu, idx });
} else {
leave_modal(self);
}
@@ -900,8 +906,26 @@ impl AppState {
if self.on_tab_bar(mouse.column, mouse.row) =>
{
match mouse.kind {
- MouseEventKind::ScrollUp => self.previous_tab(),
- MouseEventKind::ScrollDown => self.next_tab(),
+ MouseEventKind::ScrollUp => {
+ if let Some(ws) = self.active.and_then(|i| self.workspaces.get(i)) {
+ if !ws.tabs.is_empty() {
+ let prev = if ws.active_tab == 0 {
+ ws.tabs.len() - 1
+ } else {
+ ws.active_tab - 1
+ };
+ return Some(MouseAction::FocusTab { tab_idx: prev });
+ }
+ }
+ }
+ MouseEventKind::ScrollDown => {
+ if let Some(ws) = self.active.and_then(|i| self.workspaces.get(i)) {
+ if !ws.tabs.is_empty() {
+ let next = (ws.active_tab + 1) % ws.tabs.len();
+ return Some(MouseAction::FocusTab { tab_idx: next });
+ }
+ }
+ }
_ => {}
}
}
@@ -1814,10 +1838,10 @@ mod tests {
use ratatui::layout::{Direction, Rect};
use super::super::{
- app_for_mouse_test, capture_snapshot, handle_context_menu_key, mouse, numbered_lines_bytes,
- root_layout_ratio,
+ app_for_mouse_test, capture_snapshot, mouse, numbered_lines_bytes, root_layout_ratio,
};
use super::*;
+ use crate::app::input::modal::handle_context_menu_key;
use crate::{
app::state::{ContextMenuKind, ContextMenuState, MenuListState, Mode, ViewLayout},
detect::{Agent, AgentState},
@@ -2450,6 +2474,31 @@ mod tests {
}
#[test]
+ fn clicking_rename_save_submits_workspace_rename_through_api_path() {
+ let mut app = app_for_mouse_test();
+ app.state.workspaces = vec![Workspace::test_new("old")];
+ app.state.active = Some(0);
+ app.state.selected = 0;
+ app.state.mode = Mode::RenameWorkspace;
+ app.state.name_input = "new".into();
+
+ crate::ui::compute_view(&mut app.state, Rect::new(0, 0, 106, 24));
+ let inner = app.state.rename_modal_inner().unwrap();
+ let (save, _, _) = crate::ui::rename_button_rects(inner);
+
+ app.handle_mouse(mouse(
+ MouseEventKind::Down(MouseButton::Left),
+ save.x,
+ save.y,
+ ));
+
+ assert_eq!(app.state.workspaces[0].custom_name.as_deref(), Some("new"));
+ assert!(app.event_hub.events_after(0).iter().any(|(_, event)| {
+ matches!(event.event, crate::api::schema::EventKind::WorkspaceRenamed)
+ }));
+ }
+
+ #[test]
fn clicking_open_worktree_row_selects_and_requests_open() {
let mut app = app_for_mouse_test();
app.state.mode = Mode::OpenExistingWorktree;
@@ -2615,6 +2664,35 @@ mod tests {
assert_eq!(app.state.workspaces[0].display_name(), "a");
}
+ #[test]
+ fn clicking_context_menu_close_routes_through_api_path() {
+ let mut app = app_for_mouse_test();
+ app.state.workspaces = vec![Workspace::test_new("a"), Workspace::test_new("b")];
+ app.state.active = Some(0);
+ app.state.selected = 0;
+ app.state.confirm_close = false;
+ app.state.context_menu = Some(ContextMenuState {
+ kind: ContextMenuKind::Workspace { ws_idx: 1 },
+ x: 2,
+ y: 2,
+ list: MenuListState::new(1),
+ });
+ app.state.mode = Mode::ContextMenu;
+
+ let menu = app.state.context_menu_rect().unwrap();
+ app.handle_mouse(mouse(
+ MouseEventKind::Down(MouseButton::Left),
+ menu.x + 2,
+ menu.y + 2,
+ ));
+
+ assert_eq!(app.state.workspaces.len(), 1);
+ assert_eq!(app.state.workspaces[0].display_name(), "a");
+ assert!(app.event_hub.events_after(0).iter().any(|(_, event)| {
+ matches!(event.event, crate::api::schema::EventKind::WorkspaceClosed)
+ }));
+ }
+
#[cfg(unix)]
#[tokio::test]
async fn keyboard_context_menu_split_keeps_new_runtime() {