mirror of
https://github.com/servo/servo.git
synced 2025-06-20 15:18:58 +01:00
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:
parent
6cac782fb1
commit
f451dccd0b
11 changed files with 182 additions and 122 deletions
|
@ -24,7 +24,7 @@ use canvas_traits::webgl::WebGLChan;
|
|||
use compositing_traits::CrossProcessCompositorApi;
|
||||
use constellation_traits::{
|
||||
DocumentState, LoadData, LoadOrigin, NavigationHistoryBehavior, ScriptToConstellationChan,
|
||||
ScriptToConstellationMessage, ScrollState, StructuredSerializedData, WindowSizeType,
|
||||
ScriptToConstellationMessage, StructuredSerializedData, WindowSizeType,
|
||||
};
|
||||
use crossbeam_channel::{Sender, unbounded};
|
||||
use cssparser::SourceLocation;
|
||||
|
@ -2097,10 +2097,7 @@ impl Window {
|
|||
// TODO(mrobinson, #18709): Add smooth scrolling support to WebRender so that we can
|
||||
// properly process ScrollBehavior here.
|
||||
self.reflow(
|
||||
ReflowGoal::UpdateScrollNode(ScrollState {
|
||||
scroll_id,
|
||||
scroll_offset: Vector2D::new(-x, -y),
|
||||
}),
|
||||
ReflowGoal::UpdateScrollNode(scroll_id, Vector2D::new(-x, -y)),
|
||||
can_gc,
|
||||
);
|
||||
}
|
||||
|
@ -3234,7 +3231,7 @@ fn should_move_clip_rect(clip_rect: UntypedRect<Au>, new_viewport: UntypedRect<f
|
|||
fn debug_reflow_events(id: PipelineId, reflow_goal: &ReflowGoal) {
|
||||
let goal_string = match *reflow_goal {
|
||||
ReflowGoal::UpdateTheRendering => "\tFull",
|
||||
ReflowGoal::UpdateScrollNode(_) => "\tUpdateScrollNode",
|
||||
ReflowGoal::UpdateScrollNode(..) => "\tUpdateScrollNode",
|
||||
ReflowGoal::LayoutQuery(ref query_msg) => match *query_msg {
|
||||
QueryMsg::ContentBox => "\tContentBoxQuery",
|
||||
QueryMsg::ContentBoxes => "\tContentBoxesQuery",
|
||||
|
|
|
@ -39,7 +39,7 @@ use chrono::{DateTime, Local};
|
|||
use compositing_traits::CrossProcessCompositorApi;
|
||||
use constellation_traits::{
|
||||
JsEvalResult, LoadData, LoadOrigin, NavigationHistoryBehavior, ScriptToConstellationChan,
|
||||
ScriptToConstellationMessage, ScrollState, StructuredSerializedData, WindowSizeType,
|
||||
ScriptToConstellationMessage, StructuredSerializedData, WindowSizeType,
|
||||
};
|
||||
use content_security_policy::{self as csp};
|
||||
use crossbeam_channel::unbounded;
|
||||
|
@ -99,7 +99,8 @@ use timers::{TimerEventRequest, TimerId, TimerScheduler};
|
|||
use url::Position;
|
||||
#[cfg(feature = "webgpu")]
|
||||
use webgpu_traits::{WebGPUDevice, WebGPUMsg};
|
||||
use webrender_api::units::DevicePixel;
|
||||
use webrender_api::ExternalScrollId;
|
||||
use webrender_api::units::{DevicePixel, LayoutVector2D};
|
||||
|
||||
use crate::document_collection::DocumentCollection;
|
||||
use crate::document_loader::DocumentLoader;
|
||||
|
@ -2010,7 +2011,11 @@ impl ScriptThread {
|
|||
}
|
||||
}
|
||||
|
||||
fn handle_set_scroll_states(&self, pipeline_id: PipelineId, scroll_states: Vec<ScrollState>) {
|
||||
fn handle_set_scroll_states(
|
||||
&self,
|
||||
pipeline_id: PipelineId,
|
||||
scroll_states: HashMap<ExternalScrollId, LayoutVector2D>,
|
||||
) {
|
||||
let Some(window) = self.documents.borrow().find_window(pipeline_id) else {
|
||||
warn!("Received scroll states for closed pipeline {pipeline_id}");
|
||||
return;
|
||||
|
@ -2020,16 +2025,15 @@ impl ScriptThread {
|
|||
ScriptThreadEventCategory::SetScrollState,
|
||||
Some(pipeline_id),
|
||||
|| {
|
||||
window.layout_mut().set_scroll_offsets(&scroll_states);
|
||||
window
|
||||
.layout_mut()
|
||||
.set_scroll_offsets_from_renderer(&scroll_states);
|
||||
|
||||
let mut scroll_offsets = HashMap::new();
|
||||
for scroll_state in scroll_states.into_iter() {
|
||||
let scroll_offset = scroll_state.scroll_offset;
|
||||
if scroll_state.scroll_id.is_root() {
|
||||
for (scroll_id, scroll_offset) in scroll_states.into_iter() {
|
||||
if scroll_id.is_root() {
|
||||
window.update_viewport_for_scroll(-scroll_offset.x, -scroll_offset.y);
|
||||
} else if let Some(node_id) =
|
||||
node_id_from_scroll_id(scroll_state.scroll_id.0 as usize)
|
||||
{
|
||||
} else if let Some(node_id) = node_id_from_scroll_id(scroll_id.0 as usize) {
|
||||
scroll_offsets.insert(OpaqueNode(node_id), -scroll_offset);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue