diff --git a/Tests/LibWeb/Ref/reference/scroll-iframe-ref.html b/Tests/LibWeb/Ref/reference/scroll-iframe-ref.html new file mode 100644 index 0000000000..f5a10f4581 --- /dev/null +++ b/Tests/LibWeb/Ref/reference/scroll-iframe-ref.html @@ -0,0 +1,4 @@ + + +
+ diff --git a/Tests/LibWeb/Ref/scroll-iframe.html b/Tests/LibWeb/Ref/scroll-iframe.html new file mode 100644 index 0000000000..504668adc3 --- /dev/null +++ b/Tests/LibWeb/Ref/scroll-iframe.html @@ -0,0 +1,23 @@ + + + + + diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp index 366d257436..e129c24e96 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.cpp +++ b/Userland/Libraries/LibWeb/DOM/Element.cpp @@ -1711,11 +1711,10 @@ static ErrorOr scroll_an_element_into_view(DOM::Element& target, Bindings: (void)behavior; // AD-HOC: - auto& page = document.navigable()->traversable_navigable()->page(); // NOTE: Since calculated position is relative to the viewport, we need to add the viewport's position to it - // before passing to page_did_request_scroll_to() that expects a position relative to the page. + // before passing to perform_scroll_of_viewport() that expects a position relative to the page. position.set_y(position.y() + scrolling_box.y()); - page.client().page_did_request_scroll_to(position); + document.navigable()->perform_scroll_of_viewport(position); } // If scrolling box is associated with an element else { diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp index abb441e885..59f7170534 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp @@ -352,8 +352,8 @@ void BrowsingContext::scroll_to(CSSPixelPoint position) active_document()->update_layout(); } - if (this == &m_page->top_level_browsing_context()) - m_page->client().page_did_request_scroll_to(position); + if (auto navigable = active_document()->navigable()) + navigable->perform_scroll_of_viewport(position); } JS::GCPtr BrowsingContext::top_level_browsing_context() const diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.cpp b/Userland/Libraries/LibWeb/HTML/Navigable.cpp index f8b0cf3325..6671d5c92b 100644 --- a/Userland/Libraries/LibWeb/HTML/Navigable.cpp +++ b/Userland/Libraries/LibWeb/HTML/Navigable.cpp @@ -1983,6 +1983,17 @@ void Navigable::set_viewport_rect(CSSPixelRect const& rect) HTML::main_thread_event_loop().schedule(); } +void Navigable::perform_scroll_of_viewport(CSSPixelPoint position) +{ + auto viewport_rect = this->viewport_rect(); + viewport_rect.set_location(position); + set_viewport_rect(viewport_rect); + set_needs_display(); + + if (is_traversable() && active_browsing_context()) + active_browsing_context()->page().client().page_did_request_scroll_to(position); +} + void Navigable::set_size(CSSPixelSize size) { if (m_size == size) diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.h b/Userland/Libraries/LibWeb/HTML/Navigable.h index c753d7e0f7..d75c3b6de3 100644 --- a/Userland/Libraries/LibWeb/HTML/Navigable.h +++ b/Userland/Libraries/LibWeb/HTML/Navigable.h @@ -161,6 +161,7 @@ public: CSSPixelPoint viewport_scroll_offset() const { return m_viewport_scroll_offset; } CSSPixelRect viewport_rect() const { return { m_viewport_scroll_offset, m_size }; } void set_viewport_rect(CSSPixelRect const&); + void perform_scroll_of_viewport(CSSPixelPoint position); void set_needs_display(); void set_needs_display(CSSPixelRect const&); diff --git a/Userland/Libraries/LibWeb/HTML/Window.cpp b/Userland/Libraries/LibWeb/HTML/Window.cpp index 28d32a09ce..6bacf7a097 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.cpp +++ b/Userland/Libraries/LibWeb/HTML/Window.cpp @@ -1232,31 +1232,18 @@ double Window::scroll_y() const return 0; } -// https://w3c.github.io/csswg-drafts/cssom-view/#perform-a-scroll -static void perform_a_scroll(Page& page, double x, double y, JS::GCPtr element, Bindings::ScrollBehavior behavior) -{ - // FIXME: 1. Abort any ongoing smooth scroll for box. - // 2. If the user agent honors the scroll-behavior property and one of the following are true: - // - behavior is "auto" and element is not null and its computed value of the scroll-behavior property is smooth - // - behavior is smooth - // ...then perform a smooth scroll of box to position. Once the position has finished updating, emit the scrollend - // event. Otherwise, perform an instant scroll of box to position. After an instant scroll emit the scrollend event. - // FIXME: Support smooth scrolling. - (void)element; - (void)behavior; - page.client().page_did_request_scroll_to({ x, y }); -} - // https://w3c.github.io/csswg-drafts/cssom-view/#dom-window-scroll void Window::scroll(ScrollToOptions const& options) { // 4. If there is no viewport, abort these steps. - auto top_level_traversable = page().top_level_traversable(); + auto navigable = associated_document().navigable(); + if (!navigable) + return; // 1. If invoked with one argument, follow these substeps: // 1. Let options be the argument. - auto viewport_rect = top_level_traversable->viewport_rect().to_type(); + auto viewport_rect = navigable->viewport_rect().to_type(); // 2. Let x be the value of the left dictionary member of options, if present, or the viewport’s current scroll // position on the x axis otherwise. @@ -1276,7 +1263,7 @@ void Window::scroll(ScrollToOptions const& options) // 6. Let viewport height be the height of the viewport excluding the height of the scroll bar, if any. auto viewport_height = viewport_rect.height(); - auto const document = top_level_traversable->active_document(); + auto const document = navigable->active_document(); VERIFY(document); // Make sure layout is up-to-date before looking at scrollable overflow metrics. @@ -1314,8 +1301,7 @@ void Window::scroll(ScrollToOptions const& options) // 12. Perform a scroll of the viewport to position, document’s root element as the associated element, if there is // one, or null otherwise, and the scroll behavior being the value of the behavior dictionary member of options. - auto element = JS::GCPtr { document ? &document->root() : nullptr }; - perform_a_scroll(page(), x, y, element, options.behavior); + navigable->perform_scroll_of_viewport({ x, y }); } // https://w3c.github.io/csswg-drafts/cssom-view/#dom-window-scroll