Selaa lähdekoodia

LibHTML: Move layout root from HtmlView to Document

The layout root is now kept alive via Document::m_layout_root.
This will allow us to do more layout-related things inside the inner
layer of LibHTML without reaching out to the HtmlView.

I'd like to keep HtmlView at a slightly higher level, to prevent it
from getting too complex.

This patch also fixes accidental disconnection of the layout tree from
the DOM after doing a layout tree rebuild. ~LayoutNode() now only
unsets the DOM node's layout_node() if it's itself.
Andreas Kling 5 vuotta sitten
vanhempi
commit
49ac0c2e24

+ 1 - 0
Applications/Browser/main.cpp

@@ -14,6 +14,7 @@
 #include <LibHTML/Dump.h>
 #include <LibHTML/HtmlView.h>
 #include <LibHTML/Layout/LayoutBlock.h>
+#include <LibHTML/Layout/LayoutDocument.h>
 #include <LibHTML/Layout/LayoutInline.h>
 #include <LibHTML/Layout/LayoutNode.h>
 #include <LibHTML/Parser/CSSParser.h>

+ 14 - 0
Libraries/LibHTML/DOM/Document.cpp

@@ -98,10 +98,12 @@ String Document::title() const
 void Document::attach_to_frame(Badge<Frame>, Frame& frame)
 {
     m_frame = frame.make_weak_ptr();
+    layout();
 }
 
 void Document::detach_from_frame(Badge<Frame>, Frame&)
 {
+    m_layout_root = nullptr;
     m_frame = nullptr;
 }
 
@@ -149,8 +151,15 @@ URL Document::complete_url(const String& string) const
     return url;
 }
 
+void Document::layout()
+{
+    m_layout_root = create_layout_tree(style_resolver(), nullptr);
+    m_layout_root->layout();
+}
+
 void Document::invalidate_layout()
 {
+    layout();
     if (on_invalidate_layout)
         on_invalidate_layout();
 }
@@ -174,3 +183,8 @@ void Document::set_visited_link_color(Color color)
 {
     m_visited_link_color = color;
 }
+
+const LayoutDocument* Document::layout_node() const
+{
+    return static_cast<const LayoutDocument*>(Node::layout_node());
+}

+ 7 - 0
Libraries/LibHTML/DOM/Document.h

@@ -14,6 +14,7 @@ class Frame;
 class HTMLBodyElement;
 class HTMLHtmlElement;
 class HTMLHeadElement;
+class LayoutDocument;
 class LayoutNode;
 class StyleResolver;
 class StyleSheet;
@@ -64,11 +65,15 @@ public:
     Color visited_link_color() const { return m_visited_link_color; }
     void set_visited_link_color(Color);
 
+    void layout();
+
     void invalidate_layout();
     Function<void()> on_invalidate_layout;
 
     virtual bool is_child_allowed(const Node&) const override;
 
+    const LayoutDocument* layout_node() const;
+
 private:
     virtual RefPtr<LayoutNode> create_layout_node(const StyleResolver&, const StyleProperties* parent_style) const override;
 
@@ -78,6 +83,8 @@ private:
     WeakPtr<Frame> m_frame;
     URL m_url;
 
+    RefPtr<LayoutDocument> m_layout_root;
+
     Color m_link_color { Color::Blue };
     Color m_active_link_color { Color::Red };
     Color m_visited_link_color { Color::Magenta };

+ 25 - 18
Libraries/LibHTML/HtmlView.cpp

@@ -8,6 +8,7 @@
 #include <LibHTML/Dump.h>
 #include <LibHTML/Frame.h>
 #include <LibHTML/HtmlView.h>
+#include <LibHTML/Layout/LayoutDocument.h>
 #include <LibHTML/Layout/LayoutNode.h>
 #include <LibHTML/Parser/HTMLParser.h>
 #include <LibHTML/RenderingContext.h>
