Browse Source

LibWeb: Generate layout nodes for shadow subtrees

Elements with shadow roots will now recurse into those shadow trees
while building the layout tree.

This is the first step towards basic Shadow DOM support. :^)
Andreas Kling 4 years ago
parent
commit
e562819a7e

+ 6 - 0
Userland/Libraries/LibWeb/DOM/ShadowRoot.cpp

@@ -26,6 +26,7 @@
 
 
 #include <LibWeb/DOM/Event.h>
 #include <LibWeb/DOM/Event.h>
 #include <LibWeb/DOM/ShadowRoot.h>
 #include <LibWeb/DOM/ShadowRoot.h>
+#include <LibWeb/Layout/BlockBox.h>
 
 
 namespace Web::DOM {
 namespace Web::DOM {
 
 
@@ -46,4 +47,9 @@ EventTarget* ShadowRoot::get_parent(const Event& event)
     return host();
     return host();
 }
 }
 
 
+RefPtr<Layout::Node> ShadowRoot::create_layout_node()
+{
+    return adopt(*new Layout::BlockBox(document(), this, CSS::ComputedValues {}));
+}
+
 }
 }

+ 4 - 0
Userland/Libraries/LibWeb/DOM/ShadowRoot.h

@@ -49,6 +49,10 @@ public:
     String mode() const { return m_closed ? "closed" : "open"; }
     String mode() const { return m_closed ? "closed" : "open"; }
 
 
 private:
 private:
+    // ^Node
+    virtual FlyString node_name() const override { return "#shadow-root"; }
+    virtual RefPtr<Layout::Node> create_layout_node() override;
+
     // NOTE: The specification doesn't seem to specify a default value for closed. Assuming false for now.
     // NOTE: The specification doesn't seem to specify a default value for closed. Assuming false for now.
     bool m_closed { false };
     bool m_closed { false };
     bool m_delegates_focus { false };
     bool m_delegates_focus { false };

+ 8 - 3
Userland/Libraries/LibWeb/Layout/TreeBuilder.cpp

@@ -27,6 +27,7 @@
 #include <LibWeb/DOM/Document.h>
 #include <LibWeb/DOM/Document.h>
 #include <LibWeb/DOM/Element.h>
 #include <LibWeb/DOM/Element.h>
 #include <LibWeb/DOM/ParentNode.h>
 #include <LibWeb/DOM/ParentNode.h>
+#include <LibWeb/DOM/ShadowRoot.h>
 #include <LibWeb/Dump.h>
 #include <LibWeb/Dump.h>
 #include <LibWeb/Layout/InitialContainingBlockBox.h>
 #include <LibWeb/Layout/InitialContainingBlockBox.h>
 #include <LibWeb/Layout/Node.h>
 #include <LibWeb/Layout/Node.h>
@@ -92,14 +93,14 @@ static Layout::Node& insertion_parent_for_block_node(Layout::Node& layout_parent
 void TreeBuilder::create_layout_tree(DOM::Node& dom_node)
 void TreeBuilder::create_layout_tree(DOM::Node& dom_node)
 {
 {
     // If the parent doesn't have a layout node, we don't need one either.
     // If the parent doesn't have a layout node, we don't need one either.
-    if (dom_node.parent() && !dom_node.parent()->layout_node())
+    if (dom_node.parent_or_shadow_host() && !dom_node.parent_or_shadow_host()->layout_node())
         return;
         return;
 
 
     auto layout_node = dom_node.create_layout_node();
     auto layout_node = dom_node.create_layout_node();
     if (!layout_node)
     if (!layout_node)
         return;
         return;
 
 
-    if (!dom_node.parent()) {
+    if (!dom_node.parent_or_shadow_host()) {
         m_layout_root = layout_node;
         m_layout_root = layout_node;
     } else {
     } else {
         if (layout_node->is_inline()) {
         if (layout_node->is_inline()) {
@@ -122,8 +123,12 @@ void TreeBuilder::create_layout_tree(DOM::Node& dom_node)
         }
         }
     }
     }
 
 
-    if (dom_node.has_children() && layout_node->can_have_children()) {
+    auto* shadow_root = is<DOM::Element>(dom_node) ? downcast<DOM::Element>(dom_node).shadow_root() : nullptr;
+
+    if ((dom_node.has_children() || shadow_root) && layout_node->can_have_children()) {
         push_parent(downcast<NodeWithStyle>(*layout_node));
         push_parent(downcast<NodeWithStyle>(*layout_node));
+        if (shadow_root)
+            create_layout_tree(*shadow_root);
         downcast<DOM::ParentNode>(dom_node).for_each_child([&](auto& dom_child) {
         downcast<DOM::ParentNode>(dom_node).for_each_child([&](auto& dom_child) {
             create_layout_tree(dom_child);
             create_layout_tree(dom_child);
         });
         });