diff options
author | Andreas Kling <kling@serenityos.org> | 2020-06-05 16:54:28 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-06-05 19:15:20 +0200 |
commit | 7fcf61be358180365fb950fe7ba4f68314e39cad (patch) | |
tree | 1f49fe813d7773a0662f563d181e37798b1bf7ab /Libraries/LibWeb/Layout | |
parent | 762617a028e8355ea55ec2c13f12ab9d40ea9270 (diff) | |
download | serenity-7fcf61be358180365fb950fe7ba4f68314e39cad.zip |
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.
Diffstat (limited to 'Libraries/LibWeb/Layout')
-rw-r--r-- | Libraries/LibWeb/Layout/LayoutDocument.h | 2 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/LayoutNode.cpp | 39 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/LayoutNode.h | 7 |
3 files changed, 43 insertions, 5 deletions
diff --git a/Libraries/LibWeb/Layout/LayoutDocument.h b/Libraries/LibWeb/Layout/LayoutDocument.h index c89353b8ca..542b415818 100644 --- a/Libraries/LibWeb/Layout/LayoutDocument.h +++ b/Libraries/LibWeb/Layout/LayoutDocument.h @@ -45,6 +45,8 @@ public: void did_set_viewport_rect(Badge<Frame>, const Gfx::Rect&); + virtual bool is_root() const override { return true; } + private: LayoutRange m_selection; }; diff --git a/Libraries/LibWeb/Layout/LayoutNode.cpp b/Libraries/LibWeb/Layout/LayoutNode.cpp index 678e49b8b9..cbcfd4d7f6 100644 --- a/Libraries/LibWeb/Layout/LayoutNode.cpp +++ b/Libraries/LibWeb/Layout/LayoutNode.cpp @@ -29,7 +29,9 @@ #include <LibWeb/DOM/Element.h> #include <LibWeb/Frame.h> #include <LibWeb/Layout/LayoutBlock.h> +#include <LibWeb/Layout/LayoutDocument.h> #include <LibWeb/Layout/LayoutNode.h> +#include <LibWeb/Layout/LayoutReplaced.h> 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 { - for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) { - if (is<LayoutBlock>(*ancestor)) - return to<LayoutBlock>(ancestor); + if (is_text()) { + auto* ancestor = parent(); + 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) @@ -155,4 +180,10 @@ Gfx::FloatPoint LayoutNode::box_type_agnostic_position() const return position; } +bool LayoutNode::is_absolutely_positioned() const +{ + return style().position() == CSS::Position::Absolute; +} + + } diff --git a/Libraries/LibWeb/Layout/LayoutNode.h b/Libraries/LibWeb/Layout/LayoutNode.h index b9a5adbb13..8c31244e9c 100644 --- a/Libraries/LibWeb/Layout/LayoutNode.h +++ b/Libraries/LibWeb/Layout/LayoutNode.h @@ -81,7 +81,8 @@ public: 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_block() const { return false; } virtual bool is_replaced() const { return false; } @@ -108,8 +109,12 @@ public: virtual void layout(LayoutMode); virtual void render(RenderingContext&); + bool is_absolutely_positioned() const; + const LayoutBlock* containing_block() const; + bool can_contain_boxes_with_position_absolute() const; + virtual LayoutNode& inline_wrapper() { return *this; } const StyleProperties& style() const; |