diff --git a/Userland/Libraries/LibWeb/DOM/Element.h b/Userland/Libraries/LibWeb/DOM/Element.h index 918bca0630..3ba4f6d05e 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.h +++ b/Userland/Libraries/LibWeb/DOM/Element.h @@ -314,6 +314,14 @@ public: void unregister_intersection_observer(Badge, JS::NonnullGCPtr); IntersectionObserver::IntersectionObserverRegistration& get_intersection_observer_registration(Badge, IntersectionObserver::IntersectionObserver const&); + enum class ScrollOffsetFor { + Self, + PseudoBefore, + PseudoAfter + }; + CSSPixelPoint scroll_offset(ScrollOffsetFor type) const { return m_scroll_offset[to_underlying(type)]; } + void set_scroll_offset(ScrollOffsetFor type, CSSPixelPoint offset) { m_scroll_offset[to_underlying(type)] = offset; } + protected: Element(Document&, DOM::QualifiedName); virtual JS::ThrowCompletionOr initialize(JS::Realm&) override; @@ -367,6 +375,8 @@ private: // https://www.w3.org/TR/intersection-observer/#dom-element-registeredintersectionobservers-slot // Element objects have an internal [[RegisteredIntersectionObservers]] slot, which is initialized to an empty list. Vector m_registered_intersection_observers; + + Array m_scroll_offset; }; template<> diff --git a/Userland/Libraries/LibWeb/Layout/Box.cpp b/Userland/Libraries/LibWeb/Layout/Box.cpp index 31a7d6e8e9..11c3044fc2 100644 --- a/Userland/Libraries/LibWeb/Layout/Box.cpp +++ b/Userland/Libraries/LibWeb/Layout/Box.cpp @@ -61,12 +61,35 @@ bool Box::is_scrollable() const return computed_values().overflow_y() == CSS::Overflow::Scroll; } +CSSPixelPoint Box::scroll_offset() const +{ + if (is_generated_for_before_pseudo_element()) + return pseudo_element_generator()->scroll_offset(DOM::Element::ScrollOffsetFor::PseudoBefore); + if (is_generated_for_after_pseudo_element()) + return pseudo_element_generator()->scroll_offset(DOM::Element::ScrollOffsetFor::PseudoAfter); + + if (!is(*dom_node())) + return {}; + + return static_cast(dom_node())->scroll_offset(DOM::Element::ScrollOffsetFor::Self); +} + void Box::set_scroll_offset(CSSPixelPoint offset) { // FIXME: If there is horizontal and vertical scroll ignore only part of the new offset - if (offset.y() < 0 || m_scroll_offset == offset) + if (offset.y() < 0 || scroll_offset() == offset) return; - m_scroll_offset = offset; + + if (is_generated_for_before_pseudo_element()) { + pseudo_element_generator()->set_scroll_offset(DOM::Element::ScrollOffsetFor::PseudoBefore, offset); + } else if (is_generated_for_after_pseudo_element()) { + pseudo_element_generator()->set_scroll_offset(DOM::Element::ScrollOffsetFor::PseudoAfter, offset); + } else if (is(*dom_node())) { + static_cast(dom_node())->set_scroll_offset(DOM::Element::ScrollOffsetFor::Self, offset); + } else { + return; + } + set_needs_display(); } diff --git a/Userland/Libraries/LibWeb/Layout/Box.h b/Userland/Libraries/LibWeb/Layout/Box.h index 13bc82443e..c54c551bc3 100644 --- a/Userland/Libraries/LibWeb/Layout/Box.h +++ b/Userland/Libraries/LibWeb/Layout/Box.h @@ -54,7 +54,7 @@ public: bool is_scroll_container() const; bool is_scrollable() const; - CSSPixelPoint scroll_offset() const { return m_scroll_offset; } + CSSPixelPoint scroll_offset() const; void set_scroll_offset(CSSPixelPoint); protected: @@ -64,8 +64,6 @@ protected: private: virtual bool is_box() const final { return true; } - CSSPixelPoint m_scroll_offset; - Optional m_natural_width; Optional m_natural_height; Optional m_natural_aspect_ratio;