mirror of
https://github.com/RGBCube/serenity
synced 2025-07-10 05:57:35 +00:00
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.
This commit is contained in:
parent
48ef1d1bd1
commit
49ac0c2e24
6 changed files with 51 additions and 20 deletions
|
@ -14,6 +14,7 @@
|
||||||
#include <LibHTML/Dump.h>
|
#include <LibHTML/Dump.h>
|
||||||
#include <LibHTML/HtmlView.h>
|
#include <LibHTML/HtmlView.h>
|
||||||
#include <LibHTML/Layout/LayoutBlock.h>
|
#include <LibHTML/Layout/LayoutBlock.h>
|
||||||
|
#include <LibHTML/Layout/LayoutDocument.h>
|
||||||
#include <LibHTML/Layout/LayoutInline.h>
|
#include <LibHTML/Layout/LayoutInline.h>
|
||||||
#include <LibHTML/Layout/LayoutNode.h>
|
#include <LibHTML/Layout/LayoutNode.h>
|
||||||
#include <LibHTML/Parser/CSSParser.h>
|
#include <LibHTML/Parser/CSSParser.h>
|
||||||
|
|
|
@ -98,10 +98,12 @@ String Document::title() const
|
||||||
void Document::attach_to_frame(Badge<Frame>, Frame& frame)
|
void Document::attach_to_frame(Badge<Frame>, Frame& frame)
|
||||||
{
|
{
|
||||||
m_frame = frame.make_weak_ptr();
|
m_frame = frame.make_weak_ptr();
|
||||||
|
layout();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Document::detach_from_frame(Badge<Frame>, Frame&)
|
void Document::detach_from_frame(Badge<Frame>, Frame&)
|
||||||
{
|
{
|
||||||
|
m_layout_root = nullptr;
|
||||||
m_frame = nullptr;
|
m_frame = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,8 +151,15 @@ URL Document::complete_url(const String& string) const
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Document::layout()
|
||||||
|
{
|
||||||
|
m_layout_root = create_layout_tree(style_resolver(), nullptr);
|
||||||
|
m_layout_root->layout();
|
||||||
|
}
|
||||||
|
|
||||||
void Document::invalidate_layout()
|
void Document::invalidate_layout()
|
||||||
{
|
{
|
||||||
|
layout();
|
||||||
if (on_invalidate_layout)
|
if (on_invalidate_layout)
|
||||||
on_invalidate_layout();
|
on_invalidate_layout();
|
||||||
}
|
}
|
||||||
|
@ -174,3 +183,8 @@ void Document::set_visited_link_color(Color color)
|
||||||
{
|
{
|
||||||
m_visited_link_color = color;
|
m_visited_link_color = color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const LayoutDocument* Document::layout_node() const
|
||||||
|
{
|
||||||
|
return static_cast<const LayoutDocument*>(Node::layout_node());
|
||||||
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ class Frame;
|
||||||
class HTMLBodyElement;
|
class HTMLBodyElement;
|
||||||
class HTMLHtmlElement;
|
class HTMLHtmlElement;
|
||||||
class HTMLHeadElement;
|
class HTMLHeadElement;
|
||||||
|
class LayoutDocument;
|
||||||
class LayoutNode;
|
class LayoutNode;
|
||||||
class StyleResolver;
|
class StyleResolver;
|
||||||
class StyleSheet;
|
class StyleSheet;
|
||||||
|
@ -64,11 +65,15 @@ public:
|
||||||
Color visited_link_color() const { return m_visited_link_color; }
|
Color visited_link_color() const { return m_visited_link_color; }
|
||||||
void set_visited_link_color(Color);
|
void set_visited_link_color(Color);
|
||||||
|
|
||||||
|
void layout();
|
||||||
|
|
||||||
void invalidate_layout();
|
void invalidate_layout();
|
||||||
Function<void()> on_invalidate_layout;
|
Function<void()> on_invalidate_layout;
|
||||||
|
|
||||||
virtual bool is_child_allowed(const Node&) const override;
|
virtual bool is_child_allowed(const Node&) const override;
|
||||||
|
|
||||||
|
const LayoutDocument* layout_node() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual RefPtr<LayoutNode> create_layout_node(const StyleResolver&, const StyleProperties* parent_style) const override;
|
virtual RefPtr<LayoutNode> create_layout_node(const StyleResolver&, const StyleProperties* parent_style) const override;
|
||||||
|
|
||||||
|
@ -78,6 +83,8 @@ private:
|
||||||
WeakPtr<Frame> m_frame;
|
WeakPtr<Frame> m_frame;
|
||||||
URL m_url;
|
URL m_url;
|
||||||
|
|
||||||
|
RefPtr<LayoutDocument> m_layout_root;
|
||||||
|
|
||||||
Color m_link_color { Color::Blue };
|
Color m_link_color { Color::Blue };
|
||||||
Color m_active_link_color { Color::Red };
|
Color m_active_link_color { Color::Red };
|
||||||
Color m_visited_link_color { Color::Magenta };
|
Color m_visited_link_color { Color::Magenta };
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <LibHTML/Dump.h>
|
#include <LibHTML/Dump.h>
|
||||||
#include <LibHTML/Frame.h>
|
#include <LibHTML/Frame.h>
|
||||||
#include <LibHTML/HtmlView.h>
|
#include <LibHTML/HtmlView.h>
|
||||||
|
#include <LibHTML/Layout/LayoutDocument.h>
|
||||||
#include <LibHTML/Layout/LayoutNode.h>
|
#include <LibHTML/Layout/LayoutNode.h>
|
||||||
#include <LibHTML/Parser/HTMLParser.h>
|
#include <LibHTML/Parser/HTMLParser.h>
|
||||||
#include <LibHTML/RenderingContext.h>
|
#include <LibHTML/RenderingContext.h>
|
||||||
|
@ -46,24 +47,18 @@ void HtmlView::set_document(Document* document)
|
||||||
m_document = document;
|
m_document = document;
|
||||||
|
|
||||||
if (m_document) {
|
if (m_document) {
|
||||||
m_document->on_invalidate_layout = [this]() {
|
m_document->on_invalidate_layout = [this] {
|
||||||
m_layout_root = m_document->create_layout_tree(m_document->style_resolver(), nullptr);
|
|
||||||
layout_and_sync_size();
|
layout_and_sync_size();
|
||||||
update();
|
update();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
m_layout_root = nullptr;
|
|
||||||
|
|
||||||
main_frame().set_document(document);
|
main_frame().set_document(document);
|
||||||
|
|
||||||
if (document)
|
|
||||||
m_layout_root = document->create_layout_tree(document->style_resolver(), nullptr);
|
|
||||||
|
|
||||||
#ifdef HTML_DEBUG
|
#ifdef HTML_DEBUG
|
||||||
if (document != nullptr) {
|
if (document != nullptr) {
|
||||||
dbgprintf("\033[33;1mLayout tree before layout:\033[0m\n");
|
dbgprintf("\033[33;1mLayout tree before layout:\033[0m\n");
|
||||||
::dump_tree(*m_layout_root);
|
::dump_tree(*layout_root());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -73,16 +68,16 @@ void HtmlView::set_document(Document* document)
|
||||||
|
|
||||||
void HtmlView::layout_and_sync_size()
|
void HtmlView::layout_and_sync_size()
|
||||||
{
|
{
|
||||||
if (!m_layout_root)
|
if (!document())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
main_frame().set_size(available_size());
|
main_frame().set_size(available_size());
|
||||||
m_layout_root->layout();
|
document()->layout();
|
||||||
set_content_size(m_layout_root->rect().size());
|
set_content_size(layout_root()->rect().size());
|
||||||
|
|
||||||
#ifdef HTML_DEBUG
|
#ifdef HTML_DEBUG
|
||||||
dbgprintf("\033[33;1mLayout tree after layout:\033[0m\n");
|
dbgprintf("\033[33;1mLayout tree after layout:\033[0m\n");
|
||||||
::dump_tree(*m_layout_root);
|
::dump_tree(*layout_root());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +95,7 @@ void HtmlView::paint_event(GPaintEvent& event)
|
||||||
painter.add_clip_rect(widget_inner_rect());
|
painter.add_clip_rect(widget_inner_rect());
|
||||||
painter.add_clip_rect(event.rect());
|
painter.add_clip_rect(event.rect());
|
||||||
|
|
||||||
if (!m_layout_root) {
|
if (!layout_root()) {
|
||||||
painter.fill_rect(event.rect(), background_color());
|
painter.fill_rect(event.rect(), background_color());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -112,17 +107,17 @@ void HtmlView::paint_event(GPaintEvent& event)
|
||||||
|
|
||||||
RenderingContext context { painter };
|
RenderingContext context { painter };
|
||||||
context.set_should_show_line_box_borders(m_should_show_line_box_borders);
|
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)
|
void HtmlView::mousemove_event(GMouseEvent& event)
|
||||||
{
|
{
|
||||||
if (!m_layout_root)
|
if (!layout_root())
|
||||||
return GScrollableWidget::mousemove_event(event);
|
return GScrollableWidget::mousemove_event(event);
|
||||||
|
|
||||||
bool hovered_node_changed = false;
|
bool hovered_node_changed = false;
|
||||||
bool is_hovering_link = 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) {
|
if (result.layout_node) {
|
||||||
auto* node = result.layout_node->node();
|
auto* node = result.layout_node->node();
|
||||||
hovered_node_changed = node != m_document->hovered_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)
|
void HtmlView::mousedown_event(GMouseEvent& event)
|
||||||
{
|
{
|
||||||
if (!m_layout_root)
|
if (!layout_root())
|
||||||
return GScrollableWidget::mousemove_event(event);
|
return GScrollableWidget::mousemove_event(event);
|
||||||
|
|
||||||
bool hovered_node_changed = false;
|
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) {
|
if (result.layout_node) {
|
||||||
auto* node = result.layout_node->node();
|
auto* node = result.layout_node->node();
|
||||||
hovered_node_changed = node != m_document->hovered_node();
|
hovered_node_changed = node != m_document->hovered_node();
|
||||||
|
@ -205,3 +200,15 @@ void HtmlView::load(const URL& url)
|
||||||
on_title_change(document->title());
|
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());
|
||||||
|
}
|
||||||
|
|
|
@ -15,6 +15,9 @@ public:
|
||||||
const Document* document() const { return m_document; }
|
const Document* document() const { return m_document; }
|
||||||
void set_document(Document*);
|
void set_document(Document*);
|
||||||
|
|
||||||
|
const LayoutDocument* layout_root() const;
|
||||||
|
LayoutDocument* layout_root();
|
||||||
|
|
||||||
Frame& main_frame() { return *m_main_frame; }
|
Frame& main_frame() { return *m_main_frame; }
|
||||||
const Frame& main_frame() const { return *m_main_frame; }
|
const Frame& main_frame() const { return *m_main_frame; }
|
||||||
|
|
||||||
|
@ -42,7 +45,6 @@ private:
|
||||||
|
|
||||||
RefPtr<Frame> m_main_frame;
|
RefPtr<Frame> m_main_frame;
|
||||||
RefPtr<Document> m_document;
|
RefPtr<Document> m_document;
|
||||||
RefPtr<LayoutNode> m_layout_root;
|
|
||||||
|
|
||||||
bool m_should_show_line_box_borders { false };
|
bool m_should_show_line_box_borders { false };
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,7 +17,7 @@ LayoutNode::LayoutNode(const Node* node)
|
||||||
|
|
||||||
LayoutNode::~LayoutNode()
|
LayoutNode::~LayoutNode()
|
||||||
{
|
{
|
||||||
if (m_node)
|
if (m_node && m_node->layout_node() == this)
|
||||||
m_node->set_layout_node({}, nullptr);
|
m_node->set_layout_node({}, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue