1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-15 03:47:35 +00:00

LibWeb: Improve computation of a layout node's containing block

In particular, we now compute the containing block of boxes with
position:absolute and position:fixed (more) correctly.
This commit is contained in:
Andreas Kling 2020-06-05 16:54:28 +02:00
parent 762617a028
commit 7fcf61be35
3 changed files with 43 additions and 5 deletions

View file

@ -45,6 +45,8 @@ public:
void did_set_viewport_rect(Badge<Frame>, const Gfx::Rect&); void did_set_viewport_rect(Badge<Frame>, const Gfx::Rect&);
virtual bool is_root() const override { return true; }
private: private:
LayoutRange m_selection; LayoutRange m_selection;
}; };

View file

@ -29,7 +29,9 @@
#include <LibWeb/DOM/Element.h> #include <LibWeb/DOM/Element.h>
#include <LibWeb/Frame.h> #include <LibWeb/Frame.h>
#include <LibWeb/Layout/LayoutBlock.h> #include <LibWeb/Layout/LayoutBlock.h>
#include <LibWeb/Layout/LayoutDocument.h>
#include <LibWeb/Layout/LayoutNode.h> #include <LibWeb/Layout/LayoutNode.h>
#include <LibWeb/Layout/LayoutReplaced.h>
namespace Web { namespace Web {
@ -53,13 +55,36 @@ void LayoutNode::layout(LayoutMode layout_mode)
}); });
} }
bool LayoutNode::can_contain_boxes_with_position_absolute() const
{
return style().position() != CSS::Position::Static || is_root();
}
const LayoutBlock* LayoutNode::containing_block() const const LayoutBlock* LayoutNode::containing_block() const
{ {
for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) { if (is_text()) {
if (is<LayoutBlock>(*ancestor)) auto* ancestor = parent();
return to<LayoutBlock>(ancestor); while (ancestor && ((ancestor->is_inline() && !is<LayoutReplaced>(*ancestor)) || !is<LayoutBlock>(*ancestor)))
ancestor = ancestor->parent();
return to<LayoutBlock>(ancestor);
} }
return nullptr;
if (is_absolutely_positioned()) {
auto* ancestor = parent();
while (ancestor && !ancestor->can_contain_boxes_with_position_absolute())
ancestor = ancestor->parent();
while (ancestor && (!is<LayoutBlock>(ancestor) || ancestor->is_anonymous()))
ancestor = ancestor->containing_block();
return to<LayoutBlock>(ancestor);
}
if (style().position() == CSS::Position::Fixed)
return &root();
auto* ancestor = parent();
while (ancestor && ((ancestor->is_inline() && !is<LayoutReplaced>(*ancestor)) || !is<LayoutBlock>(*ancestor)))
ancestor = ancestor->parent();
return to<LayoutBlock>(ancestor);
} }
void LayoutNode::render(RenderingContext& context) void LayoutNode::render(RenderingContext& context)
@ -155,4 +180,10 @@ Gfx::FloatPoint LayoutNode::box_type_agnostic_position() const
return position; return position;
} }
bool LayoutNode::is_absolutely_positioned() const
{
return style().position() == CSS::Position::Absolute;
}
} }

View file

@ -81,7 +81,8 @@ public:
callback(*node); callback(*node);
} }
virtual const char* class_name() const { return "LayoutNode"; } virtual const char* class_name() const = 0;
virtual bool is_root() const { return false; }
virtual bool is_text() const { return false; } virtual bool is_text() const { return false; }
virtual bool is_block() const { return false; } virtual bool is_block() const { return false; }
virtual bool is_replaced() const { return false; } virtual bool is_replaced() const { return false; }
@ -108,8 +109,12 @@ public:
virtual void layout(LayoutMode); virtual void layout(LayoutMode);
virtual void render(RenderingContext&); virtual void render(RenderingContext&);
bool is_absolutely_positioned() const;
const LayoutBlock* containing_block() const; const LayoutBlock* containing_block() const;
bool can_contain_boxes_with_position_absolute() const;
virtual LayoutNode& inline_wrapper() { return *this; } virtual LayoutNode& inline_wrapper() { return *this; }
const StyleProperties& style() const; const StyleProperties& style() const;