diff --git a/crates/disktree-app/src/state.rs b/crates/disktree-app/src/state.rs index 27e1846..0992485 100644 --- a/crates/disktree-app/src/state.rs +++ b/crates/disktree-app/src/state.rs @@ -2575,10 +2575,17 @@ impl Disktree { self.toggle_mark(&crumbs, cx); } } - MouseButton::Navigate(NavigationDirection::Back) => { + // Buttons 8 and 9. gpui-pre maps them on X11, Wayland and + // Windows; a mouse with no side buttons never sends them, and + // then the header `<` / `>` and alt-arrows are the whole story. + MouseButton::Navigate(NavigationDirection::Back) + if self.screen == Screen::Explore => + { self.go_back(cx); } - MouseButton::Navigate(NavigationDirection::Forward) => { + MouseButton::Navigate(NavigationDirection::Forward) + if self.screen == Screen::Explore => + { self.go_forward(cx); } _ => {} diff --git a/crates/disktree-app/src/tests.rs b/crates/disktree-app/src/tests.rs index af151ec..fb432f8 100644 --- a/crates/disktree-app/src/tests.rs +++ b/crates/disktree-app/src/tests.rs @@ -1322,3 +1322,51 @@ fn back_and_forward_retrace_where_you_have_been(cx: &mut TestAppContext) { Vec::::new() ); } + +/// The mouse's back and forward buttons retrace the same history as +/// alt-arrows and the header buttons, and only on the explore screen. +#[gpui_kit::test] +fn mouse_side_buttons_go_back_and_forward(cx: &mut TestAppContext) { + use gpui_kit::{Modifiers, MouseButton, NavigationDirection}; + + cx.update(gpui_omarchy::init); + let temp = fixture(); + let (view, cx) = view_over(temp.path(), cx); + cx.simulate_resize(gpui_kit::size(px(1400.), px(900.))); + draw(cx); + + let (junk, deeper) = update(&view, cx, |app, cx| { + let junk = child_crumbs(app, &[], "junk"); + let deeper = child_crumbs(app, &junk, "deeper"); + app.select(Some(junk.clone()), cx); + app.descend(cx); + app.select(Some(deeper.clone()), cx); + app.descend(cx); + (junk, deeper) + }); + draw(cx); + assert_eq!(read(&view, cx, |app| app.crumbs.clone()), deeper); + + // Over the mosaic, buttons 8 and 9 step the history, as alt-arrows do. + let mosaic = cx.debug_bounds("treemap").expect("the mosaic is drawn"); + let at = mosaic.center(); + let press_button = |cx: &mut Window, button: MouseButton| { + cx.simulate_mouse_move(at, None, Modifiers::none()); + cx.simulate_mouse_down(at, button, Modifiers::none()); + cx.simulate_mouse_up(at, button, Modifiers::none()); + draw(cx); + }; + press_button(cx, MouseButton::Navigate(NavigationDirection::Back)); + assert_eq!(read(&view, cx, |app| app.crumbs.clone()), junk); + press_button(cx, MouseButton::Navigate(NavigationDirection::Forward)); + assert_eq!(read(&view, cx, |app| app.crumbs.clone()), deeper); + + // On the review screen the same press changes nothing: the marked list + // is not somewhere the history can take you back to. + update(&view, cx, |app, cx| app.toggle_mark(&junk, cx)); + press(cx, "c"); + assert_eq!(read(&view, cx, |app| app.screen), Screen::Review); + press_button(cx, MouseButton::Navigate(NavigationDirection::Back)); + assert_eq!(read(&view, cx, |app| app.crumbs.clone()), deeper); + assert_eq!(read(&view, cx, |app| app.screen), Screen::Review); +} diff --git a/crates/disktree-app/src/treemap_view.rs b/crates/disktree-app/src/treemap_view.rs index 4eaace1..84b5605 100644 --- a/crates/disktree-app/src/treemap_view.rs +++ b/crates/disktree-app/src/treemap_view.rs @@ -14,10 +14,10 @@ use std::rc::Rc; use disktree_core::treemap::Rect; use gpui_kit::{ App, Bounds, ContentMask, Context, Corners, Edges, Font, FontWeight, Hsla, - InteractiveElement as _, IntoElement, MouseButton, MouseDownEvent, - MouseMoveEvent, ParentElement as _, Pixels, Point, ScrollWheelEvent, - SharedString, Size, StatefulInteractiveElement as _, Styled, TextAlign, - TextRun, Window, canvas, div, pattern_slash, px, quad, + InteractiveElement as _, IntoElement, MouseDownEvent, MouseMoveEvent, + ParentElement as _, Pixels, Point, ScrollWheelEvent, SharedString, Size, + StatefulInteractiveElement as _, Styled, TextAlign, TextRun, Window, + canvas, div, pattern_slash, px, quad, }; use gpui_omarchy::{ActiveTheme, Theme}; @@ -86,6 +86,7 @@ pub fn mosaic( div() .id("disktree-treemap") + .debug_selector(|| "treemap".into()) .relative() .flex_1() .min_h_0() @@ -100,18 +101,13 @@ pub fn mosaic( .on_mouse_move(cx.listener(|this, event: &MouseMoveEvent, _, cx| { this.on_mouse_move(event, cx); })) - .on_mouse_down( - MouseButton::Left, - cx.listener(|this, event: &MouseDownEvent, _, cx| { - this.on_mouse_down(event, cx); - }), - ) - .on_mouse_down( - MouseButton::Middle, - cx.listener(|this, event: &MouseDownEvent, _, cx| { - this.on_mouse_down(event, cx); - }), - ) + // One listener for every button, because the interesting ones are not + // the three the platform names: buttons 8 and 9 arrive as + // `MouseButton::Navigate`, and a per-button registration would have + // to be repeated for each. + .on_any_mouse_down(cx.listener(|this, event: &MouseDownEvent, _, cx| { + this.on_mouse_down(event, cx); + })) .on_scroll_wheel(cx.listener( |this, event: &ScrollWheelEvent, _, cx| { this.on_scroll_wheel(event, cx); diff --git a/crates/disktree-app/src/views.rs b/crates/disktree-app/src/views.rs index 8f75253..c6fc632 100644 --- a/crates/disktree-app/src/views.rs +++ b/crates/disktree-app/src/views.rs @@ -2826,9 +2826,9 @@ fn card_surface(cx: &gpui_kit::App) -> Div { /// at the pointer, over the button itself. fn history_card(app: &Disktree, back: bool, cx: &gpui_kit::App) -> Div { let (label, keys) = if back { - ("Back", "alt \u{2190} back") + ("Back", "alt \u{2190} \u{00b7} side button") } else { - ("Forward", "alt \u{2192} forward") + ("Forward", "alt \u{2192} \u{00b7} side button") }; let card = app .history_target(back) @@ -3002,7 +3002,7 @@ fn help_overlay(app: &Disktree, cx: &gpui_kit::App) -> Div { ("\u{232b} / esc", "Go up one directory"), ( "alt \u{2190} / \u{2192}", - "Back or forward through where you have been", + "Back or forward, as do the mouse's side buttons", ), ( "\u{2190} \u{2191} \u{2193} \u{2192}",