diff --git a/Libraries/LibHTML/DOM/Document.cpp b/Libraries/LibHTML/DOM/Document.cpp
index 9a6c991160..ad2a552cfd 100644
--- a/Libraries/LibHTML/DOM/Document.cpp
+++ b/Libraries/LibHTML/DOM/Document.cpp
@@ -1,5 +1,6 @@
#include
#include
+#include
#include
#include
#include
@@ -18,12 +19,25 @@ Document::Document()
: ParentNode(*this, NodeType::DOCUMENT_NODE)
, m_style_resolver(make(*this))
{
+ m_style_update_timer = CTimer::construct();
+ m_style_update_timer->set_single_shot(true);
+ m_style_update_timer->set_interval(0);
+ m_style_update_timer->on_timeout = [this] {
+ update_style();
+ };
}
Document::~Document()
{
}
+void Document::schedule_style_update()
+{
+ if (m_style_update_timer->is_active())
+ return;
+ m_style_update_timer->start();
+}
+
bool Document::is_child_allowed(const Node& node) const
{
switch (node.type()) {
@@ -178,7 +192,11 @@ void Document::layout()
void Document::update_style()
{
- m_layout_root = nullptr;
+ for_each_in_subtree([&](Node& node) {
+ if (!node.needs_style_update())
+ return;
+ to(node).recompute_style();
+ });
update_layout();
}
@@ -222,8 +240,5 @@ void Document::set_hovered_node(Node* node)
RefPtr old_hovered_node = move(m_hovered_node);
m_hovered_node = node;
- if (old_hovered_node)
- old_hovered_node->invalidate_style();
- if (m_hovered_node)
- m_hovered_node->invalidate_style();
+ invalidate_style();
}
diff --git a/Libraries/LibHTML/DOM/Document.h b/Libraries/LibHTML/DOM/Document.h
index 94fb6ff49d..dc3c6c625e 100644
--- a/Libraries/LibHTML/DOM/Document.h
+++ b/Libraries/LibHTML/DOM/Document.h
@@ -10,6 +10,7 @@
#include
#include
+class CTimer;
class Frame;
class HTMLBodyElement;
class HTMLHtmlElement;
@@ -77,6 +78,8 @@ public:
const LayoutDocument* layout_node() const;
+ void schedule_style_update();
+
private:
virtual RefPtr create_layout_node(const StyleProperties* parent_style) const override;
@@ -91,6 +94,8 @@ private:
Color m_link_color { Color::Blue };
Color m_active_link_color { Color::Red };
Color m_visited_link_color { Color::Magenta };
+
+ RefPtr m_style_update_timer;
};
template<>
diff --git a/Libraries/LibHTML/DOM/Element.cpp b/Libraries/LibHTML/DOM/Element.cpp
index 4ad220860f..c93536104b 100644
--- a/Libraries/LibHTML/DOM/Element.cpp
+++ b/Libraries/LibHTML/DOM/Element.cpp
@@ -7,6 +7,7 @@
#include
#include
#include
+#include
Element::Element(Document& document, const String& tag_name)
: ParentNode(document, NodeType::ELEMENT_NODE)
@@ -129,11 +130,21 @@ static StyleDifference compute_style_difference(const StyleProperties& old_style
void Element::recompute_style()
{
+ set_needs_style_update(false);
ASSERT(parent());
auto* parent_layout_node = parent()->layout_node();
+ if (!parent_layout_node)
+ return;
ASSERT(parent_layout_node);
auto style = document().style_resolver().resolve_style(*this, &parent_layout_node->style());
- ASSERT(layout_node());
+ if (!layout_node()) {
+ if (style->string_or_fallback(CSS::PropertyID::Display, "inline") == "none")
+ return;
+ // We need a new layout tree here!
+ LayoutTreeBuilder tree_builder;
+ tree_builder.build(*this);
+ return;
+ }
auto diff = compute_style_difference(layout_node()->style(), *style, document());
if (diff == StyleDifference::None)
return;
diff --git a/Libraries/LibHTML/DOM/Node.cpp b/Libraries/LibHTML/DOM/Node.cpp
index f6880c7075..ef03875d98 100644
--- a/Libraries/LibHTML/DOM/Node.cpp
+++ b/Libraries/LibHTML/DOM/Node.cpp
@@ -70,8 +70,9 @@ RefPtr Node::create_layout_node(const StyleProperties*) const
void Node::invalidate_style()
{
- for (auto* node = this; node; node = node->parent()) {
- if (is(*node))
- to(*node).recompute_style();
- }
+ for_each_in_subtree([&](auto& node) {
+ if (is(node))
+ node.set_needs_style_update(true);
+ });
+ document().schedule_style_update();
}
diff --git a/Libraries/LibHTML/DOM/Node.h b/Libraries/LibHTML/DOM/Node.h
index a32f631092..326f619670 100644
--- a/Libraries/LibHTML/DOM/Node.h
+++ b/Libraries/LibHTML/DOM/Node.h
@@ -70,6 +70,9 @@ public:
virtual bool is_child_allowed(const Node&) const { return true; }
+ bool needs_style_update() const { return m_needs_style_update; }
+ void set_needs_style_update(bool value) { m_needs_style_update = value; }
+
void invalidate_style();
protected:
@@ -78,6 +81,7 @@ protected:
Document& m_document;
mutable LayoutNode* m_layout_node { nullptr };
NodeType m_type { NodeType::INVALID };
+ bool m_needs_style_update { false };
};
template