mirror of
https://github.com/servo/servo.git
synced 2025-08-08 06:55:31 +01:00
Include the scrollable overflow of a child box if either its parent or child has overflow: visible
(#38443)
Include the scrollable overflow of a child box if either its parent or child has `overflow: visible` **Issue**: For the blocks having property `overflow:hidden`, their scroll overflow is not added to parent's scroll overflow. Causing unable to scroll the parent block aka `Root` block in our Issue #38248 . **Testing**: css/cssom-view/scrolling-quirks-vs-nonquirks.html **Fixes**: #38248 Signed-off-by: Shubham Gupta <shubham13297@gmail.com>
This commit is contained in:
parent
5b148cf5de
commit
dcb90bb85e
5 changed files with 51 additions and 55 deletions
|
@ -24,7 +24,7 @@ use crate::formatting_contexts::Baselines;
|
|||
use crate::geom::{
|
||||
AuOrAuto, LengthPercentageOrAuto, PhysicalPoint, PhysicalRect, PhysicalSides, ToLogical,
|
||||
};
|
||||
use crate::style_ext::ComputedValuesExt;
|
||||
use crate::style_ext::{AxesOverflow, ComputedValuesExt};
|
||||
use crate::table::SpecificTableGridInfo;
|
||||
use crate::taffy::SpecificTaffyGridInfo;
|
||||
|
||||
|
@ -271,12 +271,13 @@ impl BoxFragment {
|
|||
// overflow together, but from the specification it seems that if the border
|
||||
// box of an item is in the "wholly unreachable scrollable overflow region", but
|
||||
// its scrollable overflow is not, it should also be excluded.
|
||||
let overflow_style = self.style.effective_overflow(self.base.flags);
|
||||
let scrollable_overflow = self
|
||||
.children
|
||||
.iter()
|
||||
.fold(physical_padding_rect, |acc, child| {
|
||||
let scrollable_overflow_from_child = child
|
||||
.calculate_scrollable_overflow_for_parent()
|
||||
.calculate_scrollable_overflow_for_parent(Some(overflow_style))
|
||||
.translate(content_origin);
|
||||
|
||||
// Note that this doesn't just exclude scrollable overflow outside the
|
||||
|
@ -359,27 +360,33 @@ impl BoxFragment {
|
|||
tree.end_level();
|
||||
}
|
||||
|
||||
pub(crate) fn scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> {
|
||||
pub(crate) fn scrollable_overflow_for_parent(
|
||||
&self,
|
||||
parent_overflow_style: Option<AxesOverflow>,
|
||||
) -> PhysicalRect<Au> {
|
||||
let mut overflow = self.border_rect();
|
||||
if !self.style.establishes_scroll_container(self.base.flags) {
|
||||
// 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()),
|
||||
);
|
||||
let overflow_style = self.style.effective_overflow(self.base.flags);
|
||||
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()),
|
||||
);
|
||||
|
||||
let overflow_style = self.style.effective_overflow(self.base.flags);
|
||||
if overflow_style.y == ComputedOverflow::Visible {
|
||||
overflow.origin.y = overflow.origin.y.min(scrollable_overflow.origin.y);
|
||||
overflow.size.height = bottom_right.y - overflow.origin.y;
|
||||
}
|
||||
// https://www.w3.org/TR/css-overflow-3/#scrollable
|
||||
// For each axis, we only include the scrollable overflow of a child box
|
||||
// if either its parent or child has overflow: visible.
|
||||
if parent_overflow_style.is_some_and(|style| style.y == ComputedOverflow::Visible) ||
|
||||
overflow_style.y == ComputedOverflow::Visible
|
||||
{
|
||||
overflow.origin.y = overflow.origin.y.min(scrollable_overflow.origin.y);
|
||||
overflow.size.height = bottom_right.y - overflow.origin.y;
|
||||
}
|
||||
|
||||
if overflow_style.x == ComputedOverflow::Visible {
|
||||
overflow.origin.x = overflow.origin.x.min(scrollable_overflow.origin.x);
|
||||
overflow.size.width = bottom_right.x - overflow.origin.x;
|
||||
}
|
||||
if parent_overflow_style.is_some_and(|style| style.x == ComputedOverflow::Visible) ||
|
||||
overflow_style.x == ComputedOverflow::Visible
|
||||
{
|
||||
overflow.origin.x = overflow.origin.x.min(scrollable_overflow.origin.x);
|
||||
overflow.size.width = bottom_right.x - overflow.origin.x;
|
||||
}
|
||||
|
||||
if !self
|
||||
|
|
|
@ -23,7 +23,7 @@ use super::{
|
|||
use crate::cell::ArcRefCell;
|
||||
use crate::flow::inline::SharedInlineStyles;
|
||||
use crate::geom::{LogicalSides, PhysicalPoint, PhysicalRect};
|
||||
use crate::style_ext::ComputedValuesExt;
|
||||
use crate::style_ext::{AxesOverflow, ComputedValuesExt};
|
||||
|
||||
#[derive(Clone, MallocSizeOf)]
|
||||
pub(crate) enum Fragment {
|
||||
|
@ -168,14 +168,19 @@ impl Fragment {
|
|||
let fragment = fragment.borrow();
|
||||
fragment.offset_by_containing_block(&fragment.scrollable_overflow())
|
||||
},
|
||||
_ => self.scrollable_overflow_for_parent(),
|
||||
_ => self.scrollable_overflow_for_parent(None),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> {
|
||||
pub(crate) fn scrollable_overflow_for_parent(
|
||||
&self,
|
||||
parent_overflow_style: Option<AxesOverflow>,
|
||||
) -> PhysicalRect<Au> {
|
||||
match self {
|
||||
Fragment::Box(fragment) | Fragment::Float(fragment) => {
|
||||
return fragment.borrow().scrollable_overflow_for_parent();
|
||||
return fragment
|
||||
.borrow()
|
||||
.scrollable_overflow_for_parent(parent_overflow_style);
|
||||
},
|
||||
Fragment::AbsoluteOrFixedPositioned(_) => PhysicalRect::zero(),
|
||||
Fragment::Positioning(fragment) => fragment.borrow().scrollable_overflow_for_parent(),
|
||||
|
@ -185,9 +190,12 @@ impl Fragment {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn calculate_scrollable_overflow_for_parent(&self) -> PhysicalRect<Au> {
|
||||
pub(crate) fn calculate_scrollable_overflow_for_parent(
|
||||
&self,
|
||||
parent_overflow_style: Option<AxesOverflow>,
|
||||
) -> PhysicalRect<Au> {
|
||||
self.calculate_scrollable_overflow();
|
||||
self.scrollable_overflow_for_parent()
|
||||
self.scrollable_overflow_for_parent(parent_overflow_style)
|
||||
}
|
||||
|
||||
pub(crate) fn calculate_scrollable_overflow(&self) {
|
||||
|
|
|
@ -15,6 +15,7 @@ use super::{BoxFragment, ContainingBlockManager, Fragment};
|
|||
use crate::ArcRefCell;
|
||||
use crate::context::LayoutContext;
|
||||
use crate::geom::PhysicalRect;
|
||||
use crate::style_ext::ComputedValuesExt;
|
||||
|
||||
#[derive(MallocSizeOf)]
|
||||
pub struct FragmentTree {
|
||||
|
@ -117,8 +118,15 @@ impl FragmentTree {
|
|||
let scrollable_overflow = self.root_fragments.iter().fold(
|
||||
self.initial_containing_block,
|
||||
|overflow, fragment| {
|
||||
let overflow_style = match fragment {
|
||||
Fragment::Box(fragment) | Fragment::Float(fragment) => {
|
||||
let fragment_flags = fragment.borrow().base.flags;
|
||||
Some(fragment.borrow().style.effective_overflow(fragment_flags))
|
||||
},
|
||||
_ => None,
|
||||
};
|
||||
fragment
|
||||
.calculate_scrollable_overflow_for_parent()
|
||||
.calculate_scrollable_overflow_for_parent(overflow_style)
|
||||
.union(&overflow)
|
||||
},
|
||||
);
|
||||
|
|
|
@ -79,7 +79,7 @@ impl PositioningFragment {
|
|||
|acc, child| {
|
||||
acc.union(
|
||||
&child
|
||||
.calculate_scrollable_overflow_for_parent()
|
||||
.calculate_scrollable_overflow_for_parent(None)
|
||||
.translate(self.rect.origin.to_vector()),
|
||||
)
|
||||
},
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
[scrolling-quirks-vs-nonquirks.html]
|
||||
[scrollWidth/scrollHeight on the root element in non-quirks mode]
|
||||
expected: FAIL
|
||||
|
||||
[scrollWidth/scrollHeight on the root element in quirks mode]
|
||||
expected: FAIL
|
||||
|
||||
[scrollWidth/scrollHeight on the HTML body element in quirks mode]
|
||||
expected: FAIL
|
||||
|
||||
[scroll() on the root element in non-quirks mode]
|
||||
expected: FAIL
|
||||
|
||||
[scrollBy() on the root element in non-quirks mode]
|
||||
expected: FAIL
|
||||
|
||||
[scrollLeft/scrollTop on the root element in non-quirks mode]
|
||||
expected: FAIL
|
||||
|
||||
[scroll() on the HTML body element in quirks mode]
|
||||
expected: FAIL
|
||||
|
||||
[scrollBy() on the HTML body element in quirks mode]
|
||||
expected: FAIL
|
||||
|
||||
[scrollLeft/scrollTop on the HTML body element in quirks mode]
|
||||
expected: FAIL
|
Loading…
Add table
Add a link
Reference in a new issue