From dd7bba66ed40048d548dc4c0517c57bd9c25618e Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Tue, 22 Aug 2023 16:00:42 +0200 Subject: [PATCH] LibWeb: Change viewport ownership from `BrowsingContext` to `Navigable` --- Userland/Libraries/LibWeb/CSS/Length.cpp | 4 +- .../Libraries/LibWeb/CSS/StyleComputer.cpp | 4 +- .../CSS/StyleValues/ImageStyleValue.cpp | 4 +- .../Libraries/LibWeb/CSS/VisualViewport.cpp | 16 +-- Userland/Libraries/LibWeb/DOM/Document.cpp | 9 +- Userland/Libraries/LibWeb/DOM/Element.cpp | 16 +-- .../Libraries/LibWeb/HTML/BrowsingContext.cpp | 70 +----------- .../Libraries/LibWeb/HTML/BrowsingContext.h | 10 -- Userland/Libraries/LibWeb/HTML/Navigable.cpp | 108 ++++++++++++++++++ Userland/Libraries/LibWeb/HTML/Navigable.h | 20 ++++ Userland/Libraries/LibWeb/HTML/Window.cpp | 19 +-- .../IntersectionObserver.cpp | 6 +- Userland/Libraries/LibWeb/Layout/Box.cpp | 5 +- Userland/Libraries/LibWeb/Layout/FrameBox.cpp | 4 +- Userland/Libraries/LibWeb/Layout/Node.cpp | 8 +- Userland/Libraries/LibWeb/Layout/Node.h | 2 + .../Libraries/LibWeb/Page/EventHandler.cpp | 6 +- .../LibWeb/Painting/BackgroundPainting.cpp | 2 +- .../NestedBrowsingContextPaintable.cpp | 2 +- .../LibWeb/Painting/StackingContext.cpp | 2 +- .../Libraries/LibWeb/WebDriver/Screenshot.cpp | 3 +- .../WebContent/ConnectionFromClient.cpp | 2 +- Userland/Services/WebContent/PageHost.cpp | 3 +- 23 files changed, 196 insertions(+), 129 deletions(-) diff --git a/Userland/Libraries/LibWeb/CSS/Length.cpp b/Userland/Libraries/LibWeb/CSS/Length.cpp index 2f641860a1..fc5f0bf681 100644 --- a/Userland/Libraries/LibWeb/CSS/Length.cpp +++ b/Userland/Libraries/LibWeb/CSS/Length.cpp @@ -137,7 +137,7 @@ Length::ResolutionContext Length::ResolutionContext::for_layout_node(Layout::Nod VERIFY(root_element); VERIFY(root_element->layout_node()); return Length::ResolutionContext { - .viewport_rect = node.browsing_context().viewport_rect(), + .viewport_rect = node.navigable()->viewport_rect(), .font_metrics = { node.computed_values().font_size(), node.font().pixel_metrics(), node.line_height() }, .root_font_metrics = { root_element->layout_node()->computed_values().font_size(), root_element->layout_node()->font().pixel_metrics(), root_element->layout_node()->line_height() }, }; @@ -182,7 +182,7 @@ CSSPixels Length::to_px(Layout::Node const& layout_node) const } VERIFY(is_viewport_relative()); - auto const& viewport_rect = layout_node.document().browsing_context()->viewport_rect(); + auto const& viewport_rect = layout_node.document().viewport_rect(); return viewport_relative_length_to_px(viewport_rect); } diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index d6354134a5..301a1f320e 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -2617,8 +2617,8 @@ void StyleComputer::invalidate_rule_cache() CSSPixelRect StyleComputer::viewport_rect() const { - if (auto const* browsing_context = document().browsing_context()) - return browsing_context->viewport_rect(); + if (auto const navigable = document().navigable()) + return navigable->viewport_rect(); return {}; } diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp index 03cb270c42..95fed74e47 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/ImageStyleValue.cpp @@ -41,8 +41,8 @@ void ImageStyleValue::load_any_resources(DOM::Document& document) return; // FIXME: Do less than a full repaint if possible? - if (auto* browsing_context = m_document->browsing_context()) - browsing_context->set_needs_display(); + if (auto navigable = m_document->navigable()) + navigable->set_needs_display(); auto image_data = m_image_request->image_data(); if (image_data->is_animated() && image_data->frame_count() > 1) { diff --git a/Userland/Libraries/LibWeb/CSS/VisualViewport.cpp b/Userland/Libraries/LibWeb/CSS/VisualViewport.cpp index 0afa19e727..7089f4055c 100644 --- a/Userland/Libraries/LibWeb/CSS/VisualViewport.cpp +++ b/Userland/Libraries/LibWeb/CSS/VisualViewport.cpp @@ -46,8 +46,8 @@ double VisualViewport::offset_left() const return 0; // 2. Otherwise, return the offset of the left edge of the visual viewport from the left edge of the layout viewport. - VERIFY(m_document->browsing_context()); - return m_document->browsing_context()->viewport_rect().left().to_double(); + VERIFY(m_document->navigable()); + return m_document->viewport_rect().left().to_double(); } // https://drafts.csswg.org/cssom-view/#dom-visualviewport-offsettop @@ -58,8 +58,8 @@ double VisualViewport::offset_top() const return 0; // 2. Otherwise, return the offset of the top edge of the visual viewport from the top edge of the layout viewport. - VERIFY(m_document->browsing_context()); - return m_document->browsing_context()->viewport_rect().top().to_double(); + VERIFY(m_document->navigable()); + return m_document->viewport_rect().top().to_double(); } // https://drafts.csswg.org/cssom-view/#dom-visualviewport-pageleft @@ -95,8 +95,8 @@ double VisualViewport::width() const // 2. Otherwise, return the width of the visual viewport // FIXME: excluding the width of any rendered vertical classic scrollbar that is fixed to the visual viewport. - VERIFY(m_document->browsing_context()); - return m_document->browsing_context()->viewport_rect().width().to_double(); + VERIFY(m_document->navigable()); + return m_document->viewport_rect().width().to_double(); } // https://drafts.csswg.org/cssom-view/#dom-visualviewport-height @@ -108,8 +108,8 @@ double VisualViewport::height() const // 2. Otherwise, return the height of the visual viewport // FIXME: excluding the height of any rendered vertical classic scrollbar that is fixed to the visual viewport. - VERIFY(m_document->browsing_context()); - return m_document->browsing_context()->viewport_rect().height().to_double(); + VERIFY(m_document->navigable()); + return m_document->viewport_rect().height().to_double(); } // https://drafts.csswg.org/cssom-view/#dom-visualviewport-scale diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 1baabaab6f..1e3b5721f7 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -962,7 +962,7 @@ void Document::update_layout() if (m_created_for_appropriate_template_contents) return; - if (!browsing_context()) + if (!navigable()) return; auto viewport_rect = this->viewport_rect(); @@ -1005,7 +1005,8 @@ void Document::update_layout() // Broadcast the current viewport rect to any new paintables, so they know whether they're visible or not. inform_all_viewport_clients_about_the_current_viewport_rect(); - browsing_context()->set_needs_display(); + if (navigable()) + navigable()->set_needs_display(); if (navigable()->is_traversable()) { if (auto* page = this->page()) @@ -3034,8 +3035,8 @@ HTML::ListOfAvailableImages const& Document::list_of_available_images() const CSSPixelRect Document::viewport_rect() const { - if (auto* browsing_context = this->browsing_context()) - return browsing_context->viewport_rect(); + if (auto const navigable = this->navigable()) + return navigable->viewport_rect(); return CSSPixelRect {}; } diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp index 40c23d3c1e..6442a667f5 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.cpp +++ b/Userland/Libraries/LibWeb/DOM/Element.cpp @@ -833,8 +833,8 @@ JS::NonnullGCPtr Element::get_bounding_client_rect() const if (!paintable_box) return Geometry::DOMRect::construct_impl(realm(), 0, 0, 0, 0).release_value_but_fixme_should_propagate_errors(); - VERIFY(document().browsing_context()); - auto viewport_offset = document().browsing_context()->viewport_scroll_offset(); + VERIFY(document().navigable()); + auto viewport_offset = document().navigable()->viewport_scroll_offset(); return Geometry::DOMRect::create(realm(), paintable_box->absolute_rect().translated(-viewport_offset.x(), -viewport_offset.y()).to_type()); } @@ -907,7 +907,7 @@ int Element::client_width() const // return the viewport width excluding the size of a rendered scroll bar (if any). if ((is(*this) && !document().in_quirks_mode()) || (is(*this) && document().in_quirks_mode())) { - return document().browsing_context()->viewport_rect().width().to_int(); + return document().viewport_rect().width().to_int(); } // NOTE: Ensure that layout is up-to-date before looking at metrics. @@ -932,7 +932,7 @@ int Element::client_height() const // return the viewport height excluding the size of a rendered scroll bar (if any). if ((is(*this) && !document().in_quirks_mode()) || (is(*this) && document().in_quirks_mode())) { - return document().browsing_context()->viewport_rect().height().to_int(); + return document().viewport_rect().height().to_int(); } // NOTE: Ensure that layout is up-to-date before looking at metrics. @@ -1262,8 +1262,8 @@ int Element::scroll_width() const // 3. Let viewport width be the width of the viewport excluding the width of the scroll bar, if any, // or zero if there is no viewport. - auto viewport_width = document.browsing_context()->viewport_rect().width().to_int(); - auto viewport_scroll_width = document.browsing_context()->size().width().to_int(); + auto viewport_width = document.viewport_rect().width().to_int(); + auto viewport_scroll_width = document.navigable()->size().width().to_int(); // 4. If the element is the root element and document is not in quirks mode // return max(viewport scrolling area width, viewport width). @@ -1295,8 +1295,8 @@ int Element::scroll_height() const // 3. Let viewport height be the height of the viewport excluding the height of the scroll bar, if any, // or zero if there is no viewport. - auto viewport_height = document.browsing_context()->viewport_rect().height().to_int(); - auto viewport_scroll_height = document.browsing_context()->size().height().to_int(); + auto viewport_height = document.viewport_rect().height().to_int(); + auto viewport_scroll_height = document.navigable()->size().height().to_int(); // 4. If the element is the root element and document is not in quirks mode // return max(viewport scrolling area height, viewport height). diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp index bb0f90bd82..5d40a46a92 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.cpp @@ -540,73 +540,6 @@ void BrowsingContext::set_active_document(JS::NonnullGCPtr docume previously_active_document->did_stop_being_active_document_in_browsing_context({}); } -void BrowsingContext::set_viewport_rect(CSSPixelRect const& rect) -{ - bool did_change = false; - - if (m_size != rect.size()) { - m_size = rect.size(); - if (auto* document = active_document()) { - // NOTE: Resizing the viewport changes the reference value for viewport-relative CSS lengths. - document->invalidate_style(); - document->set_needs_layout(); - } - did_change = true; - } - - if (m_viewport_scroll_offset != rect.location()) { - m_viewport_scroll_offset = rect.location(); - scroll_offset_did_change(); - did_change = true; - } - - if (did_change && active_document()) { - active_document()->inform_all_viewport_clients_about_the_current_viewport_rect(); - } - - // Schedule the HTML event loop to ensure that a `resize` event gets fired. - HTML::main_thread_event_loop().schedule(); -} - -void BrowsingContext::set_size(CSSPixelSize size) -{ - if (m_size == size) - return; - m_size = size; - - if (auto* document = active_document()) { - document->invalidate_style(); - document->set_needs_layout(); - } - - if (auto* document = active_document()) { - document->inform_all_viewport_clients_about_the_current_viewport_rect(); - } - - // Schedule the HTML event loop to ensure that a `resize` event gets fired. - HTML::main_thread_event_loop().schedule(); -} - -void BrowsingContext::set_needs_display() -{ - set_needs_display(viewport_rect()); -} - -void BrowsingContext::set_needs_display(CSSPixelRect const& rect) -{ - if (!viewport_rect().intersects(rect)) - return; - - if (is_top_level()) { - if (m_page) - m_page->client().page_did_invalidate(to_top_level_rect(rect)); - return; - } - - if (container() && container()->layout_node()) - container()->layout_node()->set_needs_display(); -} - void BrowsingContext::scroll_to(CSSPixelPoint position) { // NOTE: Scrolling to a position requires up-to-date layout *unless* we're scrolling to (0, 0) @@ -647,7 +580,8 @@ void BrowsingContext::scroll_to_anchor(DeprecatedString const& fragment) auto& layout_node = *element->layout_node(); - CSSPixelRect target_rect { layout_node.box_type_agnostic_position(), { viewport_rect().width(), viewport_rect().height() } }; + auto const viewport_rect = document->viewport_rect(); + CSSPixelRect target_rect { layout_node.box_type_agnostic_position(), { viewport_rect.width(), viewport_rect.height() } }; if (is(layout_node)) { auto& layout_box = verify_cast(layout_node); auto padding_box = layout_box.box_model().padding_box(); diff --git a/Userland/Libraries/LibWeb/HTML/BrowsingContext.h b/Userland/Libraries/LibWeb/HTML/BrowsingContext.h index 485ba9ccd9..0e9ebe7a79 100644 --- a/Userland/Libraries/LibWeb/HTML/BrowsingContext.h +++ b/Userland/Libraries/LibWeb/HTML/BrowsingContext.h @@ -138,16 +138,6 @@ public: Page* page() { return m_page; } Page const* page() const { return m_page; } - CSSPixelSize size() const { return m_size; } - void set_size(CSSPixelSize); - - void set_needs_display(); - void set_needs_display(CSSPixelRect const&); - - 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&); - FrameLoader& loader() { return m_loader; } FrameLoader const& loader() const { return m_loader; } diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.cpp b/Userland/Libraries/LibWeb/HTML/Navigable.cpp index 03380af2a9..59bec56476 100644 --- a/Userland/Libraries/LibWeb/HTML/Navigable.cpp +++ b/Userland/Libraries/LibWeb/HTML/Navigable.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -1548,4 +1549,111 @@ void perform_url_and_history_update_steps(DOM::Document& document, AK::URL new_u }); } +void Navigable::scroll_offset_did_change() +{ + // https://w3c.github.io/csswg-drafts/cssom-view-1/#scrolling-events + // Whenever a viewport gets scrolled (whether in response to user interaction or by an API), the user agent must run these steps: + + // 1. Let doc be the viewport’s associated Document. + auto doc = active_document(); + VERIFY(doc); + + // 2. If doc is already in doc’s pending scroll event targets, abort these steps. + for (auto& target : doc->pending_scroll_event_targets()) { + if (target.ptr() == doc) + return; + } + + // 3. Append doc to doc’s pending scroll event targets. + doc->pending_scroll_event_targets().append(*doc); +} + +CSSPixelRect Navigable::to_top_level_rect(CSSPixelRect const& a_rect) +{ + auto rect = a_rect; + rect.set_location(to_top_level_position(a_rect.location())); + return rect; +} + +CSSPixelPoint Navigable::to_top_level_position(CSSPixelPoint a_position) +{ + auto position = a_position; + for (auto ancestor = parent(); ancestor; ancestor = ancestor->parent()) { + if (is(*ancestor)) + break; + if (!ancestor->container()) + return {}; + if (!ancestor->container()->layout_node()) + return {}; + position.translate_by(ancestor->container()->layout_node()->box_type_agnostic_position()); + } + return position; +} + +void Navigable::set_viewport_rect(CSSPixelRect const& rect) +{ + bool did_change = false; + + if (m_size != rect.size()) { + m_size = rect.size(); + if (auto document = active_document()) { + // NOTE: Resizing the viewport changes the reference value for viewport-relative CSS lengths. + document->invalidate_style(); + document->set_needs_layout(); + } + did_change = true; + } + + if (m_viewport_scroll_offset != rect.location()) { + m_viewport_scroll_offset = rect.location(); + scroll_offset_did_change(); + did_change = true; + } + + if (did_change && active_document()) { + active_document()->inform_all_viewport_clients_about_the_current_viewport_rect(); + } + + // Schedule the HTML event loop to ensure that a `resize` event gets fired. + HTML::main_thread_event_loop().schedule(); +} + +void Navigable::set_size(CSSPixelSize size) +{ + if (m_size == size) + return; + m_size = size; + + if (auto document = active_document()) { + document->invalidate_style(); + document->set_needs_layout(); + } + + if (auto document = active_document()) { + document->inform_all_viewport_clients_about_the_current_viewport_rect(); + } + + // Schedule the HTML event loop to ensure that a `resize` event gets fired. + HTML::main_thread_event_loop().schedule(); +} + +void Navigable::set_needs_display() +{ + set_needs_display(viewport_rect()); +} + +void Navigable::set_needs_display(CSSPixelRect const& rect) +{ + if (!viewport_rect().intersects(rect)) + return; + + if (is(*this)) { + static_cast(this)->page()->client().page_did_invalidate(to_top_level_rect(rect)); + return; + } + + if (container() && container()->layout_node()) + container()->layout_node()->set_needs_display(); +} + } diff --git a/Userland/Libraries/LibWeb/HTML/Navigable.h b/Userland/Libraries/LibWeb/HTML/Navigable.h index edd549c580..4f422fa471 100644 --- a/Userland/Libraries/LibWeb/HTML/Navigable.h +++ b/Userland/Libraries/LibWeb/HTML/Navigable.h @@ -7,6 +7,7 @@ #pragma once +#include #include #include #include @@ -19,6 +20,7 @@ #include #include #include +#include #include namespace Web::HTML { @@ -134,6 +136,19 @@ public: [[nodiscard]] bool has_been_destroyed() const { return m_has_been_destroyed; } void set_has_been_destroyed() { m_has_been_destroyed = true; } + CSSPixelPoint to_top_level_position(CSSPixelPoint); + CSSPixelRect to_top_level_rect(CSSPixelRect const&); + + CSSPixelSize size() const { return m_size; } + void set_size(CSSPixelSize); + + 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 set_needs_display(); + void set_needs_display(CSSPixelRect const&); + protected: Navigable(); @@ -146,6 +161,8 @@ private: bool allowed_by_sandboxing_to_navigate(Navigable const& target, SourceSnapshotParams const&); TargetSnapshotParams snapshot_target_snapshot_params(); + void scroll_offset_did_change(); + // https://html.spec.whatwg.org/multipage/document-sequences.html#nav-id String m_id; @@ -168,6 +185,9 @@ private: JS::GCPtr m_container; bool m_has_been_destroyed { false }; + + CSSPixelSize m_size; + CSSPixelPoint m_viewport_scroll_offset; }; HashTable& all_navigables(); diff --git a/Userland/Libraries/LibWeb/HTML/Window.cpp b/Userland/Libraries/LibWeb/HTML/Window.cpp index 3c2e470a18..969dcbf324 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.cpp +++ b/Userland/Libraries/LibWeb/HTML/Window.cpp @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -1101,8 +1102,8 @@ i32 Window::inner_width() const { // The innerWidth attribute must return the viewport width including the size of a rendered scroll bar (if any), // or zero if there is no viewport. - if (auto const* browsing_context = associated_document().browsing_context()) - return browsing_context->viewport_rect().width().to_int(); + if (auto const navigable = associated_document().navigable()) + return navigable->viewport_rect().width().to_int(); return 0; } @@ -1111,8 +1112,8 @@ i32 Window::inner_height() const { // The innerHeight attribute must return the viewport height including the size of a rendered scroll bar (if any), // or zero if there is no viewport. - if (auto const* browsing_context = associated_document().browsing_context()) - return browsing_context->viewport_rect().height().to_int(); + if (auto const navigable = associated_document().navigable()) + return navigable->viewport_rect().height().to_int(); return 0; } @@ -1122,7 +1123,7 @@ double Window::scroll_x() const // The scrollX attribute must return the x-coordinate, relative to the initial containing block origin, // of the left of the viewport, or zero if there is no viewport. if (auto* page = this->page()) - return page->top_level_browsing_context().viewport_scroll_offset().x().to_double(); + return page->top_level_traversable()->viewport_scroll_offset().x().to_double(); return 0; } @@ -1132,7 +1133,7 @@ double Window::scroll_y() const // The scrollY attribute must return the y-coordinate, relative to the initial containing block origin, // of the top of the viewport, or zero if there is no viewport. if (auto* page = this->page()) - return page->top_level_browsing_context().viewport_scroll_offset().y().to_double(); + return page->top_level_traversable()->viewport_scroll_offset().y().to_double(); return 0; } @@ -1158,12 +1159,12 @@ void Window::scroll(ScrollToOptions const& options) auto* page = this->page(); if (!page) return; - auto const& top_level_browsing_context = page->top_level_browsing_context(); + auto top_level_traversable = page->top_level_traversable(); // 1. If invoked with one argument, follow these substeps: // 1. Let options be the argument. - auto viewport_rect = top_level_browsing_context.viewport_rect().to_type(); + auto viewport_rect = top_level_traversable->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. @@ -1206,7 +1207,7 @@ void Window::scroll(ScrollToOptions const& options) // smooth scroll, abort these steps. // 11. Let document be the viewport’s associated Document. - auto const* document = top_level_browsing_context.active_document(); + auto const document = top_level_traversable->active_document(); // 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. diff --git a/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp b/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp index e7031ecce0..80aa391719 100644 --- a/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp +++ b/Userland/Libraries/LibWeb/IntersectionObserver/IntersectionObserver.cpp @@ -173,12 +173,12 @@ CSSPixelRect IntersectionObserver::root_intersection_rectangle() const if (intersection_root.has>()) { auto document = intersection_root.get>(); - // Since the spec says that this is only reach if the document is fully active, that means it must have a browsing context. - VERIFY(document->browsing_context()); + // Since the spec says that this is only reach if the document is fully active, that means it must have a navigable. + VERIFY(document->navigable()); // NOTE: This rect is the *size* of the viewport. The viewport *offset* is not relevant, // as intersections are computed using viewport-relative element rects. - rect = CSSPixelRect { CSSPixelPoint { 0, 0 }, document->browsing_context()->viewport_rect().size() }; + rect = CSSPixelRect { CSSPixelPoint { 0, 0 }, document->viewport_rect().size() }; } else { VERIFY(intersection_root.has>()); auto element = intersection_root.get>(); diff --git a/Userland/Libraries/LibWeb/Layout/Box.cpp b/Userland/Libraries/LibWeb/Layout/Box.cpp index d49a8968e2..245b83b640 100644 --- a/Userland/Libraries/LibWeb/Layout/Box.cpp +++ b/Userland/Libraries/LibWeb/Layout/Box.cpp @@ -63,8 +63,11 @@ bool Box::is_user_scrollable() const void Box::set_needs_display() { + if (!navigable()) + return; + if (paintable_box()) - browsing_context().set_needs_display(paintable_box()->absolute_rect()); + navigable()->set_needs_display(paintable_box()->absolute_rect()); } bool Box::is_body() const diff --git a/Userland/Libraries/LibWeb/Layout/FrameBox.cpp b/Userland/Libraries/LibWeb/Layout/FrameBox.cpp index f9a468c385..70ee00914d 100644 --- a/Userland/Libraries/LibWeb/Layout/FrameBox.cpp +++ b/Userland/Libraries/LibWeb/Layout/FrameBox.cpp @@ -32,8 +32,8 @@ void FrameBox::did_set_content_size() { ReplacedBox::did_set_content_size(); - VERIFY(dom_node().nested_browsing_context()); - dom_node().nested_browsing_context()->set_size(paintable_box()->content_size()); + VERIFY(dom_node().content_navigable()); + dom_node().content_navigable()->set_size(paintable_box()->content_size()); } JS::GCPtr FrameBox::create_paintable() const diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp index beb08f91e5..8d5f5d5b3e 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.cpp +++ b/Userland/Libraries/LibWeb/Layout/Node.cpp @@ -196,6 +196,11 @@ HTML::BrowsingContext& Node::browsing_context() return *m_browsing_context; } +JS::GCPtr Node::navigable() const +{ + return document().navigable(); +} + Viewport const& Node::root() const { VERIFY(document().layout_node()); @@ -219,7 +224,8 @@ void Node::set_needs_display() return; static_cast(*containing_block->paintable_box()).for_each_fragment([&](auto& fragment) { if (&fragment.layout_node() == this || is_ancestor_of(fragment.layout_node())) { - browsing_context().set_needs_display(fragment.absolute_rect()); + if (navigable()) + navigable()->set_needs_display(fragment.absolute_rect()); } return IterationDecision::Continue; }); diff --git a/Userland/Libraries/LibWeb/Layout/Node.h b/Userland/Libraries/LibWeb/Layout/Node.h index 42bc4ab6ea..2183db88b2 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.h +++ b/Userland/Libraries/LibWeb/Layout/Node.h @@ -77,6 +77,8 @@ public: HTML::BrowsingContext const& browsing_context() const; HTML::BrowsingContext& browsing_context(); + JS::GCPtr navigable() const; + Viewport const& root() const; Viewport& root(); diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.cpp b/Userland/Libraries/LibWeb/Page/EventHandler.cpp index 49e4875c9b..fe2f0135dd 100644 --- a/Userland/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Userland/Libraries/LibWeb/Page/EventHandler.cpp @@ -517,7 +517,7 @@ bool EventHandler::handle_mousemove(CSSPixelPoint position, CSSPixelPoint screen else (void)selection->set_base_and_extent(*hit->paintable->dom_node(), hit->index_in_node, *hit->paintable->dom_node(), hit->index_in_node); } - m_browsing_context->set_needs_display(); + document.navigable()->set_needs_display(); } if (auto* page = m_browsing_context->page()) page->client().page_did_change_selection(); @@ -822,7 +822,7 @@ CSSPixelPoint EventHandler::compute_mouse_event_client_offset(CSSPixelPoint even // https://w3c.github.io/csswg-drafts/cssom-view/#dom-mouseevent-clientx // The clientX attribute must return the x-coordinate of the position where the event occurred relative to the origin of the viewport. - auto scroll_offset = m_browsing_context->viewport_scroll_offset(); + auto scroll_offset = m_browsing_context->active_document()->navigable()->viewport_scroll_offset(); return event_page_position.translated(-scroll_offset); } @@ -832,7 +832,7 @@ CSSPixelPoint EventHandler::compute_mouse_event_page_offset(CSSPixelPoint event_ // FIXME: 1. If the event’s dispatch flag is set, return the horizontal coordinate of the position where the event occurred relative to the origin of the initial containing block and terminate these steps. // 2. Let offset be the value of the scrollX attribute of the event’s associated Window object, if there is one, or zero otherwise. - auto scroll_offset = m_browsing_context->viewport_scroll_offset(); + auto scroll_offset = m_browsing_context->active_document()->navigable()->viewport_scroll_offset(); // 3. Return the sum of offset and the value of the event’s clientX attribute. return event_client_offset.translated(scroll_offset); diff --git a/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp b/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp index da6bdcd414..d5aa8231b6 100644 --- a/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp +++ b/Userland/Libraries/LibWeb/Painting/BackgroundPainting.cpp @@ -129,7 +129,7 @@ void paint_background(PaintContext& context, Layout::NodeWithStyleAndBoxModelMet // Attachment and Origin switch (layer.attachment) { case CSS::BackgroundAttachment::Fixed: - background_positioning_area = layout_node.root().browsing_context().viewport_rect(); + background_positioning_area = layout_node.root().navigable()->viewport_rect(); break; case CSS::BackgroundAttachment::Local: background_positioning_area = get_box(layer.origin).rect; diff --git a/Userland/Libraries/LibWeb/Painting/NestedBrowsingContextPaintable.cpp b/Userland/Libraries/LibWeb/Painting/NestedBrowsingContextPaintable.cpp index 72eba5e401..81953d80d3 100644 --- a/Userland/Libraries/LibWeb/Painting/NestedBrowsingContextPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/NestedBrowsingContextPaintable.cpp @@ -56,7 +56,7 @@ void NestedBrowsingContextPaintable::paint(PaintContext& context, PaintPhase pha auto absolute_device_rect = context.enclosing_device_rect(absolute_rect); context.painter().translate(absolute_device_rect.x().value(), absolute_device_rect.y().value()); - context.set_device_viewport_rect({ {}, context.enclosing_device_size(layout_box().dom_node().nested_browsing_context()->size()) }); + context.set_device_viewport_rect({ {}, context.enclosing_device_size(layout_box().dom_node().content_navigable()->size()) }); const_cast(hosted_paint_tree)->paint_all_phases(context); context.set_device_viewport_rect(old_viewport_rect); diff --git a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp index 5772adf34a..1b668d665b 100644 --- a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp +++ b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp @@ -542,7 +542,7 @@ Optional StackingContext::hit_test(CSSPixelPoint position, HitTes auto transformed_position = affine_transform_matrix().inverse().value_or({}).map(offset_position).to_type() + transform_origin; if (paintable_box().is_fixed_position()) { - auto scroll_offset = paintable_box().document().browsing_context()->viewport_scroll_offset(); + auto scroll_offset = paintable_box().document().navigable()->viewport_scroll_offset(); transformed_position.translate_by(-scroll_offset); } diff --git a/Userland/Libraries/LibWeb/WebDriver/Screenshot.cpp b/Userland/Libraries/LibWeb/WebDriver/Screenshot.cpp index f2a6405efe..a027410892 100644 --- a/Userland/Libraries/LibWeb/WebDriver/Screenshot.cpp +++ b/Userland/Libraries/LibWeb/WebDriver/Screenshot.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -54,7 +55,7 @@ Response capture_element_screenshot(Painter const& painter, Page& page, DOM::Ele Optional encoded_string_or_error; element.document().window().animation_frame_callback_driver().add([&](auto) { - auto viewport_rect = page.top_level_browsing_context().viewport_rect(); + auto viewport_rect = page.top_level_traversable()->viewport_rect(); rect.intersect(page.enclosing_device_rect(viewport_rect).to_type()); auto canvas_element = DOM::create_element(element.document(), HTML::TagNames::canvas, Namespace::HTML).release_value_but_fixme_should_propagate_errors(); diff --git a/Userland/Services/WebContent/ConnectionFromClient.cpp b/Userland/Services/WebContent/ConnectionFromClient.cpp index f4b2c90e5d..0b7e72c07d 100644 --- a/Userland/Services/WebContent/ConnectionFromClient.cpp +++ b/Userland/Services/WebContent/ConnectionFromClient.cpp @@ -441,7 +441,7 @@ void ConnectionFromClient::debug_request(DeprecatedString const& request, Deprec if (request == "set-line-box-borders") { bool state = argument == "on"; m_page_host->set_should_show_line_box_borders(state); - page().top_level_browsing_context().set_needs_display(page().top_level_browsing_context().viewport_rect()); + page().top_level_traversable()->set_needs_display(page().top_level_traversable()->viewport_rect()); return; } diff --git a/Userland/Services/WebContent/PageHost.cpp b/Userland/Services/WebContent/PageHost.cpp index 7c969a52c6..79f331b314 100644 --- a/Userland/Services/WebContent/PageHost.cpp +++ b/Userland/Services/WebContent/PageHost.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -146,7 +147,7 @@ void PageHost::paint(Web::DevicePixelRect const& content_rect, Gfx::Bitmap& targ void PageHost::set_viewport_rect(Web::DevicePixelRect const& rect) { - page().top_level_browsing_context().set_viewport_rect(page().device_to_css_rect(rect)); + page().top_level_traversable()->set_viewport_rect(page().device_to_css_rect(rect)); } void PageHost::page_did_invalidate(Web::CSSPixelRect const& content_rect)