A tab strip that scrolls to the selected tab and while a tab is dragged against its edge, and hooks for every mouse button and for the modifiers, for an application that hands the mouse on
CI / build + test (push) Canceled after 0s
CI / cargo audit (push) Canceled after 0s

A strip with more tabs than fit left the selected one wherever it was, so a tab opened at the end or chosen with the keyboard could stay out of sight, and a tab could only be dragged as far as the visible part reached. A terminal that passes the mouse to the program in it, as xterm does, also needs every click with its modifiers, which ltk kept to itself apart from the middle button, and the modifiers held while the wheel turns, which the wheel does not carry.
Scrolling to the selected tab. `TabRow` now knows the key of the selected tab, and in the layout it asks the `TabMotion` where the scroll of the tabs should go before drawing it; the answer is written into the scroll's own offset, which is keyed by the same index. When the selection changes the strip scrolls just enough to show that tab, through the scroll's `offset_into_view`, and keeps following it while it grows from nothing, so a new tab at the end is shown whole once it has opened. After that the strip is left where the user scrolls it.
Dragging against the edge. While a tab is dragged and its lifted copy touches either edge of the visible part, the strip scrolls 8 widget pixels further that way on each frame (`EDGE_SCROLL`), and every layout places the dragged tab under the pointer again, so it travels with the strip although the pointer holds still and drops among the tabs that come into view.
Pointer coordinates. A scroll and a viewport draw their child on a canvas of their own, so the tabs were laid out in coordinates that no longer matched the pointer once the strip scrolled. `DrawCtx.origin` now holds where the canvas being drawn on sits on the surface, set around the child of every `Scroll` and `Viewport`, and `TabCells` and `TabCards` hand it to the `TabMotion`, which takes it off the pointer in `drag_move`.
The mouse. `App::on_mouse_button( &MouseButtonEvent )` reports every press and release of the left, middle and right buttons, with the position in physical pixels and Ctrl, Shift and Alt, before ltk handles it; `MouseButton` and `MouseButtonEvent` are exported. `App::on_modifiers( ctrl, shift, alt )` is called whenever the modifiers held change. Both do nothing by default.
Tests cover a selected tab scrolled into view once and back, and a tab dragged against the edge scrolling the strip. The documentation of `tab_strip` describes the scrolling.
This commit is contained in:
2026-10-15 10:25:31 +02:00
parent ce98c7b82c
commit dcb1c7dff3
14 changed files with 181 additions and 14 deletions
+1 -1
View File
@@ -905,7 +905,7 @@ ownership.
### `tab_strip`
The open documents of an app, as a browser or a terminal shows them. On a desktop, a strip of tabs with their icon, title and close button, sharing the width between a minimum and a fifth of the screen, scrolling sideways when even the minimum does not fit, and always leaving 7.5 % of the width clear; buttons go before the tabs (`leading`), right after the last one (`after_tabs`) and at the far right (`trailing`). On a phone (`TabLayout::Mobile`), a bar with the active tab, or the app's own `mobile_center`, and a counter that sends `on_overview`; `tab_overview` is the grid of cards it opens, as a whole page with `build` or as the cards alone with `cards`. `TabStripColors` sets every colour, the theme's by default.
The open documents of an app, as a browser or a terminal shows them. On a desktop, a strip of tabs with their icon, title and close button, sharing the width between a minimum and a fifth of the screen, scrolling sideways when even the minimum does not fit, to show the selected tab when it changes and while a tab is dragged against its edge, and always leaving 7.5 % of the width clear; buttons go before the tabs (`leading`), right after the last one (`after_tabs`) and at the far right (`trailing`). On a phone (`TabLayout::Mobile`), a bar with the active tab, or the app's own `mobile_center`, and a counter that sends `on_overview`; `tab_overview` is the grid of cards it opens, as a whole page with `build` or as the cards alone with `cards`. `TabStripColors` sets every colour, the theme's by default.
Tabs grow from nothing as they open and the others narrow; a closed tab leaves a gap that shrinks away while the others keep their width for a second, so the close button that slides in lands under the pointer. The app keeps a `TabMotion`, hands it to every view and reports `TabMotion::is_animating` from `App::is_animating`.