diff options
author | Andreas Kling <kling@serenityos.org> | 2020-12-06 19:59:28 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-12-06 20:05:04 +0100 |
commit | c953e5d98a21df4d34b63012d1ac12f066bfe0e0 (patch) | |
tree | 0b8ea0c8d9ad696041f477dbe9dbe2f8b8034c61 /Libraries/LibWeb | |
parent | 85a1bd6803ba45c974f1b8adc7463cc736590679 (diff) | |
download | serenity-c953e5d98a21df4d34b63012d1ac12f066bfe0e0.zip |
LibWeb: Paint positioned elements after non-positioned ones
Within the same stacking context, positioned elements must be painted
after non-positioned ones.
I added a Layout::Node::for_each_child_in_paint_order() to help with
this since it's also needed for hit testing.
Diffstat (limited to 'Libraries/LibWeb')
-rw-r--r-- | Libraries/LibWeb/Layout/Box.cpp | 4 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/Node.cpp | 10 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/Node.h | 17 |
3 files changed, 20 insertions, 11 deletions
diff --git a/Libraries/LibWeb/Layout/Box.cpp b/Libraries/LibWeb/Layout/Box.cpp index a6a7e34b3c..62941a20ec 100644 --- a/Libraries/LibWeb/Layout/Box.cpp +++ b/Libraries/LibWeb/Layout/Box.cpp @@ -106,9 +106,7 @@ HitTestResult Box::hit_test(const Gfx::IntPoint& position, HitTestType type) con // parts of the layout tree, but currently we can't just check // m_rect.contains() since inline text rects can't be trusted.. HitTestResult result { absolute_rect().contains(position.x(), position.y()) ? this : nullptr }; - for_each_child([&](auto& child) { - if (is<Box>(child) && downcast<Box>(child).stacking_context()) - return; + for_each_child_in_paint_order([&](auto& child) { auto child_result = child.hit_test(position, type); if (child_result.layout_node) result = child_result; diff --git a/Libraries/LibWeb/Layout/Node.cpp b/Libraries/LibWeb/Layout/Node.cpp index 6086295835..b1147bd5c6 100644 --- a/Libraries/LibWeb/Layout/Node.cpp +++ b/Libraries/LibWeb/Layout/Node.cpp @@ -93,9 +93,7 @@ void Node::paint(PaintContext& context, PaintPhase phase) before_children_paint(context, phase); - for_each_child([&](auto& child) { - if (child.is_box() && downcast<Box>(child).stacking_context()) - return; + for_each_child_in_paint_order([&](auto& child) { child.paint(context, phase); }); @@ -105,11 +103,7 @@ void Node::paint(PaintContext& context, PaintPhase phase) HitTestResult Node::hit_test(const Gfx::IntPoint& position, HitTestType type) const { HitTestResult result; - for_each_child([&](auto& child) { - // Skip over children that establish their own stacking context. - // The outer loop who called us will take care of those. - if (is<Box>(child) && downcast<Box>(child).stacking_context()) - return; + for_each_child_in_paint_order([&](auto& child) { auto child_result = child.hit_test(position, type); if (child_result.layout_node) result = child_result; diff --git a/Libraries/LibWeb/Layout/Node.h b/Libraries/LibWeb/Layout/Node.h index 1fe0792bf7..69a7192b4f 100644 --- a/Libraries/LibWeb/Layout/Node.h +++ b/Libraries/LibWeb/Layout/Node.h @@ -177,6 +177,23 @@ public: SelectionState selection_state() const { return m_selection_state; } void set_selection_state(SelectionState state) { m_selection_state = state; } + template<typename Callback> + void for_each_child_in_paint_order(Callback callback) const + { + for_each_child([&](auto& child) { + if (is<Box>(child) && downcast<Box>(child).stacking_context()) + return; + if (!child.is_positioned()) + callback(child); + }); + for_each_child([&](auto& child) { + if (is<Box>(child) && downcast<Box>(child).stacking_context()) + return; + if (child.is_positioned()) + callback(child); + }); + } + protected: Node(DOM::Document&, DOM::Node*); |