diff --git a/Tests/LibWeb/Text/expected/get-bounding-client-rect.txt b/Tests/LibWeb/Text/expected/get-bounding-client-rect.txt index d7833895ea..4ecaca45e0 100644 --- a/Tests/LibWeb/Text/expected/get-bounding-client-rect.txt +++ b/Tests/LibWeb/Text/expected/get-bounding-client-rect.txt @@ -1 +1,2 @@ - {"x":8,"y":500,"width":784,"height":150,"top":500,"right":792,"bottom":650,"left":8} \ No newline at end of file + inline {"x":8,"y":500,"width":784,"height":150,"top":500,"right":792,"bottom":650,"left":8} +{"x":8,"y":650,"width":41.296875,"height":17.46875,"top":650,"right":49.296875,"bottom":667.46875,"left":8} \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/get-bounding-client-rect.html b/Tests/LibWeb/Text/input/get-bounding-client-rect.html index 3206ec0aa5..eb7da97d5d 100644 --- a/Tests/LibWeb/Text/input/get-bounding-client-rect.html +++ b/Tests/LibWeb/Text/input/get-bounding-client-rect.html @@ -9,10 +9,16 @@ }
+inline diff --git a/Userland/Libraries/LibWeb/DOM/Element.cpp b/Userland/Libraries/LibWeb/DOM/Element.cpp index 8f00731784..7cdc6aa951 100644 --- a/Userland/Libraries/LibWeb/DOM/Element.cpp +++ b/Userland/Libraries/LibWeb/DOM/Element.cpp @@ -61,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -834,16 +835,24 @@ JS::NonnullGCPtr Element::get_bounding_client_rect() const { // // NOTE: Ensure that layout is up-to-date before looking at metrics. const_cast(document()).update_layout(); - - // FIXME: Support inline layout nodes as well. - auto* paintable_box = this->paintable_box(); - if (!paintable_box) - return Geometry::DOMRect::construct_impl(realm(), 0, 0, 0, 0).release_value_but_fixme_should_propagate_errors(); - VERIFY(document().navigable()); auto viewport_offset = document().navigable()->viewport_scroll_offset(); - return Geometry::DOMRect::create(realm(), paintable_box->absolute_border_box_rect().translated(-viewport_offset.x(), -viewport_offset.y()).to_type()); + if (auto const* paintable_box = this->paintable_box()) { + auto absolute_rect = paintable_box->absolute_border_box_rect(); + absolute_rect.translate_by(-viewport_offset.x(), -viewport_offset.y()); + return Geometry::DOMRect::create(realm(), absolute_rect.to_type()); + } + + if (auto const* paintable = this->paintable(); is(*paintable)) { + auto const& inline_paintable = static_cast(*paintable); + auto absolute_rect = inline_paintable.bounding_rect(); + absolute_rect.translate_by(-viewport_offset.x(), -viewport_offset.y()); + return Geometry::DOMRect::create(realm(), absolute_rect.to_type()); + } + + dbgln("FIXME: Failed to get bounding client rect for element ({})", debug_description()); + return Geometry::DOMRect::construct_impl(realm(), 0, 0, 0, 0).release_value_but_fixme_should_propagate_errors(); } // https://drafts.csswg.org/cssom-view/#dom-element-getclientrects diff --git a/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp b/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp index 98162fd5c9..ceb4883b35 100644 --- a/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp @@ -173,4 +173,32 @@ void InlinePaintable::for_each_fragment(Callback callback) const } } +CSSPixelRect InlinePaintable::bounding_rect() const +{ + auto top = CSSPixels::max(); + auto left = CSSPixels::max(); + auto right = CSSPixels::min(); + auto bottom = CSSPixels::min(); + auto has_fragments = false; + for_each_fragment([&](auto const& fragment, bool, bool) { + has_fragments = true; + auto fragment_absolute_rect = fragment.absolute_rect(); + if (fragment_absolute_rect.top() < top) + top = fragment_absolute_rect.top(); + if (fragment_absolute_rect.left() < left) + left = fragment_absolute_rect.left(); + if (fragment_absolute_rect.right() > right) + right = fragment_absolute_rect.right(); + if (fragment_absolute_rect.bottom() > bottom) + bottom = fragment_absolute_rect.bottom(); + }); + + if (!has_fragments) { + // FIXME: This is adhoc, and we should return rect of empty fragment instead. + auto containing_block_position_in_absolute_coordinates = containing_block()->paintable_box()->absolute_position(); + return { containing_block_position_in_absolute_coordinates, { 0, 0 } }; + } + return { left, top, right - left, bottom - top }; +} + } diff --git a/Userland/Libraries/LibWeb/Painting/InlinePaintable.h b/Userland/Libraries/LibWeb/Painting/InlinePaintable.h index f53e20fcb4..204413be6b 100644 --- a/Userland/Libraries/LibWeb/Painting/InlinePaintable.h +++ b/Userland/Libraries/LibWeb/Painting/InlinePaintable.h @@ -22,6 +22,8 @@ public: Layout::InlineNode const& layout_node() const; auto const& box_model() const { return layout_node().box_model(); } + CSSPixelRect bounding_rect() const; + private: InlinePaintable(Layout::InlineNode const&);