diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 529a18f8f89..85df968491c 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -5582,17 +5582,7 @@ RefPtr Document::record_display_list(PaintConfig config) viewport_paintable.paint_all_phases(context); display_list->set_device_pixels_per_css_pixel(page().client().device_pixels_per_css_pixel()); - - Vector> scroll_state; - scroll_state.resize(viewport_paintable.scroll_state().scroll_frames().size() + viewport_paintable.scroll_state().sticky_frames().size()); - for (auto const& scroll_frame : viewport_paintable.scroll_state().scroll_frames()) { - scroll_state[scroll_frame->id()] = scroll_frame; - } - for (auto const& scroll_frame : viewport_paintable.scroll_state().sticky_frames()) { - scroll_state[scroll_frame->id()] = scroll_frame; - } - - display_list->set_scroll_state(move(scroll_state)); + display_list->set_scroll_state(viewport_paintable.scroll_state()); m_needs_repaint = false; diff --git a/Userland/Libraries/LibWeb/Painting/DisplayList.cpp b/Userland/Libraries/LibWeb/Painting/DisplayList.cpp index 28d980cb557..e67a66c5962 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayList.cpp +++ b/Userland/Libraries/LibWeb/Painting/DisplayList.cpp @@ -37,7 +37,7 @@ void DisplayListPlayer::execute(DisplayList& display_list) if (command.has()) { auto& paint_scroll_bar = command.get(); - auto const& scroll_offset = scroll_state[paint_scroll_bar.scroll_frame_id]->own_offset(); + auto scroll_offset = scroll_state.own_offset_for_frame_with_id(paint_scroll_bar.scroll_frame_id); if (paint_scroll_bar.vertical) { auto offset = scroll_offset.y() * paint_scroll_bar.scroll_size; paint_scroll_bar.rect.translate_by(0, -offset.to_int() * device_pixels_per_css_pixel); @@ -48,7 +48,8 @@ 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 cumulative_offset = scroll_state.cumulative_offset_for_frame_with_id(scroll_frame_id.value()); + auto scroll_offset = 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/DisplayList.h b/Userland/Libraries/LibWeb/Painting/DisplayList.h index 7bbad1f485a..ceffadbb7dd 100644 --- a/Userland/Libraries/LibWeb/Painting/DisplayList.h +++ b/Userland/Libraries/LibWeb/Painting/DisplayList.h @@ -30,6 +30,7 @@ #include #include #include +#include namespace Web::Painting { @@ -96,9 +97,8 @@ public: AK::SegmentedVector const& commands() const { return m_commands; } - void set_scroll_state(Vector> scroll_state) { m_scroll_state = move(scroll_state); } - - Vector> const& scroll_state() const { return m_scroll_state; } + void set_scroll_state(ScrollState scroll_state) { m_scroll_state = move(scroll_state); } + ScrollState const& scroll_state() const { return m_scroll_state; } void set_device_pixels_per_css_pixel(double device_pixels_per_css_pixel) { m_device_pixels_per_css_pixel = device_pixels_per_css_pixel; } double device_pixels_per_css_pixel() const { return m_device_pixels_per_css_pixel; } @@ -107,7 +107,7 @@ private: DisplayList() = default; AK::SegmentedVector m_commands; - Vector> m_scroll_state; + ScrollState m_scroll_state; double m_device_pixels_per_css_pixel; }; diff --git a/Userland/Libraries/LibWeb/Painting/ScrollFrame.cpp b/Userland/Libraries/LibWeb/Painting/ScrollFrame.cpp index cbb91258689..06f2fd58ccb 100644 --- a/Userland/Libraries/LibWeb/Painting/ScrollFrame.cpp +++ b/Userland/Libraries/LibWeb/Painting/ScrollFrame.cpp @@ -9,9 +9,10 @@ namespace Web::Painting { -ScrollFrame::ScrollFrame(PaintableBox const& paintable_box, size_t id, RefPtr parent) +ScrollFrame::ScrollFrame(PaintableBox const& paintable_box, size_t id, bool sticky, RefPtr parent) : m_paintable_box(paintable_box) , m_id(id) + , m_sticky(sticky) , m_parent(move(parent)) { } diff --git a/Userland/Libraries/LibWeb/Painting/ScrollFrame.h b/Userland/Libraries/LibWeb/Painting/ScrollFrame.h index 3ab7a02196e..f5c0c9ac408 100644 --- a/Userland/Libraries/LibWeb/Painting/ScrollFrame.h +++ b/Userland/Libraries/LibWeb/Painting/ScrollFrame.h @@ -13,12 +13,14 @@ namespace Web::Painting { class ScrollFrame : public RefCounted { public: - ScrollFrame(PaintableBox const& paintable_box, size_t id, RefPtr parent); + ScrollFrame(PaintableBox const& paintable_box, size_t id, bool sticky, RefPtr parent); PaintableBox const& paintable_box() const { return *m_paintable_box; } size_t id() const { return m_id; } + bool is_sticky() const { return m_sticky; } + CSSPixelPoint cumulative_offset() const { if (!m_cached_cumulative_offset.has_value()) { @@ -40,6 +42,7 @@ public: private: WeakPtr m_paintable_box; size_t m_id { 0 }; + bool m_sticky { false }; RefPtr m_parent; CSSPixelPoint m_own_offset; diff --git a/Userland/Libraries/LibWeb/Painting/ScrollState.h b/Userland/Libraries/LibWeb/Painting/ScrollState.h index a124ab2a82e..ddadbc550a0 100644 --- a/Userland/Libraries/LibWeb/Painting/ScrollState.h +++ b/Userland/Libraries/LibWeb/Painting/ScrollState.h @@ -12,32 +12,52 @@ namespace Web::Painting { class ScrollState { public: - NonnullRefPtr create_scroll_frame_for(PaintableBox const& paintable, RefPtr parent) + NonnullRefPtr create_scroll_frame_for(PaintableBox const& paintable_box, RefPtr parent) { - auto scroll_frame = adopt_ref(*new ScrollFrame(paintable, m_next_id++, parent)); + auto scroll_frame = adopt_ref(*new ScrollFrame(paintable_box, m_scroll_frames.size(), false, move(parent))); m_scroll_frames.append(scroll_frame); return scroll_frame; } - NonnullRefPtr create_sticky_frame_for(PaintableBox const& paintable, RefPtr parent) + NonnullRefPtr create_sticky_frame_for(PaintableBox const& paintable_box, RefPtr parent) { - auto scroll_frame = adopt_ref(*new ScrollFrame(paintable, m_next_id++, parent)); - m_sticky_frames.append(scroll_frame); + auto scroll_frame = adopt_ref(*new ScrollFrame(paintable_box, m_scroll_frames.size(), true, move(parent))); + m_scroll_frames.append(scroll_frame); return scroll_frame; } - void clear() + CSSPixelPoint cumulative_offset_for_frame_with_id(size_t id) const { - m_scroll_frames.clear(); + return m_scroll_frames[id]->cumulative_offset(); } - Vector> const& scroll_frames() const { return m_scroll_frames; } - Vector> const& sticky_frames() const { return m_sticky_frames; } + CSSPixelPoint own_offset_for_frame_with_id(size_t id) const + { + return m_scroll_frames[id]->own_offset(); + } + + template + void for_each_scroll_frame(Callback callback) const + { + for (auto const& scroll_frame : m_scroll_frames) { + if (scroll_frame->is_sticky()) + continue; + callback(scroll_frame); + } + } + + template + void for_each_sticky_frame(Callback callback) const + { + for (auto const& scroll_frame : m_scroll_frames) { + if (!scroll_frame->is_sticky()) + continue; + callback(scroll_frame); + } + } private: - size_t m_next_id { 0 }; Vector> m_scroll_frames; - Vector> m_sticky_frames; }; } diff --git a/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp b/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp index 8fe4fe91a06..26d658ed1ab 100644 --- a/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp @@ -179,13 +179,13 @@ void ViewportPaintable::refresh_scroll_state() return; m_needs_to_refresh_scroll_state = false; - for (auto const& scroll_frame : m_scroll_state.sticky_frames()) { + m_scroll_state.for_each_sticky_frame([&](auto& scroll_frame) { auto const& sticky_box = scroll_frame->paintable_box(); auto const& sticky_insets = sticky_box.sticky_insets(); auto const* nearest_scrollable_ancestor = sticky_box.nearest_scrollable_ancestor(); if (!nearest_scrollable_ancestor) { - continue; + return; } // Min and max offsets are needed to clamp the sticky box's position to stay within bounds of containing block. @@ -250,11 +250,11 @@ void ViewportPaintable::refresh_scroll_state() } scroll_frame->set_own_offset(sticky_offset); - } + }); - for (auto const& scroll_frame : m_scroll_state.scroll_frames()) { + m_scroll_state.for_each_scroll_frame([&](auto& scroll_frame) { scroll_frame->set_own_offset(-scroll_frame->paintable_box().scroll_offset()); - } + }); } void ViewportPaintable::resolve_paint_only_properties()