mirror of
https://github.com/servo/servo.git
synced 2025-09-30 00:29:14 +01:00
script/compositor: Handle cursor updates from script (#38518)
Instead of using WebRender hit testing to update the cursor, base it on layout hit tests. This allows removing the majority of WebRender hit test items and finally opens up the possibility of adding support for custom cursors. In addition, this change fixes an issue where cursors were not set properly on areas of the viewport that extended past the page content. Testing: This is difficult to test as verifying that the cursor changed properly is beyond the capabilities of Servo's test harnesses. Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
parent
87538282db
commit
6651f37c05
21 changed files with 279 additions and 259 deletions
|
@ -33,7 +33,7 @@ use style::values::generics::box_::Perspective;
|
|||
use style::values::generics::transform::{self, GenericRotate, GenericScale, GenericTranslate};
|
||||
use style::values::specified::box_::DisplayOutside;
|
||||
use webrender_api::units::{LayoutPoint, LayoutRect, LayoutTransform, LayoutVector2D};
|
||||
use webrender_api::{self as wr, BorderRadius};
|
||||
use webrender_api::{self as wr, BorderRadius, ExternalScrollId};
|
||||
use wr::StickyOffsetBounds;
|
||||
use wr::units::{LayoutPixel, LayoutSize};
|
||||
|
||||
|
@ -100,6 +100,22 @@ pub(crate) enum StackingContextSection {
|
|||
Outline,
|
||||
}
|
||||
|
||||
pub(crate) struct ScrollFrameHitTestItem {
|
||||
/// The [`ScrollTreeNodeId`] of the spatial node that contains this hit test item.
|
||||
pub scroll_node_id: ScrollTreeNodeId,
|
||||
|
||||
/// The [`ClipId`] of the clip that clips this [`ScrollFrameHitTestItems`].
|
||||
pub clip_id: ClipId,
|
||||
|
||||
/// The rectangle of the scroll frame in the coordinate space of [`Self::scroll_node_id`].
|
||||
pub rect: LayoutRect,
|
||||
|
||||
/// The WebRender [`ExternalScrollId`] of the scrolling spatial node that
|
||||
/// this [`ScrollFrameHitTestItem`] identifies. Note that this is a *different*
|
||||
/// spatial node than the one identified by [`Self::scroll_node_id`] (the parent).
|
||||
pub external_scroll_id: ExternalScrollId,
|
||||
}
|
||||
|
||||
pub(crate) struct StackingContextTree {
|
||||
/// The root stacking context of this [`StackingContextTree`].
|
||||
pub root_stacking_context: StackingContext,
|
||||
|
@ -114,6 +130,10 @@ pub(crate) struct StackingContextTree {
|
|||
/// for things like `overflow`. More clips may be created later during WebRender
|
||||
/// display list construction, but they are never added here.
|
||||
pub clip_store: StackingContextTreeClipStore,
|
||||
|
||||
/// A vector of hit test items, one per scroll frame. These are used for allowing
|
||||
/// renderer-side scrolling in the Servo renderer.
|
||||
pub hit_test_items: Vec<ScrollFrameHitTestItem>,
|
||||
}
|
||||
|
||||
impl StackingContextTree {
|
||||
|
@ -174,6 +194,7 @@ impl StackingContextTree {
|
|||
root_stacking_context: StackingContext::create_root(root_scroll_node_id, debug),
|
||||
compositor_info,
|
||||
clip_store: Default::default(),
|
||||
hit_test_items: Vec::new(),
|
||||
};
|
||||
|
||||
let mut root_stacking_context = StackingContext::create_root(root_scroll_node_id, debug);
|
||||
|
@ -281,7 +302,6 @@ pub(crate) enum StackingContextContent {
|
|||
section: StackingContextSection,
|
||||
containing_block: PhysicalRect<Au>,
|
||||
fragment: Fragment,
|
||||
is_hit_test_for_scrollable_overflow: bool,
|
||||
is_collapsed_table_borders: bool,
|
||||
text_decorations: Arc<Vec<FragmentTextDecoration>>,
|
||||
},
|
||||
|
@ -313,7 +333,6 @@ impl StackingContextContent {
|
|||
section,
|
||||
containing_block,
|
||||
fragment,
|
||||
is_hit_test_for_scrollable_overflow,
|
||||
is_collapsed_table_borders,
|
||||
text_decorations,
|
||||
} => {
|
||||
|
@ -324,7 +343,6 @@ impl StackingContextContent {
|
|||
builder,
|
||||
containing_block,
|
||||
*section,
|
||||
*is_hit_test_for_scrollable_overflow,
|
||||
*is_collapsed_table_borders,
|
||||
text_decorations,
|
||||
);
|
||||
|
@ -640,7 +658,6 @@ impl StackingContext {
|
|||
let mut fragment_builder = BuilderForBoxFragment::new(
|
||||
&root_fragment,
|
||||
&fragment_tree.initial_containing_block,
|
||||
false, /* is_hit_test_for_scrollable_overflow */
|
||||
false, /* is_collapsed_table_borders */
|
||||
);
|
||||
let painter = super::background::BackgroundPainter {
|
||||
|
@ -888,7 +905,6 @@ impl Fragment {
|
|||
clip_id: containing_block.clip_id,
|
||||
containing_block: containing_block.rect,
|
||||
fragment: fragment_clone,
|
||||
is_hit_test_for_scrollable_overflow: false,
|
||||
is_collapsed_table_borders: false,
|
||||
text_decorations: text_decorations.clone(),
|
||||
});
|
||||
|
@ -1088,7 +1104,6 @@ impl BoxFragment {
|
|||
BuilderForBoxFragment::new(
|
||||
self,
|
||||
&containing_block.rect,
|
||||
false, /* is_hit_test_for_scrollable_overflow */
|
||||
false, /* is_collapsed_table_borders */
|
||||
),
|
||||
)
|
||||
|
@ -1172,7 +1187,6 @@ impl BoxFragment {
|
|||
BuilderForBoxFragment::new(
|
||||
self,
|
||||
&containing_block.rect,
|
||||
false, /* is_hit_test_for_scrollable_overflow*/
|
||||
false, /* is_collapsed_table_borders */
|
||||
),
|
||||
) {
|
||||
|
@ -1205,7 +1219,6 @@ impl BoxFragment {
|
|||
section,
|
||||
containing_block: containing_block.rect,
|
||||
fragment: fragment.clone(),
|
||||
is_hit_test_for_scrollable_overflow: false,
|
||||
is_collapsed_table_borders: false,
|
||||
text_decorations: text_decorations.clone(),
|
||||
});
|
||||
|
@ -1234,21 +1247,6 @@ impl BoxFragment {
|
|||
if let Some(scroll_frame_data) = overflow_frame_data.scroll_frame_data {
|
||||
new_scroll_node_id = scroll_frame_data.scroll_tree_node_id;
|
||||
new_scroll_frame_size = Some(scroll_frame_data.scroll_frame_rect.size());
|
||||
|
||||
stacking_context
|
||||
.contents
|
||||
.push(StackingContextContent::Fragment {
|
||||
scroll_node_id: new_scroll_node_id,
|
||||
reference_frame_scroll_node_id:
|
||||
reference_frame_scroll_node_id_for_fragments,
|
||||
clip_id: new_clip_id,
|
||||
section,
|
||||
containing_block: containing_block.rect,
|
||||
fragment: fragment.clone(),
|
||||
is_hit_test_for_scrollable_overflow: true,
|
||||
is_collapsed_table_borders: false,
|
||||
text_decorations: text_decorations.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1345,7 +1343,6 @@ impl BoxFragment {
|
|||
section,
|
||||
containing_block: containing_block.rect,
|
||||
fragment: fragment.clone(),
|
||||
is_hit_test_for_scrollable_overflow: false,
|
||||
is_collapsed_table_borders: true,
|
||||
text_decorations: text_decorations.clone(),
|
||||
});
|
||||
|
@ -1417,7 +1414,7 @@ impl BoxFragment {
|
|||
// https://drafts.csswg.org/css-overflow-3/#corner-clipping
|
||||
let radii;
|
||||
if overflow.x == ComputedOverflow::Clip && overflow.y == ComputedOverflow::Clip {
|
||||
let builder = BuilderForBoxFragment::new(self, containing_block_rect, false, false);
|
||||
let builder = BuilderForBoxFragment::new(self, containing_block_rect, false);
|
||||
radii = offset_radii(builder.border_radius, clip_margin);
|
||||
} else if overflow.x != ComputedOverflow::Clip {
|
||||
overflow_clip_rect.min.x = f32::MIN;
|
||||
|
@ -1467,14 +1464,14 @@ impl BoxFragment {
|
|||
.to_webrender();
|
||||
|
||||
let clip_id = stacking_context_tree.clip_store.add(
|
||||
BuilderForBoxFragment::new(self, containing_block_rect, false, false).border_radius,
|
||||
BuilderForBoxFragment::new(self, containing_block_rect, false).border_radius,
|
||||
scroll_frame_rect,
|
||||
*parent_scroll_node_id,
|
||||
parent_clip_id,
|
||||
);
|
||||
|
||||
let tag = self.base.tag?;
|
||||
let external_id = wr::ExternalScrollId(
|
||||
let external_scroll_id = wr::ExternalScrollId(
|
||||
tag.to_display_list_fragment_id(),
|
||||
stacking_context_tree.compositor_info.pipeline_id,
|
||||
);
|
||||
|
@ -1486,12 +1483,21 @@ impl BoxFragment {
|
|||
|
||||
let scroll_tree_node_id = stacking_context_tree.define_scroll_frame(
|
||||
parent_scroll_node_id,
|
||||
external_id,
|
||||
external_scroll_id,
|
||||
self.scrollable_overflow().to_webrender(),
|
||||
scroll_frame_rect,
|
||||
sensitivity,
|
||||
);
|
||||
|
||||
stacking_context_tree
|
||||
.hit_test_items
|
||||
.push(ScrollFrameHitTestItem {
|
||||
scroll_node_id: *parent_scroll_node_id,
|
||||
clip_id,
|
||||
rect: scroll_frame_rect,
|
||||
external_scroll_id,
|
||||
});
|
||||
|
||||
Some(OverflowFrameData {
|
||||
clip_id,
|
||||
scroll_frame_data: Some(ScrollFrameData {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue