diff --git a/Userland/Libraries/LibWeb/Painting/ClipFrame.cpp b/Userland/Libraries/LibWeb/Painting/ClipFrame.cpp index 09df6d0e145..ba9fae1f2c3 100644 --- a/Userland/Libraries/LibWeb/Painting/ClipFrame.cpp +++ b/Userland/Libraries/LibWeb/Painting/ClipFrame.cpp @@ -24,12 +24,12 @@ CSSPixelRect ClipFrame::clip_rect_for_hit_testing() const VERIFY(!m_clip_rects.is_empty()); auto rect = m_clip_rects[0].rect; if (m_clip_rects[0].enclosing_scroll_frame) { - rect.translate_by(m_clip_rects[0].enclosing_scroll_frame->cumulative_offset); + rect.translate_by(m_clip_rects[0].enclosing_scroll_frame->cumulative_offset()); } for (size_t i = 1; i < m_clip_rects.size(); ++i) { auto clip_rect = m_clip_rects[i].rect; if (m_clip_rects[i].enclosing_scroll_frame) { - clip_rect.translate_by(m_clip_rects[i].enclosing_scroll_frame->cumulative_offset); + clip_rect.translate_by(m_clip_rects[i].enclosing_scroll_frame->cumulative_offset()); } rect.intersect(clip_rect); } diff --git a/Userland/Libraries/LibWeb/Painting/ClippableAndScrollable.cpp b/Userland/Libraries/LibWeb/Painting/ClippableAndScrollable.cpp index 785f8514006..566da53f0f2 100644 --- a/Userland/Libraries/LibWeb/Painting/ClippableAndScrollable.cpp +++ b/Userland/Libraries/LibWeb/Painting/ClippableAndScrollable.cpp @@ -26,7 +26,7 @@ Optional ClippableAndScrollable::scroll_frame_id() const CSSPixelPoint ClippableAndScrollable::cumulative_offset_of_enclosing_scroll_frame() const { if (m_enclosing_scroll_frame) - return m_enclosing_scroll_frame->cumulative_offset; + return m_enclosing_scroll_frame->cumulative_offset(); return {}; } diff --git a/Userland/Libraries/LibWeb/Painting/ClippableAndScrollable.h b/Userland/Libraries/LibWeb/Painting/ClippableAndScrollable.h index 023a73c7a85..dbca508c403 100644 --- a/Userland/Libraries/LibWeb/Painting/ClippableAndScrollable.h +++ b/Userland/Libraries/LibWeb/Painting/ClippableAndScrollable.h @@ -23,6 +23,7 @@ public: [[nodiscard]] CSSPixelPoint cumulative_offset_of_enclosing_scroll_frame() const; [[nodiscard]] Optional clip_rect_for_hit_testing() const; + [[nodiscard]] RefPtr own_scroll_frame() const { return m_own_scroll_frame; } [[nodiscard]] Optional own_scroll_frame_id() const; [[nodiscard]] CSSPixelPoint own_scroll_frame_offset() const { diff --git a/Userland/Libraries/LibWeb/Painting/DisplayList.cpp b/Userland/Libraries/LibWeb/Painting/DisplayList.cpp index ed93a344ef1..065ff3183da 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayList.cpp +++ b/Userland/Libraries/LibWeb/Painting/DisplayList.cpp @@ -48,7 +48,7 @@ void DisplayListPlayer::execute(DisplayList& display_list) } if (scroll_frame_id.has_value()) { - auto const& scroll_offset = scroll_state[scroll_frame_id.value()]->cumulative_offset.to_type().scaled(device_pixels_per_css_pixel).to_type(); + auto const& scroll_offset = scroll_state[scroll_frame_id.value()]->cumulative_offset().to_type().scaled(device_pixels_per_css_pixel).to_type(); command.visit( [&](auto& command) { if constexpr (requires { command.translate_by(scroll_offset); }) { diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp index f68d0bf4ac4..55713b2f48a 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -1100,4 +1100,15 @@ void PaintableWithLines::resolve_paint_properties() } } +RefPtr PaintableBox::nearest_scroll_frame() const +{ + auto const* paintable = this->containing_block(); + while (paintable) { + if (paintable->own_scroll_frame()) + return paintable->own_scroll_frame(); + paintable = paintable->containing_block(); + } + return nullptr; +} + } diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.h b/Userland/Libraries/LibWeb/Painting/PaintableBox.h index bbcee6a5a6b..e854c1425f5 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.h +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.h @@ -210,6 +210,8 @@ public: virtual void resolve_paint_properties() override; + RefPtr nearest_scroll_frame() const; + protected: explicit PaintableBox(Layout::Box const&); diff --git a/Userland/Libraries/LibWeb/Painting/ScrollFrame.h b/Userland/Libraries/LibWeb/Painting/ScrollFrame.h index afdc8b3ebc8..0c639cc749f 100644 --- a/Userland/Libraries/LibWeb/Painting/ScrollFrame.h +++ b/Userland/Libraries/LibWeb/Painting/ScrollFrame.h @@ -12,8 +12,15 @@ namespace Web::Painting { struct ScrollFrame : public RefCounted { i32 id { -1 }; - CSSPixelPoint cumulative_offset; CSSPixelPoint own_offset; + RefPtr parent; + + CSSPixelPoint cumulative_offset() const + { + if (parent) + return parent->cumulative_offset() + own_offset; + return own_offset; + } }; } diff --git a/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp b/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp index ed1b4b1ed19..64473423e56 100644 --- a/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp @@ -71,6 +71,7 @@ void ViewportPaintable::assign_scroll_frames() if (paintable_box.has_scrollable_overflow() || is(paintable_box)) { auto scroll_frame = adopt_ref(*new ScrollFrame()); scroll_frame->id = next_id++; + scroll_frame->parent = paintable_box.nearest_scroll_frame(); paintable_box.set_own_scroll_frame(scroll_frame); scroll_state.set(paintable_box, move(scroll_frame)); } @@ -82,13 +83,13 @@ void ViewportPaintable::assign_scroll_frames() return TraversalDecision::Continue; } for (auto block = paintable.containing_block(); block; block = block->containing_block()) { - if (auto scroll_frame = scroll_state.get(block); scroll_frame.has_value()) { + if (auto scroll_frame = block->own_scroll_frame(); scroll_frame) { if (paintable.is_paintable_box()) { auto const& paintable_box = static_cast(paintable); - const_cast(paintable_box).set_enclosing_scroll_frame(scroll_frame.value()); + const_cast(paintable_box).set_enclosing_scroll_frame(*scroll_frame); } else if (paintable.is_inline_paintable()) { auto const& inline_paintable = static_cast(paintable); - const_cast(inline_paintable).set_enclosing_scroll_frame(scroll_frame.value()); + const_cast(inline_paintable).set_enclosing_scroll_frame(*scroll_frame); } return TraversalDecision::Continue; } @@ -162,14 +163,6 @@ void ViewportPaintable::refresh_scroll_state() for (auto& it : scroll_state) { auto const& paintable_box = *it.key; auto& scroll_frame = *it.value; - CSSPixelPoint cumulative_offset; - for (auto const* block = &paintable_box.layout_box(); block; block = block->containing_block()) { - auto const& block_paintable_box = *block->paintable_box(); - cumulative_offset.translate_by(block_paintable_box.scroll_offset()); - if (block->is_fixed_position()) - break; - } - scroll_frame.cumulative_offset = -cumulative_offset; scroll_frame.own_offset = -paintable_box.scroll_offset(); } }