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::FormattingState formatting_state;
|
||||||
Layout::BlockFormattingContext root_formatting_context(formatting_state, *m_layout_root, nullptr);
|
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 = static_cast<Layout::InitialContainingBlock&>(*m_layout_root);
|
||||||
auto& icb_state = formatting_state.get_mutable(icb);
|
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);
|
root_formatting_context.run(*m_layout_root, Layout::LayoutMode::Default);
|
||||||
formatting_state.commit();
|
formatting_state.commit();
|
||||||
|
|
||||||
|
m_layout_root->build_stacking_context_tree();
|
||||||
|
|
||||||
browsing_context()->set_needs_display();
|
browsing_context()->set_needs_display();
|
||||||
|
|
||||||
if (browsing_context()->is_top_level()) {
|
if (browsing_context()->is_top_level()) {
|
||||||
|
|
|
@ -88,7 +88,7 @@ HitTestResult BlockContainer::hit_test(const Gfx::IntPoint& position, HitTestTyp
|
||||||
HitTestResult last_good_candidate;
|
HitTestResult last_good_candidate;
|
||||||
for (auto& line_box : m_paint_box->m_line_boxes) {
|
for (auto& line_box : m_paint_box->m_line_boxes) {
|
||||||
for (auto& fragment : line_box.fragments()) {
|
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;
|
continue;
|
||||||
if (enclosing_int_rect(fragment.absolute_rect()).contains(position)) {
|
if (enclosing_int_rect(fragment.absolute_rect()).contains(position)) {
|
||||||
if (is<BlockContainer>(fragment.layout_node()))
|
if (is<BlockContainer>(fragment.layout_node()))
|
||||||
|
|
|
@ -217,21 +217,6 @@ bool Box::is_body() const
|
||||||
return dom_node() && dom_node() == document().body();
|
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)
|
void Box::before_children_paint(PaintContext& context, Painting::PaintPhase phase)
|
||||||
{
|
{
|
||||||
NodeWithStyleAndBoxModelMetrics::before_children_paint(context, phase);
|
NodeWithStyleAndBoxModelMetrics::before_children_paint(context, phase);
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
#include <LibGfx/Rect.h>
|
#include <LibGfx/Rect.h>
|
||||||
#include <LibWeb/Layout/Node.h>
|
#include <LibWeb/Layout/Node.h>
|
||||||
#include <LibWeb/Painting/BorderPainting.h>
|
#include <LibWeb/Painting/BorderPainting.h>
|
||||||
#include <LibWeb/Painting/StackingContext.h>
|
|
||||||
|
|
||||||
namespace Web::Layout {
|
namespace Web::Layout {
|
||||||
|
|
||||||
|
@ -30,11 +29,6 @@ public:
|
||||||
|
|
||||||
bool is_body() const;
|
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(PaintContext&, Painting::PaintPhase) override;
|
||||||
virtual void paint_border(PaintContext& context);
|
virtual void paint_border(PaintContext& context);
|
||||||
virtual void paint_box_shadow(PaintContext& context);
|
virtual void paint_box_shadow(PaintContext& context);
|
||||||
|
@ -63,8 +57,6 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual bool is_box() const final { return true; }
|
virtual bool is_box() const final { return true; }
|
||||||
|
|
||||||
OwnPtr<Painting::StackingContext> m_stacking_context;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
|
|
@ -24,18 +24,18 @@ InitialContainingBlock::~InitialContainingBlock()
|
||||||
|
|
||||||
void InitialContainingBlock::build_stacking_context_tree()
|
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) {
|
for_each_in_inclusive_subtree_of_type<Box>([&](Box& box) {
|
||||||
if (&box == this)
|
if (&box == this)
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
if (!box.establishes_stacking_context()) {
|
if (!box.establishes_stacking_context()) {
|
||||||
VERIFY(!box.stacking_context());
|
VERIFY(!box.m_paint_box->stacking_context());
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
}
|
}
|
||||||
auto* parent_context = box.enclosing_stacking_context();
|
auto* parent_context = box.m_paint_box->enclosing_stacking_context();
|
||||||
VERIFY(parent_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;
|
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().fill_rect(enclosing_int_rect(m_paint_box->absolute_rect()), context.palette().base());
|
||||||
context.painter().translate(-context.viewport_rect().location());
|
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
|
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()
|
void InitialContainingBlock::recompute_selection_states()
|
||||||
|
|
|
@ -162,7 +162,7 @@ public:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto& box_child = verify_cast<Box>(child);
|
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)
|
if (stacking_context && box_child.computed_values().z_index().has_value() && box_child.computed_values().z_index().value() < 0)
|
||||||
callback(child);
|
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,
|
// 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:
|
// or other block equivalent:
|
||||||
for_each_child([&](auto& child) {
|
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;
|
return;
|
||||||
if (!child.is_positioned())
|
if (!child.is_positioned())
|
||||||
callback(child);
|
callback(child);
|
||||||
|
@ -180,7 +180,7 @@ public:
|
||||||
// a new stacking context, but any positioned descendants and descendants which actually create a new stacking context
|
// 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.
|
// should be considered part of the parent stacking context, not this new one.
|
||||||
for_each_child([&](auto& child) {
|
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;
|
return;
|
||||||
if (child.is_positioned())
|
if (child.is_positioned())
|
||||||
callback(child);
|
callback(child);
|
||||||
|
@ -195,7 +195,7 @@ public:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto& box_child = verify_cast<Box>(child);
|
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)
|
if (stacking_context && box_child.computed_values().z_index().has_value() && box_child.computed_values().z_index().value() == 0)
|
||||||
callback(child);
|
callback(child);
|
||||||
});
|
});
|
||||||
|
@ -208,7 +208,7 @@ public:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto& box_child = verify_cast<Box>(child);
|
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)
|
if (stacking_context && box_child.computed_values().z_index().has_value() && box_child.computed_values().z_index().value() > 0)
|
||||||
callback(child);
|
callback(child);
|
||||||
});
|
});
|
||||||
|
|
|
@ -49,4 +49,19 @@ void Box::set_containing_line_box_fragment(Optional<Layout::LineBoxFragmentCoord
|
||||||
m_containing_line_box_fragment = fragment_coordinate;
|
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 <AK/NonnullOwnPtr.h>
|
||||||
#include <LibWeb/Layout/Box.h>
|
#include <LibWeb/Layout/Box.h>
|
||||||
#include <LibWeb/Layout/LineBox.h>
|
#include <LibWeb/Layout/LineBox.h>
|
||||||
|
#include <LibWeb/Painting/StackingContext.h>
|
||||||
|
|
||||||
namespace Web::Painting {
|
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;
|
Layout::HitTestResult result;
|
||||||
// 6. the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
|
// 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) {
|
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);
|
result = box.hit_test(position, type);
|
||||||
if (result.layout_node)
|
if (result.layout_node)
|
||||||
return IterationDecision::Break;
|
return IterationDecision::Break;
|
||||||
|
|
|
@ -190,7 +190,7 @@ void ConnectionFromClient::debug_request(const String& request, const String& ar
|
||||||
if (request == "dump-stacking-context-tree") {
|
if (request == "dump-stacking-context-tree") {
|
||||||
if (auto* doc = page().top_level_browsing_context().active_document()) {
|
if (auto* doc = page().top_level_browsing_context().active_document()) {
|
||||||
if (auto* icb = doc->layout_node()) {
|
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();
|
stacking_context->dump();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue