Skip to main content

scroll_on_keys

Function scroll_on_keys 

Source
pub fn scroll_on_keys(
    keys: MessageReader<'_, '_, KeyPressed>,
    tracker: Res<'_, FocusTracker>,
    parents: Query<'_, '_, &ChildOf>,
    text_inputs: Query<'_, '_, (), With<TextInput>>,
    key_owning_widgets: Query<'_, '_, (), Or<(With<DropdownButton>, With<DropdownOptionButton>, With<MenuItemButton>, With<TabStripButton>, With<PopupPanel>)>>,
    children: Query<'_, '_, (&ChildOf, &Transform)>,
    scrolls: Query<'_, '_, (&Transform, &mut Scroll, &mut ScrollOffset)>,
)
Expand description

Keyboard scrolling for the focused entity, or - when the focused entity isn’t itself scrollable - its nearest Scroll-bearing ancestor. Walks the [ChildOf] chain the same way apply_a11y_scroll_into_view does for AT-driven ScrollIntoView.

  • ArrowUp / ArrowDown / ArrowLeft / ArrowRight: one line (crate::physics::LINE_HEIGHT_PX) along the arrow’s direction, masked to the container’s allowed ScrollAxis (a horizontal-only scroller ignores Up/Down and vice versa).
  • PageUp / PageDown (forwarded by the winit backend as Key::Character("PageUp"/"PageDown") - no dedicated NamedKey variant exists yet): one viewport height.
  • Home / End: jump to the top / bottom of the content.

Every target value - including Home/End - is computed against the container’s own content-extent bbox (the same bounding-box scan clamp_scroll_offsets does) and clamped inline, so this system is self-contained: it doesn’t depend on clamp_scroll_offsets running afterward to land in bounds, and (unlike a naive “seek to f32::MAX”) End lands exactly at the max offset even under macOS’s rubber-band overshoot curve rather than asymptotically approaching it.

A focused TextInput owns arrows/Home/End for caret movement (type_into_focused in lumen-input runs on the same raw key bus); this system no-ops whenever the focused entity is itself a text input, so a <textarea> sitting inside a scroll container doesn’t have its arrow keys double-handled - moving the caret AND scrolling the container out from under it.

The same double-handling guard covers the widgets that own their arrow / Home / End keys while focused (Qt: a focused control that accepts a key consumes it - the view never also scrolls): dropdown headers (crate::tabs::DropdownButton - closed-state value stepping), popup rows (crate::tabs::DropdownOptionButton / crate::tabs::MenuItemButton - highlight movement), and tab strip buttons (crate::tabs::TabStripButton - tab switching).