From 568b7ce7ea605fc35f0c4c0d5cfe21a086ad532b Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Thu, 7 May 2026 13:38:05 +0200 Subject: [PATCH] LibWeb: Make Paintable tree ref-counted The Paintable tree and its supplemental painting data structures were GC allocated because that was the easiest way to manage it and avoid leaks introduced by ref cycles. This included the Paintable subclasses themselves plus StackingContext, ChromeWidget, Scrollbar, ResizeHandle, and scroll-frame state. We are now trying to reduce GC allocation churn on layout and painting updates, so keeping this short-lived rendering tree outside the JS heap is a better fit. Move Paintable to RefCountedTreeNode, make painting helpers ref-counted or weakly reference Paintables, and update the layout and event-handler call sites to use RefPtr/WeakPtr ownership. --- .../LibWeb/Animations/ScrollTimeline.cpp | 2 +- Libraries/LibWeb/CSS/CSSStyleProperties.cpp | 23 ++--- Libraries/LibWeb/CSS/Interpolation.cpp | 7 +- Libraries/LibWeb/DOM/Document.cpp | 66 +++++++------ Libraries/LibWeb/DOM/Document.h | 9 +- Libraries/LibWeb/DOM/Element.cpp | 2 +- Libraries/LibWeb/DOM/Node.cpp | 48 ++++++---- Libraries/LibWeb/DOM/Node.h | 22 +++-- Libraries/LibWeb/DOM/Range.cpp | 7 +- Libraries/LibWeb/Dump.cpp | 15 +-- .../LibWeb/HTML/FormAssociatedElement.cpp | 4 +- Libraries/LibWeb/HTML/HTMLElement.cpp | 4 +- Libraries/LibWeb/HTML/HTMLImageElement.cpp | 8 +- Libraries/LibWeb/HTML/HTMLInputElement.cpp | 4 +- Libraries/LibWeb/HTML/HTMLLabelElement.cpp | 2 +- Libraries/LibWeb/HTML/Navigable.cpp | 2 +- Libraries/LibWeb/Internals/Internals.cpp | 2 +- Libraries/LibWeb/Layout/AudioBox.cpp | 2 +- Libraries/LibWeb/Layout/AudioBox.h | 2 +- Libraries/LibWeb/Layout/BlockContainer.cpp | 7 +- Libraries/LibWeb/Layout/BlockContainer.h | 4 +- Libraries/LibWeb/Layout/Box.cpp | 14 ++- Libraries/LibWeb/Layout/Box.h | 6 +- Libraries/LibWeb/Layout/CanvasBox.cpp | 2 +- Libraries/LibWeb/Layout/CanvasBox.h | 2 +- Libraries/LibWeb/Layout/CheckBox.cpp | 2 +- Libraries/LibWeb/Layout/CheckBox.h | 2 +- Libraries/LibWeb/Layout/FieldSetBox.cpp | 2 +- Libraries/LibWeb/Layout/FieldSetBox.h | 2 +- Libraries/LibWeb/Layout/ImageBox.cpp | 2 +- Libraries/LibWeb/Layout/ImageBox.h | 2 +- Libraries/LibWeb/Layout/InlineNode.cpp | 6 +- Libraries/LibWeb/Layout/InlineNode.h | 2 +- Libraries/LibWeb/Layout/LayoutState.cpp | 50 +++++----- Libraries/LibWeb/Layout/ListItemMarkerBox.cpp | 2 +- Libraries/LibWeb/Layout/ListItemMarkerBox.h | 2 +- .../Layout/NavigableContainerViewport.cpp | 2 +- .../Layout/NavigableContainerViewport.h | 2 +- Libraries/LibWeb/Layout/Node.cpp | 15 +-- Libraries/LibWeb/Layout/Node.h | 21 ++++- Libraries/LibWeb/Layout/RadioButton.cpp | 2 +- Libraries/LibWeb/Layout/RadioButton.h | 2 +- Libraries/LibWeb/Layout/SVGClipBox.cpp | 2 +- Libraries/LibWeb/Layout/SVGClipBox.h | 2 +- .../LibWeb/Layout/SVGForeignObjectBox.cpp | 2 +- Libraries/LibWeb/Layout/SVGForeignObjectBox.h | 2 +- Libraries/LibWeb/Layout/SVGGeometryBox.cpp | 2 +- Libraries/LibWeb/Layout/SVGGeometryBox.h | 2 +- Libraries/LibWeb/Layout/SVGGraphicsBox.cpp | 2 +- Libraries/LibWeb/Layout/SVGGraphicsBox.h | 2 +- Libraries/LibWeb/Layout/SVGImageBox.cpp | 2 +- Libraries/LibWeb/Layout/SVGImageBox.h | 2 +- Libraries/LibWeb/Layout/SVGMaskBox.cpp | 2 +- Libraries/LibWeb/Layout/SVGMaskBox.h | 2 +- Libraries/LibWeb/Layout/SVGPatternBox.cpp | 2 +- Libraries/LibWeb/Layout/SVGPatternBox.h | 2 +- Libraries/LibWeb/Layout/SVGSVGBox.cpp | 2 +- Libraries/LibWeb/Layout/SVGSVGBox.h | 2 +- Libraries/LibWeb/Layout/SVGTextBox.cpp | 2 +- Libraries/LibWeb/Layout/SVGTextBox.h | 2 +- Libraries/LibWeb/Layout/SVGTextPathBox.cpp | 2 +- Libraries/LibWeb/Layout/SVGTextPathBox.h | 2 +- Libraries/LibWeb/Layout/TextNode.cpp | 2 +- Libraries/LibWeb/Layout/TextNode.h | 2 +- Libraries/LibWeb/Layout/VideoBox.cpp | 2 +- Libraries/LibWeb/Layout/VideoBox.h | 2 +- Libraries/LibWeb/Layout/Viewport.cpp | 2 +- Libraries/LibWeb/Layout/Viewport.h | 2 +- Libraries/LibWeb/Page/AutoScrollHandler.cpp | 4 +- Libraries/LibWeb/Page/AutoScrollHandler.h | 2 +- Libraries/LibWeb/Page/ElementResizeAction.cpp | 18 ++-- Libraries/LibWeb/Page/ElementResizeAction.h | 6 +- Libraries/LibWeb/Page/EventHandler.cpp | 58 ++++++------ Libraries/LibWeb/Page/EventHandler.h | 20 ++-- .../LibWeb/Page/MiddleButtonScrollHandler.cpp | 4 +- .../LibWeb/Painting/BackgroundPainting.cpp | 2 +- Libraries/LibWeb/Painting/CanvasPaintable.cpp | 6 +- Libraries/LibWeb/Painting/CanvasPaintable.h | 6 +- .../LibWeb/Painting/CheckBoxPaintable.cpp | 6 +- Libraries/LibWeb/Painting/CheckBoxPaintable.h | 6 +- Libraries/LibWeb/Painting/ChromeWidget.h | 10 +- .../LibWeb/Painting/FieldSetPaintable.cpp | 10 +- Libraries/LibWeb/Painting/FieldSetPaintable.h | 6 +- Libraries/LibWeb/Painting/ImagePaintable.cpp | 16 +--- Libraries/LibWeb/Painting/ImagePaintable.h | 11 +-- Libraries/LibWeb/Painting/MarkerPaintable.cpp | 6 +- Libraries/LibWeb/Painting/MarkerPaintable.h | 6 +- .../NavigableContainerViewportPaintable.cpp | 6 +- .../NavigableContainerViewportPaintable.h | 6 +- Libraries/LibWeb/Painting/Paintable.cpp | 92 +++++++++---------- Libraries/LibWeb/Painting/Paintable.h | 44 ++++----- Libraries/LibWeb/Painting/PaintableBox.cpp | 59 ++++++------ Libraries/LibWeb/Painting/PaintableBox.h | 36 ++++---- .../LibWeb/Painting/PaintableFragment.cpp | 7 +- .../LibWeb/Painting/PaintableWithLines.cpp | 22 ++--- .../LibWeb/Painting/PaintableWithLines.h | 15 +-- .../LibWeb/Painting/RadioButtonPaintable.cpp | 6 +- .../LibWeb/Painting/RadioButtonPaintable.h | 6 +- Libraries/LibWeb/Painting/ResizeHandle.cpp | 36 ++++---- Libraries/LibWeb/Painting/ResizeHandle.h | 12 +-- .../LibWeb/Painting/SVGClipPaintable.cpp | 6 +- Libraries/LibWeb/Painting/SVGClipPaintable.h | 6 +- .../Painting/SVGForeignObjectPaintable.cpp | 6 +- .../Painting/SVGForeignObjectPaintable.h | 6 +- .../LibWeb/Painting/SVGGraphicsPaintable.cpp | 6 +- .../LibWeb/Painting/SVGGraphicsPaintable.h | 6 +- .../LibWeb/Painting/SVGMaskPaintable.cpp | 6 +- Libraries/LibWeb/Painting/SVGMaskPaintable.h | 6 +- Libraries/LibWeb/Painting/SVGPaintable.h | 4 +- .../LibWeb/Painting/SVGPathPaintable.cpp | 6 +- Libraries/LibWeb/Painting/SVGPathPaintable.h | 6 +- .../LibWeb/Painting/SVGPatternPaintable.cpp | 6 +- .../LibWeb/Painting/SVGPatternPaintable.h | 6 +- Libraries/LibWeb/Painting/SVGSVGPaintable.cpp | 6 +- Libraries/LibWeb/Painting/SVGSVGPaintable.h | 6 +- Libraries/LibWeb/Painting/ScrollFrame.cpp | 9 +- Libraries/LibWeb/Painting/ScrollFrame.h | 6 +- Libraries/LibWeb/Painting/Scrollbar.cpp | 57 +++++++----- Libraries/LibWeb/Painting/Scrollbar.h | 9 +- Libraries/LibWeb/Painting/StackingContext.cpp | 69 +++++++------- Libraries/LibWeb/Painting/StackingContext.h | 39 +++++--- .../LibWeb/Painting/TableBordersPainting.cpp | 6 +- Libraries/LibWeb/Painting/TextPaintable.cpp | 11 +-- Libraries/LibWeb/Painting/TextPaintable.h | 6 +- Libraries/LibWeb/Painting/VideoPaintable.cpp | 8 +- Libraries/LibWeb/Painting/VideoPaintable.h | 6 +- .../LibWeb/Painting/ViewportPaintable.cpp | 41 ++++----- Libraries/LibWeb/Painting/ViewportPaintable.h | 14 +-- Libraries/LibWeb/SVG/SVGFilterElement.cpp | 2 +- Libraries/LibWeb/SVG/SVGPatternElement.cpp | 5 +- Libraries/LibWeb/Selection/Selection.cpp | 2 +- Libraries/LibWeb/TreeNode.h | 1 + Libraries/LibWeb/WebDriver/Actions.cpp | 2 +- .../LibWeb/WebDriver/ElementReference.cpp | 2 +- Services/WebContent/ConnectionFromClient.cpp | 11 ++- 135 files changed, 682 insertions(+), 698 deletions(-) diff --git a/Libraries/LibWeb/Animations/ScrollTimeline.cpp b/Libraries/LibWeb/Animations/ScrollTimeline.cpp index c8dfc1d90f..79779db993 100644 --- a/Libraries/LibWeb/Animations/ScrollTimeline.cpp +++ b/Libraries/LibWeb/Animations/ScrollTimeline.cpp @@ -145,7 +145,7 @@ void ScrollTimeline::update_current_time(double) if (!layout_node || !layout_node->is_scroll_container()) return; - auto const& paintable_box = propagated_source.visit([](auto const& source) -> Painting::PaintableBox const* { return source->unsafe_paintable_box(); }); + auto paintable_box = propagated_source.visit([](auto const& source) -> RefPtr { return source->unsafe_paintable_box(); }); if (!paintable_box || !paintable_box->has_scrollable_overflow()) return; diff --git a/Libraries/LibWeb/CSS/CSSStyleProperties.cpp b/Libraries/LibWeb/CSS/CSSStyleProperties.cpp index 3b77455cad..843713088b 100644 --- a/Libraries/LibWeb/CSS/CSSStyleProperties.cpp +++ b/Libraries/LibWeb/CSS/CSSStyleProperties.cpp @@ -662,10 +662,12 @@ RefPtr CSSStyleProperties::style_value_for_computed_property(L auto used_value_for_property = [&layout_node, property_id](Function&& used_value_getter) -> Optional { auto const& display = layout_node.computed_values().display(); - if (!display.is_none() && !display.is_contents() && layout_node.first_paintable()) { - if (auto const* paintable_box = as_if(layout_node.first_paintable())) + if (!display.is_none() && !display.is_contents()) { + auto first_paintable = layout_node.first_paintable(); + if (auto const* paintable_box = as_if(first_paintable.ptr())) return used_value_getter(*paintable_box); - dbgln("FIXME: Support getting used value for property `{}` on {}", string_from_property_id(property_id), layout_node.debug_description()); + if (first_paintable) + dbgln("FIXME: Support getting used value for property `{}` on {}", string_from_property_id(property_id), layout_node.debug_description()); } return {}; }; @@ -889,8 +891,9 @@ RefPtr CSSStyleProperties::style_value_for_computed_property(L auto transform = FloatMatrix4x4::identity(); // 2. Post-multiply all s in to transform. - VERIFY(layout_node.first_paintable()); - auto const& paintable_box = as(*layout_node.first_paintable()); + auto first_paintable = layout_node.first_paintable(); + VERIFY(first_paintable); + auto const& paintable_box = as(*first_paintable); for (auto const& transformation : transformations) { transform = transform * transformation->to_matrix(paintable_box).release_value(); } @@ -1023,16 +1026,14 @@ RefPtr CSSStyleProperties::style_value_for_computed_property(L // For grid-template-columns and grid-template-rows the resolved value is the used value. // https://www.w3.org/TR/css-grid-2/#resolved-track-list-standalone if (property_id == PropertyID::GridTemplateColumns) { - if (layout_node.first_paintable() && layout_node.first_paintable()->is_paintable_box()) { - auto const& paintable_box = as(*layout_node.first_paintable()); - if (auto used_values_for_grid_template_columns = paintable_box.used_values_for_grid_template_columns()) { + if (auto first_paintable = layout_node.first_paintable(); auto const* paintable_box = as_if(first_paintable.ptr())) { + if (auto used_values_for_grid_template_columns = paintable_box->used_values_for_grid_template_columns()) { return used_values_for_grid_template_columns; } } } else if (property_id == PropertyID::GridTemplateRows) { - if (layout_node.first_paintable() && layout_node.first_paintable()->is_paintable_box()) { - auto const& paintable_box = as(*layout_node.first_paintable()); - if (auto used_values_for_grid_template_rows = paintable_box.used_values_for_grid_template_rows()) { + if (auto first_paintable = layout_node.first_paintable(); auto const* paintable_box = as_if(first_paintable.ptr())) { + if (auto used_values_for_grid_template_rows = paintable_box->used_values_for_grid_template_rows()) { return used_values_for_grid_template_rows; } } diff --git a/Libraries/LibWeb/CSS/Interpolation.cpp b/Libraries/LibWeb/CSS/Interpolation.cpp index e8e65b4237..428fab4855 100644 --- a/Libraries/LibWeb/CSS/Interpolation.cpp +++ b/Libraries/LibWeb/CSS/Interpolation.cpp @@ -1240,7 +1240,7 @@ RefPtr interpolate_transform(DOM::Element& element, Calculatio generic_function = TransformFunction::Matrix3d; // NB: Called during animation interpolation. auto paintable_box = [&] -> Optional { - if (auto* box = element.unsafe_paintable_box()) + if (auto box = element.unsafe_paintable_box()) return *box; return {}; }(); @@ -1343,8 +1343,9 @@ RefPtr interpolate_transform(DOM::Element& element, Calculatio // iterating over Va and Vb. // NB: Called during animation interpolation. Optional paintable_box; - if (auto* paintable = as_if(element.unsafe_paintable())) - paintable_box = *paintable; + auto paintable = element.unsafe_paintable(); + if (auto const* box = as_if(paintable.ptr())) + paintable_box = *box; auto post_multiply_remaining_transformations = [&paintable_box](size_t start_index, Vector> const& transformations) -> Optional { FloatMatrix4x4 result = FloatMatrix4x4::identity(); diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp index 3598306632..470a426db4 100644 --- a/Libraries/LibWeb/DOM/Document.cpp +++ b/Libraries/LibWeb/DOM/Document.cpp @@ -1458,13 +1458,13 @@ static void relayout_svg_root(Layout::SVGSVGBox& svg_root) Layout::LayoutState layout_state(svg_root); // Pre-populate the svg_root itself. - if (auto const* paintable = svg_root.paintable_box()) + if (auto paintable = svg_root.paintable_box()) layout_state.populate_from_paintable(svg_root, *paintable); // Pre-populate SVGGraphicsBox ancestors (up to outer SVG) for get_parent_svg_transform(). for (auto* ancestor = svg_root.parent(); ancestor; ancestor = ancestor->parent()) { if (auto const* svg_graphics_ancestor = as_if(*ancestor)) { - if (auto const* paintable = svg_graphics_ancestor->paintable_box()) + if (auto paintable = svg_graphics_ancestor->paintable_box()) layout_state.populate_from_paintable(*svg_graphics_ancestor, *paintable); } if (is(*ancestor)) @@ -1473,7 +1473,7 @@ static void relayout_svg_root(Layout::SVGSVGBox& svg_root) // Pre-populate the viewport for position:fixed elements inside . auto& viewport = svg_root.root(); - if (auto const* paintable = viewport.paintable_box()) + if (auto paintable = viewport.paintable_box()) layout_state.populate_from_paintable(viewport, *paintable); auto const& svg_state = layout_state.get(svg_root); @@ -1713,7 +1713,7 @@ void Document::update_layout(UpdateLayoutReason reason) } // Collect elements with content-visibility: auto. This is used in the HTML event loop to avoid traversing the whole tree every time. - Vector> paintable_boxes_with_auto_content_visibility; + Vector> paintable_boxes_with_auto_content_visibility; unsafe_paintable()->for_each_in_subtree_of_type([&](auto& paintable_box) { if (paintable_box.dom_node() && paintable_box.dom_node()->is_element() @@ -1964,13 +1964,13 @@ void Document::set_needs_animated_style_update() void Document::update_paint_and_hit_testing_properties_if_needed() { // NB: Called during paint property resolution. - if (auto* paintable = this->unsafe_paintable()) { + if (auto paintable = this->unsafe_paintable()) { paintable->refresh_scroll_state(); } if (m_needs_accumulated_visual_contexts_update) { m_needs_accumulated_visual_contexts_update = false; - if (auto* paintable = this->unsafe_paintable()) { + if (auto paintable = this->unsafe_paintable()) { paintable->assign_accumulated_visual_contexts(); } } @@ -4249,7 +4249,7 @@ void Document::set_page_showing(bool page_showing) void Document::invalidate_stacking_context_tree() { // NB: Called during stacking context invalidation. - if (auto* paintable_box = this->unsafe_paintable_box()) + if (auto paintable_box = this->unsafe_paintable_box()) paintable_box->invalidate_stacking_context(); } @@ -5381,15 +5381,15 @@ void Document::queue_an_intersection_observer_entry(IntersectionObserver::Inters } // https://www.w3.org/TR/intersection-observer/#compute-the-intersection -static CSSPixelRect compute_intersection(GC::Ref target, CSSPixelRect target_rect, IntersectionObserver::IntersectionObserver const& observer, Painting::PaintableBox const* root_paintable, CSSPixelRect const& root_bounds) +static CSSPixelRect compute_intersection(GC::Ref target, CSSPixelRect target_rect, IntersectionObserver::IntersectionObserver const& observer, RefPtr root_paintable, CSSPixelRect const& root_bounds) { // 1. Let intersectionRect be the result of getting the bounding box for target. auto intersection_rect = target_rect; // 2. Let container be the containing block of target. // 3. While container is not root: - if (auto const* target_paintable = target->paintable_box()) { - for (auto const* container = target_paintable->containing_block(); container; container = container->containing_block()) { + if (auto target_paintable = target->paintable_box()) { + for (auto container = target_paintable->containing_block(); container; container = container->containing_block()) { // Stop when we reach the intersection root. if (container == root_paintable) break; @@ -5460,7 +5460,7 @@ void Document::run_the_update_intersection_observations_steps(HighResolutionTime // Pre-compute per-observer values to avoid repeated work in the per-target loop. auto intersection_root_node = observer->intersection_root_node(); - auto* root_paintable = intersection_root_node->paintable_box(); + auto root_paintable = intersection_root_node->paintable_box(); bool is_implicit_root = observer->is_implicit_root(); bool root_is_element = intersection_root_node->is_element(); @@ -5807,24 +5807,36 @@ void Document::shared_declarative_refresh_steps(StringView input, GC::Ptr Document::paintable() const { - return static_cast(Node::paintable()); + auto paintable = Node::paintable(); + if (!paintable) + return nullptr; + return as(*paintable); } -Painting::ViewportPaintable* Document::paintable() +RefPtr Document::paintable() { - return static_cast(Node::paintable()); + auto paintable = Node::paintable(); + if (!paintable) + return nullptr; + return as(*paintable); } -Painting::ViewportPaintable const* Document::unsafe_paintable() const +RefPtr Document::unsafe_paintable() const { - return static_cast(Node::unsafe_paintable()); + auto paintable = Node::unsafe_paintable(); + if (!paintable) + return nullptr; + return as(*paintable); } -Painting::ViewportPaintable* Document::unsafe_paintable() +RefPtr Document::unsafe_paintable() { - return static_cast(Node::unsafe_paintable()); + auto paintable = Node::unsafe_paintable(); + if (!paintable) + return nullptr; + return as(*paintable); } // https://html.spec.whatwg.org/multipage/browsing-the-web.html#restore-the-history-object-state @@ -6399,7 +6411,7 @@ Element const* Document::element_from_point(double x, double y) // 2. If there is a box in the viewport that would be a target for hit testing at coordinates x,y, when applying the transforms // that apply to the descendants of the viewport, return the associated element and terminate these steps. GC::Ptr hit_element; - if (auto const* paintable_box = this->paintable_box()) { + if (auto paintable_box = this->paintable_box()) { (void)paintable_box->hit_test(position, Painting::HitTestType::Exact, [&](Painting::HitTestResult result) { if (auto* element = as_if(result.dom_node())) { hit_element = element; @@ -6442,7 +6454,7 @@ GC::RootVector> Document::elements_from_point(double x, double // 3. For each box in the viewport, in paint order, starting with the topmost box, that would be a target for // hit testing at coordinates x,y even if nothing would be overlapping it, when applying the transforms that // apply to the descendants of the viewport, append the associated element to sequence. - if (auto const* paintable_box = this->paintable_box()) { + if (auto paintable_box = this->paintable_box()) { (void)paintable_box->hit_test(position, Painting::HitTestType::Exact, [&](Painting::HitTestResult result) { if (auto* element = as_if(result.dom_node())) { // AD-HOC: If element is inside a UA internal shadow root, retarget to the host. @@ -6976,7 +6988,7 @@ GC::Ptr Document::topmost_auto_or_hint_popover() void Document::set_needs_to_refresh_scroll_state(bool b) { // NB: Propagating scroll state invalidation. - if (auto* paintable = this->unsafe_paintable()) + if (auto paintable = this->unsafe_paintable()) paintable->set_needs_to_refresh_scroll_state(b); } @@ -7917,7 +7929,7 @@ String Document::dump_display_list() { update_layout(UpdateLayoutReason::DumpDisplayList); - auto* viewport_paintable = paintable(); + auto viewport_paintable = paintable(); if (!viewport_paintable) return "No paintable"_string; @@ -7925,11 +7937,11 @@ String Document::dump_display_list() if (!display_list) return "No display list"_string; - HashMap context_id_to_paintable; + HashMap> context_id_to_paintable; viewport_paintable->for_each_in_inclusive_subtree_of_type([&](auto const& paintable_box) { auto visual_context_index = paintable_box.accumulated_visual_context_index(); if (visual_context_index.value()) - (void)context_id_to_paintable.try_set(visual_context_index.value(), &paintable_box); + (void)context_id_to_paintable.try_set(visual_context_index.value(), paintable_box); return TraversalDecision::Continue; }); @@ -8009,13 +8021,13 @@ String Document::dump_stacking_context_tree() { update_layout(UpdateLayoutReason::DumpDisplayList); - auto* viewport_paintable = paintable(); + auto viewport_paintable = paintable(); if (!viewport_paintable) return "No paintable"_string; viewport_paintable->build_stacking_context_tree_if_needed(); - auto* stacking_context = viewport_paintable->stacking_context(); + auto stacking_context = viewport_paintable->stacking_context(); if (!stacking_context) return "No stacking context"_string; diff --git a/Libraries/LibWeb/DOM/Document.h b/Libraries/LibWeb/DOM/Document.h index 57ddc10a3e..e87ad8e2ca 100644 --- a/Libraries/LibWeb/DOM/Document.h +++ b/Libraries/LibWeb/DOM/Document.h @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -399,11 +400,11 @@ public: Layout::Viewport const* unsafe_layout_node() const; Layout::Viewport* unsafe_layout_node(); - Painting::ViewportPaintable const* paintable() const; - Painting::ViewportPaintable* paintable(); + RefPtr paintable() const; + RefPtr paintable(); - Painting::ViewportPaintable const* unsafe_paintable() const; - Painting::ViewportPaintable* unsafe_paintable(); + RefPtr unsafe_paintable() const; + RefPtr unsafe_paintable(); GC::Ref get_elements_by_name(FlyString const&); diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp index e56da30aa9..11118353ed 100644 --- a/Libraries/LibWeb/DOM/Element.cpp +++ b/Libraries/LibWeb/DOM/Element.cpp @@ -1543,7 +1543,7 @@ static Vector compute_client_rects_assuming_layout_clean(Element c // are left in the final list. Vector rects; - if (auto const* paintable_box = element.paintable_box()) { + if (auto paintable_box = element.paintable_box()) { auto absolute_rect = paintable_box->absolute_border_box_rect(); rects.append(paintable_box->transform_rect_to_viewport(absolute_rect)); } else if (element.paintable()) { diff --git a/Libraries/LibWeb/DOM/Node.cpp b/Libraries/LibWeb/DOM/Node.cpp index 33920ab37e..7c5ad80dca 100644 --- a/Libraries/LibWeb/DOM/Node.cpp +++ b/Libraries/LibWeb/DOM/Node.cpp @@ -133,8 +133,6 @@ void Node::visit_edges(Cell::Visitor& visitor) visitor.visit(m_child_nodes); visitor.visit(m_layout_node); - visitor.visit(m_paintable); - if (m_registered_observer_list) { visitor.visit(*m_registered_observer_list); } @@ -2656,7 +2654,7 @@ Layout::Node* Node::layout_node() return m_layout_node; } -void Node::set_paintable(GC::Ptr paintable) +void Node::set_paintable(WeakPtr paintable) { m_paintable = paintable; } @@ -2670,7 +2668,7 @@ void Node::set_needs_repaint(InvalidateDisplayList should_invalidate_display_lis { if (auto* layout_node = unsafe_layout_node()) { for (auto& paintable : layout_node->paintables()) - paintable.set_needs_repaint(should_invalidate_display_list); + paintable->set_needs_repaint(should_invalidate_display_list); } } @@ -2682,45 +2680,55 @@ void Node::set_needs_layout_update(SetNeedsLayoutReason reason) } } -Painting::Paintable const* Node::paintable() const +RefPtr Node::paintable() const { if (m_paintable) VERIFY(document().layout_is_up_to_date()); - return m_paintable; + return m_paintable.strong_ref(); } -Painting::Paintable* Node::paintable() +RefPtr Node::paintable() { if (m_paintable) VERIFY(document().layout_is_up_to_date()); - return m_paintable; + return m_paintable.strong_ref(); } -Painting::PaintableBox const* Node::paintable_box() const +RefPtr Node::unsafe_paintable() const { - if (auto* p = paintable(); p && p->is_paintable_box()) - return static_cast(p); + return m_paintable.strong_ref(); +} + +RefPtr Node::unsafe_paintable() +{ + return m_paintable.strong_ref(); +} + +RefPtr Node::paintable_box() const +{ + if (auto p = paintable(); p && p->is_paintable_box()) + return static_cast(*p); return nullptr; } -Painting::PaintableBox* Node::paintable_box() +RefPtr Node::paintable_box() { - if (auto* p = paintable(); p && p->is_paintable_box()) - return static_cast(p); + if (auto p = paintable(); p && p->is_paintable_box()) + return static_cast(*p); return nullptr; } -Painting::PaintableBox const* Node::unsafe_paintable_box() const +RefPtr Node::unsafe_paintable_box() const { - if (m_paintable && m_paintable->is_paintable_box()) - return static_cast(m_paintable.ptr()); + if (auto paintable = m_paintable.strong_ref(); paintable && paintable->is_paintable_box()) + return static_cast(*paintable); return nullptr; } -Painting::PaintableBox* Node::unsafe_paintable_box() +RefPtr Node::unsafe_paintable_box() { - if (m_paintable && m_paintable->is_paintable_box()) - return static_cast(m_paintable.ptr()); + if (auto paintable = m_paintable.strong_ref(); paintable && paintable->is_paintable_box()) + return static_cast(*paintable); return nullptr; } diff --git a/Libraries/LibWeb/DOM/Node.h b/Libraries/LibWeb/DOM/Node.h index ef61c501d8..09327c8c34 100644 --- a/Libraries/LibWeb/DOM/Node.h +++ b/Libraries/LibWeb/DOM/Node.h @@ -10,8 +10,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -329,17 +331,17 @@ public: Layout::Node const* unsafe_layout_node() const { return m_layout_node; } Layout::Node* unsafe_layout_node() { return m_layout_node; } - Painting::PaintableBox const* paintable_box() const; - Painting::PaintableBox* paintable_box(); - Painting::Paintable const* paintable() const; - Painting::Paintable* paintable(); + RefPtr paintable_box() const; + RefPtr paintable_box(); + RefPtr paintable() const; + RefPtr paintable(); - Painting::PaintableBox const* unsafe_paintable_box() const; - Painting::PaintableBox* unsafe_paintable_box(); - Painting::Paintable const* unsafe_paintable() const { return m_paintable; } - Painting::Paintable* unsafe_paintable() { return m_paintable; } + RefPtr unsafe_paintable_box() const; + RefPtr unsafe_paintable_box(); + RefPtr unsafe_paintable() const; + RefPtr unsafe_paintable(); - void set_paintable(GC::Ptr); + void set_paintable(WeakPtr); void clear_paintable(); void set_needs_repaint(InvalidateDisplayList = InvalidateDisplayList::Yes); @@ -498,7 +500,7 @@ protected: GC::Ptr m_document; GC::Ptr m_layout_node; - GC::Ptr m_paintable; + WeakPtr m_paintable; NodeType m_type { NodeType::INVALID }; bool m_needs_layout_tree_update { false }; bool m_child_needs_layout_tree_update { false }; diff --git a/Libraries/LibWeb/DOM/Range.cpp b/Libraries/LibWeb/DOM/Range.cpp index bb510d5efe..d28eb93b91 100644 --- a/Libraries/LibWeb/DOM/Range.cpp +++ b/Libraries/LibWeb/DOM/Range.cpp @@ -113,7 +113,7 @@ void Range::update_associated_selection() document.reset_cursor_blink_cycle(); // NB: Called during selection update after range change. - if (auto* viewport = document.unsafe_paintable()) { + if (auto viewport = document.unsafe_paintable()) { viewport->recompute_selection_states(*this); viewport->set_needs_repaint(); } @@ -1210,9 +1210,10 @@ GC::Ref Range::get_client_rects() // 2. For each Text node selected or partially selected by the range (including when the boundary-points // are identical), include scaled DOMRect object (for the part that is selected, not the whole line box). auto const& text = static_cast(*node); - auto const* paintable = text.paintable(); + auto paintable = text.paintable(); if (paintable && selection_state != Painting::Paintable::SelectionState::None) { - if (auto const* paintable_lines = as_if(paintable->containing_block())) { + auto containing_block = paintable->containing_block(); + if (auto const* paintable_lines = as_if(containing_block.ptr())) { auto fragments = paintable_lines->fragments(); for (auto frag = fragments.begin(); frag != fragments.end(); frag++) { auto rect = frag->range_rect(selection_state, start_offset(), end_offset()); diff --git a/Libraries/LibWeb/Dump.cpp b/Libraries/LibWeb/Dump.cpp index 432118a417..a4bcd57f00 100644 --- a/Libraries/LibWeb/Dump.cpp +++ b/Libraries/LibWeb/Dump.cpp @@ -208,13 +208,13 @@ void dump_tree(StringBuilder& builder, Layout::Node const& layout_node, bool sho } auto dump_position = [&] { - if (auto* paintable_box = as_if(layout_node.first_paintable())) + if (auto first_paintable = layout_node.first_paintable(); auto const* paintable_box = as_if(first_paintable.ptr())) builder.appendff("at {}", paintable_box->absolute_rect().location()); else builder.appendff("(not painted)"); }; auto dump_box_model = [&] { - if (auto const* paintable_box = as_if(layout_node.first_paintable())) { + if (auto first_paintable = layout_node.first_paintable(); auto const* paintable_box = as_if(first_paintable.ptr())) { auto const& box_model = paintable_box->box_model(); // Dump the horizontal box properties builder.appendff(" [{}+{}+{} {} {}+{}+{}]", @@ -385,14 +385,15 @@ void dump_tree(StringBuilder& builder, Layout::Node const& layout_node, bool sho if (auto const* block_container = as_if(layout_node); block_container && block_container->children_are_inline() && block_container->paintable_with_lines()) { size_t fragment_index = 0; - for (auto const& fragment : block_container->paintable_with_lines()->fragments()) + auto paintable_with_lines = block_container->paintable_with_lines(); + for (auto const& fragment : paintable_with_lines->fragments()) dump_fragment(fragment, fragment_index++); } if (is(layout_node) && layout_node.first_paintable()) { auto const& inline_node = static_cast(layout_node); for (auto const& paintable : inline_node.paintables()) { - auto const& paintable_with_lines = static_cast(paintable); + auto const& paintable_with_lines = static_cast(*paintable); auto const& fragments = paintable_with_lines.fragments(); for (size_t fragment_index = 0; fragment_index < fragments.size(); ++fragment_index) { auto const& fragment = fragments[fragment_index]; @@ -748,9 +749,9 @@ void dump_tree(StringBuilder& builder, Painting::Paintable const& paintable, boo else builder.append(paintable_color_on); - builder.appendff("{}{} ({})", node_paintable.class_name(), color_off, node_paintable.layout_node().debug_description()); + builder.appendff("{}{} ({})", node_paintable->class_name(), color_off, node_paintable->layout_node().debug_description()); - if (auto const* paintable_box = as_if(node_paintable)) { + if (auto const* paintable_box = as_if(*node_paintable)) { builder.appendff(" {}", paintable_box->absolute_border_box_rect()); if (paintable_box->has_scrollable_overflow()) @@ -761,7 +762,7 @@ void dump_tree(StringBuilder& builder, Painting::Paintable const& paintable, boo } builder.append("\n"sv); - for (auto const* child = node_paintable.first_child(); child; child = child->next_sibling()) + for (auto child = node_paintable->first_child(); child; child = child->next_sibling()) dump_tree(builder, *child, colorize, indent + 1); dumped_any = true; } diff --git a/Libraries/LibWeb/HTML/FormAssociatedElement.cpp b/Libraries/LibWeb/HTML/FormAssociatedElement.cpp index 10d6f6b737..e4731b1549 100644 --- a/Libraries/LibWeb/HTML/FormAssociatedElement.cpp +++ b/Libraries/LibWeb/HTML/FormAssociatedElement.cpp @@ -1118,7 +1118,7 @@ void FormAssociatedTextControlElement::scroll_cursor_into_view() if (!text_node) return; - auto* paintable = text_node->paintable(); + auto paintable = text_node->paintable(); if (!paintable) return; @@ -1140,7 +1140,7 @@ void FormAssociatedTextControlElement::selection_was_changed(SelectionSource sou if (!text_node) return; // NB: Called during selection change handling, layout may be stale. - auto* text_paintable = text_node->unsafe_paintable(); + auto text_paintable = text_node->unsafe_paintable(); if (!text_paintable) return; diff --git a/Libraries/LibWeb/HTML/HTMLElement.cpp b/Libraries/LibWeb/HTML/HTMLElement.cpp index 16fd5408fb..7aae7b5ebd 100644 --- a/Libraries/LibWeb/HTML/HTMLElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLElement.cpp @@ -676,7 +676,7 @@ int HTMLElement::offset_width() const const_cast(document()).update_layout_if_needed_for_node(*this, DOM::UpdateLayoutReason::HTMLElementOffsetWidth); // 1. If the element does not have any associated box return zero and terminate this algorithm. - auto const* box = paintable_box(); + auto box = paintable_box(); if (!box) return 0; @@ -695,7 +695,7 @@ int HTMLElement::offset_height() const const_cast(document()).update_layout_if_needed_for_node(*this, DOM::UpdateLayoutReason::HTMLElementOffsetHeight); // 1. If the element does not have any associated box return zero and terminate this algorithm. - auto const* box = paintable_box(); + auto box = paintable_box(); if (!box) return 0; diff --git a/Libraries/LibWeb/HTML/HTMLImageElement.cpp b/Libraries/LibWeb/HTML/HTMLImageElement.cpp index 50a8a555a7..3a02e3c978 100644 --- a/Libraries/LibWeb/HTML/HTMLImageElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLImageElement.cpp @@ -292,7 +292,7 @@ WebIDL::UnsignedLong HTMLImageElement::width() const const_cast(document()).update_layout_if_needed_for_node(*this, DOM::UpdateLayoutReason::HTMLImageElementWidth); // Return the rendered width of the image, in CSS pixels, if the image is being rendered. - if (auto* paintable_box = this->paintable_box()) + if (auto paintable_box = this->paintable_box()) return paintable_box->content_width().to_int(); // On setting [the width or height IDL attribute], they must act as if they reflected the respective content attributes of the same name. @@ -323,7 +323,7 @@ WebIDL::UnsignedLong HTMLImageElement::height() const const_cast(document()).update_layout_if_needed_for_node(*this, DOM::UpdateLayoutReason::HTMLImageElementHeight); // Return the rendered height of the image, in CSS pixels, if the image is being rendered. - if (auto* paintable_box = this->paintable_box()) + if (auto paintable_box = this->paintable_box()) return paintable_box->content_height().to_int(); // On setting [the width or height IDL attribute], they must act as if they reflected the respective content attributes of the same name. @@ -380,7 +380,7 @@ int HTMLImageElement::x() const // to the element and its ancestors, or zero if there is no box. const_cast(document()).update_layout_if_needed_for_node(*this, DOM::UpdateLayoutReason::HTMLImageElementX); - auto const* paintable_box = this->paintable_box(); + auto paintable_box = this->paintable_box(); if (!paintable_box) return 0; @@ -399,7 +399,7 @@ int HTMLImageElement::y() const // to the element and its ancestors, or zero if there is no box. const_cast(document()).update_layout_if_needed_for_node(*this, DOM::UpdateLayoutReason::HTMLImageElementY); - auto const* paintable_box = this->paintable_box(); + auto paintable_box = this->paintable_box(); if (!paintable_box) return 0; diff --git a/Libraries/LibWeb/HTML/HTMLInputElement.cpp b/Libraries/LibWeb/HTML/HTMLInputElement.cpp index 54361297bb..515996a445 100644 --- a/Libraries/LibWeb/HTML/HTMLInputElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLInputElement.cpp @@ -2376,7 +2376,7 @@ WebIDL::UnsignedLong HTMLInputElement::height() const return 0; // Return the rendered height of the image, in CSS pixels, if the image is being rendered. - if (auto* paintable_box = this->paintable_box()) + if (auto paintable_box = this->paintable_box()) return paintable_box->content_height().to_int(); // On setting [the width or height IDL attribute], they must act as if they reflected the respective content attributes of the same name. @@ -2411,7 +2411,7 @@ WebIDL::UnsignedLong HTMLInputElement::width() const return 0; // Return the rendered width of the image, in CSS pixels, if the image is being rendered. - if (auto* paintable_box = this->paintable_box()) + if (auto paintable_box = this->paintable_box()) return paintable_box->content_width().to_int(); // On setting [the width or height IDL attribute], they must act as if they reflected the respective content attributes of the same name. diff --git a/Libraries/LibWeb/HTML/HTMLLabelElement.cpp b/Libraries/LibWeb/HTML/HTMLLabelElement.cpp index 9abd8d9236..9c3caf1b98 100644 --- a/Libraries/LibWeb/HTML/HTMLLabelElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLLabelElement.cpp @@ -86,7 +86,7 @@ void HTMLLabelElement::activation_behavior(DOM::Event const& event) document().update_layout(DOM::UpdateLayoutReason::HTMLLabelElementActivationBehavior); // Recompute offsetX/offsetY relative to the control element, since the original values are relative to the label. - if (auto const* paintable = control_element->paintable(); paintable && document().navigable()) { + if (auto paintable = control_element->paintable(); paintable && document().navigable()) { auto scroll_offset = document().navigable()->viewport_scroll_offset(); auto page_position = CSSPixelPoint { CSSPixels(mouse_event.client_x()) + scroll_offset.x(), CSSPixels(mouse_event.client_y()) + scroll_offset.y() }; auto box_position = paintable->box_type_agnostic_position(); diff --git a/Libraries/LibWeb/HTML/Navigable.cpp b/Libraries/LibWeb/HTML/Navigable.cpp index 46b1a6d5d0..84e1c83bf7 100644 --- a/Libraries/LibWeb/HTML/Navigable.cpp +++ b/Libraries/LibWeb/HTML/Navigable.cpp @@ -2813,7 +2813,7 @@ CSSPixelPoint Navigable::to_top_level_position(CSSPixelPoint a_position) break; if (!ancestor->container()) return {}; - auto const* paintable = ancestor->container()->paintable(); + auto paintable = ancestor->container()->paintable(); if (!paintable) return {}; diff --git a/Libraries/LibWeb/Internals/Internals.cpp b/Libraries/LibWeb/Internals/Internals.cpp index 1b24677894..d45c36c3f3 100644 --- a/Libraries/LibWeb/Internals/Internals.cpp +++ b/Libraries/LibWeb/Internals/Internals.cpp @@ -489,7 +489,7 @@ String Internals::dump_paintable_tree(GC::Ref node) { node->document().update_layout(DOM::UpdateLayoutReason::Debugging); - auto* paintable = node->paintable(); + auto paintable = node->paintable(); if (!paintable) return "(no paintable)"_string; diff --git a/Libraries/LibWeb/Layout/AudioBox.cpp b/Libraries/LibWeb/Layout/AudioBox.cpp index aa26fec379..bfdd9d63c8 100644 --- a/Libraries/LibWeb/Layout/AudioBox.cpp +++ b/Libraries/LibWeb/Layout/AudioBox.cpp @@ -33,7 +33,7 @@ bool AudioBox::can_have_children() const return dom_node().shadow_root() != nullptr; } -GC::Ptr AudioBox::create_paintable() const +RefPtr AudioBox::create_paintable() const { return Painting::PaintableBox::create(*this); } diff --git a/Libraries/LibWeb/Layout/AudioBox.h b/Libraries/LibWeb/Layout/AudioBox.h index 14193fe642..bc7c3d3ee7 100644 --- a/Libraries/LibWeb/Layout/AudioBox.h +++ b/Libraries/LibWeb/Layout/AudioBox.h @@ -22,7 +22,7 @@ public: virtual bool can_have_children() const override; - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: // Treat the audio element as if it was not a replaced element, sizing based on its content. diff --git a/Libraries/LibWeb/Layout/BlockContainer.cpp b/Libraries/LibWeb/Layout/BlockContainer.cpp index fdd8545b85..6e1663c19b 100644 --- a/Libraries/LibWeb/Layout/BlockContainer.cpp +++ b/Libraries/LibWeb/Layout/BlockContainer.cpp @@ -23,12 +23,13 @@ BlockContainer::BlockContainer(DOM::Document& document, DOM::Node* node, Nonnull BlockContainer::~BlockContainer() = default; -Painting::PaintableWithLines const* BlockContainer::paintable_with_lines() const +RefPtr BlockContainer::paintable_with_lines() const { - return as_if(Box::paintable_box()); + auto paintable_box = Box::paintable_box(); + return as_if(paintable_box.ptr()); } -GC::Ptr BlockContainer::create_paintable() const +RefPtr BlockContainer::create_paintable() const { return Painting::PaintableWithLines::create(*this); } diff --git a/Libraries/LibWeb/Layout/BlockContainer.h b/Libraries/LibWeb/Layout/BlockContainer.h index a816e630fb..cba3753593 100644 --- a/Libraries/LibWeb/Layout/BlockContainer.h +++ b/Libraries/LibWeb/Layout/BlockContainer.h @@ -21,9 +21,9 @@ public: BlockContainer(DOM::Document&, DOM::Node*, NonnullOwnPtr); virtual ~BlockContainer() override; - Painting::PaintableWithLines const* paintable_with_lines() const; + RefPtr paintable_with_lines() const; - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual bool is_block_container() const final { return true; } diff --git a/Libraries/LibWeb/Layout/Box.cpp b/Libraries/LibWeb/Layout/Box.cpp index 36520c6c14..0509a91858 100644 --- a/Libraries/LibWeb/Layout/Box.cpp +++ b/Libraries/LibWeb/Layout/Box.cpp @@ -48,19 +48,23 @@ void Box::visit_edges(Cell::Visitor& visitor) visitor.visit(m_contained_abspos_children); } -GC::Ptr Box::create_paintable() const +RefPtr Box::create_paintable() const { return Painting::PaintableBox::create(*this); } -Painting::PaintableBox* Box::paintable_box() +RefPtr Box::paintable_box() { - return static_cast(Node::first_paintable()); + if (auto paintable = Node::first_paintable()) + return static_cast(*paintable); + return nullptr; } -Painting::PaintableBox const* Box::paintable_box() const +RefPtr Box::paintable_box() const { - return static_cast(Node::first_paintable()); + if (auto paintable = Node::first_paintable()) + return static_cast(*paintable); + return nullptr; } Optional Box::preferred_aspect_ratio() const diff --git a/Libraries/LibWeb/Layout/Box.h b/Libraries/LibWeb/Layout/Box.h index 99434ee626..aa6ca6eb4e 100644 --- a/Libraries/LibWeb/Layout/Box.h +++ b/Libraries/LibWeb/Layout/Box.h @@ -31,8 +31,8 @@ class WEB_API Box : public NodeWithStyleAndBoxModelMetrics { GC_DECLARE_ALLOCATOR(Box); public: - Painting::PaintableBox const* paintable_box() const; - Painting::PaintableBox* paintable_box(); + RefPtr paintable_box() const; + RefPtr paintable_box(); // https://www.w3.org/TR/css-images-3/#natural-dimensions virtual CSS::SizeWithAspectRatio natural_size() const { return {}; } @@ -53,7 +53,7 @@ public: virtual void did_set_content_size() { } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; void add_contained_abspos_child(GC::Ref child) { m_contained_abspos_children.append(child); } void clear_contained_abspos_children() { m_contained_abspos_children.clear(); } diff --git a/Libraries/LibWeb/Layout/CanvasBox.cpp b/Libraries/LibWeb/Layout/CanvasBox.cpp index 72f1bde0b3..5079fe8131 100644 --- a/Libraries/LibWeb/Layout/CanvasBox.cpp +++ b/Libraries/LibWeb/Layout/CanvasBox.cpp @@ -27,7 +27,7 @@ CSS::SizeWithAspectRatio CanvasBox::compute_auto_content_box_size() const return { width, height, CSSPixelFraction(width, height) }; } -GC::Ptr CanvasBox::create_paintable() const +RefPtr CanvasBox::create_paintable() const { return Painting::CanvasPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/CanvasBox.h b/Libraries/LibWeb/Layout/CanvasBox.h index a2c1271dbe..027bb8c873 100644 --- a/Libraries/LibWeb/Layout/CanvasBox.h +++ b/Libraries/LibWeb/Layout/CanvasBox.h @@ -21,7 +21,7 @@ public: HTML::HTMLCanvasElement const& dom_node() const { return static_cast(*ReplacedBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual CSS::SizeWithAspectRatio compute_auto_content_box_size() const override; diff --git a/Libraries/LibWeb/Layout/CheckBox.cpp b/Libraries/LibWeb/Layout/CheckBox.cpp index d41ed2ceba..4a017d87a9 100644 --- a/Libraries/LibWeb/Layout/CheckBox.cpp +++ b/Libraries/LibWeb/Layout/CheckBox.cpp @@ -20,7 +20,7 @@ CheckBox::CheckBox(DOM::Document& document, HTML::HTMLInputElement& element, GC: CheckBox::~CheckBox() = default; -GC::Ptr CheckBox::create_paintable() const +RefPtr CheckBox::create_paintable() const { return Painting::CheckBoxPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/CheckBox.h b/Libraries/LibWeb/Layout/CheckBox.h index d7f406606a..561d3a3f31 100644 --- a/Libraries/LibWeb/Layout/CheckBox.h +++ b/Libraries/LibWeb/Layout/CheckBox.h @@ -21,7 +21,7 @@ public: private: virtual CSS::SizeWithAspectRatio compute_auto_content_box_size() const override { return { 13, 13, {} }; } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; }; } diff --git a/Libraries/LibWeb/Layout/FieldSetBox.cpp b/Libraries/LibWeb/Layout/FieldSetBox.cpp index d1a938f5bd..4953a7b5ee 100644 --- a/Libraries/LibWeb/Layout/FieldSetBox.cpp +++ b/Libraries/LibWeb/Layout/FieldSetBox.cpp @@ -37,7 +37,7 @@ GC::Ptr FieldSetBox::rendered_legend() const return legend; } -GC::Ptr FieldSetBox::create_paintable() const +RefPtr FieldSetBox::create_paintable() const { return Painting::FieldSetPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/FieldSetBox.h b/Libraries/LibWeb/Layout/FieldSetBox.h index da0ca4b23b..85e81d3933 100644 --- a/Libraries/LibWeb/Layout/FieldSetBox.h +++ b/Libraries/LibWeb/Layout/FieldSetBox.h @@ -25,7 +25,7 @@ public: DOM::Element const& dom_node() const { return static_cast(*BlockContainer::dom_node()); } GC::Ptr rendered_legend() const; - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual bool is_fieldset_box() const final diff --git a/Libraries/LibWeb/Layout/ImageBox.cpp b/Libraries/LibWeb/Layout/ImageBox.cpp index 1a3f60ef6d..8d1c176a66 100644 --- a/Libraries/LibWeb/Layout/ImageBox.cpp +++ b/Libraries/LibWeb/Layout/ImageBox.cpp @@ -69,7 +69,7 @@ bool ImageBox::renders_as_alt_text() const return !m_image_provider.is_image_available(); } -GC::Ptr ImageBox::create_paintable() const +RefPtr ImageBox::create_paintable() const { return Painting::ImagePaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/ImageBox.h b/Libraries/LibWeb/Layout/ImageBox.h index 7efbb22159..371e700894 100644 --- a/Libraries/LibWeb/Layout/ImageBox.h +++ b/Libraries/LibWeb/Layout/ImageBox.h @@ -21,7 +21,7 @@ public: bool renders_as_alt_text() const; - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; auto const& image_provider() const { return m_image_provider; } auto& image_provider() { return m_image_provider; } diff --git a/Libraries/LibWeb/Layout/InlineNode.cpp b/Libraries/LibWeb/Layout/InlineNode.cpp index fc23e9f784..bf76422d3b 100644 --- a/Libraries/LibWeb/Layout/InlineNode.cpp +++ b/Libraries/LibWeb/Layout/InlineNode.cpp @@ -23,11 +23,11 @@ InlineNode::InlineNode(DOM::Document& document, DOM::Element* element, GC::Ref InlineNode::create_paintable_for_line_with_index(size_t line_index) const +NonnullRefPtr InlineNode::create_paintable_for_line_with_index(size_t line_index) const { for (auto const& paintable : paintables()) { - if (is(paintable)) { - auto const& paintable_with_lines = static_cast(paintable); + if (is(*paintable)) { + auto const& paintable_with_lines = static_cast(*paintable); if (paintable_with_lines.line_index() == line_index) { return const_cast(paintable_with_lines); } diff --git a/Libraries/LibWeb/Layout/InlineNode.h b/Libraries/LibWeb/Layout/InlineNode.h index a443468a81..705917bf4d 100644 --- a/Libraries/LibWeb/Layout/InlineNode.h +++ b/Libraries/LibWeb/Layout/InlineNode.h @@ -18,7 +18,7 @@ public: InlineNode(DOM::Document&, DOM::Element*, GC::Ref); virtual ~InlineNode() override; - GC::Ptr create_paintable_for_line_with_index(size_t line_index) const; + NonnullRefPtr create_paintable_for_line_with_index(size_t line_index) const; private: virtual bool is_inline_node() const override { return true; } diff --git a/Libraries/LibWeb/Layout/LayoutState.cpp b/Libraries/LibWeb/Layout/LayoutState.cpp index 9575eed8c8..f424c4ff9c 100644 --- a/Libraries/LibWeb/Layout/LayoutState.cpp +++ b/Libraries/LibWeb/Layout/LayoutState.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -189,7 +188,7 @@ static CSSPixelRect measure_scrollable_overflow(Box const& box, ContainedBoxesMa auto overflow_directions = physical_overflow_directions(box); // - All line boxes directly contained by the scroll container. - if (auto const* paintable_with_lines = as_if(box.first_paintable())) { + if (auto first_paintable = box.first_paintable(); auto const* paintable_with_lines = as_if(first_paintable.ptr())) { for (auto const& fragment : paintable_with_lines->fragments()) scrollable_overflow_rect.unite(fragment.absolute_rect()); } @@ -315,11 +314,11 @@ void LayoutState::resolve_relative_positions() auto& node = const_cast(used_values.node()); for (auto& paintable : node.paintables()) { - if (!(is(paintable) && is(paintable.layout_node()))) + auto* inline_paintable = as_if(paintable.ptr()); + if (!inline_paintable || !is(inline_paintable->layout_node())) continue; - auto const& inline_paintable = static_cast(paintable); - for (auto& fragment : inline_paintable.fragments()) { + for (auto& fragment : inline_paintable->fragments()) { auto const& fragment_node = fragment.layout_node(); if (!is(*fragment_node.parent())) continue; @@ -332,7 +331,8 @@ void LayoutState::resolve_relative_positions() break; if (ancestor->computed_values().position() == CSS::Positioning::Relative) { VERIFY(ancestor->first_paintable()); - auto const& ancestor_node = as(*ancestor->first_paintable()); + auto ancestor_paintable = ancestor->first_paintable(); + auto const& ancestor_node = as(*ancestor_paintable); auto const& inset = ancestor_node.box_model().inset; offset.translate_by(inset.left, inset.top); } @@ -343,14 +343,14 @@ void LayoutState::resolve_relative_positions() }); } -static void build_paint_tree(Node& node, Painting::Paintable* parent_paintable = nullptr) +static void build_paint_tree(Node& node, RefPtr parent_paintable = nullptr) { for (auto& paintable : node.paintables()) { - if (parent_paintable && !paintable.forms_unconnected_subtree()) { - VERIFY(!paintable.parent()); + if (parent_paintable && !paintable->forms_unconnected_subtree()) { + VERIFY(!paintable->parent()); parent_paintable->append_child(paintable); } - paintable.set_dom_node(node.dom_node()); + paintable->set_dom_node(node.dom_node()); if (node.dom_node()) node.dom_node()->set_paintable(paintable); } @@ -361,19 +361,19 @@ static void build_paint_tree(Node& node, Painting::Paintable* parent_paintable = void LayoutState::commit(Box& root) { - Painting::Paintable* parent_paintable = nullptr; + RefPtr parent_paintable; if (!root.is_viewport()) { - if (auto* existing = as_if(root.first_paintable())) { - parent_paintable = existing->parent(); + if (auto existing = root.first_paintable(); auto* existing_box = as_if(existing.ptr())) { + parent_paintable = existing_box->parent(); if (parent_paintable) - parent_paintable->remove_child(*existing); + parent_paintable->remove_child(*existing_box); } } // Cache existing paintables before clearing. - GC::RootHashMap> paintable_cache(root.document().heap()); + HashMap> paintable_cache; root.for_each_in_inclusive_subtree([&](Node& node) { - if (auto* paintable_box = as_if(node.first_paintable())) { + if (auto paintable = node.first_paintable(); auto* paintable_box = as_if(paintable.ptr())) { // InlineNodes are excluded because they can span multiple lines, with a separate // InlinePaintable created for each line via create_paintable_for_line_with_index(). // This 1:N relationship between layout node and paintables, combined with the @@ -410,7 +410,7 @@ void LayoutState::commit(Box& root) }); HashTable text_nodes; - HashTable inline_node_paintables; + HashTable> inline_node_paintables; auto transfer_box_model_metrics = [](Painting::BoxModelMetrics& box_model, UsedValues const& used_values) { box_model.inset = { used_values.inset_top, used_values.inset_right, used_values.inset_bottom, used_values.inset_left }; @@ -430,7 +430,7 @@ void LayoutState::commit(Box& root) if (auto const* used_values = try_get(inline_node)) transfer_box_model_metrics(line_paintable->box_model(), *used_values); if (!inline_node_paintables.contains(line_paintable.ptr())) { - inline_node_paintables.set(line_paintable.ptr()); + inline_node_paintables.set(line_paintable); inline_node.add_paintable(line_paintable); } return true; @@ -445,7 +445,7 @@ void LayoutState::commit(Box& root) if (m_subtree_root && !m_subtree_root->is_inclusive_ancestor_of(node)) return; - GC::Ptr paintable; + RefPtr paintable; // Try to reuse cached paintable for Box nodes if (auto cached = paintable_cache.get(&node); cached.has_value()) { @@ -524,7 +524,8 @@ void LayoutState::commit(Box& root) if (!node.is_box()) return; - auto& paintable = as(*node.first_paintable()); + auto paintable_ref = node.first_paintable(); + auto& paintable = as(*paintable_ref); CSSPixelPoint offset; if (used_values.containing_line_box_fragment.has_value()) { @@ -559,7 +560,10 @@ void LayoutState::commit(Box& root) resolve_relative_positions(); // Measure size of paintables created for inline nodes. - for (auto* paintable_with_lines : inline_node_paintables) { + for (auto const& weak_paintable_with_lines : inline_node_paintables) { + auto paintable_with_lines = weak_paintable_with_lines.strong_ref(); + if (!paintable_with_lines) + continue; if (!is(paintable_with_lines->layout_node())) continue; @@ -636,7 +640,7 @@ void LayoutState::commit(Box& root) m_used_values_store.for_each([&](UsedValues& used_values) { auto& node = used_values.node(); for (auto& paintable : node.paintables()) { - auto* paintable_box = as_if(paintable); + auto* paintable_box = as_if(paintable.ptr()); if (!paintable_box) continue; @@ -648,7 +652,7 @@ void LayoutState::commit(Box& root) auto sticky_insets = make(); auto const& inset = node.computed_values().inset(); - auto const* nearest_scrollable_ancestor = paintable_box->nearest_scrollable_ancestor(); + auto nearest_scrollable_ancestor = paintable_box->nearest_scrollable_ancestor(); CSSPixelSize scrollport_size; if (nearest_scrollable_ancestor) scrollport_size = nearest_scrollable_ancestor->absolute_rect().size(); diff --git a/Libraries/LibWeb/Layout/ListItemMarkerBox.cpp b/Libraries/LibWeb/Layout/ListItemMarkerBox.cpp index 9b59cc8f0c..cfb9323345 100644 --- a/Libraries/LibWeb/Layout/ListItemMarkerBox.cpp +++ b/Libraries/LibWeb/Layout/ListItemMarkerBox.cpp @@ -75,7 +75,7 @@ Optional ListItemMarkerBox::text() const }); } -GC::Ptr ListItemMarkerBox::create_paintable() const +RefPtr ListItemMarkerBox::create_paintable() const { return Painting::MarkerPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/ListItemMarkerBox.h b/Libraries/LibWeb/Layout/ListItemMarkerBox.h index 8fa14bb2ba..89de9ca2e3 100644 --- a/Libraries/LibWeb/Layout/ListItemMarkerBox.h +++ b/Libraries/LibWeb/Layout/ListItemMarkerBox.h @@ -24,7 +24,7 @@ public: Optional text() const; - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; CSS::ListStyleType const& list_style_type() const { return m_list_style_type; } CSS::ListStylePosition list_style_position() const { return m_list_style_position; } diff --git a/Libraries/LibWeb/Layout/NavigableContainerViewport.cpp b/Libraries/LibWeb/Layout/NavigableContainerViewport.cpp index 3b763a4b1f..0cced7128d 100644 --- a/Libraries/LibWeb/Layout/NavigableContainerViewport.cpp +++ b/Libraries/LibWeb/Layout/NavigableContainerViewport.cpp @@ -48,7 +48,7 @@ void NavigableContainerViewport::did_set_content_size() dom_node().content_navigable()->set_viewport_size(paintable_box()->content_size()); } -GC::Ptr NavigableContainerViewport::create_paintable() const +RefPtr NavigableContainerViewport::create_paintable() const { return Painting::NavigableContainerViewportPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/NavigableContainerViewport.h b/Libraries/LibWeb/Layout/NavigableContainerViewport.h index cefa91cbed..b55bf54cf8 100644 --- a/Libraries/LibWeb/Layout/NavigableContainerViewport.h +++ b/Libraries/LibWeb/Layout/NavigableContainerViewport.h @@ -22,7 +22,7 @@ public: [[nodiscard]] HTML::NavigableContainer const& dom_node() const { return as(*ReplacedBox::dom_node()); } [[nodiscard]] HTML::NavigableContainer& dom_node() { return as(*ReplacedBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual CSS::SizeWithAspectRatio natural_size() const override; diff --git a/Libraries/LibWeb/Layout/Node.cpp b/Libraries/LibWeb/Layout/Node.cpp index 7daecfa145..d9db6c4bed 100644 --- a/Libraries/LibWeb/Layout/Node.cpp +++ b/Libraries/LibWeb/Layout/Node.cpp @@ -59,9 +59,6 @@ void Node::visit_edges(Cell::Visitor& visitor) { Base::visit_edges(visitor); visitor.visit(m_dom_node); - for (auto const& paintable : m_paintable) { - visitor.visit(GC::Ptr { &paintable }); - } visitor.visit(m_containing_block); visitor.visit(m_inline_containing_block_if_applicable); visitor.visit(m_pseudo_element_generator); @@ -610,7 +607,7 @@ void NodeWithStyle::ImageObserver::image_style_value_did_update(CSS::ImageStyleV VERIFY(m_owner); for (auto& paintable : m_owner->paintables()) - paintable.set_needs_repaint(); + paintable->set_needs_repaint(); // The body's background propagates to the root element's paintable, which holds the cached draw commands. if (m_owner->is_body()) { @@ -619,7 +616,7 @@ void NodeWithStyle::ImageObserver::image_style_value_did_update(CSS::ImageStyleV if (auto html_layout_node = html_element->unsafe_layout_node()) { if (html_element->should_use_body_background_properties()) { for (auto& paintable : html_layout_node->paintables()) - paintable.set_needs_repaint(); + paintable->set_needs_repaint(); } } } @@ -1256,7 +1253,7 @@ bool NodeWithStyle::is_scroll_container() const || overflow_value_makes_box_a_scroll_container(computed_values().overflow_y()); } -void Node::add_paintable(GC::Ptr paintable) +void Node::add_paintable(RefPtr paintable) { if (!paintable) return; @@ -1265,10 +1262,14 @@ void Node::add_paintable(GC::Ptr paintable) void Node::clear_paintables() { + for (auto& paintable : m_paintable) { + if (paintable->parent()) + paintable->remove(); + } m_paintable.clear(); } -GC::Ptr Node::create_paintable() const +RefPtr Node::create_paintable() const { return nullptr; } diff --git a/Libraries/LibWeb/Layout/Node.h b/Libraries/LibWeb/Layout/Node.h index 9166a569ad..4418706919 100644 --- a/Libraries/LibWeb/Layout/Node.h +++ b/Libraries/LibWeb/Layout/Node.h @@ -7,6 +7,7 @@ #pragma once +#include #include #include #include @@ -65,16 +66,26 @@ public: m_pseudo_element_generator = &element; } - using PaintableList = IntrusiveList<&Painting::Paintable::m_list_node>; + using PaintableList = DoublyLinkedList>; - Painting::Paintable* first_paintable() { return m_paintable.first(); } - Painting::Paintable const* first_paintable() const { return m_paintable.first(); } + RefPtr first_paintable() + { + if (m_paintable.is_empty()) + return nullptr; + return m_paintable.first(); + } + RefPtr first_paintable() const + { + if (m_paintable.is_empty()) + return nullptr; + return m_paintable.first(); + } PaintableList& paintables() { return m_paintable; } PaintableList const& paintables() const { return m_paintable; } - void add_paintable(GC::Ptr); + void add_paintable(RefPtr); void clear_paintables(); - virtual GC::Ptr create_paintable() const; + virtual RefPtr create_paintable() const; DOM::Document& document(); DOM::Document const& document() const; diff --git a/Libraries/LibWeb/Layout/RadioButton.cpp b/Libraries/LibWeb/Layout/RadioButton.cpp index 53b3c60956..57fa36d904 100644 --- a/Libraries/LibWeb/Layout/RadioButton.cpp +++ b/Libraries/LibWeb/Layout/RadioButton.cpp @@ -21,7 +21,7 @@ RadioButton::RadioButton(DOM::Document& document, HTML::HTMLInputElement& elemen RadioButton::~RadioButton() = default; -GC::Ptr RadioButton::create_paintable() const +RefPtr RadioButton::create_paintable() const { return Painting::RadioButtonPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/RadioButton.h b/Libraries/LibWeb/Layout/RadioButton.h index 6db6d4c9a1..482397b597 100644 --- a/Libraries/LibWeb/Layout/RadioButton.h +++ b/Libraries/LibWeb/Layout/RadioButton.h @@ -21,7 +21,7 @@ public: private: CSS::SizeWithAspectRatio compute_auto_content_box_size() const override { return { 12, 12, {} }; } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; }; } diff --git a/Libraries/LibWeb/Layout/SVGClipBox.cpp b/Libraries/LibWeb/Layout/SVGClipBox.cpp index 6896b309f2..5d0c8e1d29 100644 --- a/Libraries/LibWeb/Layout/SVGClipBox.cpp +++ b/Libraries/LibWeb/Layout/SVGClipBox.cpp @@ -17,7 +17,7 @@ SVGClipBox::SVGClipBox(DOM::Document& document, SVG::SVGClipPathElement& element { } -GC::Ptr SVGClipBox::create_paintable() const +RefPtr SVGClipBox::create_paintable() const { return Painting::SVGClipPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGClipBox.h b/Libraries/LibWeb/Layout/SVGClipBox.h index 407892162f..e30f872f7f 100644 --- a/Libraries/LibWeb/Layout/SVGClipBox.h +++ b/Libraries/LibWeb/Layout/SVGClipBox.h @@ -23,7 +23,7 @@ public: SVG::SVGClipPathElement& dom_node() { return as(SVGBox::dom_node()); } SVG::SVGClipPathElement const& dom_node() const { return as(SVGBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual bool is_svg_clip_box() const final { return true; } diff --git a/Libraries/LibWeb/Layout/SVGForeignObjectBox.cpp b/Libraries/LibWeb/Layout/SVGForeignObjectBox.cpp index 6eb8ac9b08..b458ef52df 100644 --- a/Libraries/LibWeb/Layout/SVGForeignObjectBox.cpp +++ b/Libraries/LibWeb/Layout/SVGForeignObjectBox.cpp @@ -17,7 +17,7 @@ SVGForeignObjectBox::SVGForeignObjectBox(DOM::Document& document, SVG::SVGForeig { } -GC::Ptr SVGForeignObjectBox::create_paintable() const +RefPtr SVGForeignObjectBox::create_paintable() const { return Painting::SVGForeignObjectPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGForeignObjectBox.h b/Libraries/LibWeb/Layout/SVGForeignObjectBox.h index c462c891d3..c8efcb2f91 100644 --- a/Libraries/LibWeb/Layout/SVGForeignObjectBox.h +++ b/Libraries/LibWeb/Layout/SVGForeignObjectBox.h @@ -24,7 +24,7 @@ public: SVG::SVGForeignObjectElement& dom_node() { return static_cast(*BlockContainer::dom_node()); } SVG::SVGForeignObjectElement const& dom_node() const { return static_cast(*BlockContainer::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual bool is_svg_foreign_object_box() const override { return true; } diff --git a/Libraries/LibWeb/Layout/SVGGeometryBox.cpp b/Libraries/LibWeb/Layout/SVGGeometryBox.cpp index 1290097058..c3a7c551da 100644 --- a/Libraries/LibWeb/Layout/SVGGeometryBox.cpp +++ b/Libraries/LibWeb/Layout/SVGGeometryBox.cpp @@ -19,7 +19,7 @@ SVGGeometryBox::SVGGeometryBox(DOM::Document& document, SVG::SVGGeometryElement& { } -GC::Ptr SVGGeometryBox::create_paintable() const +RefPtr SVGGeometryBox::create_paintable() const { return Painting::SVGPathPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGGeometryBox.h b/Libraries/LibWeb/Layout/SVGGeometryBox.h index 848a706210..10410772cd 100644 --- a/Libraries/LibWeb/Layout/SVGGeometryBox.h +++ b/Libraries/LibWeb/Layout/SVGGeometryBox.h @@ -23,7 +23,7 @@ public: SVG::SVGGeometryElement& dom_node() { return static_cast(SVGGraphicsBox::dom_node()); } SVG::SVGGeometryElement const& dom_node() const { return static_cast(SVGGraphicsBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual bool is_svg_geometry_box() const final { return true; } diff --git a/Libraries/LibWeb/Layout/SVGGraphicsBox.cpp b/Libraries/LibWeb/Layout/SVGGraphicsBox.cpp index fca4156049..0b1af66300 100644 --- a/Libraries/LibWeb/Layout/SVGGraphicsBox.cpp +++ b/Libraries/LibWeb/Layout/SVGGraphicsBox.cpp @@ -17,7 +17,7 @@ SVGGraphicsBox::SVGGraphicsBox(DOM::Document& document, SVG::SVGGraphicsElement& { } -GC::Ptr SVGGraphicsBox::create_paintable() const +RefPtr SVGGraphicsBox::create_paintable() const { return Painting::SVGGraphicsPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGGraphicsBox.h b/Libraries/LibWeb/Layout/SVGGraphicsBox.h index 98e05e0423..539803269f 100644 --- a/Libraries/LibWeb/Layout/SVGGraphicsBox.h +++ b/Libraries/LibWeb/Layout/SVGGraphicsBox.h @@ -24,7 +24,7 @@ public: SVG::SVGGraphicsElement& dom_node() { return as(SVGBox::dom_node()); } SVG::SVGGraphicsElement const& dom_node() const { return as(SVGBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual bool is_svg_graphics_box() const override { return true; } diff --git a/Libraries/LibWeb/Layout/SVGImageBox.cpp b/Libraries/LibWeb/Layout/SVGImageBox.cpp index f2c24636d5..18fb066188 100644 --- a/Libraries/LibWeb/Layout/SVGImageBox.cpp +++ b/Libraries/LibWeb/Layout/SVGImageBox.cpp @@ -18,7 +18,7 @@ SVGImageBox::SVGImageBox(DOM::Document& document, SVG::SVGGraphicsElement& eleme { } -GC::Ptr SVGImageBox::create_paintable() const +RefPtr SVGImageBox::create_paintable() const { return Painting::ImagePaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGImageBox.h b/Libraries/LibWeb/Layout/SVGImageBox.h index a4f5b9c5ee..efbca46f3e 100644 --- a/Libraries/LibWeb/Layout/SVGImageBox.h +++ b/Libraries/LibWeb/Layout/SVGImageBox.h @@ -23,7 +23,7 @@ public: SVG::SVGImageElement& dom_node() { return static_cast(SVGGraphicsBox::dom_node()); } SVG::SVGImageElement const& dom_node() const { return static_cast(SVGGraphicsBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; }; } diff --git a/Libraries/LibWeb/Layout/SVGMaskBox.cpp b/Libraries/LibWeb/Layout/SVGMaskBox.cpp index f1ec31d91c..1d96018412 100644 --- a/Libraries/LibWeb/Layout/SVGMaskBox.cpp +++ b/Libraries/LibWeb/Layout/SVGMaskBox.cpp @@ -17,7 +17,7 @@ SVGMaskBox::SVGMaskBox(DOM::Document& document, SVG::SVGMaskElement& element, GC { } -GC::Ptr SVGMaskBox::create_paintable() const +RefPtr SVGMaskBox::create_paintable() const { return Painting::SVGMaskPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGMaskBox.h b/Libraries/LibWeb/Layout/SVGMaskBox.h index fe0ad02728..88cf4e1947 100644 --- a/Libraries/LibWeb/Layout/SVGMaskBox.h +++ b/Libraries/LibWeb/Layout/SVGMaskBox.h @@ -25,7 +25,7 @@ public: SVG::SVGMaskElement& dom_node() { return as(SVGGraphicsBox::dom_node()); } SVG::SVGMaskElement const& dom_node() const { return as(SVGGraphicsBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; }; template<> diff --git a/Libraries/LibWeb/Layout/SVGPatternBox.cpp b/Libraries/LibWeb/Layout/SVGPatternBox.cpp index b163b72e01..662325f3bc 100644 --- a/Libraries/LibWeb/Layout/SVGPatternBox.cpp +++ b/Libraries/LibWeb/Layout/SVGPatternBox.cpp @@ -16,7 +16,7 @@ SVGPatternBox::SVGPatternBox(DOM::Document& document, SVG::SVGPatternElement& el { } -GC::Ptr SVGPatternBox::create_paintable() const +RefPtr SVGPatternBox::create_paintable() const { return Painting::SVGPatternPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGPatternBox.h b/Libraries/LibWeb/Layout/SVGPatternBox.h index 393dba50b1..8921a97d16 100644 --- a/Libraries/LibWeb/Layout/SVGPatternBox.h +++ b/Libraries/LibWeb/Layout/SVGPatternBox.h @@ -22,7 +22,7 @@ public: SVG::SVGPatternElement& dom_node() { return as(SVGBox::dom_node()); } SVG::SVGPatternElement const& dom_node() const { return as(SVGBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual bool is_svg_pattern_box() const final { return true; } diff --git a/Libraries/LibWeb/Layout/SVGSVGBox.cpp b/Libraries/LibWeb/Layout/SVGSVGBox.cpp index 6cdabf30e3..d3805ee646 100644 --- a/Libraries/LibWeb/Layout/SVGSVGBox.cpp +++ b/Libraries/LibWeb/Layout/SVGSVGBox.cpp @@ -20,7 +20,7 @@ SVGSVGBox::SVGSVGBox(DOM::Document& document, SVG::SVGSVGElement& element, GC::R { } -GC::Ptr SVGSVGBox::create_paintable() const +RefPtr SVGSVGBox::create_paintable() const { return Painting::SVGSVGPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGSVGBox.h b/Libraries/LibWeb/Layout/SVGSVGBox.h index 300574d579..3eb1525d0c 100644 --- a/Libraries/LibWeb/Layout/SVGSVGBox.h +++ b/Libraries/LibWeb/Layout/SVGSVGBox.h @@ -24,7 +24,7 @@ public: virtual bool can_have_children() const override { return true; } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual CSS::SizeWithAspectRatio natural_size() const override; diff --git a/Libraries/LibWeb/Layout/SVGTextBox.cpp b/Libraries/LibWeb/Layout/SVGTextBox.cpp index c4a77530e2..2a3dcfb0d4 100644 --- a/Libraries/LibWeb/Layout/SVGTextBox.cpp +++ b/Libraries/LibWeb/Layout/SVGTextBox.cpp @@ -17,7 +17,7 @@ SVGTextBox::SVGTextBox(DOM::Document& document, SVG::SVGTextPositioningElement& { } -GC::Ptr SVGTextBox::create_paintable() const +RefPtr SVGTextBox::create_paintable() const { return Painting::SVGPathPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGTextBox.h b/Libraries/LibWeb/Layout/SVGTextBox.h index 0ca7e4c085..79a967372d 100644 --- a/Libraries/LibWeb/Layout/SVGTextBox.h +++ b/Libraries/LibWeb/Layout/SVGTextBox.h @@ -23,7 +23,7 @@ public: SVG::SVGTextPositioningElement& dom_node() { return static_cast(SVGGraphicsBox::dom_node()); } SVG::SVGTextPositioningElement const& dom_node() const { return static_cast(SVGGraphicsBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: CSSPixelPoint viewbox_origin() const; diff --git a/Libraries/LibWeb/Layout/SVGTextPathBox.cpp b/Libraries/LibWeb/Layout/SVGTextPathBox.cpp index 602cc4e013..5e397242f0 100644 --- a/Libraries/LibWeb/Layout/SVGTextPathBox.cpp +++ b/Libraries/LibWeb/Layout/SVGTextPathBox.cpp @@ -16,7 +16,7 @@ SVGTextPathBox::SVGTextPathBox(DOM::Document& document, SVG::SVGTextPathElement& { } -GC::Ptr SVGTextPathBox::create_paintable() const +RefPtr SVGTextPathBox::create_paintable() const { return Painting::SVGPathPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/SVGTextPathBox.h b/Libraries/LibWeb/Layout/SVGTextPathBox.h index 690c577d50..ba38affadf 100644 --- a/Libraries/LibWeb/Layout/SVGTextPathBox.h +++ b/Libraries/LibWeb/Layout/SVGTextPathBox.h @@ -22,7 +22,7 @@ public: SVG::SVGTextPathElement& dom_node() { return static_cast(SVGGraphicsBox::dom_node()); } SVG::SVGTextPathElement const& dom_node() const { return static_cast(SVGGraphicsBox::dom_node()); } - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: CSSPixelPoint viewbox_origin() const; diff --git a/Libraries/LibWeb/Layout/TextNode.cpp b/Libraries/LibWeb/Layout/TextNode.cpp index 50cf142b48..5f4392570e 100644 --- a/Libraries/LibWeb/Layout/TextNode.cpp +++ b/Libraries/LibWeb/Layout/TextNode.cpp @@ -804,7 +804,7 @@ Optional TextNode::ChunkIterator::try_commit_chunk(size_t start return {}; } -GC::Ptr TextNode::create_paintable() const +RefPtr TextNode::create_paintable() const { return Painting::TextPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/TextNode.h b/Libraries/LibWeb/Layout/TextNode.h index 366b7099ad..69d497c05d 100644 --- a/Libraries/LibWeb/Layout/TextNode.h +++ b/Libraries/LibWeb/Layout/TextNode.h @@ -83,7 +83,7 @@ public: Unicode::Segmenter& grapheme_segmenter() const; Unicode::Segmenter& line_segmenter() const; - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: virtual bool is_text_node() const final { return true; } diff --git a/Libraries/LibWeb/Layout/VideoBox.cpp b/Libraries/LibWeb/Layout/VideoBox.cpp index 29e51e408b..f620300455 100644 --- a/Libraries/LibWeb/Layout/VideoBox.cpp +++ b/Libraries/LibWeb/Layout/VideoBox.cpp @@ -44,7 +44,7 @@ CSS::SizeWithAspectRatio VideoBox::natural_size() const return { natural_size->width(), natural_size->height(), natural_size->width() / natural_size->height() }; } -GC::Ptr VideoBox::create_paintable() const +RefPtr VideoBox::create_paintable() const { return Painting::VideoPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/VideoBox.h b/Libraries/LibWeb/Layout/VideoBox.h index 1d65ff665e..c2f57b7c92 100644 --- a/Libraries/LibWeb/Layout/VideoBox.h +++ b/Libraries/LibWeb/Layout/VideoBox.h @@ -21,7 +21,7 @@ public: virtual bool can_have_children() const override; - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; private: VideoBox(DOM::Document&, DOM::Element&, GC::Ref); diff --git a/Libraries/LibWeb/Layout/Viewport.cpp b/Libraries/LibWeb/Layout/Viewport.cpp index 022df27fa5..fef68bb998 100644 --- a/Libraries/LibWeb/Layout/Viewport.cpp +++ b/Libraries/LibWeb/Layout/Viewport.cpp @@ -29,7 +29,7 @@ DOM::Document const& Viewport::dom_node() const return static_cast(*Node::dom_node()); } -GC::Ptr Viewport::create_paintable() const +RefPtr Viewport::create_paintable() const { return Painting::ViewportPaintable::create(*this); } diff --git a/Libraries/LibWeb/Layout/Viewport.h b/Libraries/LibWeb/Layout/Viewport.h index b76d8a0366..236959a54a 100644 --- a/Libraries/LibWeb/Layout/Viewport.h +++ b/Libraries/LibWeb/Layout/Viewport.h @@ -35,7 +35,7 @@ public: virtual void visit_edges(Visitor&) override; private: - virtual GC::Ptr create_paintable() const override; + virtual RefPtr create_paintable() const override; void update_text_blocks(); diff --git a/Libraries/LibWeb/Page/AutoScrollHandler.cpp b/Libraries/LibWeb/Page/AutoScrollHandler.cpp index 0737c4f323..7c37fa918f 100644 --- a/Libraries/LibWeb/Page/AutoScrollHandler.cpp +++ b/Libraries/LibWeb/Page/AutoScrollHandler.cpp @@ -120,7 +120,7 @@ CSSPixelPoint AutoScrollHandler::process(CSSPixelPoint mouse_position) GC::Ptr AutoScrollHandler::find_scrollable_ancestor(Painting::Paintable const& paintable) { - auto* paintable_box = paintable.containing_block(); + auto paintable_box = paintable.containing_block(); while (paintable_box) { if (paintable_box->could_be_scrolled_by_wheel_event()) { if (auto* element = as_if(paintable_box->dom_node().ptr())) @@ -141,7 +141,7 @@ GC::Ptr AutoScrollHandler::find_scrollable_ancestor(Painting::Pain // Returns the paintable box that manages the scrollport for an auto-scroll container element. When the element is the // document's scrolling element, the viewport paintable is the scroll container. -GC::Ptr AutoScrollHandler::auto_scroll_paintable(DOM::Element& element) +RefPtr AutoScrollHandler::auto_scroll_paintable(DOM::Element& element) { if (element.document().scrolling_element().ptr() == &element) return element.document().paintable(); diff --git a/Libraries/LibWeb/Page/AutoScrollHandler.h b/Libraries/LibWeb/Page/AutoScrollHandler.h index 455ac4249a..94cf77f71e 100644 --- a/Libraries/LibWeb/Page/AutoScrollHandler.h +++ b/Libraries/LibWeb/Page/AutoScrollHandler.h @@ -25,7 +25,7 @@ public: bool is_active() const { return m_active; } static GC::Ptr find_scrollable_ancestor(Painting::Paintable const&); - static GC::Ptr auto_scroll_paintable(DOM::Element&); + static RefPtr auto_scroll_paintable(DOM::Element&); private: void activate(); diff --git a/Libraries/LibWeb/Page/ElementResizeAction.cpp b/Libraries/LibWeb/Page/ElementResizeAction.cpp index 6df33e0bf6..bfee7d64b4 100644 --- a/Libraries/LibWeb/Page/ElementResizeAction.cpp +++ b/Libraries/LibWeb/Page/ElementResizeAction.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -20,7 +21,7 @@ static Optional containing_block_padding_box_size(Layout::Node con auto parent_box = layout_node.containing_block(); if (!parent_box) return {}; - if (auto const* paintable_box = as_if(parent_box->first_paintable())) + if (auto first_paintable = parent_box->first_paintable(); auto const* paintable_box = as_if(first_paintable.ptr())) return paintable_box->absolute_padding_box_rect().size(); return {}; } @@ -29,14 +30,18 @@ ElementResizeAction::ElementResizeAction(GC::Ref element, CSSPixel : m_element(element) , m_pointer_down_origin(pointer_down_origin) { - auto const* paintable_box = m_element->paintable_box(); + auto paintable_box = element->paintable_box(); if (paintable_box) m_initial_border_box_size = paintable_box->absolute_border_box_rect().size(); } void ElementResizeAction::handle_pointer_move(CSSPixelPoint pointer_position) { - auto const* paintable_box = m_element->paintable_box(); + auto element = m_element.ptr(); + if (!element || !element->is_connected()) + return; + + auto paintable_box = element->paintable_box(); if (!paintable_box) return; auto const& layout_node = paintable_box->layout_node(); @@ -89,7 +94,7 @@ void ElementResizeAction::handle_pointer_move(CSSPixelPoint pointer_position) css_height -= metrics.padding.top + metrics.padding.bottom + computed.border_top().width + computed.border_bottom().width; } - auto style = m_element->style_for_bindings(); + auto style = element->style_for_bindings(); auto width_str = MUST(String::formatted("{:.2f}px", max(0.0, css_width.to_double()))); auto height_str = MUST(String::formatted("{:.2f}px", max(0.0, css_height.to_double()))); @@ -97,9 +102,4 @@ void ElementResizeAction::handle_pointer_move(CSSPixelPoint pointer_position) MUST(style->set_property(CSS::PropertyID::Height, height_str)); } -void ElementResizeAction::visit_edges(GC::Cell::Visitor& visitor) const -{ - visitor.visit(m_element); -} - } diff --git a/Libraries/LibWeb/Page/ElementResizeAction.h b/Libraries/LibWeb/Page/ElementResizeAction.h index 7566f7936e..ca2bb94f26 100644 --- a/Libraries/LibWeb/Page/ElementResizeAction.h +++ b/Libraries/LibWeb/Page/ElementResizeAction.h @@ -6,7 +6,7 @@ #pragma once -#include +#include #include #include @@ -20,10 +20,8 @@ public: void handle_pointer_move(CSSPixelPoint pointer_position); - void visit_edges(GC::Cell::Visitor&) const; - private: - GC::Ref m_element; + GC::Weak m_element; CSSPixelPoint m_pointer_down_origin; CSSPixelSize m_initial_border_box_size; }; diff --git a/Libraries/LibWeb/Page/EventHandler.cpp b/Libraries/LibWeb/Page/EventHandler.cpp index 6cbcee5bec..bde18945d2 100644 --- a/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Libraries/LibWeb/Page/EventHandler.cpp @@ -67,7 +67,7 @@ static GC::Ptr dom_node_for_event_dispatch(Painting::Paintable& paint { if (auto node = paintable.dom_node()) return node; - auto* parent = paintable.parent(); + auto parent = paintable.parent(); while (parent) { if (auto node = parent->dom_node()) return node; @@ -197,9 +197,9 @@ static CSSPixelPoint compute_mouse_event_offset(CSSPixelPoint position, Painting // return the x-coordinate of the position where the event occurred, // ignoring the transforms that apply to the element and its ancestors, CSSPixelPoint offset_position = position; - if (is(paintable)) { - offset_position = static_cast(paintable).inverse_transform_point(position); - } else if (auto* containing_block = paintable.containing_block()) { + if (auto const* paintable_box = as_if(paintable)) { + offset_position = paintable_box->inverse_transform_point(position); + } else if (auto containing_block = paintable.containing_block()) { offset_position = containing_block->inverse_transform_point(position); } @@ -550,14 +550,14 @@ EventHandler::EventHandler(Badge, HTML::Navigable& navigable) EventHandler::~EventHandler() = default; -GC::Ptr EventHandler::paint_root() +RefPtr EventHandler::paint_root() { if (!m_navigable->active_document()) return nullptr; return m_navigable->active_document()->paintable_box(); } -GC::Ptr EventHandler::paint_root() const +RefPtr EventHandler::paint_root() const { if (!m_navigable->active_document()) return nullptr; @@ -587,12 +587,12 @@ EventResult EventHandler::handle_mousewheel(CSSPixelPoint visual_viewport_positi auto handled_event = EventResult::Dropped; - GC::Ptr paintable; + RefPtr paintable; if (auto result = target_for_mouse_position(visual_viewport_position); result.has_value()) paintable = result->paintable; if (paintable) { - Painting::Paintable* containing_block = paintable; + RefPtr containing_block = paintable; while (containing_block) { auto handled_scroll_event = containing_block->handle_mousewheel({}, visual_viewport_position, buttons, modifiers, wheel_delta_x, wheel_delta_y); if (handled_scroll_event) @@ -621,7 +621,9 @@ EventResult EventHandler::handle_mousewheel(CSSPixelPoint visual_viewport_positi return EventResult::Dropped; auto page_offset = compute_mouse_event_page_offset(viewport_position); - auto const& offset_paintable = layout_node->first_paintable() ? layout_node->first_paintable() : paintable.ptr(); + RefPtr offset_paintable = layout_node->first_paintable(); + if (!offset_paintable) + offset_paintable = paintable; auto scroll_offset = document->navigable()->viewport_scroll_offset(); auto offset = compute_mouse_event_offset(visual_viewport_position.translated(scroll_offset), *offset_paintable); bool could_scroll_viewport = document->paintable_box()->could_be_scrolled_by_wheel_event(); @@ -643,7 +645,7 @@ EventResult EventHandler::handle_mousewheel(CSSPixelPoint visual_viewport_positi return handled_event; } -void EventHandler::update_hovered_chrome_widget(GC::Ptr widget) +void EventHandler::update_hovered_chrome_widget(RefPtr widget) { if (m_hovered_chrome_widget == widget) return; @@ -657,13 +659,15 @@ void EventHandler::update_hovered_chrome_widget(GC::Ptr EventHandler::MouseEventCoordinates EventHandler::compute_mouse_event_coordinates(CSSPixelPoint visual_viewport_position, CSSPixelPoint viewport_position, Painting::Paintable const& paintable, Layout::Node const& layout_node) const { auto page_offset = compute_mouse_event_page_offset(viewport_position); - auto const& offset_paintable = layout_node.first_paintable() ? layout_node.first_paintable() : &paintable; + RefPtr offset_paintable = layout_node.first_paintable(); + if (!offset_paintable) + offset_paintable = paintable; auto scroll_offset = m_navigable->active_document()->navigable()->viewport_scroll_offset(); auto offset = compute_mouse_event_offset(visual_viewport_position.translated(scroll_offset), *offset_paintable); return { page_offset, visual_viewport_position, viewport_position, offset }; } -bool EventHandler::dispatch_chrome_widget_pointer_event(GC::Ptr target, FlyString const& type, unsigned button, CSSPixelPoint visual_viewport_position) +bool EventHandler::dispatch_chrome_widget_pointer_event(RefPtr target, FlyString const& type, unsigned button, CSSPixelPoint visual_viewport_position) { bool allow_default_behavior = true; @@ -688,7 +692,7 @@ bool EventHandler::dispatch_chrome_widget_pointer_event(GC::Ptr node, GC::Ptr chrome_widget, MouseEventCoordinates const& coordinates, CSSPixelPoint screen_position, CSSPixelPoint movement, unsigned button, unsigned buttons, unsigned modifiers, int click_count) +bool EventHandler::dispatch_a_pointer_event_for_a_device_that_supports_hover(PointerEventType type, GC::Ptr node, RefPtr chrome_widget, MouseEventCoordinates const& coordinates, CSSPixelPoint screen_position, CSSPixelPoint movement, unsigned button, unsigned buttons, unsigned modifiers, int click_count) { auto& document = *m_navigable->active_document(); auto& realm = document.realm(); @@ -837,7 +841,7 @@ static void set_page_cursor(Page& page, Gfx::Cursor cursor) } } -void EventHandler::update_cursor(GC::Ptr paintable, GC::Ptr host_element, GC::Ptr chrome_widget) +void EventHandler::update_cursor(RefPtr paintable, GC::Ptr host_element, RefPtr chrome_widget) { // AD-HOC: Update the cursor image based on the CSS rules before the steps terminate if the target hasn't changed. auto cursor = [&] -> Gfx::Cursor { @@ -1036,8 +1040,8 @@ EventResult EventHandler::handle_mouseup(CSSPixelPoint visual_viewport_position, if (!paint_root()) return EventResult::Dropped; - GC::Ptr paintable; - GC::Ptr chrome_widget; + RefPtr paintable; + RefPtr chrome_widget; if (auto result = target_for_mouse_position(visual_viewport_position); result.has_value()) { paintable = result->paintable; chrome_widget = result->chrome_widget; @@ -1140,11 +1144,11 @@ bool EventHandler::initiate_character_selection(DOM::Document& document, Paintin bool EventHandler::initiate_word_selection(DOM::Document& document, Painting::HitTestResult const& hit, CSS::UserSelect user_select) { - if (!is(*hit.paintable)) + auto* hit_paintable = as_if(*hit.paintable); + if (!hit_paintable) return false; - auto& hit_paintable = static_cast(*hit.paintable); - auto& hit_node = as(*hit_paintable.dom_node()); + auto& hit_node = as(*hit_paintable->dom_node()); size_t previous_boundary = 0; size_t next_boundary = 0; @@ -1153,7 +1157,7 @@ bool EventHandler::initiate_word_selection(DOM::Document& document, Painting::Hi next_boundary = hit_node.length_in_utf16_code_units(); } else { auto& segmenter = word_segmenter(); - segmenter.set_segmented_text(hit_paintable.layout_node().text_for_rendering()); + segmenter.set_segmented_text(hit_paintable->layout_node().text_for_rendering()); previous_boundary = segmenter.previous_boundary(hit.index_in_node, Unicode::Segmenter::Inclusive::Yes).value_or(0); next_boundary = segmenter.next_boundary(hit.index_in_node).value_or(hit_node.length()); @@ -1310,8 +1314,8 @@ EventResult EventHandler::handle_mousedown(CSSPixelPoint visual_viewport_positio GC::Ptr node; - GC::Ptr paintable; - GC::Ptr chrome_widget; + RefPtr paintable; + RefPtr chrome_widget; if (auto result = target_for_mouse_position(visual_viewport_position); result.has_value()) { paintable = result->paintable; chrome_widget = result->chrome_widget; @@ -1427,8 +1431,8 @@ EventResult EventHandler::handle_mousemove(CSSPixelPoint visual_viewport_positio } } - GC::Ptr paintable; - GC::Ptr chrome_widget; + RefPtr paintable; + RefPtr chrome_widget; Optional start_index; if (auto result = target_for_mouse_position(visual_viewport_position); result.has_value()) { @@ -1556,7 +1560,7 @@ EventResult EventHandler::handle_drag_and_drop_event(DragEvent::Type type, CSSPi if (!paint_root()) return EventResult::Dropped; - GC::Ptr paintable; + RefPtr paintable; if (auto result = target_for_mouse_position(visual_viewport_position); result.has_value()) paintable = result->paintable; else @@ -1678,7 +1682,7 @@ GC::Ptr EventHandler::focus_candidate_for_position(CSSPixelPoint visu if (!exact_hit.has_value()) return {}; - auto focus_dom_node = exact_hit->paintable ? exact_hit->paintable->dom_node() : nullptr; + auto focus_dom_node = exact_hit->paintable->dom_node(); while (focus_dom_node && !focus_dom_node->is_focusable()) focus_dom_node = focus_dom_node->parent_or_shadow_host(); @@ -2151,8 +2155,6 @@ bool EventHandler::should_ignore_device_input_event() const void EventHandler::visit_edges(JS::Cell::Visitor& visitor) const { m_drag_and_drop_event_handler->visit_edges(visitor); - visitor.visit(m_hovered_chrome_widget); - visitor.visit(m_captured_chrome_widget); if (m_mouse_selection_target) visitor.visit(m_mouse_selection_target->as_cell()); visitor.visit(m_selection_origin); diff --git a/Libraries/LibWeb/Page/EventHandler.h b/Libraries/LibWeb/Page/EventHandler.h index e3a8b78965..653fff582b 100644 --- a/Libraries/LibWeb/Page/EventHandler.h +++ b/Libraries/LibWeb/Page/EventHandler.h @@ -92,8 +92,8 @@ private: CSSPixelPoint compute_mouse_event_movement(CSSPixelPoint screen_position) const; struct Target { - GC::Ptr paintable; - GC::Ptr chrome_widget; + RefPtr paintable; + RefPtr chrome_widget; Optional index_in_node; }; Optional target_for_mouse_position(CSSPixelPoint position); @@ -112,11 +112,11 @@ private: PointerMove, PointerCancel }; - bool dispatch_a_pointer_event_for_a_device_that_supports_hover(PointerEventType, GC::Ptr, GC::Ptr, MouseEventCoordinates const&, CSSPixelPoint screen_position, CSSPixelPoint movement, unsigned button, unsigned buttons, unsigned modifiers, int click_count = 0); + bool dispatch_a_pointer_event_for_a_device_that_supports_hover(PointerEventType, GC::Ptr, RefPtr, MouseEventCoordinates const&, CSSPixelPoint screen_position, CSSPixelPoint movement, unsigned button, unsigned buttons, unsigned modifiers, int click_count = 0); void track_the_effective_position_of_the_legacy_mouse_pointer(GC::Ptr); - void update_cursor(GC::Ptr paintable, GC::Ptr host_element, GC::Ptr chrome_widget); - bool dispatch_chrome_widget_pointer_event(GC::Ptr, FlyString const& type, unsigned button, CSSPixelPoint visual_viewport_position); - void update_hovered_chrome_widget(GC::Ptr); + void update_cursor(RefPtr paintable, GC::Ptr host_element, RefPtr chrome_widget); + bool dispatch_chrome_widget_pointer_event(RefPtr, FlyString const& type, unsigned button, CSSPixelPoint visual_viewport_position); + void update_hovered_chrome_widget(RefPtr); bool fire_click_events(GC::Ref, MouseEventCoordinates const&, CSSPixelPoint screen_position, unsigned button, unsigned buttons, unsigned modifiers, int click_count); void run_activation_behavior(GC::Ref, unsigned button, unsigned modifiers); void maybe_show_context_menu(GC::Ref, MouseEventCoordinates const&, CSSPixelPoint screen_position, CSSPixelPoint viewport_position, unsigned buttons, unsigned modifiers); @@ -126,8 +126,8 @@ private: void update_mouse_selection(CSSPixelPoint visual_viewport_position); void apply_mouse_selection(CSSPixelPoint visual_viewport_position); - GC::Ptr paint_root(); - GC::Ptr paint_root() const; + RefPtr paint_root(); + RefPtr paint_root() const; bool should_ignore_device_input_event() const; @@ -141,8 +141,8 @@ private: InputEventsTarget* m_mouse_selection_target { nullptr }; GC::Ptr m_selection_origin; - GC::Ptr m_hovered_chrome_widget; - GC::Ptr m_captured_chrome_widget; + RefPtr m_hovered_chrome_widget; + RefPtr m_captured_chrome_widget; NonnullOwnPtr m_drag_and_drop_event_handler; diff --git a/Libraries/LibWeb/Page/MiddleButtonScrollHandler.cpp b/Libraries/LibWeb/Page/MiddleButtonScrollHandler.cpp index bb1ec10346..c11c0aa417 100644 --- a/Libraries/LibWeb/Page/MiddleButtonScrollHandler.cpp +++ b/Libraries/LibWeb/Page/MiddleButtonScrollHandler.cpp @@ -25,7 +25,7 @@ MiddleButtonScrollHandler::MiddleButtonScrollHandler(DOM::Element& container, CS , m_origin(origin) , m_mouse_position(origin) { - if (auto* paintable = m_container_element->document().paintable()) + if (auto paintable = m_container_element->document().paintable()) paintable->set_needs_repaint(); } @@ -33,7 +33,7 @@ MiddleButtonScrollHandler::~MiddleButtonScrollHandler() { if (!m_container_element->document().layout_is_up_to_date()) return; - if (auto* paintable = m_container_element->document().paintable()) + if (auto paintable = m_container_element->document().paintable()) paintable->set_needs_repaint(); } diff --git a/Libraries/LibWeb/Painting/BackgroundPainting.cpp b/Libraries/LibWeb/Painting/BackgroundPainting.cpp index f209a08dbd..61b81b18e8 100644 --- a/Libraries/LibWeb/Painting/BackgroundPainting.cpp +++ b/Libraries/LibWeb/Painting/BackgroundPainting.cpp @@ -30,7 +30,7 @@ static void append_text_clip_paths(DisplayListRecordingContext& context, Paintab if (!layout_node.is_in_flow() && !layout_node.is_floating()) return TraversalDecision::SkipChildrenAndContinue; } - if (auto* paintable_lines = as_if(sub_paintable)) { + if (auto const* paintable_lines = as_if(sub_paintable)) { for (auto const& fragment : paintable_lines->fragments()) { if (!is(fragment.layout_node())) continue; diff --git a/Libraries/LibWeb/Painting/CanvasPaintable.cpp b/Libraries/LibWeb/Painting/CanvasPaintable.cpp index f8df497b9c..e2c9035607 100644 --- a/Libraries/LibWeb/Painting/CanvasPaintable.cpp +++ b/Libraries/LibWeb/Painting/CanvasPaintable.cpp @@ -9,11 +9,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(CanvasPaintable); - -GC::Ref CanvasPaintable::create(Layout::CanvasBox const& layout_box) +NonnullRefPtr CanvasPaintable::create(Layout::CanvasBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new CanvasPaintable(layout_box)); } CanvasPaintable::CanvasPaintable(Layout::CanvasBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/CanvasPaintable.h b/Libraries/LibWeb/Painting/CanvasPaintable.h index 86164239ac..1583b53322 100644 --- a/Libraries/LibWeb/Painting/CanvasPaintable.h +++ b/Libraries/LibWeb/Painting/CanvasPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class CanvasPaintable final : public PaintableBox { - GC_CELL(CanvasPaintable, PaintableBox); - GC_DECLARE_ALLOCATOR(CanvasPaintable); - public: - static GC::Ref create(Layout::CanvasBox const&); + static NonnullRefPtr create(Layout::CanvasBox const&); + virtual StringView class_name() const override { return "CanvasPaintable"sv; } virtual void paint(DisplayListRecordingContext&, PaintPhase) const override; diff --git a/Libraries/LibWeb/Painting/CheckBoxPaintable.cpp b/Libraries/LibWeb/Painting/CheckBoxPaintable.cpp index a69bb15b5e..f5d85f5c58 100644 --- a/Libraries/LibWeb/Painting/CheckBoxPaintable.cpp +++ b/Libraries/LibWeb/Painting/CheckBoxPaintable.cpp @@ -15,8 +15,6 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(CheckBoxPaintable); - static Gfx::Path check_mark_path(Gfx::IntRect checkbox_rect) { Gfx::Path path; @@ -35,10 +33,10 @@ static Gfx::Path check_mark_path(Gfx::IntRect checkbox_rect) return path.copy_transformed(scale_checkmark_to_fit); } -GC::Ref +NonnullRefPtr CheckBoxPaintable::create(Layout::CheckBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new CheckBoxPaintable(layout_box)); } CheckBoxPaintable::CheckBoxPaintable(Layout::CheckBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/CheckBoxPaintable.h b/Libraries/LibWeb/Painting/CheckBoxPaintable.h index 5125bcc30b..7606811042 100644 --- a/Libraries/LibWeb/Painting/CheckBoxPaintable.h +++ b/Libraries/LibWeb/Painting/CheckBoxPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class CheckBoxPaintable final : public PaintableBox { - GC_CELL(CheckBoxPaintable, PaintableBox); - GC_DECLARE_ALLOCATOR(CheckBoxPaintable); - public: - static GC::Ref create(Layout::CheckBox const&); + static NonnullRefPtr create(Layout::CheckBox const&); + virtual StringView class_name() const override { return "CheckBoxPaintable"sv; } virtual void paint(DisplayListRecordingContext&, PaintPhase) const override; diff --git a/Libraries/LibWeb/Painting/ChromeWidget.h b/Libraries/LibWeb/Painting/ChromeWidget.h index f92c29cf73..aef095728b 100644 --- a/Libraries/LibWeb/Painting/ChromeWidget.h +++ b/Libraries/LibWeb/Painting/ChromeWidget.h @@ -7,6 +7,8 @@ #pragma once #include +#include +#include #include #include #include @@ -22,10 +24,12 @@ enum class MouseAction : u8 { AK_ENUM_BITWISE_OPERATORS(MouseAction); -class ChromeWidget : public JS::Cell { - GC_CELL(ChromeWidget, JS::Cell); - +class ChromeWidget + : public RefCounted + , public Weakable { public: + virtual ~ChromeWidget() = default; + virtual MouseAction handle_pointer_event(FlyString const& type, unsigned button, CSSPixelPoint visual_viewport_position) = 0; virtual void mouse_enter() = 0; virtual void mouse_leave() = 0; diff --git a/Libraries/LibWeb/Painting/FieldSetPaintable.cpp b/Libraries/LibWeb/Painting/FieldSetPaintable.cpp index 1c712b8383..0e191b0bc8 100644 --- a/Libraries/LibWeb/Painting/FieldSetPaintable.cpp +++ b/Libraries/LibWeb/Painting/FieldSetPaintable.cpp @@ -11,11 +11,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(FieldSetPaintable); - -GC::Ref FieldSetPaintable::create(Layout::FieldSetBox const& layout_box) +NonnullRefPtr FieldSetPaintable::create(Layout::FieldSetBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new FieldSetPaintable(layout_box)); } FieldSetPaintable::FieldSetPaintable(Layout::FieldSetBox const& layout_box) @@ -41,7 +39,7 @@ CSSPixels FieldSetPaintable::effective_border_top() const // whichever is greater. auto css_border_top = computed_values().border_top().width; if (auto legend = layout_box().rendered_legend()) { - auto const* legend_paintable = legend->paintable_box(); + auto legend_paintable = legend->paintable_box(); auto legend_margin_box_height = legend_paintable->box_model().margin.top + legend_paintable->absolute_border_box_rect().height() + legend_paintable->box_model().margin.bottom; @@ -90,7 +88,7 @@ void FieldSetPaintable::paint(DisplayListRecordingContext& context, PaintPhase p return; } - auto const* legend_paintable = legend->paintable_box(); + auto legend_paintable = legend->paintable_box(); auto legend_border_rect = context.rounded_device_rect(legend_paintable->absolute_border_box_rect()); diff --git a/Libraries/LibWeb/Painting/FieldSetPaintable.h b/Libraries/LibWeb/Painting/FieldSetPaintable.h index f7528fe745..d0bcd795f1 100644 --- a/Libraries/LibWeb/Painting/FieldSetPaintable.h +++ b/Libraries/LibWeb/Painting/FieldSetPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class FieldSetPaintable final : public PaintableBox { - GC_CELL(FieldSetPaintable, PaintableBox); - GC_DECLARE_ALLOCATOR(FieldSetPaintable); - public: - static GC::Ref create(Layout::FieldSetBox const&); + static NonnullRefPtr create(Layout::FieldSetBox const&); + virtual StringView class_name() const override { return "FieldSetPaintable"sv; } virtual void paint(DisplayListRecordingContext&, PaintPhase) const override; virtual void paint_background(DisplayListRecordingContext&) const override; diff --git a/Libraries/LibWeb/Painting/ImagePaintable.cpp b/Libraries/LibWeb/Painting/ImagePaintable.cpp index ff38ebd6a9..0707a162c7 100644 --- a/Libraries/LibWeb/Painting/ImagePaintable.cpp +++ b/Libraries/LibWeb/Painting/ImagePaintable.cpp @@ -16,19 +16,17 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(ImagePaintable); - -GC::Ref ImagePaintable::create(Layout::SVGImageBox const& layout_box) +NonnullRefPtr ImagePaintable::create(Layout::SVGImageBox const& layout_box) { - return layout_box.heap().allocate(layout_box, layout_box.dom_node(), false, String {}, true); + return adopt_ref(*new ImagePaintable(layout_box, layout_box.dom_node(), false, String {}, true)); } -GC::Ref ImagePaintable::create(Layout::ImageBox const& layout_box) +NonnullRefPtr ImagePaintable::create(Layout::ImageBox const& layout_box) { String alt; if (auto element = layout_box.dom_node()) alt = element->get_attribute_value(HTML::AttributeNames::alt); - return layout_box.heap().allocate(layout_box, layout_box.image_provider(), layout_box.renders_as_alt_text(), move(alt), false); + return adopt_ref(*new ImagePaintable(layout_box, layout_box.image_provider(), layout_box.renders_as_alt_text(), move(alt), false)); } ImagePaintable::ImagePaintable(Layout::Box const& layout_box, Layout::ImageProvider const& image_provider, bool renders_as_alt_text, String alt_text, bool is_svg_image) @@ -40,12 +38,6 @@ ImagePaintable::ImagePaintable(Layout::Box const& layout_box, Layout::ImageProvi { } -void ImagePaintable::visit_edges(JS::Cell::Visitor& visitor) -{ - Base::visit_edges(visitor); - m_image_provider.image_provider_visit_edges(visitor); -} - void ImagePaintable::reset_for_relayout() { PaintableBox::reset_for_relayout(); diff --git a/Libraries/LibWeb/Painting/ImagePaintable.h b/Libraries/LibWeb/Painting/ImagePaintable.h index 852fe56a48..4bfcd7e813 100644 --- a/Libraries/LibWeb/Painting/ImagePaintable.h +++ b/Libraries/LibWeb/Painting/ImagePaintable.h @@ -13,20 +13,15 @@ namespace Web::Painting { class ImagePaintable final : public PaintableBox { - GC_CELL(ImagePaintable, PaintableBox); - GC_DECLARE_ALLOCATOR(ImagePaintable); - public: - static GC::Ref create(Layout::ImageBox const& layout_box); - static GC::Ref create(Layout::SVGImageBox const& layout_box); + static NonnullRefPtr create(Layout::ImageBox const& layout_box); + static NonnullRefPtr create(Layout::SVGImageBox const& layout_box); + virtual StringView class_name() const override { return "ImagePaintable"sv; } virtual void paint(DisplayListRecordingContext&, PaintPhase) const override; virtual void reset_for_relayout() override; private: - // ^JS::Cell - virtual void visit_edges(Visitor&) override; - ImagePaintable(Layout::Box const& layout_box, Layout::ImageProvider const& image_provider, bool renders_as_alt_text, String alt_text, bool is_svg_image); bool m_renders_as_alt_text { false }; diff --git a/Libraries/LibWeb/Painting/MarkerPaintable.cpp b/Libraries/LibWeb/Painting/MarkerPaintable.cpp index 368ab31505..03e6ca48a6 100644 --- a/Libraries/LibWeb/Painting/MarkerPaintable.cpp +++ b/Libraries/LibWeb/Painting/MarkerPaintable.cpp @@ -12,11 +12,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(MarkerPaintable); - -GC::Ref MarkerPaintable::create(Layout::ListItemMarkerBox const& layout_box) +NonnullRefPtr MarkerPaintable::create(Layout::ListItemMarkerBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new MarkerPaintable(layout_box)); } MarkerPaintable::MarkerPaintable(Layout::ListItemMarkerBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/MarkerPaintable.h b/Libraries/LibWeb/Painting/MarkerPaintable.h index cd4744f2c5..f0a9d3930c 100644 --- a/Libraries/LibWeb/Painting/MarkerPaintable.h +++ b/Libraries/LibWeb/Painting/MarkerPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class MarkerPaintable final : public PaintableBox { - GC_CELL(MarkerPaintable, PaintableBox); - GC_DECLARE_ALLOCATOR(MarkerPaintable); - public: - static GC::Ref create(Layout::ListItemMarkerBox const&); + static NonnullRefPtr create(Layout::ListItemMarkerBox const&); + virtual StringView class_name() const override { return "MarkerPaintable"sv; } virtual void paint(DisplayListRecordingContext&, PaintPhase) const override; diff --git a/Libraries/LibWeb/Painting/NavigableContainerViewportPaintable.cpp b/Libraries/LibWeb/Painting/NavigableContainerViewportPaintable.cpp index fc4a586a62..6bff780797 100644 --- a/Libraries/LibWeb/Painting/NavigableContainerViewportPaintable.cpp +++ b/Libraries/LibWeb/Painting/NavigableContainerViewportPaintable.cpp @@ -16,11 +16,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(NavigableContainerViewportPaintable); - -GC::Ref NavigableContainerViewportPaintable::create(Layout::NavigableContainerViewport const& layout_box) +NonnullRefPtr NavigableContainerViewportPaintable::create(Layout::NavigableContainerViewport const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new NavigableContainerViewportPaintable(layout_box)); } NavigableContainerViewportPaintable::NavigableContainerViewportPaintable(Layout::NavigableContainerViewport const& layout_box) diff --git a/Libraries/LibWeb/Painting/NavigableContainerViewportPaintable.h b/Libraries/LibWeb/Painting/NavigableContainerViewportPaintable.h index 4f35494943..5f0379eaf0 100644 --- a/Libraries/LibWeb/Painting/NavigableContainerViewportPaintable.h +++ b/Libraries/LibWeb/Painting/NavigableContainerViewportPaintable.h @@ -12,13 +12,11 @@ namespace Web::Painting { class NavigableContainerViewportPaintable final : public PaintableBox { - GC_CELL(NavigableContainerViewportPaintable, PaintableBox); - GC_DECLARE_ALLOCATOR(NavigableContainerViewportPaintable); - public: virtual bool is_navigable_container_viewport_paintable() const override { return true; } - static GC::Ref create(Layout::NavigableContainerViewport const&); + static NonnullRefPtr create(Layout::NavigableContainerViewport const&); + virtual StringView class_name() const override { return "NavigableContainerViewportPaintable"sv; } virtual void paint(DisplayListRecordingContext&, PaintPhase) const override; diff --git a/Libraries/LibWeb/Painting/Paintable.cpp b/Libraries/LibWeb/Painting/Paintable.cpp index b4f21c6dcc..2c43415b0c 100644 --- a/Libraries/LibWeb/Painting/Paintable.cpp +++ b/Libraries/LibWeb/Painting/Paintable.cpp @@ -46,22 +46,6 @@ Paintable::Paintable(Layout::Node const& layout_node) Paintable::~Paintable() = default; -void Paintable::finalize() -{ - Base::finalize(); - if (m_list_node.is_in_list()) - m_list_node.remove(); -} - -void Paintable::visit_edges(Cell::Visitor& visitor) -{ - Base::visit_edges(visitor); - TreeNode::visit_edges(visitor); - visitor.visit(m_dom_node); - visitor.visit(m_layout_node); - visitor.visit(m_containing_block); -} - String Paintable::debug_description() const { return MUST(String::formatted("{}({})", class_name(), layout_node().debug_description())); @@ -77,19 +61,29 @@ DOM::Document& Paintable::document() return layout_node().document(); } -PaintableBox* Paintable::containing_block() const +RefPtr Paintable::containing_block() const { - return m_containing_block.ensure([&] -> GC::Ptr { - auto containing_layout_box = m_layout_node->containing_block(); + if (m_containing_block.has_value()) { + if (auto containing_block = m_containing_block->strong_ref()) + return containing_block; + } + + auto containing_block = [&] -> RefPtr { + auto containing_layout_box = layout_node().containing_block(); if (!containing_layout_box) return nullptr; - return const_cast(containing_layout_box->paintable_box()); - }); + auto paintable_box = containing_layout_box->paintable_box(); + if (!paintable_box) + return nullptr; + return const_cast(*paintable_box); + }(); + m_containing_block = containing_block; + return containing_block; } CSS::ImmutableComputedValues const& Paintable::computed_values() const { - return m_layout_node->computed_values(); + return layout_node().computed_values(); } bool Paintable::visible_for_hit_testing() const @@ -101,17 +95,17 @@ bool Paintable::visible_for_hit_testing() const void Paintable::set_dom_node(GC::Ptr dom_node) { - m_dom_node = dom_node; + m_dom_node = dom_node.ptr(); } GC::Ptr Paintable::dom_node() { - return m_dom_node; + return m_dom_node.ptr(); } GC::Ptr Paintable::dom_node() const { - return m_dom_node; + return m_dom_node.ptr(); } GC::Ptr Paintable::navigable() const @@ -131,18 +125,19 @@ TraversalDecision Paintable::hit_test(CSSPixelPoint, HitTestType, Function(*this).stacking_context(); + if (auto const* paintable_box = as_if(this)) + return paintable_box->stacking_context(); return false; } -StackingContext* Paintable::enclosing_stacking_context() +RefPtr Paintable::enclosing_stacking_context() { - for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) { - if (!ancestor->is_paintable_box()) + for (auto ancestor = parent(); ancestor; ancestor = ancestor->parent()) { + auto* paintable_box = as_if(ancestor.ptr()); + if (!paintable_box) continue; - if (auto* stacking_context = static_cast(*ancestor).stacking_context()) - return const_cast(stacking_context); + if (auto stacking_context = paintable_box->stacking_context()) + return stacking_context; } // We should always reach the viewport's stacking context. VERIFY_NOT_REACHED(); @@ -151,12 +146,16 @@ StackingContext* Paintable::enclosing_stacking_context() void Paintable::paint_inspector_overlay(DisplayListRecordingContext& context) const { auto& display_list_recorder = context.display_list_recorder(); - auto const* paintable_box = as_if(this); - if (!paintable_box) + RefPtr paintable_box; + if (is(*this)) + paintable_box = static_cast(*this); + else paintable_box = first_ancestor_of_type(); if (paintable_box) { - auto& visual_context_tree = const_cast(document().paintable())->visual_context_tree(); + auto viewport_paintable = document().paintable(); + VERIFY(viewport_paintable); + auto& visual_context_tree = const_cast(*viewport_paintable).visual_context_tree(); auto visual_context_index = paintable_box->accumulated_visual_context_index(); if (visual_context_index.value()) { @@ -189,7 +188,7 @@ void Paintable::paint_inspector_overlay(DisplayListRecordingContext& context) co void Paintable::set_needs_repaint(InvalidateDisplayList should_invalidate_display_list) { if (should_invalidate_display_list == InvalidateDisplayList::Yes) { - if (auto* containing_block = this->containing_block()) + if (auto containing_block = this->containing_block()) containing_block->invalidate_paint_cache(); } document().set_needs_repaint(Badge {}, should_invalidate_display_list); @@ -197,13 +196,13 @@ void Paintable::set_needs_repaint(InvalidateDisplayList should_invalidate_displa CSSPixelPoint Paintable::box_type_agnostic_position() const { - if (is_paintable_box()) - return static_cast(this)->absolute_position(); + if (auto const* paintable_box = as_if(this)) + return paintable_box->absolute_position(); VERIFY(is_inline()); CSSPixelPoint position; - if (auto const* block = containing_block(); block && is(*block)) { + if (auto block = containing_block(); block && is(*block)) { auto const& fragments = static_cast(*block).fragments(); if (!fragments.is_empty()) { position = fragments[0].absolute_rect().location(); @@ -352,11 +351,11 @@ void Paintable::set_selection_state(SelectionState state) m_selection_state = state; if (auto* box = as_if(this)) { box->invalidate_paint_cache(); - } else if (auto* containing_block = this->containing_block()) { + } else if (auto containing_block = this->containing_block()) { containing_block->invalidate_paint_cache(); for (auto const* ancestor = layout_node().parent(); ancestor && ancestor != &containing_block->layout_node(); ancestor = ancestor->parent()) { for (auto& paintable : ancestor->paintables()) { - if (auto* ancestor_box = as_if(paintable)) + if (auto* ancestor_box = as_if(paintable.ptr())) ancestor_box->invalidate_paint_cache(); } } @@ -366,11 +365,12 @@ void Paintable::set_selection_state(SelectionState state) void Paintable::scroll_ancestor_to_offset_into_view(size_t offset) { // Walk up to find the containing PaintableWithLines. - GC::Ptr paintable_with_lines; - for (auto* ancestor = this; ancestor; ancestor = ancestor->parent()) { - paintable_with_lines = as_if(*ancestor); - if (paintable_with_lines) + RefPtr paintable_with_lines; + for (RefPtr ancestor = *this; ancestor; ancestor = ancestor->parent()) { + if (auto* ancestor_lines = as_if(*ancestor)) { + paintable_with_lines = *ancestor_lines; break; + } } if (!paintable_with_lines) return; @@ -385,7 +385,7 @@ void Paintable::scroll_ancestor_to_offset_into_view(size_t offset) auto cursor_rect = fragment.range_rect(SelectionState::StartAndEnd, offset, offset); // Walk up the containing block chain to find the nearest scrollable ancestor. - for (auto* ancestor = containing_block(); ancestor; ancestor = ancestor->containing_block()) { + for (auto ancestor = containing_block(); ancestor; ancestor = ancestor->containing_block()) { if (ancestor->has_scrollable_overflow()) { ancestor->scroll_into_view(cursor_rect); break; diff --git a/Libraries/LibWeb/Painting/Paintable.h b/Libraries/LibWeb/Painting/Paintable.h index fc5ed12d3b..f62348692b 100644 --- a/Libraries/LibWeb/Painting/Paintable.h +++ b/Libraries/LibWeb/Painting/Paintable.h @@ -6,8 +6,11 @@ #pragma once +#include +#include +#include #include -#include +#include #include #include #include @@ -15,8 +18,8 @@ #include #include #include +#include #include -#include namespace Web::Painting { @@ -32,8 +35,8 @@ enum class PaintPhase { }; struct HitTestResult { - GC::Root paintable; - GC::Ptr chrome_widget {}; + NonnullRefPtr paintable; + RefPtr chrome_widget {}; size_t index_in_node { 0 }; Optional vertical_distance {}; Optional horizontal_distance {}; @@ -55,15 +58,15 @@ enum class HitTestType { }; class WEB_API Paintable - : public JS::Cell - , public TreeNode { - GC_CELL(Paintable, JS::Cell); + : public RefCounted + , public Weakable + , public RefCountedTreeNode { public: - static constexpr bool OVERRIDES_FINALIZE = true; - virtual ~Paintable(); + virtual StringView class_name() const { return "Paintable"sv; } + void detach_from_layout_node(); [[nodiscard]] bool is_visible() const @@ -80,7 +83,7 @@ public: [[nodiscard]] CSS::Display display() const { return m_display; } bool has_stacking_context() const; - StackingContext* enclosing_stacking_context(); + RefPtr enclosing_stacking_context(); virtual void paint(DisplayListRecordingContext&, PaintPhase) const { } void paint_inspector_overlay(DisplayListRecordingContext&) const; @@ -91,8 +94,12 @@ public: virtual bool handle_mousewheel(Badge, CSSPixelPoint, unsigned buttons, unsigned modifiers, int wheel_delta_x, int wheel_delta_y); - Layout::Node const& layout_node() const { return m_layout_node; } - Layout::Node& layout_node() { return const_cast(*m_layout_node); } + Layout::Node const& layout_node() const + { + VERIFY(m_layout_node); + return *m_layout_node; + } + Layout::Node& layout_node() { return const_cast(const_cast(*this).layout_node()); } [[nodiscard]] GC::Ptr dom_node(); [[nodiscard]] GC::Ptr dom_node() const; @@ -106,7 +113,7 @@ public: virtual void set_needs_repaint(InvalidateDisplayList = InvalidateDisplayList::Yes); - PaintableBox* containing_block() const; + RefPtr containing_block() const; template bool fast_is() const = delete; @@ -160,22 +167,17 @@ public: [[nodiscard]] String debug_description() const; - virtual void finalize() override; - friend class Layout::Node; protected: explicit Paintable(Layout::Node const&); virtual void paint_inspector_overlay_internal(DisplayListRecordingContext&) const { } - virtual void visit_edges(Cell::Visitor&) override; - - Optional> mutable m_containing_block; + Optional> mutable m_containing_block; private: - IntrusiveListNode m_list_node; - GC::Ptr m_dom_node; - GC::Ref m_layout_node; + GC::Weak m_dom_node; + GC::Weak m_layout_node; SelectionState m_selection_state { SelectionState::None }; diff --git a/Libraries/LibWeb/Painting/PaintableBox.cpp b/Libraries/LibWeb/Painting/PaintableBox.cpp index f7a3e3b768..7ee7c76685 100644 --- a/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -34,8 +34,6 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(PaintableBox); - static bool g_paint_viewport_scrollbars = true; void set_paint_viewport_scrollbars(bool const enabled) @@ -98,7 +96,7 @@ ResolvedCSSFilter resolve_css_filter(CSS::Filter const& computed_filter, Paintab result.svg_filter = filter_element->gfx_filter(layout_node); auto bounds = paintable_box.absolute_border_box_rect(); if (bounds.is_empty()) { - if (auto const* svg_ancestor = paintable_box.first_ancestor_of_type()) + if (auto svg_ancestor = paintable_box.first_ancestor_of_type()) result.svg_filter_bounds = svg_ancestor->absolute_rect(); } if (!bounds.is_empty()) @@ -109,14 +107,14 @@ ResolvedCSSFilter resolve_css_filter(CSS::Filter const& computed_filter, Paintab return result; } -GC::Ref PaintableBox::create(Layout::Box const& layout_box) +NonnullRefPtr PaintableBox::create(Layout::Box const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new PaintableBox(layout_box)); } -GC::Ref PaintableBox::create(Layout::InlineNode const& layout_box) +NonnullRefPtr PaintableBox::create(Layout::InlineNode const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new PaintableBox(layout_box)); } PaintableBox::PaintableBox(Layout::Box const& layout_box) @@ -169,15 +167,6 @@ void PaintableBox::reset_for_relayout() invalidate_stacking_context(); } -void PaintableBox::visit_edges(Cell::Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_stacking_context); - visitor.visit(m_horizontal_scrollbar); - visitor.visit(m_vertical_scrollbar); - visitor.visit(m_resize_handle); -} - CSSPixelPoint PaintableBox::scroll_offset() const { if (is_viewport_paintable()) { @@ -308,7 +297,7 @@ CSSPixelPoint PaintableBox::offset() const CSSPixelRect PaintableBox::compute_absolute_rect() const { CSSPixelRect rect { offset(), content_size() }; - for (auto const* block = containing_block(); block; block = block->containing_block()) + for (auto block = containing_block(); block; block = block->containing_block()) rect.translate_by(block->offset()); return rect; } @@ -402,7 +391,7 @@ static CSSPixelRect united_rect_for_continuation_chain(PaintableBox const& start for (auto const& paintable : node->paintables()) { if (!is(paintable)) continue; - auto const& paintable_box = static_cast(paintable); + auto const& paintable_box = static_cast(*paintable); auto paintable_border_box_rect = get_rect(paintable_box); if (!result.has_value()) result = paintable_border_box_rect; @@ -444,16 +433,16 @@ Optional PaintableBox::get_clip_rect() const return {}; } -GC::Ptr PaintableBox::scrollbar(ScrollDirection direction) const +RefPtr PaintableBox::scrollbar(ScrollDirection direction) const { return direction == ScrollDirection::Horizontal ? m_horizontal_scrollbar : m_vertical_scrollbar; } -GC::Ref PaintableBox::ensure_scrollbar(ScrollDirection direction) +NonnullRefPtr PaintableBox::ensure_scrollbar(ScrollDirection direction) { auto& slot = direction == ScrollDirection::Horizontal ? m_horizontal_scrollbar : m_vertical_scrollbar; if (!slot) - slot = Scrollbar::create(heap(), const_cast(*this), direction); + slot = Scrollbar::create(const_cast(*this), direction); return *slot; } @@ -800,11 +789,21 @@ void PaintableBox::paint_inspector_overlay_internal(DisplayListRecordingContext& context.display_list_recorder().draw_text(size_text_device_rect, size_text, font->with_size(font->point_size() * context.device_pixels_per_css_pixel()), Gfx::TextAlignment::Center, context.palette().color(Gfx::ColorRole::TooltipText)); } -void PaintableBox::set_stacking_context(GC::Ref stacking_context) +void PaintableBox::set_stacking_context(NonnullRefPtr stacking_context) { m_stacking_context = move(stacking_context); } +RefPtr PaintableBox::stacking_context() +{ + return m_stacking_context; +} + +RefPtr PaintableBox::stacking_context() const +{ + return m_stacking_context; +} + void PaintableBox::invalidate_stacking_context() { m_stacking_context = nullptr; @@ -1013,15 +1012,15 @@ bool PaintableBox::is_chrome_mirrored() const || writing_mode == CSS::WritingMode::SidewaysRl; } -GC::Ptr PaintableBox::resize_handle() const +RefPtr PaintableBox::resize_handle() const { return m_resize_handle; } -GC::Ref PaintableBox::ensure_resize_handle() +NonnullRefPtr PaintableBox::ensure_resize_handle() { if (!m_resize_handle) - m_resize_handle = ResizeHandle::create(heap(), *this); + m_resize_handle = ResizeHandle::create(*this); return *m_resize_handle; } @@ -1168,7 +1167,7 @@ Optional PaintableBox::hit_test(CSSPixelPoint position, HitTestTy TraversalDecision PaintableBox::hit_test_children(CSSPixelPoint position, HitTestType type, Function const& callback) const { - for (auto const* child = last_child(); child; child = child->previous_sibling()) { + for (auto child = last_child(); child; child = child->previous_sibling()) { if (child->is_positioned() && child->computed_values().z_index().value_or(0) == 0) continue; if (child->has_stacking_context()) @@ -1252,7 +1251,7 @@ CSSPixelRect PaintableBox::transform_reference_box() const // FIXME: If a viewBox attribute is specified for the SVG viewport creating element: // - The reference box is positioned at the origin of the coordinate system established by the viewBox attribute. // - The dimension of the reference box is set to the width and height values of the viewBox attribute. - auto* svg_paintable = first_ancestor_of_type(); + auto svg_paintable = first_ancestor_of_type(); if (!svg_paintable) return absolute_border_box_rect(); return svg_paintable->absolute_rect(); @@ -1286,7 +1285,7 @@ ScrollFrameIndex PaintableBox::nearest_scroll_frame_index() const { if (is_fixed_position()) return {}; - auto const* paintable = this->containing_block(); + auto paintable = this->containing_block(); while (paintable) { if (paintable->own_scroll_frame_index().value()) return paintable->own_scroll_frame_index(); @@ -1299,9 +1298,9 @@ ScrollFrameIndex PaintableBox::nearest_scroll_frame_index() const return {}; } -PaintableBox const* PaintableBox::nearest_scrollable_ancestor() const +RefPtr PaintableBox::nearest_scrollable_ancestor() const { - auto const* paintable = this->containing_block(); + auto paintable = this->containing_block(); while (paintable) { if (paintable->could_be_scrolled_by_wheel_event()) return paintable; diff --git a/Libraries/LibWeb/Painting/PaintableBox.h b/Libraries/LibWeb/Painting/PaintableBox.h index 72582e8132..43e29e700d 100644 --- a/Libraries/LibWeb/Painting/PaintableBox.h +++ b/Libraries/LibWeb/Painting/PaintableBox.h @@ -8,6 +8,8 @@ #pragma once #include +#include +#include #include #include #include @@ -32,21 +34,19 @@ WEB_API void set_paint_viewport_scrollbars(bool enabled); ResolvedCSSFilter resolve_css_filter(CSS::Filter const& computed_filter, PaintableBox const& paintable_box); class WEB_API PaintableBox : public Paintable { - GC_CELL(PaintableBox, Paintable); - GC_DECLARE_ALLOCATOR(PaintableBox); - public: - static GC::Ref create(Layout::Box const&); - static GC::Ref create(Layout::InlineNode const&); + static NonnullRefPtr create(Layout::Box const&); + static NonnullRefPtr create(Layout::InlineNode const&); virtual ~PaintableBox(); + virtual StringView class_name() const override { return "PaintableBox"sv; } virtual void reset_for_relayout(); virtual void paint(DisplayListRecordingContext&, PaintPhase) const override; - StackingContext* stacking_context() { return m_stacking_context; } - StackingContext const* stacking_context() const { return m_stacking_context; } - void set_stacking_context(GC::Ref); + RefPtr stacking_context(); + RefPtr stacking_context() const; + void set_stacking_context(NonnullRefPtr); void invalidate_stacking_context(); Optional effective_z_index() const; @@ -174,8 +174,8 @@ public: ScrollStateSnapshot const* = nullptr) const; Optional absolute_scrollbar_rect(ScrollDirection direction, bool with_gutter, ChromeMetrics const& chrome_metrics) const; - GC::Ptr scrollbar(ScrollDirection) const; - GC::Ref ensure_scrollbar(ScrollDirection); + RefPtr scrollbar(ScrollDirection) const; + NonnullRefPtr ensure_scrollbar(ScrollDirection); enum class ConflictingElementKind { Cell, @@ -240,14 +240,14 @@ public: bool is_chrome_mirrored() const; bool has_resizer() const; - GC::Ptr resize_handle() const; - GC::Ref ensure_resize_handle(); + RefPtr resize_handle() const; + NonnullRefPtr ensure_resize_handle(); CSSPixelRect transform_reference_box() const; ScrollFrameIndex nearest_scroll_frame_index() const; - PaintableBox const* nearest_scrollable_ancestor() const; + RefPtr nearest_scrollable_ancestor() const; using StickyInsets = Painting::StickyInsets; StickyInsets const& sticky_insets() const { return *m_sticky_insets; } @@ -301,8 +301,6 @@ protected: explicit PaintableBox(Layout::Box const&); explicit PaintableBox(Layout::InlineNode const&); - virtual void visit_edges(Visitor&) override; - virtual void paint_border(DisplayListRecordingContext&) const; virtual void paint_backdrop_filter(DisplayListRecordingContext&) const; virtual void paint_background(DisplayListRecordingContext&) const; @@ -325,7 +323,7 @@ private: void paint_middle_button_scroll_indicator(DisplayListRecordingContext&) const; - GC::Ptr m_stacking_context; + RefPtr m_stacking_context; Optional m_overflow_data; @@ -346,9 +344,9 @@ private: ResolvedCSSFilter m_filter; - GC::Ptr m_horizontal_scrollbar; - GC::Ptr m_vertical_scrollbar; - GC::Ptr m_resize_handle; + RefPtr m_horizontal_scrollbar; + RefPtr m_vertical_scrollbar; + RefPtr m_resize_handle; bool m_has_non_invertible_css_transform { false }; OwnPtr m_sticky_insets; diff --git a/Libraries/LibWeb/Painting/PaintableFragment.cpp b/Libraries/LibWeb/Painting/PaintableFragment.cpp index 4243767552..8f182787f8 100644 --- a/Libraries/LibWeb/Painting/PaintableFragment.cpp +++ b/Libraries/LibWeb/Painting/PaintableFragment.cpp @@ -52,7 +52,7 @@ PaintableFragment::PaintableFragment(Layout::LineBoxFragment const& fragment) CSSPixelRect const PaintableFragment::absolute_rect() const { CSSPixelRect rect { offset(), size() }; - if (auto const* containing_block = paintable().containing_block()) + if (auto containing_block = paintable().containing_block()) rect.translate_by(containing_block->absolute_position()); return rect; } @@ -294,9 +294,10 @@ CSSPixelRect PaintableFragment::selection_rect() const Utf16View PaintableFragment::text() const { - if (!is(paintable())) + auto const* text_paintable = as_if(paintable()); + if (!text_paintable) return {}; - return as(paintable()).layout_node().text_for_rendering().substring_view(m_start_offset, m_length_in_code_units); + return text_paintable->layout_node().text_for_rendering().substring_view(m_start_offset, m_length_in_code_units); } } diff --git a/Libraries/LibWeb/Painting/PaintableWithLines.cpp b/Libraries/LibWeb/Painting/PaintableWithLines.cpp index 55db4ef8b2..110d14b76e 100644 --- a/Libraries/LibWeb/Painting/PaintableWithLines.cpp +++ b/Libraries/LibWeb/Painting/PaintableWithLines.cpp @@ -20,26 +20,25 @@ #include #include #include +#include #include #include namespace Web::Painting { -GC_DEFINE_ALLOCATOR(PaintableWithLines); - static void paint_text_decoration(DisplayListRecordingContext&, TextPaintable const&, PaintableFragment::FragmentSpan const&); static Gfx::Path build_triangle_wave_path(Gfx::IntPoint from, Gfx::IntPoint to, float amplitude); static void compute_render_spans(PaintableFragment const&, Vector&); static void paint_text_fragment(DisplayListRecordingContext&, PaintableFragment::FragmentSpan const&); -GC::Ref PaintableWithLines::create(Layout::BlockContainer const& block_container) +NonnullRefPtr PaintableWithLines::create(Layout::BlockContainer const& block_container) { - return block_container.heap().allocate(block_container); + return adopt_ref(*new PaintableWithLines(block_container)); } -GC::Ref PaintableWithLines::create(Layout::InlineNode const& inline_node, size_t line_index) +NonnullRefPtr PaintableWithLines::create(Layout::InlineNode const& inline_node, size_t line_index) { - return inline_node.heap().allocate(inline_node, line_index); + return adopt_ref(*new PaintableWithLines(inline_node, line_index)); } PaintableWithLines::PaintableWithLines(Layout::BlockContainer const& layout_box) @@ -288,8 +287,8 @@ void PaintableWithLines::paint(DisplayListRecordingContext& context, PaintPhase void compute_render_spans(PaintableFragment const& fragment, Vector& spans) { - auto const* text_paintable = as_if(fragment.paintable()); - if (!text_paintable) { + auto const* maybe_text_paintable = as_if(fragment.paintable()); + if (!maybe_text_paintable) { // Non-text fragments still need shadow painting. spans.append({ .fragment = fragment, @@ -302,11 +301,12 @@ void compute_render_spans(PaintableFragment const& fragment, Vectoris_visible()) + if (!text_paintable.is_visible()) return; - auto text_color = text_paintable->computed_values().webkit_text_fill_color(); + auto text_color = text_paintable.computed_values().webkit_text_fill_color(); auto selection_offsets = fragment.selection_offsets(); // No selection: single span with base styling. @@ -324,7 +324,7 @@ void compute_render_spans(PaintableFragment const& fragment, Vectorselection_style(); + auto selection_style = text_paintable.selection_style(); auto selection_text_color = selection_style.text_color.value_or(text_color); // Convert selection text decoration to fragment text decoration data. diff --git a/Libraries/LibWeb/Painting/PaintableWithLines.h b/Libraries/LibWeb/Painting/PaintableWithLines.h index f7efd81bec..c65f5746e3 100644 --- a/Libraries/LibWeb/Painting/PaintableWithLines.h +++ b/Libraries/LibWeb/Painting/PaintableWithLines.h @@ -14,13 +14,11 @@ namespace Web::Painting { class PaintableWithLines : public PaintableBox { - GC_CELL(PaintableWithLines, PaintableBox); - GC_DECLARE_ALLOCATOR(PaintableWithLines); - public: - static GC::Ref create(Layout::BlockContainer const&); - static GC::Ref create(Layout::InlineNode const&, size_t line_index); + static NonnullRefPtr create(Layout::BlockContainer const&); + static NonnullRefPtr create(Layout::InlineNode const&, size_t line_index); virtual ~PaintableWithLines() override; + virtual StringView class_name() const override { return "PaintableWithLines"sv; } virtual void reset_for_relayout() override; @@ -38,13 +36,6 @@ public: [[nodiscard]] virtual TraversalDecision hit_test(CSSPixelPoint position, HitTestType type, Function const& callback) const override; [[nodiscard]] TraversalDecision hit_test_fragments(CSSPixelPoint position, CSSPixelPoint local_position, HitTestType type, Function const& callback) const; - virtual void visit_edges(Cell::Visitor& visitor) override - { - Base::visit_edges(visitor); - for (auto& fragment : m_fragments) - visitor.visit(GC::Ref { fragment.layout_node() }); - } - size_t line_index() const { return m_line_index; } protected: diff --git a/Libraries/LibWeb/Painting/RadioButtonPaintable.cpp b/Libraries/LibWeb/Painting/RadioButtonPaintable.cpp index 709180ca42..6c2a4fb945 100644 --- a/Libraries/LibWeb/Painting/RadioButtonPaintable.cpp +++ b/Libraries/LibWeb/Painting/RadioButtonPaintable.cpp @@ -15,11 +15,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(RadioButtonPaintable); - -GC::Ref RadioButtonPaintable::create(Layout::RadioButton const& layout_box) +NonnullRefPtr RadioButtonPaintable::create(Layout::RadioButton const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new RadioButtonPaintable(layout_box)); } RadioButtonPaintable::RadioButtonPaintable(Layout::RadioButton const& layout_box) diff --git a/Libraries/LibWeb/Painting/RadioButtonPaintable.h b/Libraries/LibWeb/Painting/RadioButtonPaintable.h index a2d6b2b1b6..326f0e3a53 100644 --- a/Libraries/LibWeb/Painting/RadioButtonPaintable.h +++ b/Libraries/LibWeb/Painting/RadioButtonPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class RadioButtonPaintable final : public PaintableBox { - GC_CELL(RadioButtonPaintable, PaintableBox); - GC_DECLARE_ALLOCATOR(RadioButtonPaintable); - public: - static GC::Ref create(Layout::RadioButton const&); + static NonnullRefPtr create(Layout::RadioButton const&); + virtual StringView class_name() const override { return "RadioButtonPaintable"sv; } virtual void paint(DisplayListRecordingContext&, PaintPhase) const override; diff --git a/Libraries/LibWeb/Painting/ResizeHandle.cpp b/Libraries/LibWeb/Painting/ResizeHandle.cpp index 325fbd1cc3..e4a12ed9c6 100644 --- a/Libraries/LibWeb/Painting/ResizeHandle.cpp +++ b/Libraries/LibWeb/Painting/ResizeHandle.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -14,11 +15,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(ResizeHandle); - -GC::Ref ResizeHandle::create(GC::Heap& heap, PaintableBox& paintable_box) +NonnullRefPtr ResizeHandle::create(PaintableBox& paintable_box) { - return heap.allocate(paintable_box); + return adopt_ref(*new ResizeHandle(paintable_box)); } ResizeHandle::ResizeHandle(PaintableBox& paintable_box) @@ -27,26 +26,23 @@ ResizeHandle::ResizeHandle(PaintableBox& paintable_box) { } -void ResizeHandle::visit_edges(Cell::Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_paintable_box); - visitor.visit(m_element); - if (m_resize_action) - m_resize_action->visit_edges(visitor); -} - bool ResizeHandle::contains(CSSPixelPoint position, ChromeMetrics const& metrics) const { - return m_paintable_box->resizer_contains(position, metrics); + auto paintable_box = m_paintable_box.strong_ref(); + if (!paintable_box) + return false; + return paintable_box->resizer_contains(position, metrics); } Optional ResizeHandle::cursor() const { - auto axes = m_paintable_box->physical_resize_axes(); + auto paintable_box = m_paintable_box.strong_ref(); + if (!paintable_box) + return {}; + auto axes = paintable_box->physical_resize_axes(); if (axes.vertical) { if (axes.horizontal) { - if (m_paintable_box->is_chrome_mirrored()) + if (paintable_box->is_chrome_mirrored()) return CSS::CursorPredefined::SwResize; return CSS::CursorPredefined::SeResize; } @@ -64,8 +60,14 @@ MouseAction ResizeHandle::handle_pointer_event(FlyString const& type, unsigned b return MouseAction::None; } + auto element = m_element.ptr(); + if (!element || !element->is_connected()) { + m_resize_action.clear(); + return MouseAction::None; + } + if (!m_resize_action) - m_resize_action = make(m_element, visual_viewport_position); + m_resize_action = make(*element, visual_viewport_position); else m_resize_action->handle_pointer_move(visual_viewport_position); diff --git a/Libraries/LibWeb/Painting/ResizeHandle.h b/Libraries/LibWeb/Painting/ResizeHandle.h index 923a23e83c..9d95c8b8a4 100644 --- a/Libraries/LibWeb/Painting/ResizeHandle.h +++ b/Libraries/LibWeb/Painting/ResizeHandle.h @@ -6,17 +6,15 @@ #pragma once +#include #include #include namespace Web::Painting { class ResizeHandle final : public ChromeWidget { - GC_CELL(ResizeHandle, ChromeWidget); - GC_DECLARE_ALLOCATOR(ResizeHandle); - public: - static GC::Ref create(GC::Heap&, PaintableBox&); + static NonnullRefPtr create(PaintableBox&); bool contains(CSSPixelPoint position, ChromeMetrics const&) const; @@ -29,10 +27,8 @@ public: private: ResizeHandle(PaintableBox&); - virtual void visit_edges(Cell::Visitor&) override; - - GC::Ref m_paintable_box; - GC::Ref m_element; + WeakPtr m_paintable_box; + GC::Weak m_element; OwnPtr m_resize_action; }; diff --git a/Libraries/LibWeb/Painting/SVGClipPaintable.cpp b/Libraries/LibWeb/Painting/SVGClipPaintable.cpp index 676858f95b..6ab671a2e7 100644 --- a/Libraries/LibWeb/Painting/SVGClipPaintable.cpp +++ b/Libraries/LibWeb/Painting/SVGClipPaintable.cpp @@ -8,11 +8,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(SVGClipPaintable); - -GC::Ref SVGClipPaintable::create(Layout::SVGClipBox const& layout_box) +NonnullRefPtr SVGClipPaintable::create(Layout::SVGClipBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new SVGClipPaintable(layout_box)); } SVGClipPaintable::SVGClipPaintable(Layout::SVGClipBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/SVGClipPaintable.h b/Libraries/LibWeb/Painting/SVGClipPaintable.h index 7aa2ae14ef..19a76acaaf 100644 --- a/Libraries/LibWeb/Painting/SVGClipPaintable.h +++ b/Libraries/LibWeb/Painting/SVGClipPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class SVGClipPaintable : public SVGPaintable { - GC_CELL(SVGClipPaintable, SVGPaintable); - GC_DECLARE_ALLOCATOR(SVGClipPaintable); - public: - static GC::Ref create(Layout::SVGClipBox const&); + static NonnullRefPtr create(Layout::SVGClipBox const&); + virtual StringView class_name() const override { return "SVGClipPaintable"sv; } bool forms_unconnected_subtree() const override { diff --git a/Libraries/LibWeb/Painting/SVGForeignObjectPaintable.cpp b/Libraries/LibWeb/Painting/SVGForeignObjectPaintable.cpp index ae0cb53dbd..56909a992e 100644 --- a/Libraries/LibWeb/Painting/SVGForeignObjectPaintable.cpp +++ b/Libraries/LibWeb/Painting/SVGForeignObjectPaintable.cpp @@ -9,11 +9,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(SVGForeignObjectPaintable); - -GC::Ref SVGForeignObjectPaintable::create(Layout::SVGForeignObjectBox const& layout_box) +NonnullRefPtr SVGForeignObjectPaintable::create(Layout::SVGForeignObjectBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new SVGForeignObjectPaintable(layout_box)); } SVGForeignObjectPaintable::SVGForeignObjectPaintable(Layout::SVGForeignObjectBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/SVGForeignObjectPaintable.h b/Libraries/LibWeb/Painting/SVGForeignObjectPaintable.h index 960e8747f5..62e32ea78f 100644 --- a/Libraries/LibWeb/Painting/SVGForeignObjectPaintable.h +++ b/Libraries/LibWeb/Painting/SVGForeignObjectPaintable.h @@ -14,11 +14,9 @@ namespace Web::Painting { class SVGForeignObjectPaintable final : public PaintableWithLines , public SVGMaskable { - GC_CELL(SVGForeignObjectPaintable, PaintableWithLines); - GC_DECLARE_ALLOCATOR(SVGForeignObjectPaintable); - public: - static GC::Ref create(Layout::SVGForeignObjectBox const&); + static NonnullRefPtr create(Layout::SVGForeignObjectBox const&); + virtual StringView class_name() const override { return "SVGForeignObjectPaintable"sv; } virtual TraversalDecision hit_test(CSSPixelPoint, HitTestType, Function const& callback) const override; diff --git a/Libraries/LibWeb/Painting/SVGGraphicsPaintable.cpp b/Libraries/LibWeb/Painting/SVGGraphicsPaintable.cpp index 77a116004f..7c4476caf6 100644 --- a/Libraries/LibWeb/Painting/SVGGraphicsPaintable.cpp +++ b/Libraries/LibWeb/Painting/SVGGraphicsPaintable.cpp @@ -14,11 +14,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(SVGGraphicsPaintable); - -GC::Ref SVGGraphicsPaintable::create(Layout::SVGGraphicsBox const& layout_box) +NonnullRefPtr SVGGraphicsPaintable::create(Layout::SVGGraphicsBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new SVGGraphicsPaintable(layout_box)); } SVGGraphicsPaintable::SVGGraphicsPaintable(Layout::SVGGraphicsBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/SVGGraphicsPaintable.h b/Libraries/LibWeb/Painting/SVGGraphicsPaintable.h index 6b16ea0356..90b66eaaa3 100644 --- a/Libraries/LibWeb/Painting/SVGGraphicsPaintable.h +++ b/Libraries/LibWeb/Painting/SVGGraphicsPaintable.h @@ -14,9 +14,6 @@ namespace Web::Painting { class SVGGraphicsPaintable : public SVGPaintable , public SVGMaskable { - GC_CELL(SVGGraphicsPaintable, SVGPaintable); - GC_DECLARE_ALLOCATOR(SVGGraphicsPaintable); - public: class ComputedTransforms { public: @@ -48,7 +45,8 @@ public: Gfx::AffineTransform m_svg_transform {}; }; - static GC::Ref create(Layout::SVGGraphicsBox const&); + static NonnullRefPtr create(Layout::SVGGraphicsBox const&); + virtual StringView class_name() const override { return "SVGGraphicsPaintable"sv; } virtual GC::Ptr dom_node_of_svg() const override { return dom_node(); } virtual Optional get_mask_area() const override { return get_svg_mask_area(); } diff --git a/Libraries/LibWeb/Painting/SVGMaskPaintable.cpp b/Libraries/LibWeb/Painting/SVGMaskPaintable.cpp index cb4c367113..0824300234 100644 --- a/Libraries/LibWeb/Painting/SVGMaskPaintable.cpp +++ b/Libraries/LibWeb/Painting/SVGMaskPaintable.cpp @@ -8,11 +8,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(SVGMaskPaintable); - -GC::Ref SVGMaskPaintable::create(Layout::SVGMaskBox const& layout_box) +NonnullRefPtr SVGMaskPaintable::create(Layout::SVGMaskBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new SVGMaskPaintable(layout_box)); } SVGMaskPaintable::SVGMaskPaintable(Layout::SVGMaskBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/SVGMaskPaintable.h b/Libraries/LibWeb/Painting/SVGMaskPaintable.h index 253fe35bdf..816aca1d36 100644 --- a/Libraries/LibWeb/Painting/SVGMaskPaintable.h +++ b/Libraries/LibWeb/Painting/SVGMaskPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class SVGMaskPaintable : public SVGGraphicsPaintable { - GC_CELL(SVGMaskPaintable, SVGGraphicsPaintable); - GC_DECLARE_ALLOCATOR(SVGMaskPaintable); - public: - static GC::Ref create(Layout::SVGMaskBox const&); + static NonnullRefPtr create(Layout::SVGMaskBox const&); + virtual StringView class_name() const override { return "SVGMaskPaintable"sv; } bool forms_unconnected_subtree() const override { diff --git a/Libraries/LibWeb/Painting/SVGPaintable.h b/Libraries/LibWeb/Painting/SVGPaintable.h index 00acac2343..a181d9009c 100644 --- a/Libraries/LibWeb/Painting/SVGPaintable.h +++ b/Libraries/LibWeb/Painting/SVGPaintable.h @@ -12,9 +12,9 @@ namespace Web::Painting { class SVGPaintable : public PaintableBox { - GC_CELL(SVGPaintable, PaintableBox); - public: + virtual StringView class_name() const override { return "SVGPaintable"sv; } + Layout::SVGBox const& layout_box() const; virtual Optional clip_path_geometry_bounds(Gfx::AffineTransform const& additional_transform) const; bool contributes_to_clip_path() const; diff --git a/Libraries/LibWeb/Painting/SVGPathPaintable.cpp b/Libraries/LibWeb/Painting/SVGPathPaintable.cpp index 3a16e6320b..2817b2a0e6 100644 --- a/Libraries/LibWeb/Painting/SVGPathPaintable.cpp +++ b/Libraries/LibWeb/Painting/SVGPathPaintable.cpp @@ -12,11 +12,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(SVGPathPaintable); - -GC::Ref SVGPathPaintable::create(Layout::SVGGraphicsBox const& layout_box) +NonnullRefPtr SVGPathPaintable::create(Layout::SVGGraphicsBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new SVGPathPaintable(layout_box)); } SVGPathPaintable::SVGPathPaintable(Layout::SVGGraphicsBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/SVGPathPaintable.h b/Libraries/LibWeb/Painting/SVGPathPaintable.h index 4b76c9839c..097b0fb9b2 100644 --- a/Libraries/LibWeb/Painting/SVGPathPaintable.h +++ b/Libraries/LibWeb/Painting/SVGPathPaintable.h @@ -14,11 +14,9 @@ namespace Web::Painting { class WEB_API SVGPathPaintable final : public SVGGraphicsPaintable { - GC_CELL(SVGPathPaintable, SVGGraphicsPaintable); - GC_DECLARE_ALLOCATOR(SVGPathPaintable); - public: - static GC::Ref create(Layout::SVGGraphicsBox const&); + static NonnullRefPtr create(Layout::SVGGraphicsBox const&); + virtual StringView class_name() const override { return "SVGPathPaintable"sv; } virtual TraversalDecision hit_test(CSSPixelPoint, HitTestType, Function const& callback) const override; virtual Optional clip_path_geometry_bounds(Gfx::AffineTransform const& additional_transform) const override; diff --git a/Libraries/LibWeb/Painting/SVGPatternPaintable.cpp b/Libraries/LibWeb/Painting/SVGPatternPaintable.cpp index c7e1c66e5b..82c637484b 100644 --- a/Libraries/LibWeb/Painting/SVGPatternPaintable.cpp +++ b/Libraries/LibWeb/Painting/SVGPatternPaintable.cpp @@ -8,11 +8,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(SVGPatternPaintable); - -GC::Ref SVGPatternPaintable::create(Layout::SVGPatternBox const& layout_box) +NonnullRefPtr SVGPatternPaintable::create(Layout::SVGPatternBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new SVGPatternPaintable(layout_box)); } SVGPatternPaintable::SVGPatternPaintable(Layout::SVGPatternBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/SVGPatternPaintable.h b/Libraries/LibWeb/Painting/SVGPatternPaintable.h index 59cd0ecd92..5014d77738 100644 --- a/Libraries/LibWeb/Painting/SVGPatternPaintable.h +++ b/Libraries/LibWeb/Painting/SVGPatternPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class SVGPatternPaintable : public SVGPaintable { - GC_CELL(SVGPatternPaintable, SVGPaintable); - GC_DECLARE_ALLOCATOR(SVGPatternPaintable); - public: - static GC::Ref create(Layout::SVGPatternBox const&); + static NonnullRefPtr create(Layout::SVGPatternBox const&); + virtual StringView class_name() const override { return "SVGPatternPaintable"sv; } bool forms_unconnected_subtree() const override { diff --git a/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp b/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp index 626468251c..cf1bc893c8 100644 --- a/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp +++ b/Libraries/LibWeb/Painting/SVGSVGPaintable.cpp @@ -10,11 +10,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(SVGSVGPaintable); - -GC::Ref SVGSVGPaintable::create(Layout::SVGSVGBox const& layout_box) +NonnullRefPtr SVGSVGPaintable::create(Layout::SVGSVGBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new SVGSVGPaintable(layout_box)); } SVGSVGPaintable::SVGSVGPaintable(Layout::SVGSVGBox const& layout_box) diff --git a/Libraries/LibWeb/Painting/SVGSVGPaintable.h b/Libraries/LibWeb/Painting/SVGSVGPaintable.h index 76779e4b80..8b84bb1b83 100644 --- a/Libraries/LibWeb/Painting/SVGSVGPaintable.h +++ b/Libraries/LibWeb/Painting/SVGSVGPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class SVGSVGPaintable final : public PaintableBox { - GC_CELL(SVGSVGPaintable, PaintableBox); - GC_DECLARE_ALLOCATOR(SVGSVGPaintable); - public: - static GC::Ref create(Layout::SVGSVGBox const&); + static NonnullRefPtr create(Layout::SVGSVGBox const&); + virtual StringView class_name() const override { return "SVGSVGPaintable"sv; } static void paint_svg_box(DisplayListRecordingContext& context, PaintableBox const& svg_box, PaintPhase phase); static void paint_descendants(DisplayListRecordingContext& context, PaintableBox const& paintable, PaintPhase phase); diff --git a/Libraries/LibWeb/Painting/ScrollFrame.cpp b/Libraries/LibWeb/Painting/ScrollFrame.cpp index 1b1e77a44f..a8bdfb93fd 100644 --- a/Libraries/LibWeb/Painting/ScrollFrame.cpp +++ b/Libraries/LibWeb/Painting/ScrollFrame.cpp @@ -4,8 +4,6 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include -#include #include #include @@ -18,4 +16,11 @@ ScrollFrame::ScrollFrame(PaintableBox const& paintable_box, bool sticky, ScrollF { } +PaintableBox const& ScrollFrame::paintable_box() const +{ + auto paintable_box = m_paintable_box.strong_ref(); + VERIFY(paintable_box); + return *paintable_box; +} + } diff --git a/Libraries/LibWeb/Painting/ScrollFrame.h b/Libraries/LibWeb/Painting/ScrollFrame.h index a65c2f7318..0497cfaa14 100644 --- a/Libraries/LibWeb/Painting/ScrollFrame.h +++ b/Libraries/LibWeb/Painting/ScrollFrame.h @@ -7,7 +7,7 @@ #pragma once #include -#include +#include #include #include @@ -36,7 +36,7 @@ public: ScrollFrame() = default; ScrollFrame(PaintableBox const& paintable_box, bool sticky, ScrollFrameIndex parent_index); - PaintableBox const& paintable_box() const { return *m_paintable_box; } + PaintableBox const& paintable_box() const; bool is_sticky() const { return m_sticky; } @@ -57,7 +57,7 @@ private: friend class ScrollState; friend class ScrollStateSnapshot; - GC::Weak m_paintable_box; + WeakPtr m_paintable_box; bool m_sticky { false }; ScrollFrameIndex m_parent_index; CSSPixelPoint m_own_offset; diff --git a/Libraries/LibWeb/Painting/Scrollbar.cpp b/Libraries/LibWeb/Painting/Scrollbar.cpp index e88872fcdd..68e20713b1 100644 --- a/Libraries/LibWeb/Painting/Scrollbar.cpp +++ b/Libraries/LibWeb/Painting/Scrollbar.cpp @@ -14,11 +14,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(Scrollbar); - -GC::Ref Scrollbar::create(GC::Heap& heap, PaintableBox& paintable_box, PaintableBox::ScrollDirection direction) +NonnullRefPtr Scrollbar::create(PaintableBox& paintable_box, PaintableBox::ScrollDirection direction) { - return heap.allocate(paintable_box, direction); + return adopt_ref(*new Scrollbar(paintable_box, direction)); } Scrollbar::Scrollbar(PaintableBox& paintable_box, PaintableBox::ScrollDirection direction) @@ -27,15 +25,12 @@ Scrollbar::Scrollbar(PaintableBox& paintable_box, PaintableBox::ScrollDirection { } -void Scrollbar::visit_edges(Cell::Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_paintable_box); -} - bool Scrollbar::contains(CSSPixelPoint position, ChromeMetrics const& metrics) const { - if (auto rect = m_paintable_box->absolute_scrollbar_rect(m_direction, is_enlarged(), metrics); rect.has_value()) + auto paintable_box = m_paintable_box.strong_ref(); + if (!paintable_box) + return false; + if (auto rect = paintable_box->absolute_scrollbar_rect(m_direction, is_enlarged(), metrics); rect.has_value()) return rect->contains(position); return false; } @@ -49,9 +44,13 @@ MouseAction Scrollbar::handle_pointer_event(FlyString const& type, unsigned butt return MouseAction::None; } - auto position = m_paintable_box->transform_to_local_coordinates(visual_viewport_position); + auto paintable_box = m_paintable_box.strong_ref(); + if (!paintable_box) + return MouseAction::None; + + auto position = paintable_box->transform_to_local_coordinates(visual_viewport_position); scroll_to_mouse_position(position); - m_paintable_box->set_needs_repaint(); + paintable_box->set_needs_repaint(); if (type == UIEvents::EventNames::pointerup) { m_thumb_grab_position.clear(); @@ -64,7 +63,10 @@ MouseAction Scrollbar::handle_pointer_event(FlyString const& type, unsigned butt MouseAction Scrollbar::mouse_move(CSSPixelPoint position) { if (m_thumb_grab_position.has_value()) { - position = m_paintable_box->transform_to_local_coordinates(position); + auto paintable_box = m_paintable_box.strong_ref(); + if (!paintable_box) + return MouseAction::None; + position = paintable_box->transform_to_local_coordinates(position); scroll_to_mouse_position(position); return MouseAction::SwallowEvent; } @@ -74,7 +76,8 @@ MouseAction Scrollbar::mouse_move(CSSPixelPoint position) MouseAction Scrollbar::mouse_up(CSSPixelPoint, unsigned) { m_thumb_grab_position.clear(); - m_paintable_box->set_needs_repaint(); + if (auto paintable_box = m_paintable_box.strong_ref()) + paintable_box->set_needs_repaint(); return MouseAction::None; } @@ -83,7 +86,8 @@ void Scrollbar::mouse_enter() if (m_hovered) return; m_hovered = true; - m_paintable_box->set_needs_repaint(); + if (auto paintable_box = m_paintable_box.strong_ref()) + paintable_box->set_needs_repaint(); } void Scrollbar::mouse_leave() @@ -91,15 +95,20 @@ void Scrollbar::mouse_leave() if (!m_hovered) return; m_hovered = false; - m_paintable_box->set_needs_repaint(); + if (auto paintable_box = m_paintable_box.strong_ref()) + paintable_box->set_needs_repaint(); } void Scrollbar::scroll_to_mouse_position(CSSPixelPoint position) { - ChromeMetrics metrics = m_paintable_box->document().page().chrome_metrics(); + auto paintable_box = m_paintable_box.strong_ref(); + if (!paintable_box) + return; - auto const& scroll_state = m_paintable_box->document().paintable()->scroll_state_snapshot(); - auto scrollbar_data = m_paintable_box->compute_scrollbar_data(m_direction, metrics, &scroll_state); + ChromeMetrics metrics = paintable_box->document().page().chrome_metrics(); + + auto const& scroll_state = paintable_box->document().paintable()->scroll_state_snapshot(); + auto scrollbar_data = paintable_box->compute_scrollbar_data(m_direction, metrics, &scroll_state); VERIFY(scrollbar_data.has_value()); auto orientation = m_direction == PaintableBox::ScrollDirection::Horizontal ? Orientation::Horizontal : Orientation::Vertical; @@ -119,13 +128,13 @@ void Scrollbar::scroll_to_mouse_position(CSSPixelPoint position) auto constrained_offset = AK::clamp(offset_relative_to_gutter - m_thumb_grab_position.value(), 0, gutter_size - thumb_size); auto scroll_position = constrained_offset.to_double() / (gutter_size - thumb_size).to_double(); - auto scrollable_overflow_size = m_paintable_box->scrollable_overflow_rect()->primary_size_for_orientation(orientation); - auto padding_size = m_paintable_box->absolute_padding_box_rect().primary_size_for_orientation(orientation); + auto scrollable_overflow_size = paintable_box->scrollable_overflow_rect()->primary_size_for_orientation(orientation); + auto padding_size = paintable_box->absolute_padding_box_rect().primary_size_for_orientation(orientation); auto scroll_position_in_pixels = CSSPixels::nearest_value_for(scroll_position * (scrollable_overflow_size - padding_size)); - auto new_scroll_offset = m_paintable_box->scroll_offset(); + auto new_scroll_offset = paintable_box->scroll_offset(); new_scroll_offset.set_primary_offset_for_orientation(orientation, scroll_position_in_pixels); - m_paintable_box->set_scroll_offset(new_scroll_offset); + paintable_box->set_scroll_offset(new_scroll_offset); } } diff --git a/Libraries/LibWeb/Painting/Scrollbar.h b/Libraries/LibWeb/Painting/Scrollbar.h index 257973d59e..f718dc01af 100644 --- a/Libraries/LibWeb/Painting/Scrollbar.h +++ b/Libraries/LibWeb/Painting/Scrollbar.h @@ -12,11 +12,8 @@ namespace Web::Painting { class Scrollbar final : public ChromeWidget { - GC_CELL(Scrollbar, ChromeWidget); - GC_DECLARE_ALLOCATOR(Scrollbar); - public: - static GC::Ref create(GC::Heap&, PaintableBox&, PaintableBox::ScrollDirection); + static NonnullRefPtr create(PaintableBox&, PaintableBox::ScrollDirection); PaintableBox::ScrollDirection direction() const { return m_direction; } bool is_enlarged() const { return m_hovered || m_thumb_grab_position.has_value(); } @@ -30,14 +27,12 @@ public: private: Scrollbar(PaintableBox&, PaintableBox::ScrollDirection); - virtual void visit_edges(Cell::Visitor&) override; - MouseAction mouse_down(CSSPixelPoint, unsigned button); MouseAction mouse_move(CSSPixelPoint); MouseAction mouse_up(CSSPixelPoint, unsigned button); void scroll_to_mouse_position(CSSPixelPoint); - GC::Ref m_paintable_box; + WeakPtr m_paintable_box; PaintableBox::ScrollDirection m_direction; bool m_hovered { false }; Optional m_thumb_grab_position; diff --git a/Libraries/LibWeb/Painting/StackingContext.cpp b/Libraries/LibWeb/Painting/StackingContext.cpp index e6eb1b3c03..2f84c24cc8 100644 --- a/Libraries/LibWeb/Painting/StackingContext.cpp +++ b/Libraries/LibWeb/Painting/StackingContext.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -25,13 +26,11 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(StackingContext); - static void paint_node(Paintable const& paintable, DisplayListRecordingContext& context, PaintPhase phase) { TemporaryChange save_nesting_level(context.display_list_recorder().m_save_nesting_level, 0); - auto const* paintable_box = as_if(paintable); + RefPtr paintable_box = as_if(paintable); if (paintable_box) { // Text fragments in a PaintableWithLines are content of the block container. @@ -58,14 +57,20 @@ static void paint_node(Paintable const& paintable, DisplayListRecordingContext& VERIFY(context.display_list_recorder().m_save_nesting_level == 0); } -StackingContext::StackingContext(PaintableBox& paintable, StackingContext* parent, size_t index_in_tree_order) +NonnullRefPtr StackingContext::create(PaintableBox& paintable, RefPtr parent, size_t index_in_tree_order) +{ + auto stacking_context = adopt_ref(*new StackingContext(paintable, parent, index_in_tree_order)); + if (parent) + parent->m_children.append(stacking_context); + return stacking_context; +} + +StackingContext::StackingContext(PaintableBox& paintable, RefPtr parent, size_t index_in_tree_order) : m_paintable(paintable) , m_parent(parent) , m_index_in_tree_order(index_in_tree_order) { - VERIFY(m_parent != this); - if (m_parent) - m_parent->m_children.append(*this); + VERIFY(!parent || parent.ptr() != this); } void StackingContext::sort() @@ -78,24 +83,14 @@ void StackingContext::sort() return a_z_index < b_z_index; }); - for (auto child : m_children) + for (auto& child : m_children) child->sort(); } -void StackingContext::visit_edges(Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_paintable); - visitor.visit(m_non_positioned_floating_descendants); - visitor.visit(m_positioned_descendants_and_stacking_contexts_with_stack_level_0); - visitor.visit(m_parent); - visitor.visit(m_children); -} - void StackingContext::set_last_paint_generation_id(u64 generation_id) { if (m_last_paint_generation_id.has_value() && m_last_paint_generation_id.value() >= generation_id) { - dbgln("FIXME: Painting commands are recorded twice for stacking context: {}", m_paintable->layout_node().debug_description()); + dbgln("FIXME: Painting commands are recorded twice for stacking context: {}", paintable_box().layout_node().debug_description()); } m_last_paint_generation_id = generation_id; } @@ -255,7 +250,7 @@ void StackingContext::paint_internal(DisplayListRecordingContext& context) const // Here, we treat non-positioned stacking contexts as if they were positioned, because CSS 2.0 spec does not // account for new properties like `transform` and `opacity` that can create stacking contexts. // https://github.com/w3c/csswg-drafts/issues/2717 - for (auto child : m_children) { + for (auto& child : m_children) { if (child->paintable_box().effective_z_index().has_value() && child->paintable_box().effective_z_index().value() < 0) paint_child(context, *child); } @@ -273,13 +268,16 @@ void StackingContext::paint_internal(DisplayListRecordingContext& context) const // Here, we treat non-positioned stacking contexts as if they were positioned, because CSS 2.0 spec does not // account for new properties like `transform` and `opacity` that can create stacking contexts. // https://github.com/w3c/csswg-drafts/issues/2717 - for (auto const& paintable : m_positioned_descendants_and_stacking_contexts_with_stack_level_0) { + for (auto const& weak_paintable : m_positioned_descendants_and_stacking_contexts_with_stack_level_0) { + auto paintable = weak_paintable.strong_ref(); + if (!paintable) + continue; // At this point, `paintable_box` is a positioned descendant with z-index: auto. // FIXME: This is basically duplicating logic found elsewhere in this same function. Find a way to make this more elegant. - if (auto* child = paintable->stacking_context()) { + if (auto child = paintable->stacking_context()) { paint_child(context, *child); } else { - paint_node_as_stacking_context(paintable, context); + paint_node_as_stacking_context(*paintable, context); } }; @@ -288,7 +286,7 @@ void StackingContext::paint_internal(DisplayListRecordingContext& context) const // Here, we treat non-positioned stacking contexts as if they were positioned, because CSS 2.0 spec does not // account for new properties like `transform` and `opacity` that can create stacking contexts. // https://github.com/w3c/csswg-drafts/issues/2717 - for (auto child : m_children) { + for (auto& child : m_children) { if (child->paintable_box().effective_z_index().has_value() && child->paintable_box().effective_z_index().value() >= 1) paint_child(context, *child); } @@ -385,7 +383,7 @@ TraversalDecision StackingContext::hit_test(CSSPixelPoint position, HitTestType // 7. the child stacking contexts with positive stack levels (least positive first). // NOTE: Hit testing follows reverse painting order, that's why the conditions here are reversed. - for (auto const child : m_children.in_reverse()) { + for (auto const& child : m_children.in_reverse()) { if (child->paintable_box().effective_z_index().value_or(0) <= 0) break; if (child->hit_test(position, type, callback) == TraversalDecision::Break) @@ -393,7 +391,10 @@ TraversalDecision StackingContext::hit_test(CSSPixelPoint position, HitTestType } // 6. the child stacking contexts with stack level 0 and the positioned descendants with stack level 0. - for (auto const& paintable_box : m_positioned_descendants_and_stacking_contexts_with_stack_level_0.in_reverse()) { + for (auto const& weak_paintable_box : m_positioned_descendants_and_stacking_contexts_with_stack_level_0.in_reverse()) { + auto paintable_box = weak_paintable_box.strong_ref(); + if (!paintable_box) + continue; if (paintable_box->stacking_context()) { if (paintable_box->stacking_context()->hit_test(position, type, callback) == TraversalDecision::Break) return TraversalDecision::Break; @@ -405,7 +406,7 @@ TraversalDecision StackingContext::hit_test(CSSPixelPoint position, HitTestType // 5. the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks. if (paintable_box().layout_node().children_are_inline() && is(paintable_box().layout_node())) { - for (auto const* paintable = paintable_box().last_child(); paintable; paintable = paintable->previous_sibling()) { + for (auto paintable = paintable_box().last_child(); paintable; paintable = paintable->previous_sibling()) { if (paintable->is_inline() && !paintable->is_absolutely_positioned() && !paintable->has_stacking_context()) { if (paintable->hit_test(position, type, callback) == TraversalDecision::Break) return TraversalDecision::Break; @@ -413,26 +414,28 @@ TraversalDecision StackingContext::hit_test(CSSPixelPoint position, HitTestType } // Hit test the stacking context root's own fragments if it's a PaintableWithLines. - if (is(paintable_box())) { - auto const& paintable_with_lines = as(paintable_box()); + if (auto const* paintable_with_lines = as_if(paintable_box())) { auto local_position = paintable_box().transform_point_to_local(position); if (local_position.has_value()) { - if (paintable_with_lines.hit_test_fragments(position, local_position.value(), type, callback) == TraversalDecision::Break) + if (paintable_with_lines->hit_test_fragments(position, local_position.value(), type, callback) == TraversalDecision::Break) return TraversalDecision::Break; } } } // 4. the non-positioned floats. - for (auto const& paintable_box : m_non_positioned_floating_descendants.in_reverse()) { + for (auto const& weak_paintable_box : m_non_positioned_floating_descendants.in_reverse()) { + auto paintable_box = weak_paintable_box.strong_ref(); + if (!paintable_box) + continue; if (paintable_box->hit_test(position, type, callback) == TraversalDecision::Break) return TraversalDecision::Break; } // 3. the in-flow, non-inline-level, non-positioned descendants. if (!paintable_box().layout_node().children_are_inline()) { - for (auto const* child = paintable_box().last_child(); child; child = child->previous_sibling()) { + for (auto child = paintable_box().last_child(); child; child = child->previous_sibling()) { if (!child->is_paintable_box()) continue; @@ -446,7 +449,7 @@ TraversalDecision StackingContext::hit_test(CSSPixelPoint position, HitTestType // 2. the child stacking contexts with negative stack levels (most negative first). // NB: Hit testing follows reverse painting order, so we visit the least negative stack levels first. - for (auto const child : m_children.in_reverse()) { + for (auto const& child : m_children.in_reverse()) { // Skip positive/ zero index child stacking contexts, which have already been handled above. if (child->paintable_box().effective_z_index().value_or(0) >= 0) continue; diff --git a/Libraries/LibWeb/Painting/StackingContext.h b/Libraries/LibWeb/Painting/StackingContext.h index e69144938f..481773b620 100644 --- a/Libraries/LibWeb/Painting/StackingContext.h +++ b/Libraries/LibWeb/Painting/StackingContext.h @@ -6,25 +6,34 @@ #pragma once +#include +#include +#include #include -#include +#include +#include #include #include namespace Web::Painting { -class WEB_API StackingContext final : public GC::Cell { - GC_CELL(StackingContext, GC::Cell); - GC_DECLARE_ALLOCATOR(StackingContext); +class WEB_API StackingContext final + : public RefCounted + , public Weakable { friend class ViewportPaintable; public: - StackingContext(PaintableBox&, StackingContext* parent, size_t index_in_tree_order); + static NonnullRefPtr create(PaintableBox&, RefPtr parent, size_t index_in_tree_order); - StackingContext* parent() { return m_parent; } - StackingContext const* parent() const { return m_parent; } + RefPtr parent() { return m_parent.strong_ref(); } + RefPtr parent() const { return m_parent.strong_ref(); } - PaintableBox const& paintable_box() const { return *m_paintable; } + PaintableBox const& paintable_box() const + { + auto paintable = m_paintable.strong_ref(); + VERIFY(paintable); + return *paintable; + } enum class StackingContextPaintPhase { BackgroundAndBorders, @@ -46,17 +55,17 @@ public: void set_last_paint_generation_id(u64 generation_id); - virtual void visit_edges(Visitor&) override; - private: - GC::Ref m_paintable; - GC::Ptr m_parent; - Vector> m_children; + StackingContext(PaintableBox&, RefPtr parent, size_t index_in_tree_order); + + WeakPtr m_paintable; + WeakPtr m_parent; + Vector> m_children; size_t m_index_in_tree_order { 0 }; Optional m_last_paint_generation_id; - Vector> m_positioned_descendants_and_stacking_contexts_with_stack_level_0; - Vector> m_non_positioned_floating_descendants; + Vector> m_positioned_descendants_and_stacking_contexts_with_stack_level_0; + Vector> m_non_positioned_floating_descendants; static void paint_child(DisplayListRecordingContext&, StackingContext const&); void paint_internal(DisplayListRecordingContext&) const; diff --git a/Libraries/LibWeb/Painting/TableBordersPainting.cpp b/Libraries/LibWeb/Painting/TableBordersPainting.cpp index 1e1064b51f..0d4ee43a22 100644 --- a/Libraries/LibWeb/Painting/TableBordersPainting.cpp +++ b/Libraries/LibWeb/Painting/TableBordersPainting.cpp @@ -297,7 +297,7 @@ static void paint_collected_edges(DisplayListRecordingContext& context, Vector snap_cells_to_device_coordinates(HashMap const& cell_coordinates_to_box, size_t row_count, size_t column_count, DisplayListRecordingContext const& context) +static HashMap snap_cells_to_device_coordinates(HashMap> const& cell_coordinates_to_box, size_t row_count, size_t column_count, DisplayListRecordingContext const& context) { Vector y_line_start_coordinates; Vector y_line_end_coordinates; @@ -364,14 +364,14 @@ void paint_table_borders(DisplayListRecordingContext& context, PaintableBox cons Vector cell_boxes; collect_cell_boxes(cell_boxes, table_paintable); Vector border_edge_painting_info_list; - HashMap cell_coordinates_to_box; + HashMap> cell_coordinates_to_box; size_t row_count = 0; size_t column_count = 0; for (auto const& cell_box : cell_boxes) { cell_coordinates_to_box.set(CellCoordinates { .row_index = cell_box.table_cell_coordinates()->row_index, .column_index = cell_box.table_cell_coordinates()->column_index }, - &cell_box); + cell_box); row_count = max(row_count, cell_box.table_cell_coordinates()->row_index + cell_box.table_cell_coordinates()->row_span); column_count = max(column_count, cell_box.table_cell_coordinates()->column_index + cell_box.table_cell_coordinates()->column_span); } diff --git a/Libraries/LibWeb/Painting/TextPaintable.cpp b/Libraries/LibWeb/Painting/TextPaintable.cpp index 1a9f656223..d293453960 100644 --- a/Libraries/LibWeb/Painting/TextPaintable.cpp +++ b/Libraries/LibWeb/Painting/TextPaintable.cpp @@ -9,11 +9,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(TextPaintable); - -GC::Ref TextPaintable::create(Layout::TextNode const& layout_node) +NonnullRefPtr TextPaintable::create(Layout::TextNode const& layout_node) { - return layout_node.heap().allocate(layout_node); + return adopt_ref(*new TextPaintable(layout_node)); } TextPaintable::TextPaintable(Layout::TextNode const& layout_node) @@ -23,8 +21,9 @@ TextPaintable::TextPaintable(Layout::TextNode const& layout_node) void TextPaintable::paint_inspector_overlay_internal(DisplayListRecordingContext& context) const { - if (auto const* parent_paintable = as_if(parent())) { - for (auto const& fragment : parent_paintable->fragments()) { + auto parent_paintable = parent(); + if (auto const* paintable_with_lines = as_if(parent_paintable.ptr())) { + for (auto const& fragment : paintable_with_lines->fragments()) { if (&fragment.paintable() == this) { PaintableWithLines::paint_text_fragment_debug_highlight(context, fragment); } diff --git a/Libraries/LibWeb/Painting/TextPaintable.h b/Libraries/LibWeb/Painting/TextPaintable.h index e8b954f411..e502d4bf72 100644 --- a/Libraries/LibWeb/Painting/TextPaintable.h +++ b/Libraries/LibWeb/Painting/TextPaintable.h @@ -12,11 +12,9 @@ namespace Web::Painting { class TextPaintable final : public Paintable { - GC_CELL(TextPaintable, Paintable); - GC_DECLARE_ALLOCATOR(TextPaintable); - public: - static GC::Ref create(Layout::TextNode const&); + static NonnullRefPtr create(Layout::TextNode const&); + virtual StringView class_name() const override { return "TextPaintable"sv; } Layout::TextNode const& layout_node() const { return static_cast(Paintable::layout_node()); } diff --git a/Libraries/LibWeb/Painting/VideoPaintable.cpp b/Libraries/LibWeb/Painting/VideoPaintable.cpp index fa85cb2e47..0b93f39039 100644 --- a/Libraries/LibWeb/Painting/VideoPaintable.cpp +++ b/Libraries/LibWeb/Painting/VideoPaintable.cpp @@ -20,11 +20,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(VideoPaintable); - -GC::Ref VideoPaintable::create(Layout::VideoBox const& layout_box) +NonnullRefPtr VideoPaintable::create(Layout::VideoBox const& layout_box) { - return layout_box.heap().allocate(layout_box); + return adopt_ref(*new VideoPaintable(layout_box)); } VideoPaintable::VideoPaintable(Layout::VideoBox const& layout_box) @@ -37,7 +35,7 @@ void VideoPaintable::paint(DisplayListRecordingContext& context, PaintPhase phas if (!is_visible()) return; - Base::paint(context, phase); + PaintableBox::paint(context, phase); if (phase != PaintPhase::Foreground) return; diff --git a/Libraries/LibWeb/Painting/VideoPaintable.h b/Libraries/LibWeb/Painting/VideoPaintable.h index b29505e0c2..fdca334178 100644 --- a/Libraries/LibWeb/Painting/VideoPaintable.h +++ b/Libraries/LibWeb/Painting/VideoPaintable.h @@ -13,11 +13,9 @@ namespace Web::Painting { class VideoPaintable final : public PaintableBox { - GC_CELL(VideoPaintable, PaintableBox); - GC_DECLARE_ALLOCATOR(VideoPaintable); - public: - static GC::Ref create(Layout::VideoBox const&); + static NonnullRefPtr create(Layout::VideoBox const&); + virtual StringView class_name() const override { return "VideoPaintable"sv; } virtual void paint(DisplayListRecordingContext&, PaintPhase) const override; diff --git a/Libraries/LibWeb/Painting/ViewportPaintable.cpp b/Libraries/LibWeb/Painting/ViewportPaintable.cpp index 914c167cf5..b14c7228aa 100644 --- a/Libraries/LibWeb/Painting/ViewportPaintable.cpp +++ b/Libraries/LibWeb/Painting/ViewportPaintable.cpp @@ -24,11 +24,9 @@ namespace Web::Painting { -GC_DEFINE_ALLOCATOR(ViewportPaintable); - -GC::Ref ViewportPaintable::create(Layout::Viewport const& layout_viewport) +NonnullRefPtr ViewportPaintable::create(Layout::Viewport const& layout_viewport) { - return layout_viewport.heap().allocate(layout_viewport); + return adopt_ref(*new ViewportPaintable(layout_viewport)); } ViewportPaintable::ViewportPaintable(Layout::Viewport const& layout_viewport) @@ -58,12 +56,12 @@ void ViewportPaintable::build_stacking_context_tree_if_needed() void ViewportPaintable::build_stacking_context_tree() { - set_stacking_context(heap().allocate(*this, nullptr, 0)); + set_stacking_context(StackingContext::create(*this, nullptr, 0)); size_t index_in_tree_order = 1; for_each_in_subtree_of_type([&](auto& paintable_box) { paintable_box.invalidate_stacking_context(); - auto* parent_context = paintable_box.enclosing_stacking_context(); + auto parent_context = paintable_box.enclosing_stacking_context(); auto establishes_stacking_context = paintable_box.layout_node().establishes_stacking_context(); if ((paintable_box.is_positioned() || establishes_stacking_context) && paintable_box.effective_z_index().value_or(0) == 0) parent_context->m_positioned_descendants_and_stacking_contexts_with_stack_level_0.append(paintable_box); @@ -74,7 +72,7 @@ void ViewportPaintable::build_stacking_context_tree() return TraversalDecision::Continue; } VERIFY(parent_context); - paintable_box.set_stacking_context(heap().allocate(paintable_box, parent_context, index_in_tree_order++)); + paintable_box.set_stacking_context(StackingContext::create(paintable_box, parent_context, index_in_tree_order++)); return TraversalDecision::Continue; }); @@ -97,12 +95,13 @@ void ViewportPaintable::assign_scroll_frames() return; auto const& scroll_ancestor_paintable = m_scroll_state.frame_at(nearest_scrolling_ancestor_index).paintable_box(); + RefPtr scroll_ancestor_paintable_ref = scroll_ancestor_paintable; auto sticky_border_box_rect = paintable_box.absolute_border_box_rect(); - auto const* containing_block_of_sticky = paintable_box.containing_block(); + RefPtr containing_block_of_sticky = paintable_box.containing_block(); CSSPixelRect containing_block_region; bool needs_parent_offset_adjustment = false; - if (containing_block_of_sticky == &scroll_ancestor_paintable) { + if (containing_block_of_sticky == scroll_ancestor_paintable_ref) { containing_block_region = { {}, containing_block_of_sticky->scrollable_overflow_rect()->size() }; } else { containing_block_region = containing_block_of_sticky->absolute_border_box_rect() @@ -342,7 +341,8 @@ void ViewportPaintable::assign_accumulated_visual_contexts() set_accumulated_visual_context_for_descendants(viewport_state_for_descendants); for_each_in_subtree_of_type([&](auto& paintable_box) { - auto* visual_parent = as_if(paintable_box.parent()); + auto visual_parent_paintable = paintable_box.parent(); + auto* visual_parent = as_if(visual_parent_paintable.ptr()); if (!visual_parent) return TraversalDecision::Continue; @@ -359,7 +359,7 @@ void ViewportPaintable::assign_accumulated_visual_contexts() inherited_state = m_visual_viewport_context_index; } else if (paintable_box.is_absolutely_positioned()) { // For position: absolute, use containing block's state to correctly escape scroll containers. - auto* containing = paintable_box.containing_block(); + auto containing = paintable_box.containing_block(); inherited_state = containing->accumulated_visual_context_for_descendants_index(); // Abspos elements escape scroll containers and overflow clips of non-positioned @@ -369,8 +369,9 @@ void ViewportPaintable::assign_accumulated_visual_contexts() // NOTE: transforms/perspectives/filters establish containing blocks for abspos, // so they cannot appear as intermediates. Vector intermediate_effects; - for (Paintable* paintable = visual_parent; paintable && paintable != containing; paintable = paintable->parent()) { - auto* ancestor_box = as_if(paintable); + RefPtr containing_paintable = containing; + for (RefPtr paintable = visual_parent; paintable && paintable != containing_paintable; paintable = paintable->parent()) { + auto* ancestor_box = as_if(paintable.ptr()); if (!ancestor_box) continue; if (auto effects = make_effects_data(*ancestor_box); effects.has_value()) @@ -542,14 +543,14 @@ void ViewportPaintable::recompute_selection_states(DOM::Range& range) // 2. If it's a text node, mark it as StartAndEnd and return. if (is(*start_container) && !range.start().node->is_inert()) { - if (auto* paintable = start_container->unsafe_paintable()) + if (auto paintable = start_container->unsafe_paintable()) paintable->set_selection_state(SelectionState::StartAndEnd); return; } } // 3. Mark the selection start node as Start (if text) or Full (if anything else). - if (auto* paintable = start_container->unsafe_paintable(); paintable && !range.start().node->is_inert()) { + if (auto paintable = start_container->unsafe_paintable(); paintable && !range.start().node->is_inert()) { if (is(*start_container)) paintable->set_selection_state(SelectionState::Start); else @@ -572,12 +573,12 @@ void ViewportPaintable::recompute_selection_states(DOM::Range& range) for (auto* node = start_at; node && (node != stop_at && !(node == end_container && !end_container->has_children())); node = node->next_in_pre_order(end_container)) { if (node->is_inert()) continue; - if (auto* paintable = node->unsafe_paintable()) + if (auto paintable = node->unsafe_paintable()) paintable->set_selection_state(SelectionState::Full); } // 5. Mark the selection end node as End if it is a text node. - if (auto* paintable = end_container->unsafe_paintable(); paintable && !range.end().node->is_inert() && is(*end_container)) { + if (auto paintable = end_container->unsafe_paintable(); paintable && !range.end().node->is_inert() && is(*end_container)) { paintable->set_selection_state(SelectionState::End); } } @@ -587,10 +588,4 @@ bool ViewportPaintable::handle_mousewheel(Badge, CSSPixelPoint, un return false; } -void ViewportPaintable::visit_edges(Visitor& visitor) -{ - Base::visit_edges(visitor); - visitor.visit(m_paintable_boxes_with_auto_content_visibility); -} - } diff --git a/Libraries/LibWeb/Painting/ViewportPaintable.h b/Libraries/LibWeb/Painting/ViewportPaintable.h index 91c970f2d5..5252c0769c 100644 --- a/Libraries/LibWeb/Painting/ViewportPaintable.h +++ b/Libraries/LibWeb/Painting/ViewportPaintable.h @@ -14,12 +14,10 @@ namespace Web::Painting { class WEB_API ViewportPaintable final : public PaintableWithLines { - GC_CELL(ViewportPaintable, PaintableWithLines); - GC_DECLARE_ALLOCATOR(ViewportPaintable); - public: - static GC::Ref create(Layout::Viewport const&); + static NonnullRefPtr create(Layout::Viewport const&); virtual ~ViewportPaintable() override; + virtual StringView class_name() const override { return "ViewportPaintable"sv; } virtual void reset_for_relayout() override; @@ -41,8 +39,8 @@ public: ScrollState const& scroll_state() const { return m_scroll_state; } ScrollStateSnapshot const& scroll_state_snapshot() const { return m_scroll_state_snapshot; } - void set_paintable_boxes_with_auto_content_visibility(Vector> paintable_boxes) { m_paintable_boxes_with_auto_content_visibility = move(paintable_boxes); } - ReadonlySpan> paintable_boxes_with_auto_content_visibility() const { return m_paintable_boxes_with_auto_content_visibility; } + void set_paintable_boxes_with_auto_content_visibility(Vector> paintable_boxes) { m_paintable_boxes_with_auto_content_visibility = move(paintable_boxes); } + Vector> const& paintable_boxes_with_auto_content_visibility() const { return m_paintable_boxes_with_auto_content_visibility; } AccumulatedVisualContextTree const& visual_context_tree() const { @@ -62,13 +60,11 @@ private: explicit ViewportPaintable(Layout::Viewport const&); - virtual void visit_edges(Visitor&) override; - ScrollState m_scroll_state; ScrollStateSnapshot m_scroll_state_snapshot; bool m_needs_to_refresh_scroll_state { true }; - Vector> m_paintable_boxes_with_auto_content_visibility; + Vector> m_paintable_boxes_with_auto_content_visibility; RefPtr m_visual_context_tree; VisualContextIndex m_visual_viewport_context_index {}; diff --git a/Libraries/LibWeb/SVG/SVGFilterElement.cpp b/Libraries/LibWeb/SVG/SVGFilterElement.cpp index 15c92b1c6a..ebf82cd37d 100644 --- a/Libraries/LibWeb/SVG/SVGFilterElement.cpp +++ b/Libraries/LibWeb/SVG/SVGFilterElement.cpp @@ -281,7 +281,7 @@ Optional SVGFilterElement::gfx_filter(Layout::NodeWithStyle const& // during layout update, before the layout-is-up-to-date flag // has been set. The paintable is valid since layout has already // been performed at this point. - auto* paintable_box = dom_node->unsafe_paintable_box(); + auto paintable_box = dom_node->unsafe_paintable_box(); if (!paintable_box) return IterationDecision::Continue; diff --git a/Libraries/LibWeb/SVG/SVGPatternElement.cpp b/Libraries/LibWeb/SVG/SVGPatternElement.cpp index 9b7d24db65..f99887db2f 100644 --- a/Libraries/LibWeb/SVG/SVGPatternElement.cpp +++ b/Libraries/LibWeb/SVG/SVGPatternElement.cpp @@ -249,7 +249,7 @@ Optional SVGPatternElement::to_gfx_paint_style(SVGPaintCon if (!pattern_box) return {}; - auto* pattern_paintable = pattern_box->paintable_box(); + auto pattern_paintable = pattern_box->paintable_box(); if (!pattern_paintable) return {}; @@ -296,7 +296,8 @@ Optional SVGPatternElement::to_gfx_paint_style(SVGPaintCon auto paint_context_copy = recording_context.clone(display_list_recorder); Gfx::AffineTransform target_svg_transform; - if (auto const* svg_graphics_paintable = as_if(*target_layout_node.first_paintable())) + auto first_paintable = target_layout_node.first_paintable(); + if (auto const* svg_graphics_paintable = as_if(first_paintable.ptr())) target_svg_transform = svg_graphics_paintable->computed_transforms().svg_transform(); paint_context_copy.set_svg_transform(target_svg_transform); diff --git a/Libraries/LibWeb/Selection/Selection.cpp b/Libraries/LibWeb/Selection/Selection.cpp index e49a6b1fe9..21494114da 100644 --- a/Libraries/LibWeb/Selection/Selection.cpp +++ b/Libraries/LibWeb/Selection/Selection.cpp @@ -734,7 +734,7 @@ void Selection::scroll_focus_into_view() m_document->update_layout(DOM::UpdateLayoutReason::ScrollCursorIntoView); - auto* paintable = focus->paintable(); + auto paintable = focus->paintable(); if (!paintable) return; diff --git a/Libraries/LibWeb/TreeNode.h b/Libraries/LibWeb/TreeNode.h index d5a4fc4c48..7d9b3f96d0 100644 --- a/Libraries/LibWeb/TreeNode.h +++ b/Libraries/LibWeb/TreeNode.h @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include diff --git a/Libraries/LibWeb/WebDriver/Actions.cpp b/Libraries/LibWeb/WebDriver/Actions.cpp index 89661f3f96..4de4306cd4 100644 --- a/Libraries/LibWeb/WebDriver/Actions.cpp +++ b/Libraries/LibWeb/WebDriver/Actions.cpp @@ -150,7 +150,7 @@ static CSSPixelPoint get_parent_offset(HTML::BrowsingContext const& browsing_con CSSPixels border_left_width = 0; CSSPixels border_top_width = 0; - if (auto* paintable_box = container_element->paintable_box()) { + if (auto paintable_box = container_element->paintable_box()) { // 7. Let borderLeftWidth be the computed border-left-width of containerElement in CSS pixels. border_left_width = paintable_box->computed_values().border_left().width; diff --git a/Libraries/LibWeb/WebDriver/ElementReference.cpp b/Libraries/LibWeb/WebDriver/ElementReference.cpp index f9ff8c9f11..608809fcf2 100644 --- a/Libraries/LibWeb/WebDriver/ElementReference.cpp +++ b/Libraries/LibWeb/WebDriver/ElementReference.cpp @@ -257,7 +257,7 @@ bool is_element_pointer_interactable(Web::HTML::BrowsingContext const& browsing_ if (!document) return false; - auto const* paint_root = document->paintable_box(); + auto paint_root = document->paintable_box(); if (!paint_root) return false; diff --git a/Services/WebContent/ConnectionFromClient.cpp b/Services/WebContent/ConnectionFromClient.cpp index d34394d7bc..4c967826a0 100644 --- a/Services/WebContent/ConnectionFromClient.cpp +++ b/Services/WebContent/ConnectionFromClient.cpp @@ -307,7 +307,7 @@ void ConnectionFromClient::debug_request(u64 page_id, ByteString request, ByteSt if (request == "dump-paint-tree") { if (auto* doc = page->page().top_level_browsing_context().active_document()) { - if (auto* paintable = doc->paintable()) + if (auto paintable = doc->paintable()) Web::dump_tree(*paintable); } return; @@ -318,7 +318,7 @@ void ConnectionFromClient::debug_request(u64 page_id, ByteString request, ByteSt if (auto* viewport = doc->layout_node()) { auto& viewport_paintable = static_cast(*viewport->paintable_box()); viewport_paintable.build_stacking_context_tree_if_needed(); - if (auto* stacking_context = viewport_paintable.stacking_context()) { + if (auto stacking_context = viewport_paintable.stacking_context()) { StringBuilder builder; stacking_context->dump(builder); dbgln("{}", builder.string_view()); @@ -517,11 +517,12 @@ void ConnectionFromClient::inspect_dom_node(u64 page_id, WebView::DOMNodePropert }; auto serialize_layout = [&](Web::Layout::Node const* layout_node) { - if (!layout_node || !layout_node->is_box() || !layout_node->first_paintable() || !layout_node->first_paintable()->is_paintable_box()) { + auto first_paintable = layout_node ? layout_node->first_paintable() : nullptr; + if (!layout_node || !layout_node->is_box() || !first_paintable || !first_paintable->is_paintable_box()) { return JsonObject {}; } - auto const& paintable_box = as(*layout_node->first_paintable()); + auto const& paintable_box = as(*first_paintable); auto const& box_model = paintable_box.box_model(); JsonObject serialized; @@ -1025,7 +1026,7 @@ static void append_stacking_context_tree(Web::Page& page, StringBuilder& builder auto& viewport_paintable = static_cast(*layout_root->paintable_box()); viewport_paintable.build_stacking_context_tree_if_needed(); - if (auto* stacking_context = viewport_paintable.stacking_context()) { + if (auto stacking_context = viewport_paintable.stacking_context()) { stacking_context->dump(builder); } }