mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 04:12:43 +00:00 
			
		
		
		
	LibWeb: Change viewport ownership from BrowsingContext to Navigable
				
					
				
			This commit is contained in:
		
							parent
							
								
									4356d37b2c
								
							
						
					
					
						commit
						dd7bba66ed
					
				
					 23 changed files with 196 additions and 129 deletions
				
			
		|  | @ -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); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 {}; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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) { | ||||
|  |  | |||
|  | @ -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
 | ||||
|  |  | |||
|  | @ -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 {}; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -833,8 +833,8 @@ JS::NonnullGCPtr<Geometry::DOMRect> 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<float>()); | ||||
| } | ||||
|  | @ -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<HTML::HTMLHtmlElement>(*this) && !document().in_quirks_mode()) | ||||
|         || (is<HTML::HTMLBodyElement>(*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<HTML::HTMLHtmlElement>(*this) && !document().in_quirks_mode()) | ||||
|         || (is<HTML::HTMLBodyElement>(*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).
 | ||||
|  |  | |||
|  | @ -540,73 +540,6 @@ void BrowsingContext::set_active_document(JS::NonnullGCPtr<DOM::Document> 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::Box>(layout_node)) { | ||||
|         auto& layout_box = verify_cast<Layout::Box>(layout_node); | ||||
|         auto padding_box = layout_box.box_model().padding_box(); | ||||
|  |  | |||
|  | @ -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; } | ||||
| 
 | ||||
|  |  | |||
|  | @ -25,6 +25,7 @@ | |||
| #include <LibWeb/HTML/StructuredSerialize.h> | ||||
| #include <LibWeb/HTML/TraversableNavigable.h> | ||||
| #include <LibWeb/Infra/Strings.h> | ||||
| #include <LibWeb/Layout/Node.h> | ||||
| #include <LibWeb/Platform/EventLoopPlugin.h> | ||||
| #include <LibWeb/XHR/FormData.h> | ||||
| 
 | ||||
|  | @ -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<TraversableNavigable>(*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<TraversableNavigable>(*this)) { | ||||
|         static_cast<TraversableNavigable*>(this)->page()->client().page_did_invalidate(to_top_level_rect(rect)); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (container() && container()->layout_node()) | ||||
|         container()->layout_node()->set_needs_display(); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include <AK/HashTable.h> | ||||
| #include <AK/String.h> | ||||
| #include <LibJS/Heap/Cell.h> | ||||
| #include <LibWeb/Bindings/NavigationPrototype.h> | ||||
|  | @ -19,6 +20,7 @@ | |||
| #include <LibWeb/HTML/SourceSnapshotParams.h> | ||||
| #include <LibWeb/HTML/StructuredSerialize.h> | ||||
| #include <LibWeb/HTML/TokenizedFeatures.h> | ||||
| #include <LibWeb/PixelUnits.h> | ||||
| #include <LibWeb/XHR/FormDataEntry.h> | ||||
| 
 | ||||
| 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<NavigableContainer> m_container; | ||||
| 
 | ||||
|     bool m_has_been_destroyed { false }; | ||||
| 
 | ||||
|     CSSPixelSize m_size; | ||||
|     CSSPixelPoint m_viewport_scroll_offset; | ||||
| }; | ||||
| 
 | ||||
| HashTable<Navigable*>& all_navigables(); | ||||
|  |  | |||
|  | @ -46,6 +46,7 @@ | |||
| #include <LibWeb/HTML/Scripting/ExceptionReporter.h> | ||||
| #include <LibWeb/HTML/Storage.h> | ||||
| #include <LibWeb/HTML/TokenizedFeatures.h> | ||||
| #include <LibWeb/HTML/TraversableNavigable.h> | ||||
| #include <LibWeb/HTML/Window.h> | ||||
| #include <LibWeb/HTML/WindowProxy.h> | ||||
| #include <LibWeb/HighResolutionTime/Performance.h> | ||||
|  | @ -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<float>(); | ||||
|     auto viewport_rect = top_level_traversable->viewport_rect().to_type<float>(); | ||||
| 
 | ||||
|     // 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.
 | ||||
|  |  | |||
|  | @ -173,12 +173,12 @@ CSSPixelRect IntersectionObserver::root_intersection_rectangle() const | |||
|     if (intersection_root.has<JS::Handle<DOM::Document>>()) { | ||||
|         auto document = intersection_root.get<JS::Handle<DOM::Document>>(); | ||||
| 
 | ||||
|         // 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<JS::Handle<DOM::Element>>()); | ||||
|         auto element = intersection_root.get<JS::Handle<DOM::Element>>(); | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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<Painting::Paintable> FrameBox::create_paintable() const | ||||
|  |  | |||
|  | @ -196,6 +196,11 @@ HTML::BrowsingContext& Node::browsing_context() | |||
|     return *m_browsing_context; | ||||
| } | ||||
| 
 | ||||
| JS::GCPtr<HTML::Navigable> 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<Painting::PaintableWithLines const&>(*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; | ||||
|     }); | ||||
|  |  | |||
|  | @ -77,6 +77,8 @@ public: | |||
|     HTML::BrowsingContext const& browsing_context() const; | ||||
|     HTML::BrowsingContext& browsing_context(); | ||||
| 
 | ||||
|     JS::GCPtr<HTML::Navigable> navigable() const; | ||||
| 
 | ||||
|     Viewport const& root() const; | ||||
|     Viewport& root(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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<ViewportPaintable*>(hosted_paint_tree)->paint_all_phases(context); | ||||
| 
 | ||||
|         context.set_device_viewport_rect(old_viewport_rect); | ||||
|  |  | |||
|  | @ -542,7 +542,7 @@ Optional<HitTestResult> StackingContext::hit_test(CSSPixelPoint position, HitTes | |||
|     auto transformed_position = affine_transform_matrix().inverse().value_or({}).map(offset_position).to_type<CSSPixels>() + 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); | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ | |||
| #include <LibWeb/HTML/BrowsingContext.h> | ||||
| #include <LibWeb/HTML/HTMLCanvasElement.h> | ||||
| #include <LibWeb/HTML/TagNames.h> | ||||
| #include <LibWeb/HTML/TraversableNavigable.h> | ||||
| #include <LibWeb/HTML/Window.h> | ||||
| #include <LibWeb/Namespace.h> | ||||
| #include <LibWeb/Page/Page.h> | ||||
|  | @ -54,7 +55,7 @@ Response capture_element_screenshot(Painter const& painter, Page& page, DOM::Ele | |||
|     Optional<Response> 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<int>()); | ||||
| 
 | ||||
|         auto canvas_element = DOM::create_element(element.document(), HTML::TagNames::canvas, Namespace::HTML).release_value_but_fixme_should_propagate_errors(); | ||||
|  |  | |||
|  | @ -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; | ||||
|     } | ||||
| 
 | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ | |||
| #include <LibWeb/CSS/SystemColor.h> | ||||
| #include <LibWeb/Cookie/ParsedCookie.h> | ||||
| #include <LibWeb/HTML/BrowsingContext.h> | ||||
| #include <LibWeb/HTML/TraversableNavigable.h> | ||||
| #include <LibWeb/Layout/Viewport.h> | ||||
| #include <LibWeb/Painting/PaintableBox.h> | ||||
| #include <LibWeb/Painting/ViewportPaintable.h> | ||||
|  | @ -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) | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Aliaksandr Kalenik
						Aliaksandr Kalenik