diff options
author | Simon Wanner <skyrising@pvpctutorials.de> | 2022-03-18 01:32:50 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-03-18 18:51:42 +0100 |
commit | 48efdaa8c4c0c03a895bc788d46ff0e242be813f (patch) | |
tree | 32af1812e92928e082aedd6279065489555e72b8 /Userland/Libraries | |
parent | a2331e8dd387fee7f75f165df740aeb4a3069ab7 (diff) | |
download | serenity-48efdaa8c4c0c03a895bc788d46ff0e242be813f.zip |
LibWeb: Update hit_test for CSS Transforms
This now also takes a FloatPoint instead of an IntPoint to avoid
excessive rounding when multiple transforms apply on top of each other.
Diffstat (limited to 'Userland/Libraries')
7 files changed, 28 insertions, 23 deletions
diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.cpp b/Userland/Libraries/LibWeb/Page/EventHandler.cpp index bb08639407..b940d5c104 100644 --- a/Userland/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Userland/Libraries/LibWeb/Page/EventHandler.cpp @@ -138,7 +138,7 @@ bool EventHandler::handle_mousewheel(const Gfx::IntPoint& position, unsigned int // FIXME: Support wheel events in nested browsing contexts. - auto result = paint_root()->hit_test(position, Painting::HitTestType::Exact); + auto result = paint_root()->hit_test(position.to_type<float>(), Painting::HitTestType::Exact); if (result.paintable && result.paintable->handle_mousewheel({}, position, buttons, modifiers, wheel_delta_x, wheel_delta_y)) return true; @@ -164,7 +164,7 @@ bool EventHandler::handle_mouseup(const Gfx::IntPoint& position, unsigned button if (m_mouse_event_tracking_layout_node) { paintable = m_mouse_event_tracking_layout_node->paintable(); } else { - auto result = paint_root()->hit_test(position, Painting::HitTestType::Exact); + auto result = paint_root()->hit_test(position.to_type<float>(), Painting::HitTestType::Exact); paintable = result.paintable; } @@ -175,7 +175,7 @@ bool EventHandler::handle_mouseup(const Gfx::IntPoint& position, unsigned button // Things may have changed as a consequence of Layout::Node::handle_mouseup(). Hit test again. if (!paint_root()) return true; - auto result = paint_root()->hit_test(position, Painting::HitTestType::Exact); + auto result = paint_root()->hit_test(position.to_type<float>(), Painting::HitTestType::Exact); paintable = result.paintable; } @@ -222,7 +222,7 @@ bool EventHandler::handle_mousedown(const Gfx::IntPoint& position, unsigned butt if (m_mouse_event_tracking_layout_node) { paintable = m_mouse_event_tracking_layout_node->paintable(); } else { - auto result = paint_root()->hit_test(position, Painting::HitTestType::Exact); + auto result = paint_root()->hit_test(position.to_type<float>(), Painting::HitTestType::Exact); if (!result.paintable) return false; paintable = result.paintable; @@ -300,7 +300,7 @@ bool EventHandler::handle_mousedown(const Gfx::IntPoint& position, unsigned butt } } else { if (button == GUI::MouseButton::Primary) { - auto result = paint_root()->hit_test(position, Painting::HitTestType::TextCursor); + auto result = paint_root()->hit_test(position.to_type<float>(), Painting::HitTestType::TextCursor); if (result.paintable && result.paintable->layout_node().dom_node()) { // See if we want to focus something. @@ -348,7 +348,7 @@ bool EventHandler::handle_mousemove(const Gfx::IntPoint& position, unsigned butt if (m_mouse_event_tracking_layout_node) { paintable = m_mouse_event_tracking_layout_node->paintable(); } else { - auto result = paint_root()->hit_test(position, Painting::HitTestType::Exact); + auto result = paint_root()->hit_test(position.to_type<float>(), Painting::HitTestType::Exact); paintable = result.paintable; start_index = result.index_in_node; } @@ -408,7 +408,7 @@ bool EventHandler::handle_mousemove(const Gfx::IntPoint& position, unsigned butt return true; } if (m_in_mouse_selection) { - auto hit = paint_root()->hit_test(position, Painting::HitTestType::TextCursor); + auto hit = paint_root()->hit_test(position.to_type<float>(), Painting::HitTestType::TextCursor); if (start_index.has_value() && hit.paintable && hit.paintable->layout_node().dom_node()) { m_browsing_context.set_cursor_position(DOM::Position(*hit.paintable->layout_node().dom_node(), *start_index)); layout_root()->set_selection_end({ hit.paintable->layout_node(), hit.index_in_node }); diff --git a/Userland/Libraries/LibWeb/Painting/Paintable.cpp b/Userland/Libraries/LibWeb/Painting/Paintable.cpp index fa122cbc27..83a19f6a4e 100644 --- a/Userland/Libraries/LibWeb/Painting/Paintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/Paintable.cpp @@ -41,7 +41,7 @@ bool Paintable::handle_mousewheel(Badge<EventHandler>, Gfx::IntPoint const&, uns return false; } -HitTestResult Paintable::hit_test(Gfx::IntPoint const&, HitTestType) const +HitTestResult Paintable::hit_test(Gfx::FloatPoint const&, HitTestType) const { VERIFY_NOT_REACHED(); } diff --git a/Userland/Libraries/LibWeb/Painting/Paintable.h b/Userland/Libraries/LibWeb/Painting/Paintable.h index 692e7f1265..8ea71f748d 100644 --- a/Userland/Libraries/LibWeb/Painting/Paintable.h +++ b/Userland/Libraries/LibWeb/Painting/Paintable.h @@ -50,7 +50,7 @@ public: virtual void before_children_paint(PaintContext&, PaintPhase) const { } virtual void after_children_paint(PaintContext&, PaintPhase) const { } - virtual HitTestResult hit_test(Gfx::IntPoint const&, HitTestType) const; + virtual HitTestResult hit_test(Gfx::FloatPoint const&, HitTestType) const; virtual bool wants_mouse_events() const { return false; } diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp index e0685a5b07..d1deb1f8da 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -526,7 +526,7 @@ void PaintableBox::for_each_child_in_paint_order(Callback callback) const }); } -HitTestResult PaintableBox::hit_test(Gfx::IntPoint const& position, HitTestType type) const +HitTestResult PaintableBox::hit_test(Gfx::FloatPoint const& position, HitTestType type) const { if (layout_box().is_initial_containing_block_box()) return stacking_context()->hit_test(position, type); @@ -542,7 +542,7 @@ HitTestResult PaintableBox::hit_test(Gfx::IntPoint const& position, HitTestType return result; } -HitTestResult PaintableWithLines::hit_test(const Gfx::IntPoint& position, HitTestType type) const +HitTestResult PaintableWithLines::hit_test(const Gfx::FloatPoint& position, HitTestType type) const { if (!layout_box().children_are_inline()) return PaintableBox::hit_test(position, type); @@ -552,7 +552,7 @@ HitTestResult PaintableWithLines::hit_test(const Gfx::IntPoint& position, HitTes for (auto& fragment : line_box.fragments()) { if (is<Layout::Box>(fragment.layout_node()) && static_cast<Layout::Box const&>(fragment.layout_node()).paint_box()->stacking_context()) continue; - if (enclosing_int_rect(fragment.absolute_rect()).contains(position)) { + if (fragment.absolute_rect().contains(position)) { if (is<Layout::BlockContainer>(fragment.layout_node()) && fragment.layout_node().paintable()) return fragment.layout_node().paintable()->hit_test(position, type); return { fragment.layout_node().paintable(), fragment.text_index_at(position.x()) }; diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.h b/Userland/Libraries/LibWeb/Painting/PaintableBox.h index 20ffd214d6..649586d9ac 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.h +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.h @@ -115,7 +115,7 @@ public: virtual void before_children_paint(PaintContext&, PaintPhase) const override; virtual void after_children_paint(PaintContext&, PaintPhase) const override; - virtual HitTestResult hit_test(Gfx::IntPoint const&, HitTestType) const override; + virtual HitTestResult hit_test(Gfx::FloatPoint const&, HitTestType) const override; protected: explicit PaintableBox(Layout::Box const&); @@ -164,7 +164,7 @@ public: virtual bool wants_mouse_events() const override { return false; } virtual bool handle_mousewheel(Badge<EventHandler>, const Gfx::IntPoint&, unsigned buttons, unsigned modifiers, int wheel_delta_x, int wheel_delta_y) override; - virtual HitTestResult hit_test(Gfx::IntPoint const&, HitTestType) const override; + virtual HitTestResult hit_test(Gfx::FloatPoint const&, HitTestType) const override; protected: PaintableWithLines(Layout::BlockContainer const&); diff --git a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp index 0429c4f2ad..808b3fc315 100644 --- a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp +++ b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp @@ -272,8 +272,13 @@ void StackingContext::paint(PaintContext& context) const } } -HitTestResult StackingContext::hit_test(Gfx::IntPoint const& position, HitTestType type) const +HitTestResult StackingContext::hit_test(Gfx::FloatPoint const& position, HitTestType type) const { + // FIXME: Use the transform origin specified in CSS or SVG + auto transform_origin = m_box.paint_box()->absolute_position(); + auto affine_transform = combine_transformations_2d(m_box.computed_values().transformations()); + auto transformed_position = affine_transform.inverse().value_or({}).map(position - transform_origin) + transform_origin; + // NOTE: Hit testing basically happens in reverse painting order. // https://www.w3.org/TR/CSS22/visuren.html#z-index @@ -282,7 +287,7 @@ HitTestResult StackingContext::hit_test(Gfx::IntPoint const& position, HitTestTy auto const& child = *m_children[i]; if (child.m_box.computed_values().z_index().value_or(0) < 0) break; - auto result = child.hit_test(position, type); + auto result = child.hit_test(transformed_position, type); if (result.paintable) return result; } @@ -291,7 +296,7 @@ HitTestResult StackingContext::hit_test(Gfx::IntPoint const& position, HitTestTy // 6. the child stacking contexts with stack level 0 and the positioned descendants with stack level 0. m_box.for_each_in_subtree_of_type<Layout::Box>([&](Layout::Box const& box) { if (box.is_positioned() && !box.paint_box()->stacking_context()) { - result = box.paint_box()->hit_test(position, type); + result = box.paint_box()->hit_test(transformed_position, type); if (result.paintable) return IterationDecision::Break; } @@ -302,7 +307,7 @@ HitTestResult StackingContext::hit_test(Gfx::IntPoint const& position, HitTestTy // 5. the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks. if (m_box.children_are_inline() && is<Layout::BlockContainer>(m_box)) { - auto result = m_box.paint_box()->hit_test(position, type); + auto result = m_box.paint_box()->hit_test(transformed_position, type); if (result.paintable) return result; } @@ -310,7 +315,7 @@ HitTestResult StackingContext::hit_test(Gfx::IntPoint const& position, HitTestTy // 4. the non-positioned floats. m_box.for_each_in_subtree_of_type<Layout::Box>([&](Layout::Box const& box) { if (box.is_floating()) { - result = box.paint_box()->hit_test(position, type); + result = box.paint_box()->hit_test(transformed_position, type); if (result.paintable) return IterationDecision::Break; } @@ -321,7 +326,7 @@ HitTestResult StackingContext::hit_test(Gfx::IntPoint const& position, HitTestTy if (!m_box.children_are_inline()) { m_box.for_each_in_subtree_of_type<Layout::Box>([&](Layout::Box const& box) { if (!box.is_absolutely_positioned() && !box.is_floating()) { - result = box.paint_box()->hit_test(position, type); + result = box.paint_box()->hit_test(transformed_position, type); if (result.paintable) return IterationDecision::Break; } @@ -336,13 +341,13 @@ HitTestResult StackingContext::hit_test(Gfx::IntPoint const& position, HitTestTy auto const& child = *m_children[i]; if (child.m_box.computed_values().z_index().value_or(0) < 0) break; - auto result = child.hit_test(position, type); + auto result = child.hit_test(transformed_position, type); if (result.paintable) return result; } // 1. the background and borders of the element forming the stacking context. - if (m_box.paint_box()->absolute_border_box_rect().contains(position.to_type<float>())) { + if (m_box.paint_box()->absolute_border_box_rect().contains(transformed_position)) { return HitTestResult { .paintable = m_box.paintable(), }; diff --git a/Userland/Libraries/LibWeb/Painting/StackingContext.h b/Userland/Libraries/LibWeb/Painting/StackingContext.h index 5d33dc739b..8cd9d7d4c0 100644 --- a/Userland/Libraries/LibWeb/Painting/StackingContext.h +++ b/Userland/Libraries/LibWeb/Painting/StackingContext.h @@ -30,7 +30,7 @@ public: void paint_descendants(PaintContext&, Layout::Node&, StackingContextPaintPhase) const; void paint(PaintContext&) const; - HitTestResult hit_test(Gfx::IntPoint const&, HitTestType) const; + HitTestResult hit_test(Gfx::FloatPoint const&, HitTestType) const; void dump(int indent = 0) const; |