re-work Window::post_event_processing
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 9.7k
- Forks
- 565
- PR merge metrics
- No merged PRs in 30d
Description
`post_event_processing` does a number of tasks:
- it registers new timers (all contexts)
- it sends `WidgetAdded` if a widget was added (`event`, `lifecycle` and `update`, but not in `layout`)
- it forwards animation requests (all but `layout`)
- it schedules an idle call if there are any unhandled commands, but only if a flag is set
- it updates any invalid regions accumulated during the traversal
It is also called after a bunch of different traversal methods: `layout`, `update`, `lifecycle`, and `event`.
This means there's a bunch of duplicate calling, since (for instance) an event can cause multiple lifecycle calls, there's a lifecycle call in layout, etc.
Let's think this through.
The druid event-loop can be thought of as having two 'phases'; the *event* phase and the *render* phase.
The *event* phase begins when some event, like a key-press, arrives from the system. We handle that event; we handle any commands dispatched during that event, and then we call `update`. The `update` call represents the end of the event phase, and it is guaranteed to be called every time an event arrives. At the end of the event phase, if any part of the view is marked as invalid or as needing layout, we ask the platform to call us back for the render phase.
The *render* phase begins when we get that callback. First we layout any widgets that need it, and then we paint any widgets that need it.
Given this, when should we be doing the various tasks currently performed in `post_event_processing`?
- timers: timer state is stored in the transitive `WidgetState` object, so we need to merge these after each traversal.
- `WidgetAdded`: I believe this should always be added *immediately* after whatever event caused the widget to be added; so we should check this aggressively, likely at the end of all `event`/`lifecycle`/`update`.
- animation requests: these can be handled once, at the end of `update`.
- unhandled commands: there are two scenarios where we need to schedule an idle handler when there are pending commands: The first is when they are submitted during `update` *and there will be no render phase*, and the second is when they are submitted during the render phase.
- invalid regions: these *need* to be handled after each traversal, because they do not persist.
**conclusion**: these items should be split into three: things that need to be done after *every* traversal; things that can be done after `update` only, and things that can be done after `paint` only:
- after each traversal: timers, `WidgetAdded`, invalidation.
- after update: animation frame, schedule idle *if nothing has been invalidated*.
- after paint: idle, if there are commands.
annoyingly, timers should be added after layout, but `WidgtAdded` and invalidation should be disallowed here; however those should not be settable via the `LayoutCtx` so I think we can just treat them the same.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing Window::post_event_processing and its callers for layout, update, lifecycle, event, and paint traversal. Compare each task with the issue's proposed phase split, then verify that timers, WidgetAdded, invalidation, animation requests, and idle scheduling occur at the specified boundaries without duplicate processing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- desktop-dev
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100