layout: Store scroll offsets in the ScrollTree (#37428)

There are currently five places that scroll offsets are stored:

 - DOM: A set of scroll offsets used for script.
 - Layout: An array of scroll offsets that is used for tracking
   layout-side scroll offsets.
 - Layout: The scroll offsets stored in the `ScrollTree`. These are
   currently unset and unused.
 - Compositor: The scroll offsets stored in the `ScrollTree` mirrored
   from layout.
 - WebRender: The scrolled offsets stored in the WebRender spatial tree.

This change is the first step in combining the first three into the
layout `ScrollTree`. It eliminates the extra array of scroll offsets
stored in layout in favor of the storing them in the `ScrollTree`. A
followup change will eliminate the ones stored in the DOM.

- In addition the `ScrollState` data structure is eliminated as these
are
now stored in a `HashMap` everywhere when passing them via IPC.
- The offsests stored in layout can now never scroll past the boundaries
of the scrolled content.

Testing: This should not change behavior and is thus covered by existing
WPT tests.

Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Co-authored-by: stevennovaryo <steven.novaryo@gmail.com>
This commit is contained in:
Martin Robinson 2025-06-13 14:01:27 +02:00 committed by GitHub
parent 6cac782fb1
commit f451dccd0b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 182 additions and 122 deletions

View file

@ -13,7 +13,7 @@ use compositing_traits::viewport_description::{
DEFAULT_ZOOM, MAX_ZOOM, MIN_ZOOM, ViewportDescription,
};
use compositing_traits::{SendableFrameTree, WebViewTrait};
use constellation_traits::{EmbedderToConstellationMessage, ScrollState, WindowSizeType};
use constellation_traits::{EmbedderToConstellationMessage, WindowSizeType};
use embedder_traits::{
AnimationState, CompositorHitTestResult, InputEvent, MouseButton, MouseButtonAction,
MouseButtonEvent, MouseMoveEvent, ShutdownState, TouchEvent, TouchEventResult, TouchEventType,
@ -204,18 +204,18 @@ impl WebViewRenderer {
return;
};
let mut scroll_states = Vec::new();
details.scroll_tree.nodes.iter().for_each(|node| {
if let (Some(scroll_id), Some(scroll_offset)) = (node.external_id(), node.offset()) {
scroll_states.push(ScrollState {
scroll_id,
scroll_offset,
});
}
});
let scroll_offsets = details.scroll_tree.scroll_offsets();
// This might be true if we have not received a display list from the layout
// associated with this pipeline yet. In that case, the layout is not ready to
// receive scroll offsets anyway, so just save time and prevent other issues by
// not sending them.
if scroll_offsets.is_empty() {
return;
}
let _ = self.global.borrow().constellation_sender.send(
EmbedderToConstellationMessage::SetScrollStates(pipeline_id, scroll_states),
EmbedderToConstellationMessage::SetScrollStates(pipeline_id, scroll_offsets),
);
}