mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 08:57:34 +00:00
LibWeb: Hang StackingContext off of the paint boxes
Stacking contexts have nothing to do with layout and everything with painting, so let's keep them in Painting::Box.
This commit is contained in:
parent
cc8e429126
commit
9f5cbcaad3
10 changed files with 39 additions and 38 deletions
|
@ -570,7 +570,6 @@ void Document::update_layout()
|
|||
|
||||
Layout::FormattingState formatting_state;
|
||||
Layout::BlockFormattingContext root_formatting_context(formatting_state, *m_layout_root, nullptr);
|
||||
m_layout_root->build_stacking_context_tree();
|
||||
|
||||
auto& icb = static_cast<Layout::InitialContainingBlock&>(*m_layout_root);
|
||||
auto& icb_state = formatting_state.get_mutable(icb);
|
||||
|
@ -583,6 +582,8 @@ void Document::update_layout()
|
|||
root_formatting_context.run(*m_layout_root, Layout::LayoutMode::Default);
|
||||
formatting_state.commit();
|
||||
|
||||
m_layout_root->build_stacking_context_tree();
|
||||
|
||||
browsing_context()->set_needs_display();
|
||||
|
||||
if (browsing_context()->is_top_level()) {
|
||||
|
|
|
@ -88,7 +88,7 @@ HitTestResult BlockContainer::hit_test(const Gfx::IntPoint& position, HitTestTyp
|
|||
HitTestResult last_good_candidate;
|
||||
for (auto& line_box : m_paint_box->m_line_boxes) {
|
||||
for (auto& fragment : line_box.fragments()) {
|
||||
if (is<Box>(fragment.layout_node()) && verify_cast<Box>(fragment.layout_node()).stacking_context())
|
||||
if (is<Box>(fragment.layout_node()) && verify_cast<Box>(fragment.layout_node()).m_paint_box->stacking_context())
|
||||
continue;
|
||||
if (enclosing_int_rect(fragment.absolute_rect()).contains(position)) {
|
||||
if (is<BlockContainer>(fragment.layout_node()))
|
||||
|
|
|
@ -217,21 +217,6 @@ bool Box::is_body() const
|
|||
return dom_node() && dom_node() == document().body();
|
||||
}
|
||||
|
||||
Painting::StackingContext* Box::enclosing_stacking_context()
|
||||
{
|
||||
for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
|
||||
if (!is<Box>(ancestor))
|
||||
continue;
|
||||
auto& ancestor_box = verify_cast<Box>(*ancestor);
|
||||
if (!ancestor_box.establishes_stacking_context())
|
||||
continue;
|
||||
VERIFY(ancestor_box.stacking_context());
|
||||
return ancestor_box.stacking_context();
|
||||
}
|
||||
// We should always reach the Layout::InitialContainingBlock stacking context.
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
void Box::before_children_paint(PaintContext& context, Painting::PaintPhase phase)
|
||||
{
|
||||
NodeWithStyleAndBoxModelMetrics::before_children_paint(context, phase);
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include <LibGfx/Rect.h>
|
||||
#include <LibWeb/Layout/Node.h>
|
||||
#include <LibWeb/Painting/BorderPainting.h>
|
||||
#include <LibWeb/Painting/StackingContext.h>
|
||||
|
||||
namespace Web::Layout {
|
||||
|
||||
|
@ -30,11 +29,6 @@ public:
|
|||
|
||||
bool is_body() const;
|
||||
|
||||
Painting::StackingContext* stacking_context() { return m_stacking_context; }
|
||||
Painting::StackingContext const* stacking_context() const { return m_stacking_context; }
|
||||
void set_stacking_context(NonnullOwnPtr<Painting::StackingContext> context) { m_stacking_context = move(context); }
|
||||
Painting::StackingContext* enclosing_stacking_context();
|
||||
|
||||
virtual void paint(PaintContext&, Painting::PaintPhase) override;
|
||||
virtual void paint_border(PaintContext& context);
|
||||
virtual void paint_box_shadow(PaintContext& context);
|
||||
|
@ -63,8 +57,6 @@ protected:
|
|||
|
||||
private:
|
||||
virtual bool is_box() const final { return true; }
|
||||
|
||||
OwnPtr<Painting::StackingContext> m_stacking_context;
|
||||
};
|
||||
|
||||
template<>
|
||||
|
|
|
@ -24,18 +24,18 @@ InitialContainingBlock::~InitialContainingBlock()
|
|||
|
||||
void InitialContainingBlock::build_stacking_context_tree()
|
||||
{
|
||||
set_stacking_context(make<Painting::StackingContext>(*this, nullptr));
|
||||
m_paint_box->set_stacking_context(make<Painting::StackingContext>(*this, nullptr));
|
||||
|
||||
for_each_in_inclusive_subtree_of_type<Box>([&](Box& box) {
|
||||
if (&box == this)
|
||||
return IterationDecision::Continue;
|
||||
if (!box.establishes_stacking_context()) {
|
||||
VERIFY(!box.stacking_context());
|
||||
VERIFY(!box.m_paint_box->stacking_context());
|
||||
return IterationDecision::Continue;
|
||||
}
|
||||
auto* parent_context = box.enclosing_stacking_context();
|
||||
auto* parent_context = box.m_paint_box->enclosing_stacking_context();
|
||||
VERIFY(parent_context);
|
||||
box.set_stacking_context(make<Painting::StackingContext>(box, parent_context));
|
||||
box.m_paint_box->set_stacking_context(make<Painting::StackingContext>(box, parent_context));
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
|
@ -44,12 +44,12 @@ void InitialContainingBlock::paint_all_phases(PaintContext& context)
|
|||
{
|
||||
context.painter().fill_rect(enclosing_int_rect(m_paint_box->absolute_rect()), context.palette().base());
|
||||
context.painter().translate(-context.viewport_rect().location());
|
||||
stacking_context()->paint(context);
|
||||
m_paint_box->stacking_context()->paint(context);
|
||||
}
|
||||
|
||||
HitTestResult InitialContainingBlock::hit_test(const Gfx::IntPoint& position, HitTestType type) const
|
||||
{
|
||||
return stacking_context()->hit_test(position, type);
|
||||
return m_paint_box->stacking_context()->hit_test(position, type);
|
||||
}
|
||||
|
||||
void InitialContainingBlock::recompute_selection_states()
|
||||
|
|
|
@ -162,7 +162,7 @@ public:
|
|||
return;
|
||||
|
||||
auto& box_child = verify_cast<Box>(child);
|
||||
auto* stacking_context = box_child.stacking_context();
|
||||
auto* stacking_context = box_child.m_paint_box->stacking_context();
|
||||
if (stacking_context && box_child.computed_values().z_index().has_value() && box_child.computed_values().z_index().value() < 0)
|
||||
callback(child);
|
||||
});
|
||||
|
@ -170,7 +170,7 @@ public:
|
|||
// 4. For all its in-flow, non-positioned, block-level descendants in tree order: If the element is a block, list-item,
|
||||
// or other block equivalent:
|
||||
for_each_child([&](auto& child) {
|
||||
if (is<Box>(child) && verify_cast<Box>(child).stacking_context())
|
||||
if (is<Box>(child) && verify_cast<Box>(child).m_paint_box->stacking_context())
|
||||
return;
|
||||
if (!child.is_positioned())
|
||||
callback(child);
|
||||
|
@ -180,7 +180,7 @@ public:
|
|||
// a new stacking context, but any positioned descendants and descendants which actually create a new stacking context
|
||||
// should be considered part of the parent stacking context, not this new one.
|
||||
for_each_child([&](auto& child) {
|
||||
if (is<Box>(child) && verify_cast<Box>(child).stacking_context())
|
||||
if (is<Box>(child) && verify_cast<Box>(child).m_paint_box->stacking_context())
|
||||
return;
|
||||
if (child.is_positioned())
|
||||
callback(child);
|
||||
|
@ -195,7 +195,7 @@ public:
|
|||
return;
|
||||
|
||||
auto& box_child = verify_cast<Box>(child);
|
||||
auto* stacking_context = box_child.stacking_context();
|
||||
auto* stacking_context = box_child.m_paint_box->stacking_context();
|
||||
if (stacking_context && box_child.computed_values().z_index().has_value() && box_child.computed_values().z_index().value() == 0)
|
||||
callback(child);
|
||||
});
|
||||
|
@ -208,7 +208,7 @@ public:
|
|||
return;
|
||||
|
||||
auto& box_child = verify_cast<Box>(child);
|
||||
auto* stacking_context = box_child.stacking_context();
|
||||
auto* stacking_context = box_child.m_paint_box->stacking_context();
|
||||
if (stacking_context && box_child.computed_values().z_index().has_value() && box_child.computed_values().z_index().value() > 0)
|
||||
callback(child);
|
||||
});
|
||||
|
|
|
@ -49,4 +49,19 @@ void Box::set_containing_line_box_fragment(Optional<Layout::LineBoxFragmentCoord
|
|||
m_containing_line_box_fragment = fragment_coordinate;
|
||||
}
|
||||
|
||||
Painting::StackingContext* Box::enclosing_stacking_context()
|
||||
{
|
||||
for (auto* ancestor = m_layout_box.parent(); ancestor; ancestor = ancestor->parent()) {
|
||||
if (!is<Layout::Box>(ancestor))
|
||||
continue;
|
||||
auto& ancestor_box = static_cast<Layout::Box&>(const_cast<Layout::NodeWithStyle&>(*ancestor));
|
||||
if (!ancestor_box.establishes_stacking_context())
|
||||
continue;
|
||||
VERIFY(ancestor_box.m_paint_box->stacking_context());
|
||||
return ancestor_box.m_paint_box->stacking_context();
|
||||
}
|
||||
// We should always reach the Layout::InitialContainingBlock stacking context.
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <AK/NonnullOwnPtr.h>
|
||||
#include <LibWeb/Layout/Box.h>
|
||||
#include <LibWeb/Layout/LineBox.h>
|
||||
#include <LibWeb/Painting/StackingContext.h>
|
||||
|
||||
namespace Web::Painting {
|
||||
|
||||
|
@ -121,6 +122,13 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
StackingContext* stacking_context() { return m_stacking_context; }
|
||||
StackingContext const* stacking_context() const { return m_stacking_context; }
|
||||
void set_stacking_context(NonnullOwnPtr<Painting::StackingContext> context) { m_stacking_context = move(context); }
|
||||
StackingContext* enclosing_stacking_context();
|
||||
|
||||
OwnPtr<Painting::StackingContext> m_stacking_context;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -165,7 +165,7 @@ Layout::HitTestResult StackingContext::hit_test(const Gfx::IntPoint& position, L
|
|||
Layout::HitTestResult result;
|
||||
// 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.stacking_context()) {
|
||||
if (box.is_positioned() && !box.m_paint_box->stacking_context()) {
|
||||
result = box.hit_test(position, type);
|
||||
if (result.layout_node)
|
||||
return IterationDecision::Break;
|
||||
|
|
|
@ -190,7 +190,7 @@ void ConnectionFromClient::debug_request(const String& request, const String& ar
|
|||
if (request == "dump-stacking-context-tree") {
|
||||
if (auto* doc = page().top_level_browsing_context().active_document()) {
|
||||
if (auto* icb = doc->layout_node()) {
|
||||
if (auto* stacking_context = icb->stacking_context())
|
||||
if (auto* stacking_context = icb->m_paint_box->stacking_context())
|
||||
stacking_context->dump();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue