diff options
19 files changed, 129 insertions, 63 deletions
diff --git a/components/layout_2020/display_list/mod.rs b/components/layout_2020/display_list/mod.rs index 96ac84032a9..fa193874892 100644 --- a/components/layout_2020/display_list/mod.rs +++ b/components/layout_2020/display_list/mod.rs @@ -9,9 +9,11 @@ use crate::replaced::IntrinsicSizes; use embedder_traits::Cursor; use euclid::{Point2D, SideOffsets2D, Size2D}; use gfx::text::glyph::GlyphStore; +use gfx_traits::{combine_id_with_fragment_type, FragmentType}; use mitochondria::OnceCell; use net_traits::image_cache::UsePlaceholder; use std::sync::Arc; +use style::computed_values::overflow_x::T as ComputedOverflow; use style::dom::OpaqueNode; use style::properties::ComputedValues; use style::values::computed::{BorderStyle, Length, LengthPercentage}; @@ -63,8 +65,6 @@ impl<'a> DisplayListBuilder<'a> { wr::CommonItemProperties::new(clip_rect, self.current_space_and_clip) } - // FIXME: use this for the `overflow` property or anything else that clips an entire subtree. - #[allow(unused)] fn clipping_and_scrolling_scope<R>(&mut self, f: impl FnOnce(&mut Self) -> R) -> R { let previous = self.current_space_and_clip; let result = f(self); @@ -256,14 +256,49 @@ impl<'a> BuilderForBoxFragment<'a> { self.build_background(builder); self.build_border(builder); - let content_rect = self - .fragment - .content_rect - .to_physical(self.fragment.style.writing_mode, self.containing_block) - .translate(self.containing_block.origin.to_vector()); - for child in &self.fragment.children { - child.build_display_list(builder, &content_rect) - } + + builder.clipping_and_scrolling_scope(|builder| { + let overflow_x = self.fragment.style.get_box().overflow_x; + let overflow_y = self.fragment.style.get_box().overflow_y; + let original_scroll_and_clip_info = builder.current_space_and_clip; + if overflow_x != ComputedOverflow::Visible || overflow_y != ComputedOverflow::Visible { + // TODO(mrobinson): We should use the correct fragment type, once we generate + // fragments from ::before and ::after generated content selectors. + let id = combine_id_with_fragment_type( + self.fragment.tag.id() as usize, + FragmentType::FragmentBody, + ) as u64; + let external_id = wr::ExternalScrollId(id, builder.wr.pipeline_id); + + let sensitivity = if ComputedOverflow::Hidden == overflow_x && + ComputedOverflow::Hidden == overflow_y + { + wr::ScrollSensitivity::Script + } else { + wr::ScrollSensitivity::ScriptAndInputEvents + }; + + builder.current_space_and_clip = builder.wr.define_scroll_frame( + &original_scroll_and_clip_info, + Some(external_id), + self.fragment.scrollable_overflow().to_webrender(), + *self.padding_rect(), + vec![], // complex_clips + None, // image_mask + sensitivity, + wr::units::LayoutVector2D::zero(), + ); + } + + let content_rect = self + .fragment + .content_rect + .to_physical(self.fragment.style.writing_mode, self.containing_block) + .translate(self.containing_block.origin.to_vector()); + for child in &self.fragment.children { + child.build_display_list(builder, &content_rect) + } + }); } fn build_background(&mut self, builder: &mut DisplayListBuilder) { diff --git a/components/layout_2020/fragments.rs b/components/layout_2020/fragments.rs index 37f81978108..c46b332dec5 100644 --- a/components/layout_2020/fragments.rs +++ b/components/layout_2020/fragments.rs @@ -3,11 +3,12 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::geom::flow_relative::{Rect, Sides, Vec2}; -use crate::geom::PhysicalRect; +use crate::geom::{PhysicalPoint, PhysicalRect}; use gfx::text::glyph::GlyphStore; use gfx_traits::print_tree::PrintTree; use servo_arc::Arc as ServoArc; use std::sync::Arc; +use style::computed_values::overflow_x::T as ComputedOverflow; use style::dom::OpaqueNode; use style::logical_geometry::WritingMode; use style::properties::ComputedValues; @@ -39,7 +40,7 @@ pub(crate) struct BoxFragment { pub block_margins_collapsed_with_children: CollapsedBlockMargins, /// The scrollable overflow of this box fragment. - pub scrollable_overflow: PhysicalRect<Length>, + pub scrollable_overflow_from_children: PhysicalRect<Length>, } pub(crate) struct CollapsedBlockMargins { @@ -101,15 +102,16 @@ impl Fragment { pub fn scrollable_overflow(&self) -> PhysicalRect<Length> { // FIXME(mrobinson, bug 25564): We should be using the containing block // here to properly convert scrollable overflow to physical geometry. + let containing_block = PhysicalRect::zero(); match self { - Fragment::Box(fragment) => fragment.scrollable_overflow.clone(), + Fragment::Box(fragment) => fragment.scrollable_overflow_for_parent(&containing_block), Fragment::Anonymous(fragment) => fragment.scrollable_overflow.clone(), Fragment::Text(fragment) => fragment .rect - .to_physical(fragment.parent_style.writing_mode, &PhysicalRect::zero()), + .to_physical(fragment.parent_style.writing_mode, &containing_block), Fragment::Image(fragment) => fragment .rect - .to_physical(fragment.style.writing_mode, &PhysicalRect::zero()), + .to_physical(fragment.style.writing_mode, &containing_block), } } } @@ -125,10 +127,13 @@ impl AnonymousFragment { } pub fn new(rect: Rect<Length>, children: Vec<Fragment>, mode: WritingMode) -> Self { - // FIXME(mrobinson, bug 25564): We should be using the containing block - // here to properly convert scrollable overflow to physical geometry. + let content_origin = rect.start_corner.to_physical(mode); let scrollable_overflow = children.iter().fold(PhysicalRect::zero(), |acc, child| { - acc.union(&child.scrollable_overflow()) + acc.union( + &child + .scrollable_overflow() + .translate(content_origin.to_vector()), + ) }); AnonymousFragment { rect, @@ -141,8 +146,9 @@ impl AnonymousFragment { pub fn print(&self, tree: &mut PrintTree) { tree.new_level(format!( "Anonymous\ - \nrect={:?}", - self.rect + \nrect={:?}\ + \nscrollable_overflow={:?}", + self.rect, self.scrollable_overflow )); for child in &self.children { @@ -163,14 +169,10 @@ impl BoxFragment { margin: Sides<Length>, block_margins_collapsed_with_children: CollapsedBlockMargins, ) -> BoxFragment { - // FIXME(mrobinson, bug 25564): We should be using the containing block - // here to properly convert scrollable overflow to physical geometry. - let scrollable_overflow = children.iter().fold( - content_rect - .inflate(&border) - .to_physical(style.writing_mode, &PhysicalRect::zero()), - |acc, child| acc.union(&child.scrollable_overflow()), - ); + let scrollable_overflow_from_children = + children.iter().fold(PhysicalRect::zero(), |acc, child| { + acc.union(&child.scrollable_overflow()) + }); BoxFragment { tag, style, @@ -180,10 +182,28 @@ impl BoxFragment { border, margin, block_margins_collapsed_with_children, - scrollable_overflow, + scrollable_overflow_from_children, } } + pub fn scrollable_overflow(&self) -> PhysicalRect<Length> { + // FIXME(mrobinson, bug 25564): We should be using the containing block + // here to properly convert scrollable overflow to physical geometry. + let physical_padding_rect = self + .padding_rect() + .to_physical(self.style.writing_mode, &PhysicalRect::zero()); + + let content_origin = self + .content_rect + .start_corner + .to_physical(self.style.writing_mode); + physical_padding_rect.union( + &self + .scrollable_overflow_from_children + .translate(content_origin.to_vector()), + ) + } + pub fn padding_rect(&self) -> Rect<Length> { self.content_rect.inflate(&self.padding) } @@ -197,10 +217,17 @@ impl BoxFragment { "Box\ \ncontent={:?}\ \npadding rect={:?}\ - \nborder rect={:?}", + \nborder rect={:?}\ + \nscrollable_overflow={:?}\ + \noverflow={:?} / {:?}\ + \nstyle={:p}", self.content_rect, self.padding_rect(), - self.border_rect() + self.border_rect(), + self.scrollable_overflow(), + self.style.get_box().overflow_x, + self.style.get_box().overflow_y, + self.style, )); for child in &self.children { @@ -208,6 +235,41 @@ impl BoxFragment { } tree.end_level(); } + + pub fn scrollable_overflow_for_parent( + &self, + containing_block: &PhysicalRect<Length>, + ) -> PhysicalRect<Length> { + let mut overflow = self + .border_rect() + .to_physical(self.style.writing_mode, containing_block); + + if self.style.get_box().overflow_y != ComputedOverflow::Visible && + self.style.get_box().overflow_x != ComputedOverflow::Visible + { + return overflow; + } + + // https://www.w3.org/TR/css-overflow-3/#scrollable + // Only include the scrollable overflow of a child box if it has overflow: visible. + let scrollable_overflow = self.scrollable_overflow(); + let bottom_right = PhysicalPoint::new( + overflow.max_x().max(scrollable_overflow.max_x()), + overflow.max_y().max(scrollable_overflow.max_y()), + ); + + if self.style.get_box().overflow_y == ComputedOverflow::Visible { + overflow.origin.y = overflow.origin.y.min(scrollable_overflow.origin.y); + overflow.size.height = bottom_right.y - overflow.origin.y; + } + + if self.style.get_box().overflow_x == ComputedOverflow::Visible { + overflow.origin.x = overflow.origin.x.min(scrollable_overflow.origin.x); + overflow.size.width = bottom_right.x - overflow.origin.x; + } + + overflow + } } impl TextFragment { diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs index f5f09f32e6e..fba2fac66dc 100644 --- a/components/style/properties/longhands/box.mako.rs +++ b/components/style/properties/longhands/box.mako.rs @@ -131,7 +131,6 @@ ${helpers.single_keyword( "Overflow", "computed::Overflow::Visible", engines="gecko servo-2013 servo-2020", - servo_2020_pref="layout.2020.unimplemented", logical_group="overflow", logical=logical, animation_value_type="discrete", diff --git a/components/style/properties/shorthands/box.mako.rs b/components/style/properties/shorthands/box.mako.rs index 351b8cec606..c5fe60834ed 100644 --- a/components/style/properties/shorthands/box.mako.rs +++ b/components/style/properties/shorthands/box.mako.rs @@ -9,7 +9,7 @@ ${helpers.two_properties_shorthand( "overflow-x", "overflow-y", "specified::Overflow::parse", - engines="gecko servo-2013", + engines="gecko servo-2013 servo-2020", flags="SHORTHAND_IN_GETCS", needs_context=False, spec="https://drafts.csswg.org/css-overflow/#propdef-overflow", diff --git a/tests/wpt/metadata-layout-2020/css/css-backgrounds/background-repeat/background-repeat-repeat-x.xht.ini b/tests/wpt/metadata-layout-2020/css/css-backgrounds/background-repeat/background-repeat-repeat-x.xht.ini deleted file mode 100644 index 717b8f77595..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-backgrounds/background-repeat/background-repeat-repeat-x.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[background-repeat-repeat-x.xht] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-backgrounds/background-repeat/background-repeat-repeat-y.xht.ini b/tests/wpt/metadata-layout-2020/css/css-backgrounds/background-repeat/background-repeat-repeat-y.xht.ini deleted file mode 100644 index 252cadf070d..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-backgrounds/background-repeat/background-repeat-repeat-y.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[background-repeat-repeat-y.xht] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-backgrounds/background-size/background-size-contain.xht.ini b/tests/wpt/metadata-layout-2020/css/css-backgrounds/background-size/background-size-contain.xht.ini deleted file mode 100644 index 9576c2c23bb..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-backgrounds/background-size/background-size-contain.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[background-size-contain.xht] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-backgrounds/background-size/background-size-cover.xht.ini b/tests/wpt/metadata-layout-2020/css/css-backgrounds/background-size/background-size-cover.xht.ini deleted file mode 100644 index c72a601887c..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-backgrounds/background-size/background-size-cover.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[background-size-cover.xht] - expected: FAIL diff --git a/tests/wpt/mozilla/meta-layout-2020/css/acid2_ref.html.ini b/tests/wpt/mozilla/meta-layout-2020/css/acid2_ref.html.ini deleted file mode 100644 index acbcb878252..00000000000 --- a/tests/wpt/mozilla/meta-layout-2020/css/acid2_ref.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[acid2_ref.html] - expected: FAIL diff --git a/tests/wpt/mozilla/meta-layout-2020/css/border_radius_clip_a.html.ini b/tests/wpt/mozilla/meta-layout-2020/css/border_radius_clip_a.html.ini deleted file mode 100644 index 833b04a6a88..00000000000 --- a/tests/wpt/mozilla/meta-layout-2020/css/border_radius_clip_a.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[border_radius_clip_a.html] - expected: FAIL diff --git a/tests/wpt/mozilla/meta-layout-2020/css/css-position-3/position-sticky-bottom.html.ini b/tests/wpt/mozilla/meta-layout-2020/css/css-position-3/position-sticky-bottom.html.ini deleted file mode 100644 index bbcf4b45799..00000000000 --- a/tests/wpt/mozilla/meta-layout-2020/css/css-position-3/position-sticky-bottom.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[position-sticky-bottom.html] - expected: FAIL diff --git a/tests/wpt/mozilla/meta-layout-2020/css/css-position-3/position-sticky-top.html.ini b/tests/wpt/mozilla/meta-layout-2020/css/css-position-3/position-sticky-top.html.ini deleted file mode 100644 index 62f8d7a2409..00000000000 --- a/tests/wpt/mozilla/meta-layout-2020/css/css-position-3/position-sticky-top.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[position-sticky-top.html] - expected: FAIL diff --git a/tests/wpt/mozilla/meta-layout-2020/css/overflow_auto.html.ini b/tests/wpt/mozilla/meta-layout-2020/css/overflow_auto.html.ini deleted file mode 100644 index 7db72e1707c..00000000000 --- a/tests/wpt/mozilla/meta-layout-2020/css/overflow_auto.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[overflow_auto.html] - expected: FAIL diff --git a/tests/wpt/mozilla/meta-layout-2020/css/overflow_position_abs_simple_a.html.ini b/tests/wpt/mozilla/meta-layout-2020/css/overflow_position_abs_simple_a.html.ini deleted file mode 100644 index 799983ed073..00000000000 --- a/tests/wpt/mozilla/meta-layout-2020/css/overflow_position_abs_simple_a.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[overflow_position_abs_simple_a.html] - expected: FAIL diff --git a/tests/wpt/mozilla/meta-layout-2020/css/overflow_scroll.html.ini b/tests/wpt/mozilla/meta-layout-2020/css/overflow_scroll.html.ini deleted file mode 100644 index 8744f4c28bd..00000000000 --- a/tests/wpt/mozilla/meta-layout-2020/css/overflow_scroll.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[overflow_scroll.html] - expected: FAIL diff --git a/tests/wpt/mozilla/meta-layout-2020/css/overflow_simple_a.html.ini b/tests/wpt/mozilla/meta-layout-2020/css/overflow_simple_a.html.ini deleted file mode 100644 index 354afc282c1..00000000000 --- a/tests/wpt/mozilla/meta-layout-2020/css/overflow_simple_a.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[overflow_simple_a.html] - expected: FAIL diff --git a/tests/wpt/mozilla/meta-layout-2020/css/overflow_xy_a.html.ini b/tests/wpt/mozilla/meta-layout-2020/css/overflow_xy_a.html.ini deleted file mode 100644 index 99413c09f58..00000000000 --- a/tests/wpt/mozilla/meta-layout-2020/css/overflow_xy_a.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[overflow_xy_a.html] - expected: FAIL diff --git a/tests/wpt/mozilla/meta-layout-2020/css/text_overflow_ellipsis.html.ini b/tests/wpt/mozilla/meta-layout-2020/css/text_overflow_ellipsis.html.ini deleted file mode 100644 index c5aa371e273..00000000000 --- a/tests/wpt/mozilla/meta-layout-2020/css/text_overflow_ellipsis.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[text_overflow_ellipsis.html] - expected: FAIL diff --git a/tests/wpt/mozilla/meta-layout-2020/css/text_overflow_string.html.ini b/tests/wpt/mozilla/meta-layout-2020/css/text_overflow_string.html.ini deleted file mode 100644 index 9baeea13322..00000000000 --- a/tests/wpt/mozilla/meta-layout-2020/css/text_overflow_string.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[text_overflow_string.html] - expected: FAIL |