Skip to content

Add widget timers to Masonry and use them for delayed UI behavior.#1779

Draft
waywardmonkeys wants to merge 4 commits intolinebender:mainfrom
waywardmonkeys:integrate-understory-timing
Draft

Add widget timers to Masonry and use them for delayed UI behavior.#1779
waywardmonkeys wants to merge 4 commits intolinebender:mainfrom
waywardmonkeys:integrate-understory-timing

Conversation

@waywardmonkeys
Copy link
Copy Markdown
Contributor

  • Add understory_timing as a masonry_core dependency.
  • Store pending widget timers in RenderRoot.
  • Add TimerToken and deliver expired timers through Update::Timer.
  • Add context APIs:
    • request_timer(delay) -> TimerToken
    • cancel_timer(token)
  • Add backend hooks for timer driving:
    • RenderRoot::set_timer_time
    • RenderRoot::next_timer_deadline
    • RenderRoot::handle_timers
  • Update masonry_winit to drive timer time and platform wakeups.
  • Convert TextArea cursor blinking to one-shot timers.
  • Convert the layers tooltip-delay example to one-shot timers.
  • Document when to use timers versus animation frames.

Rationale

Masonry has several UI behaviors that are delayed but not frame-cadenced. Examples include cursor blinking, tooltip
delays, debounce, and long press recognition. These fit a timer model better than animation frames.

This PR adds a widget-local timer lifecycle: widgets request a timer, keep the returned TimerToken, and receive
Update::Timer when it expires. Widgets can cancel pending timers when the relevant state changes.

Animation frames remain the right tool for continuous visual updates, such as interpolation or motion that should advance with frame cadence.

@waywardmonkeys waywardmonkeys marked this pull request as draft April 30, 2026 05:49
@waywardmonkeys
Copy link
Copy Markdown
Contributor Author

This was done with LLM assistance to avoid typing out the boring stuff.

Draft since I will publish understory_timing soon rather than a git dep.

Add `understory_timing` as a `masonry_core` dependency and keep the timer queue inside `RenderRoot` so widget timer requests synchronously return the queue-assigned identity.

Expose timer time/deadline/drain hooks for backends, and update `masonry_winit` to own only the host clock origin and platform wakeup scheduling. Add focused tests for targeted timer delivery and cancellation.
Replace `TextArea`'s animation-frame polling for caret blinking with one-shot widget timers. Focus and text activity reset the blink state and schedule a half-cycle timer; timer updates toggle the caret and reschedule while the text area remains focused.

Update the text input cursor blink snapshot test to advance the simulated timer clock instead of sending an animation frame.
Replace the layers example's animation-frame polling loop with a one-shot hover timer. Pointer movement cancels and reschedules the delay, hover exit cancels it, and the timer update creates the tooltip layer once the cursor has settled.
Clarify that `request_anim_frame` and `Widget::on_anim_frame` are for frame-cadenced visual updates, while delayed one-shot UI behavior should use widget timers.

Update the pass-system and widget-implementation docs to describe timer delivery through `Update::Timer`, the non-bubbling delivery model, and the usual `Option<TimerToken>` request/cancel pattern.
@waywardmonkeys waywardmonkeys force-pushed the integrate-understory-timing branch from 8e792bf to cfeb24c Compare April 30, 2026 06:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant