1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 23:37:35 +00:00

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.
This commit is contained in:
Andreas Kling 2020-12-06 19:59:28 +01:00
parent 85a1bd6803
commit c953e5d98a
3 changed files with 20 additions and 11 deletions

View file

@ -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;

View file

@ -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;

View file

@ -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*);