aboutsummaryrefslogtreecommitdiff
path: root/src/app/input/mouse.rs
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-07-31 18:15:55 +0300
committerGitHub <noreply@github.com>2026-07-31 18:15:55 +0300
commit02fe7d7659e37d9f05eed80af382d1dcdccb6876 (patch)
tree0ca1ad4e912b36eb3e3294501cc73ac8a0d9466f /src/app/input/mouse.rs
parentb1d14fe984c92ab4a81438ba07c7d94b464d0d3a (diff)
feat: support bottom tab bar placement (#2118)
* feat: support bottom tab bar placement * fix: preserve mouse cleanup under bottom mode bar refs #2117
Diffstat (limited to 'src/app/input/mouse.rs')
-rw-r--r--src/app/input/mouse.rs76
1 files changed, 75 insertions, 1 deletions
diff --git a/src/app/input/mouse.rs b/src/app/input/mouse.rs
index 56b9b676..2c32c95a 100644
--- a/src/app/input/mouse.rs
+++ b/src/app/input/mouse.rs
@@ -483,6 +483,10 @@ impl AppState {
}
}
+ if self.mode_bar_covers_tab_row(mouse.column, mouse.row) {
+ return None;
+ }
+
if self.on_tab_scroll_left_button(mouse.column, mouse.row) {
self.scroll_tabs_left();
return None;
@@ -913,6 +917,9 @@ impl AppState {
}
MouseEventKind::ScrollUp | MouseEventKind::ScrollDown
+ if self.mode_bar_covers_tab_row(mouse.column, mouse.row) => {}
+
+ MouseEventKind::ScrollUp | MouseEventKind::ScrollDown
if self.on_tab_bar(mouse.column, mouse.row) =>
{
match mouse.kind {
@@ -1063,7 +1070,8 @@ impl AppState {
}
MouseEventKind::Down(MouseButton::Right)
- if self.tab_at(mouse.column, mouse.row).is_some() =>
+ if !self.mode_bar_covers_tab_row(mouse.column, mouse.row)
+ && self.tab_at(mouse.column, mouse.row).is_some() =>
{
if let (Some(ws_idx), Some(tab_idx)) =
(self.active, self.tab_at(mouse.column, mouse.row))
@@ -1272,6 +1280,15 @@ impl AppState {
})
}
+ fn mode_bar_covers_tab_row(&self, col: u16, row: u16) -> bool {
+ self.tab_bar_position == crate::config::TabBarPositionConfig::Bottom
+ && matches!(
+ self.mode,
+ Mode::Navigate | Mode::Prefix | Mode::Copy | Mode::Resize
+ )
+ && self.on_tab_bar(col, row)
+ }
+
pub(super) fn on_tab_bar(&self, col: u16, row: u16) -> bool {
let area = self.view.tab_bar_rect;
area.width > 0
@@ -3393,6 +3410,63 @@ mod tests {
}
#[test]
+ fn bottom_mode_bar_consumes_hidden_tab_mouse_actions() {
+ let mut app = app_for_mouse_test();
+ let mut ws = Workspace::test_new("one");
+ ws.test_add_tab(Some("two"));
+ app.state.workspaces = vec![ws];
+ app.state.active = Some(0);
+ app.state.selected = 0;
+ app.state.mode = Mode::Prefix;
+ app.state.tab_bar_position = crate::config::TabBarPositionConfig::Bottom;
+
+ crate::ui::compute_view(&mut app.state, Rect::new(0, 0, 106, 20));
+ let second_tab = app.state.view.tab_hit_areas[1];
+ let new_tab = app.state.view.new_tab_hit_area;
+
+ app.handle_mouse(mouse(
+ MouseEventKind::Down(MouseButton::Left),
+ second_tab.x,
+ second_tab.y,
+ ));
+ app.handle_mouse(mouse(
+ MouseEventKind::Up(MouseButton::Left),
+ second_tab.x,
+ second_tab.y,
+ ));
+ app.handle_mouse(mouse(
+ MouseEventKind::ScrollDown,
+ second_tab.x,
+ second_tab.y,
+ ));
+ app.handle_mouse(mouse(
+ MouseEventKind::Down(MouseButton::Right),
+ second_tab.x,
+ second_tab.y,
+ ));
+ app.handle_mouse(mouse(
+ MouseEventKind::Down(MouseButton::Left),
+ new_tab.x,
+ new_tab.y,
+ ));
+
+ app.state.drag = Some(DragState {
+ target: DragTarget::SidebarDivider,
+ });
+ app.handle_mouse(mouse(
+ MouseEventKind::Up(MouseButton::Left),
+ second_tab.x,
+ second_tab.y,
+ ));
+
+ assert_eq!(app.state.workspaces[0].active_tab, 0);
+ assert_eq!(app.state.workspaces[0].tabs.len(), 2);
+ assert!(app.state.context_menu.is_none());
+ assert!(app.state.tab_press.is_none());
+ assert!(app.state.drag.is_none());
+ }
+
+ #[test]
fn right_click_inactive_tab_opens_menu_without_switching_tabs() {
let mut app = app_for_mouse_test();
let mut ws = Workspace::test_new("one");