servoshell: fix lockups while animating #30322
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
With the minibrowser enabled, we respond to input events by calling request_redraw, which defers the egui update to a RedrawRequested event. But once we’re there, we run the compositor asynchronously by dispatching Servo a Refresh event, which defers painting (both compositor and egui) and presenting to some later tick of the event loop.
Per rust-windowing/winit#2900, this seems to be incorrect:
When there are active animations (CSS animations, CSS transitions, and sometimes rAF), servoshell pumps its event loop as quickly as possible, without waiting for a waker. For reasons that are unclear to me, our misuse of RedrawRequested interacts with active animations to create a situation where:
This patch fixes those lockups by moving all painting and presenting to the RedrawRequested event handler, with two exceptions. When the compositor paints a frame of its own volition (e.g. due to WebRender), we request a redraw but suppress the recomposite step, since it already happened. When we are handling a resize event, we continue to call Servo::repaint_synchronously as before, but now we also update and paint the minibrowser and present the frame.
We also add trace logs for the flow of EmbedderEvent, EmbedderMsg, and winit events, trace logs for the major RedrawRequested and PumpRequest branches, and a debug message when we recomposite without presenting.
To test this manually, run the repros in #30312 and check that you can interact with the minibrowser ui, click on the page (TWGL Tunnel only), and resize the window, for at least 30 seconds.
./mach build -d
does not report any errors./mach test-tidy
does not report any errors