@@ -46,24 +47,18 @@ void HtmlView::set_document(Document* document)
     m_document = document;
 
     if (m_document) {
-        m_document->on_invalidate_layout = [this]() {
-            m_layout_root = m_document->create_layout_tree(m_document->style_resolver(), nullptr);
+        m_document->on_invalidate_layout = [this] {
             layout_and_sync_size();
             update();
         };
     }
 
-    m_layout_root = nullptr;
-
     main_frame().set_document(document);
 
-    if (document)
-        m_layout_root = document->create_layout_tree(document->style_resolver(), nullptr);
-
 #ifdef HTML_DEBUG
     if (document != nullptr) {
         dbgprintf("\033[33;1mLayout tree before layout:\033[0m\n");
-        ::dump_tree(*m_layout_root);
+        ::dump_tree(*layout_root());
     }
 #endif
 
@@ -73,16 +68,16 @@ void HtmlView::set_document(Document* document)
 
 void HtmlView::layout_and_sync_size()
 {
-    if (!m_layout_root)
+    if (!document())
         return;
 
     main_frame().set_size(available_size());
-    m_layout_root->layout();
-    set_content_size(m_layout_root->rect().size());
+    document()->layout();
+    set_content_size(layout_root()->rect().size());
 
 #ifdef HTML_DEBUG
     dbgprintf("\033[33;1mLayout tree after layout:\033[0m\n");
-    ::dump_tree(*m_layout_root);
+    ::dump_tree(*layout_root());
 #endif
 }
 
@@ -100,7 +95,7 @@ void HtmlView::paint_event(GPaintEvent& event)
     painter.add_clip_rect(widget_inner_rect());
     painter.add_clip_rect(event.rect());
 
-    if (!m_layout_root) {
+    if (!layout_root()) {
         painter.fill_rect(event.rect(), background_color());
         return;
     }
@@ -112,17 +107,17 @@ void HtmlView::paint_event(GPaintEvent& event)
 
     RenderingContext context { painter };
     context.set_should_show_line_box_borders(m_should_show_line_box_borders);
-    m_layout_root->render(context);
+    layout_root()->render(context);
 }
 
 void HtmlView::mousemove_event(GMouseEvent& event)
 {
-    if (!m_layout_root)
+    if (!layout_root())
         return GScrollableWidget::mousemove_event(event);
 
     bool hovered_node_changed = false;
     bool is_hovering_link = false;
-    auto result = m_layout_root->hit_test(to_content_position(event.position()));
+    auto result = layout_root()->hit_test(to_content_position(event.position()));
     if (result.layout_node) {
         auto* node = result.layout_node->node();
         hovered_node_changed = node != m_document->hovered_node();
@@ -154,11 +149,11 @@ void HtmlView::mousemove_event(GMouseEvent& event)
 
 void HtmlView::mousedown_event(GMouseEvent& event)
 {
-    if (!m_layout_root)
+    if (!layout_root())
         return GScrollableWidget::mousemove_event(event);
 
     bool hovered_node_changed = false;
-    auto result = m_layout_root->hit_test(to_content_position(event.position()));
+    auto result = layout_root()->hit_test(to_content_position(event.position()));
     if (result.layout_node) {
         auto* node = result.layout_node->node();
         hovered_node_changed = node != m_document->hovered_node();
@@ -205,3 +200,15 @@ void HtmlView::load(const URL& url)
             on_title_change(document->title());
     });
 }
+
+const LayoutDocument* HtmlView::layout_root() const
+{
+    return document() ? document()->layout_node() : nullptr;
+}
+
+LayoutDocument* HtmlView::layout_root()
+{
+    if (!document())
+        return nullptr;
+    return const_cast<LayoutDocument*>(document()->layout_node());
+}

+ 3 - 1
Libraries/LibHTML/HtmlView.h

@@ -15,6 +15,9 @@ public:
     const Document* document() const { return m_document; }
     void set_document(Document*);
 
+    const LayoutDocument* layout_root() const;
+    LayoutDocument* layout_root();
+
     Frame& main_frame() { return *m_main_frame; }
     const Frame& main_frame() const { return *m_main_frame; }
 
@@ -42,7 +45,6 @@ private:
 
     RefPtr<Frame> m_main_frame;
     RefPtr<Document> m_document;
-    RefPtr<LayoutNode> m_layout_root;
 
     bool m_should_show_line_box_borders { false };
 };

+ 1 - 1
Libraries/LibHTML/Layout/LayoutNode.cpp

@@ -17,7 +17,7 @@ LayoutNode::LayoutNode(const Node* node)
 
 LayoutNode::~LayoutNode()
 {
-    if (m_node)
+    if (m_node && m_node->layout_node() == this)
         m_node->set_layout_node({}, nullptr);
 }