aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2024-03-13 10:17:09 +0100
committerGitHub <noreply@github.com>2024-03-13 09:17:09 +0000
commit716f4a006d3e2c3d920eea82caf82521d4e7f86c (patch)
tree08531efcb7eca0da4a4f792e41d59b3bf4123279
parent03d64d0675d4d1878232829293e7fdacaec5844e (diff)
downloadservo-716f4a006d3e2c3d920eea82caf82521d4e7f86c.tar.gz
servo-716f4a006d3e2c3d920eea82caf82521d4e7f86c.zip
layout: Propagate overflow values from `<body>` to root element (#31618)
The specification gives instructions for how these values should be propagated. The other big changs here is that they aren't applied to the `<body>`. Co-authored-by: Oriol Brufau <obrufau@igalia.com>
-rw-r--r--components/layout/display_list/webrender_helpers.rs8
-rw-r--r--components/layout_2020/display_list/mod.rs4
-rw-r--r--components/layout_2020/display_list/stacking_context.rs20
-rw-r--r--components/layout_2020/flow/root.rs48
-rw-r--r--components/layout_2020/fragment_tree/fragment_tree.rs5
-rw-r--r--components/layout_thread_2020/lib.rs1
-rw-r--r--components/shared/script/compositor.rs3
-rw-r--r--tests/wpt/meta/css/CSS2/visufx/overflow-propagation-001a.html.ini2
-rw-r--r--tests/wpt/meta/css/CSS2/visufx/overflow-propagation-001b.html.ini2
-rw-r--r--tests/wpt/meta/css/CSS2/visufx/overflow-propagation-001c.html.ini2
-rw-r--r--tests/wpt/meta/css/css-backgrounds/background-origin/origin-border-box.html.ini2
-rw-r--r--tests/wpt/meta/css/css-backgrounds/background-origin/origin-border-box_with_size.html.ini2
-rw-r--r--tests/wpt/meta/css/css-backgrounds/background-origin/origin-content-box_with_size.html.ini2
-rw-r--r--tests/wpt/meta/css/css-backgrounds/background-origin/origin-padding-box_with_size.html.ini2
-rw-r--r--tests/wpt/meta/css/css-transforms/transform-inherit-001.html.ini2
-rw-r--r--tests/wpt/meta/css/css-transforms/transform-transformed-td-contains-fixed-position.html.ini2
-rw-r--r--tests/wpt/meta/css/css-transforms/transform-transformed-th-contains-fixed-position.html.ini2
17 files changed, 82 insertions, 27 deletions
diff --git a/components/layout/display_list/webrender_helpers.rs b/components/layout/display_list/webrender_helpers.rs
index 04d8d825e06..49002b6b7cd 100644
--- a/components/layout/display_list/webrender_helpers.rs
+++ b/components/layout/display_list/webrender_helpers.rs
@@ -121,7 +121,13 @@ impl DisplayList {
let content_size = self.bounds().size;
let mut state = ClipScrollState::new(
&mut self.clip_scroll_nodes,
- CompositorDisplayListInfo::new(viewport_size, content_size, webrender_pipeline, epoch),
+ CompositorDisplayListInfo::new(
+ viewport_size,
+ content_size,
+ webrender_pipeline,
+ epoch,
+ webrender_api::ScrollSensitivity::ScriptAndInputEvents,
+ ),
&mut builder,
);
diff --git a/components/layout_2020/display_list/mod.rs b/components/layout_2020/display_list/mod.rs
index 35a58be985a..d755faae1cd 100644
--- a/components/layout_2020/display_list/mod.rs
+++ b/components/layout_2020/display_list/mod.rs
@@ -25,7 +25,7 @@ use style::values::specified::ui::CursorKind;
use style_traits::CSSPixel;
use webrender_api::{self as wr, units, ClipChainId, ClipId, CommonItemProperties};
use wr::units::LayoutVector2D;
-use wr::BoxShadowClipMode;
+use wr::{BoxShadowClipMode, ScrollSensitivity};
use crate::context::LayoutContext;
use crate::display_list::conversions::ToWebRender;
@@ -77,6 +77,7 @@ impl DisplayList {
content_size: units::LayoutSize,
pipeline_id: wr::PipelineId,
epoch: wr::Epoch,
+ root_scroll_sensitivity: ScrollSensitivity,
) -> Self {
Self {
wr: wr::DisplayListBuilder::new(pipeline_id),
@@ -85,6 +86,7 @@ impl DisplayList {
content_size,
pipeline_id,
epoch,
+ root_scroll_sensitivity,
),
}
}
diff --git a/components/layout_2020/display_list/stacking_context.rs b/components/layout_2020/display_list/stacking_context.rs
index 68be4cc312b..6dd10641d0a 100644
--- a/components/layout_2020/display_list/stacking_context.rs
+++ b/components/layout_2020/display_list/stacking_context.rs
@@ -32,7 +32,7 @@ use crate::cell::ArcRefCell;
use crate::display_list::conversions::{FilterToWebRender, ToWebRender};
use crate::display_list::DisplayListBuilder;
use crate::fragment_tree::{
- BoxFragment, ContainingBlockManager, Fragment, FragmentTree, PositioningFragment,
+ BoxFragment, ContainingBlockManager, Fragment, FragmentFlags, FragmentTree, PositioningFragment,
};
use crate::geom::{PhysicalRect, PhysicalSides};
use crate::style_ext::ComputedValuesExt;
@@ -1247,6 +1247,24 @@ impl BoxFragment {
return None;
}
+ // From https://drafts.csswg.org/css-overflow/#propdef-overflow:
+ // > UAs must apply the overflow-* values set on the root element to the viewport when the
+ // > root element’s display value is not none. However, when the root element is an [HTML]
+ // > html element (including XML syntax for HTML) whose overflow value is visible (in both
+ // > axes), and that element has as a child a body element whose display value is also not
+ // > none, user agents must instead apply the overflow-* values of the first such child
+ // > element to the viewport. The element from which the value is propagated must then have a
+ // > used overflow value of visible.
+ //
+ // TODO: This should only happen when the `display` value is actually propagated.
+ if self
+ .base
+ .flags
+ .contains(FragmentFlags::IS_BODY_ELEMENT_OF_HTML_ELEMENT_ROOT)
+ {
+ return None;
+ }
+
let tag = self.base.tag?;
let external_id = wr::ExternalScrollId(
tag.to_display_list_fragment_id(),
diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs
index b41d7b6b999..ebdf690aac7 100644
--- a/components/layout_2020/flow/root.rs
+++ b/components/layout_2020/flow/root.rs
@@ -3,14 +3,17 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use atomic_refcell::AtomicRef;
-use script_layout_interface::wrapper_traits::LayoutNode;
+use script_layout_interface::wrapper_traits::{
+ LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
+};
use script_layout_interface::{LayoutElementType, LayoutNodeType};
use serde::Serialize;
use servo_arc::Arc;
use style::dom::OpaqueNode;
use style::properties::ComputedValues;
-use style::values::computed::Length;
+use style::values::computed::{Length, Overflow};
use style_traits::CSSPixel;
+use webrender_api::ScrollSensitivity;
use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
@@ -36,6 +39,9 @@ pub struct BoxTree {
/// <https://drafts.csswg.org/css-backgrounds/#special-backgrounds>
canvas_background: CanvasBackground,
+
+ /// Whether or not the root element should be sensitive to scrolling input events.
+ sensitive_to_scroll_input: bool,
}
impl BoxTree {
@@ -48,6 +54,35 @@ impl BoxTree {
// Zero box for `:root { display: none }`, one for the root element otherwise.
assert!(boxes.len() <= 1);
+ // From https://drafts.csswg.org/css-overflow/#propdef-overflow:
+ // > UAs must apply the overflow-* values set on the root element to the viewport when the
+ // > root element’s display value is not none. However, when the root element is an [HTML]
+ // > html element (including XML syntax for HTML) whose overflow value is visible (in both
+ // > axes), and that element has as a child a body element whose display value is also not
+ // > none, user agents must instead apply the overflow-* values of the first such child
+ // > element to the viewport. The element from which the value is propagated must then have a
+ // > used overflow value of visible.
+ //
+ // TODO: This should handle when different overflow is set multiple axes, which requires the
+ // compositor scroll tree to allow setting a value per axis.
+ let root_style = root_element.style(context);
+ let mut root_overflow = root_style.get_box().overflow_y;
+ if root_overflow == Overflow::Visible && !root_style.get_box().display.is_none() {
+ for child in iter_child_nodes(root_element) {
+ if !child.to_threadsafe().as_element().map_or(false, |element| {
+ element.is_body_element_of_html_element_root()
+ }) {
+ continue;
+ }
+
+ let style = child.style(context);
+ if !style.get_box().display.is_none() {
+ root_overflow = style.get_box().overflow_y;
+ break;
+ }
+ }
+ }
+
let contents = BlockContainer::BlockLevelBoxes(boxes);
let contains_floats = contents.contains_floats();
Self {
@@ -56,6 +91,7 @@ impl BoxTree {
contains_floats,
},
canvas_background: CanvasBackground::for_root_element(context, root_element),
+ sensitive_to_scroll_input: root_overflow != Overflow::Hidden,
}
}
@@ -252,6 +288,7 @@ fn construct_for_root_element<'dom>(
propagated_text_decoration_line,
))
};
+
let root_box = ArcRefCell::new(root_box);
root_element
.element_box_slot()
@@ -330,11 +367,18 @@ impl BoxTree {
acc.union(&child_overflow)
});
+ let root_scroll_sensitivity = if self.sensitive_to_scroll_input {
+ ScrollSensitivity::ScriptAndInputEvents
+ } else {
+ ScrollSensitivity::Script
+ };
+
FragmentTree {
root_fragments,
scrollable_overflow,
initial_containing_block: physical_containing_block,
canvas_background: self.canvas_background.clone(),
+ root_scroll_sensitivity,
}
}
}
diff --git a/components/layout_2020/fragment_tree/fragment_tree.rs b/components/layout_2020/fragment_tree/fragment_tree.rs
index 4bce1e9b125..21e4911fe63 100644
--- a/components/layout_2020/fragment_tree/fragment_tree.rs
+++ b/components/layout_2020/fragment_tree/fragment_tree.rs
@@ -10,7 +10,7 @@ use serde::Serialize;
use style::animation::AnimationSetKey;
use style::dom::OpaqueNode;
use style::values::computed::Length;
-use webrender_api::units;
+use webrender_api::{units, ScrollSensitivity};
use super::{ContainingBlockManager, Fragment, Tag};
use crate::cell::ArcRefCell;
@@ -40,6 +40,9 @@ pub struct FragmentTree {
/// <https://drafts.csswg.org/css-backgrounds/#special-backgrounds>
#[serde(skip)]
pub(crate) canvas_background: CanvasBackground,
+
+ /// Whether or not the root element is sensitive to scroll input events.
+ pub root_scroll_sensitivity: ScrollSensitivity,
}
impl FragmentTree {
diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs
index 5ab2ca653e3..8528128150a 100644
--- a/components/layout_thread_2020/lib.rs
+++ b/components/layout_thread_2020/lib.rs
@@ -1026,6 +1026,7 @@ impl LayoutThread {
fragment_tree.scrollable_overflow(),
self.id.to_webrender(),
epoch.into(),
+ fragment_tree.root_scroll_sensitivity,
);
// `dump_serialized_display_list` doesn't actually print anything. It sets up
diff --git a/components/shared/script/compositor.rs b/components/shared/script/compositor.rs
index d874cc871b2..55e76beb85c 100644
--- a/components/shared/script/compositor.rs
+++ b/components/shared/script/compositor.rs
@@ -252,6 +252,7 @@ impl CompositorDisplayListInfo {
content_size: LayoutSize,
pipeline_id: PipelineId,
epoch: Epoch,
+ root_scroll_sensitivity: ScrollSensitivity,
) -> Self {
let mut scroll_tree = ScrollTree::default();
let root_reference_frame_id = scroll_tree.add_scroll_tree_node(
@@ -265,7 +266,7 @@ impl CompositorDisplayListInfo {
Some(ScrollableNodeInfo {
external_id: ExternalScrollId(0, pipeline_id),
scrollable_size: content_size - viewport_size,
- scroll_sensitivity: ScrollSensitivity::ScriptAndInputEvents,
+ scroll_sensitivity: root_scroll_sensitivity,
offset: LayoutVector2D::zero(),
}),
);
diff --git a/tests/wpt/meta/css/CSS2/visufx/overflow-propagation-001a.html.ini b/tests/wpt/meta/css/CSS2/visufx/overflow-propagation-001a.html.ini
deleted file mode 100644
index 81d6ac64849..00000000000
--- a/tests/wpt/meta/css/CSS2/visufx/overflow-propagation-001a.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[overflow-propagation-001a.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/CSS2/visufx/overflow-propagation-001b.html.ini b/tests/wpt/meta/css/CSS2/visufx/overflow-propagation-001b.html.ini
deleted file mode 100644
index ca92af5f99d..00000000000
--- a/tests/wpt/meta/css/CSS2/visufx/overflow-propagation-001b.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[overflow-propagation-001b.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/CSS2/visufx/overflow-propagation-001c.html.ini b/tests/wpt/meta/css/CSS2/visufx/overflow-propagation-001c.html.ini
deleted file mode 100644
index f62da303dbc..00000000000
--- a/tests/wpt/meta/css/CSS2/visufx/overflow-propagation-001c.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[overflow-propagation-001c.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-backgrounds/background-origin/origin-border-box.html.ini b/tests/wpt/meta/css/css-backgrounds/background-origin/origin-border-box.html.ini
deleted file mode 100644
index 5cb526d200a..00000000000
--- a/tests/wpt/meta/css/css-backgrounds/background-origin/origin-border-box.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[origin-border-box.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-backgrounds/background-origin/origin-border-box_with_size.html.ini b/tests/wpt/meta/css/css-backgrounds/background-origin/origin-border-box_with_size.html.ini
deleted file mode 100644
index 2b3c71c8ba0..00000000000
--- a/tests/wpt/meta/css/css-backgrounds/background-origin/origin-border-box_with_size.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[origin-border-box_with_size.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-backgrounds/background-origin/origin-content-box_with_size.html.ini b/tests/wpt/meta/css/css-backgrounds/background-origin/origin-content-box_with_size.html.ini
deleted file mode 100644
index cd17a133995..00000000000
--- a/tests/wpt/meta/css/css-backgrounds/background-origin/origin-content-box_with_size.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[origin-content-box_with_size.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-backgrounds/background-origin/origin-padding-box_with_size.html.ini b/tests/wpt/meta/css/css-backgrounds/background-origin/origin-padding-box_with_size.html.ini
deleted file mode 100644
index fd6e5b300fe..00000000000
--- a/tests/wpt/meta/css/css-backgrounds/background-origin/origin-padding-box_with_size.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[origin-padding-box_with_size.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-transforms/transform-inherit-001.html.ini b/tests/wpt/meta/css/css-transforms/transform-inherit-001.html.ini
deleted file mode 100644
index 26ab9cab286..00000000000
--- a/tests/wpt/meta/css/css-transforms/transform-inherit-001.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[transform-inherit-001.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-transforms/transform-transformed-td-contains-fixed-position.html.ini b/tests/wpt/meta/css/css-transforms/transform-transformed-td-contains-fixed-position.html.ini
deleted file mode 100644
index 9fce6a3d73d..00000000000
--- a/tests/wpt/meta/css/css-transforms/transform-transformed-td-contains-fixed-position.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[transform-transformed-td-contains-fixed-position.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-transforms/transform-transformed-th-contains-fixed-position.html.ini b/tests/wpt/meta/css/css-transforms/transform-transformed-th-contains-fixed-position.html.ini
deleted file mode 100644
index dd64b75e741..00000000000
--- a/tests/wpt/meta/css/css-transforms/transform-transformed-th-contains-fixed-position.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[transform-transformed-th-contains-fixed-position.html]
- expected: FAIL