mirror of
https://github.com/servo/servo.git
synced 2025-09-30 16:49:16 +01:00
layout: Add a layout hit test and use it for document.elementsFromPoint
(#38463)
In #18933, hit testing was moved from layout to WebRender. This presents some issues. For instance, the DOM can change at the same time that hit test is happening. This can mean that hit test returns references to defunct DOM nodes, introducing memory safety issues. Currently, Servo will try to ensure that the epochs used for testing and those recorded in the DOM match, but this is not very reliable and has led to code that retries failed hit tests. This change reintroduces (8 years later) a layout hit tester and turns it on for `document.elementFromPoint` and `document.elementsFromPoint`. The idea is that this hit tester will gradually replace the majority of the WebRender hit testing happening in the renderer. Testing: This shouldn't really change the behavior hit testing, but it seems to improve one WPT test. Signed-off-by: Martin Robinson <mrobinson@igalia.com> Co-authored-by: Oriol Brufau <obrufau@igalia.com> Co-authored-by: kongbai1996 <1782765876@qq.com>
This commit is contained in:
parent
3e856cbf11
commit
11844ca5af
11 changed files with 539 additions and 113 deletions
|
@ -293,7 +293,7 @@ pub(crate) enum StackingContextContent {
|
|||
}
|
||||
|
||||
impl StackingContextContent {
|
||||
fn section(&self) -> StackingContextSection {
|
||||
pub(crate) fn section(&self) -> StackingContextSection {
|
||||
match self {
|
||||
Self::Fragment { section, .. } => *section,
|
||||
Self::AtomicInlineStackingContainer { .. } => StackingContextSection::Foreground,
|
||||
|
@ -365,7 +365,7 @@ pub struct StackingContext {
|
|||
context_type: StackingContextType,
|
||||
|
||||
/// The contents that need to be painted in fragment order.
|
||||
contents: Vec<StackingContextContent>,
|
||||
pub(super) contents: Vec<StackingContextContent>,
|
||||
|
||||
/// Stacking contexts that need to be stolen by the parent stacking context
|
||||
/// if this is a stacking container, that is, real stacking contexts and
|
||||
|
@ -376,13 +376,13 @@ pub struct StackingContext {
|
|||
/// > if it created a new stacking context, but omitting any positioned
|
||||
/// > descendants or descendants that actually create a stacking context
|
||||
/// > (letting the parent stacking context paint them, instead).
|
||||
real_stacking_contexts_and_positioned_stacking_containers: Vec<StackingContext>,
|
||||
pub(super) real_stacking_contexts_and_positioned_stacking_containers: Vec<StackingContext>,
|
||||
|
||||
/// Float stacking containers.
|
||||
/// Separate from real_stacking_contexts_or_positioned_stacking_containers
|
||||
/// because they should never be stolen by the parent stacking context.
|
||||
/// <https://drafts.csswg.org/css-position-4/#paint-a-stacking-container>
|
||||
float_stacking_containers: Vec<StackingContext>,
|
||||
pub(super) float_stacking_containers: Vec<StackingContext>,
|
||||
|
||||
/// Atomic inline stacking containers.
|
||||
/// Separate from real_stacking_contexts_or_positioned_stacking_containers
|
||||
|
@ -391,7 +391,7 @@ pub struct StackingContext {
|
|||
/// can index into this vec to paint them in fragment order.
|
||||
/// <https://drafts.csswg.org/css-position-4/#paint-a-stacking-container>
|
||||
/// <https://drafts.csswg.org/css-position-4/#paint-a-box-in-a-line-box>
|
||||
atomic_inline_stacking_containers: Vec<StackingContext>,
|
||||
pub(super) atomic_inline_stacking_containers: Vec<StackingContext>,
|
||||
|
||||
/// Information gathered about the painting order, for [Self::debug_print].
|
||||
debug_print_items: Option<RefCell<Vec<DebugPrintItem>>>,
|
||||
|
@ -472,7 +472,7 @@ impl StackingContext {
|
|||
.push(stacking_context)
|
||||
}
|
||||
|
||||
fn z_index(&self) -> i32 {
|
||||
pub(crate) fn z_index(&self) -> i32 {
|
||||
self.initializing_fragment.as_ref().map_or(0, |fragment| {
|
||||
let fragment = fragment.borrow();
|
||||
fragment.style.effective_z_index(fragment.base.flags)
|
||||
|
@ -651,6 +651,9 @@ impl StackingContext {
|
|||
fragment_builder.build_background_image(builder, &painter);
|
||||
}
|
||||
|
||||
/// Build a display list from a a [`StackingContext`]. Note that this is the forward
|
||||
/// version of the reversed stacking context walk algorithm in `hit_test.rs`. Any
|
||||
/// changes made here should be reflected in the reverse version in that file.
|
||||
pub(crate) fn build_display_list(&self, builder: &mut DisplayListBuilder) {
|
||||
let pushed_context = self.push_webrender_stacking_context_if_necessary(builder);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue