mirror of
https://github.com/servo/servo.git
synced 2025-06-10 09:33:13 +00:00
* layout: Add AxesScrollSensitivity to enable control of scroll in axis Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com> * layout_2013: Be compatible with AxesScrollSensitivity Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com> * layout: update struct AxesScrollSensitivity to euclid::Vector2D Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com> * display_list: implement From<Overflow> for ScrollSensitivity Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com> * layout: simplify and reuse scroll related logic Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com> * layout_2013: simplify and reuse scroll related logic Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com> * layout, layout_2013: revert AxesScrollSensitivity to pair struct Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com> * layout: Reimport ComputedOverflow as #35103 depends on it Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com> * layout: Add AxesOverflow to replace PhysicalVec Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com> * layout: implement scroll of viewport for different axes Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com> * layout: explicitly handle overflow match Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com> * Update components/shared/webrender/Cargo.toml Co-authored-by: Martin Robinson <mrobinson@igalia.com> Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com> --------- Signed-off-by: Euclid Ye <yezhizhenjiakang@gmail.com> Co-authored-by: Martin Robinson <mrobinson@igalia.com>
187 lines
6.5 KiB
Rust
187 lines
6.5 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
|
|
use euclid::Size2D;
|
|
use webrender_api::units::LayoutVector2D;
|
|
use webrender_api::{ExternalScrollId, PipelineId, ScrollLocation, SpatialId};
|
|
use webrender_traits::display_list::{
|
|
AxesScrollSensitivity, ScrollSensitivity, ScrollTree, ScrollTreeNodeId, ScrollableNodeInfo,
|
|
};
|
|
|
|
fn add_mock_scroll_node(tree: &mut ScrollTree) -> ScrollTreeNodeId {
|
|
let pipeline_id = PipelineId(0, 0);
|
|
let num_nodes = tree.nodes.len();
|
|
let parent = if num_nodes > 0 {
|
|
Some(ScrollTreeNodeId {
|
|
index: num_nodes - 1,
|
|
spatial_id: SpatialId::new(num_nodes - 1, pipeline_id),
|
|
})
|
|
} else {
|
|
None
|
|
};
|
|
|
|
tree.add_scroll_tree_node(
|
|
parent.as_ref(),
|
|
SpatialId::new(num_nodes, pipeline_id),
|
|
Some(ScrollableNodeInfo {
|
|
external_id: ExternalScrollId(num_nodes as u64, pipeline_id),
|
|
scrollable_size: Size2D::new(100.0, 100.0),
|
|
scroll_sensitivity: AxesScrollSensitivity {
|
|
x: ScrollSensitivity::ScriptAndInputEvents,
|
|
y: ScrollSensitivity::ScriptAndInputEvents,
|
|
},
|
|
offset: LayoutVector2D::zero(),
|
|
}),
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn test_scroll_tree_simple_scroll() {
|
|
let mut scroll_tree = ScrollTree::default();
|
|
let pipeline_id = PipelineId(0, 0);
|
|
let id = add_mock_scroll_node(&mut scroll_tree);
|
|
|
|
let (scrolled_id, offset) = scroll_tree
|
|
.scroll_node_or_ancestor(
|
|
&id,
|
|
ScrollLocation::Delta(LayoutVector2D::new(-20.0, -40.0)),
|
|
)
|
|
.unwrap();
|
|
let expected_offset = LayoutVector2D::new(-20.0, -40.0);
|
|
assert_eq!(scrolled_id, ExternalScrollId(0, pipeline_id));
|
|
assert_eq!(offset, expected_offset);
|
|
assert_eq!(scroll_tree.get_node(&id).offset(), Some(expected_offset));
|
|
|
|
let (scrolled_id, offset) = scroll_tree
|
|
.scroll_node_or_ancestor(&id, ScrollLocation::Delta(LayoutVector2D::new(20.0, 40.0)))
|
|
.unwrap();
|
|
let expected_offset = LayoutVector2D::new(0.0, 0.0);
|
|
assert_eq!(scrolled_id, ExternalScrollId(0, pipeline_id));
|
|
assert_eq!(offset, expected_offset);
|
|
assert_eq!(scroll_tree.get_node(&id).offset(), Some(expected_offset));
|
|
|
|
// Scroll offsets must be negative.
|
|
let result = scroll_tree
|
|
.scroll_node_or_ancestor(&id, ScrollLocation::Delta(LayoutVector2D::new(20.0, 40.0)));
|
|
assert!(result.is_none());
|
|
assert_eq!(
|
|
scroll_tree.get_node(&id).offset(),
|
|
Some(LayoutVector2D::new(0.0, 0.0))
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_scroll_tree_simple_scroll_chaining() {
|
|
let mut scroll_tree = ScrollTree::default();
|
|
|
|
let pipeline_id = PipelineId(0, 0);
|
|
let parent_id = add_mock_scroll_node(&mut scroll_tree);
|
|
let unscrollable_child_id =
|
|
scroll_tree.add_scroll_tree_node(Some(&parent_id), SpatialId::new(1, pipeline_id), None);
|
|
|
|
let (scrolled_id, offset) = scroll_tree
|
|
.scroll_node_or_ancestor(
|
|
&unscrollable_child_id,
|
|
ScrollLocation::Delta(LayoutVector2D::new(-20.0, -40.0)),
|
|
)
|
|
.unwrap();
|
|
let expected_offset = LayoutVector2D::new(-20.0, -40.0);
|
|
assert_eq!(scrolled_id, ExternalScrollId(0, pipeline_id));
|
|
assert_eq!(offset, expected_offset);
|
|
assert_eq!(
|
|
scroll_tree.get_node(&parent_id).offset(),
|
|
Some(expected_offset)
|
|
);
|
|
|
|
let (scrolled_id, offset) = scroll_tree
|
|
.scroll_node_or_ancestor(
|
|
&unscrollable_child_id,
|
|
ScrollLocation::Delta(LayoutVector2D::new(-10.0, -15.0)),
|
|
)
|
|
.unwrap();
|
|
let expected_offset = LayoutVector2D::new(-30.0, -55.0);
|
|
assert_eq!(scrolled_id, ExternalScrollId(0, pipeline_id));
|
|
assert_eq!(offset, expected_offset);
|
|
assert_eq!(
|
|
scroll_tree.get_node(&parent_id).offset(),
|
|
Some(expected_offset)
|
|
);
|
|
assert_eq!(scroll_tree.get_node(&unscrollable_child_id).offset(), None);
|
|
}
|
|
|
|
#[test]
|
|
fn test_scroll_tree_chain_when_at_extent() {
|
|
let mut scroll_tree = ScrollTree::default();
|
|
|
|
let pipeline_id = PipelineId(0, 0);
|
|
let parent_id = add_mock_scroll_node(&mut scroll_tree);
|
|
let child_id = add_mock_scroll_node(&mut scroll_tree);
|
|
|
|
let (scrolled_id, offset) = scroll_tree
|
|
.scroll_node_or_ancestor(&child_id, ScrollLocation::End)
|
|
.unwrap();
|
|
|
|
let expected_offset = LayoutVector2D::new(0.0, -100.0);
|
|
assert_eq!(scrolled_id, ExternalScrollId(1, pipeline_id));
|
|
assert_eq!(offset, expected_offset);
|
|
assert_eq!(
|
|
scroll_tree.get_node(&child_id).offset(),
|
|
Some(expected_offset)
|
|
);
|
|
|
|
// The parent will have scrolled because the child is already at the extent
|
|
// of its scroll area in the y axis.
|
|
let (scrolled_id, offset) = scroll_tree
|
|
.scroll_node_or_ancestor(
|
|
&child_id,
|
|
ScrollLocation::Delta(LayoutVector2D::new(0.0, -10.0)),
|
|
)
|
|
.unwrap();
|
|
let expected_offset = LayoutVector2D::new(0.0, -10.0);
|
|
assert_eq!(scrolled_id, ExternalScrollId(0, pipeline_id));
|
|
assert_eq!(offset, expected_offset);
|
|
assert_eq!(
|
|
scroll_tree.get_node(&parent_id).offset(),
|
|
Some(expected_offset)
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn test_scroll_tree_chain_through_overflow_hidden() {
|
|
let mut scroll_tree = ScrollTree::default();
|
|
|
|
// Create a tree with a scrollable leaf, but make its `scroll_sensitivity`
|
|
// reflect `overflow: hidden` ie not responsive to non-script scroll events.
|
|
let pipeline_id = PipelineId(0, 0);
|
|
let parent_id = add_mock_scroll_node(&mut scroll_tree);
|
|
let overflow_hidden_id = add_mock_scroll_node(&mut scroll_tree);
|
|
scroll_tree
|
|
.get_node_mut(&overflow_hidden_id)
|
|
.scroll_info
|
|
.as_mut()
|
|
.map(|info| {
|
|
info.scroll_sensitivity = AxesScrollSensitivity {
|
|
x: ScrollSensitivity::Script,
|
|
y: ScrollSensitivity::Script,
|
|
};
|
|
});
|
|
|
|
let (scrolled_id, offset) = scroll_tree
|
|
.scroll_node_or_ancestor(
|
|
&overflow_hidden_id,
|
|
ScrollLocation::Delta(LayoutVector2D::new(-20.0, -40.0)),
|
|
)
|
|
.unwrap();
|
|
let expected_offset = LayoutVector2D::new(-20.0, -40.0);
|
|
assert_eq!(scrolled_id, ExternalScrollId(0, pipeline_id));
|
|
assert_eq!(offset, expected_offset);
|
|
assert_eq!(
|
|
scroll_tree.get_node(&parent_id).offset(),
|
|
Some(expected_offset)
|
|
);
|
|
assert_eq!(
|
|
scroll_tree.get_node(&overflow_hidden_id).offset(),
|
|
Some(LayoutVector2D::new(0.0, 0.0))
|
|
);
|
|
}
|