// SPDX-License-Identifier: LGPL-2.1-only // Copyright (C) 2026 Liberux Labs, S. L. 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, }