summaryrefslogtreecommitdiff
path: root/Libraries/LibWeb/Layout
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-06-05 16:54:28 +0200
committerAndreas Kling <kling@serenityos.org>2020-06-05 19:15:20 +0200
commit7fcf61be358180365fb950fe7ba4f68314e39cad (patch)
tree1f49fe813d7773a0662f563d181e37798b1bf7ab /Libraries/LibWeb/Layout
parent762617a028e8355ea55ec2c13f12ab9d40ea9270 (diff)
downloadserenity-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.h2
-rw-r--r--Libraries/LibWeb/Layout/LayoutNode.cpp39
-rw-r--r--Libraries/LibWeb/Layout/LayoutNode.h7
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;