summaryrefslogtreecommitdiff
path: root/Libraries/LibWeb
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-12-06 19:59:28 +0100
committerAndreas Kling <kling@serenityos.org>2020-12-06 20:05:04 +0100
commitc953e5d98a21df4d34b63012d1ac12f066bfe0e0 (patch)
tree0b8ea0c8d9ad696041f477dbe9dbe2f8b8034c61 /Libraries/LibWeb
parent85a1bd6803ba45c974f1b8adc7463cc736590679 (diff)
downloadserenity-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.cpp4
-rw-r--r--Libraries/LibWeb/Layout/Node.cpp10
-rw-r--r--Libraries/LibWeb/Layout/Node.h17
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*);