ltk/event_loop/repeat.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
// SPDX-License-Identifier: LGPL-2.1-only
// Copyright (C) 2026 Liberux Labs, S. L. <info@liberux.net>
use calloop::RegistrationToken;
use smithay_client_toolkit::seat::keyboard::KeyEvent;
/// Snapshot of the key whose repeat timer is currently armed.
///
/// Stored on [`super::app_data::AppData::key_repeat`] between press and
/// release of a held-down key. The timer's calloop callback reads this
/// back to re-dispatch the same `KeyEvent` against the same focus, so a
/// held arrow key keeps moving the cursor in the originally-focused text
/// input even if the focus migrates mid-repeat (which it should not —
/// release cancels the timer, and focus changes only happen via Tab /
/// pointer events that arrive after `release_key` is processed).
pub( crate ) struct KeyRepeatState
{
pub event: KeyEvent,
pub token: RegistrationToken,
}
/// Snapshot of the button whose press-and-hold repeat timer is
/// currently armed. Mirrors [`KeyRepeatState`] for pointer / touch
/// presses on a [`crate::widget::button::Button`] built with
/// `.repeating( true )`. The timer's callback re-runs the press
/// against the *current* widget tree: it looks the pressed widget
/// up by `flat_idx` on the focus surface, reads its `on_press`
/// fresh, and pushes that into the pending queue. Re-resolving each
/// tick is what makes a stepper button work — the message a stepper
/// builds is `"go to value + step"` computed at view-build time, so
/// replaying the captured message would re-issue the same target
/// after the first fire and the user would see the value freeze
/// after one step. Reading the live `on_press` instead picks up the
/// new target the time picker just rebuilt with the updated value.
///
/// Cancelled on release, pointer leave, gesture cancel, focus loss
/// and long-press promotion. Also self-cancels on the first tick
/// where the widget at `idx` no longer exists or no longer carries
/// an `on_press` message — view restructuring (e.g. tab switch)
/// invalidates the snapshot and we stop rather than firing the
/// wrong widget's message.
pub( crate ) struct ButtonRepeatState
{
/// calloop registration handle so [`super::app_data::AppData::stop_button_repeat`]
/// can remove the timer from the event loop without leaking the
/// source. The surface focus and pressed `flat_idx` live in
/// the timer's closure capture instead of here — the only
/// caller that needs to act on them is the closure itself.
pub token: RegistrationToken,
}