From ee7282cbe4873f02514d82a368eacd6841eb2ea2 Mon Sep 17 00:00:00 2001 From: Simon Wanner Date: Fri, 2 Jun 2023 22:50:11 +0200 Subject: LibWeb: Make pseudo-elements inspectable This makes it possible to set a pseudo-element as the inspected node using Document::set_inspected_node(), Document then provides inspected_layout_node() for the painting related functions. --- Userland/Libraries/LibWeb/DOM/Document.cpp | 23 ++++++++++++++++------ Userland/Libraries/LibWeb/DOM/Document.h | 5 ++++- .../Libraries/LibWeb/Painting/InlinePaintable.cpp | 4 +--- .../Libraries/LibWeb/Painting/MarkerPaintable.cpp | 2 ++ .../Libraries/LibWeb/Painting/PaintableBox.cpp | 4 ++-- 5 files changed, 26 insertions(+), 12 deletions(-) (limited to 'Userland/Libraries') diff --git a/Userland/Libraries/LibWeb/DOM/Document.cpp b/Userland/Libraries/LibWeb/DOM/Document.cpp index 321525d278..3ed261fd9d 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.cpp +++ b/Userland/Libraries/LibWeb/DOM/Document.cpp @@ -985,18 +985,29 @@ Layout::Viewport* Document::layout_node() return static_cast(Node::layout_node()); } -void Document::set_inspected_node(Node* node) +void Document::set_inspected_node(Node* node, Optional pseudo_element) { - if (m_inspected_node.ptr() == node) + if (m_inspected_node.ptr() == node && m_inspected_pseudo_element == pseudo_element) return; - if (m_inspected_node && m_inspected_node->layout_node()) - m_inspected_node->layout_node()->set_needs_display(); + if (auto layout_node = inspected_layout_node()) + layout_node->set_needs_display(); m_inspected_node = node; + m_inspected_pseudo_element = pseudo_element; - if (m_inspected_node && m_inspected_node->layout_node()) - m_inspected_node->layout_node()->set_needs_display(); + if (auto layout_node = inspected_layout_node()) + layout_node->set_needs_display(); +} + +Layout::Node* Document::inspected_layout_node() +{ + if (!m_inspected_node) + return nullptr; + if (!m_inspected_pseudo_element.has_value() || !m_inspected_node->is_element()) + return m_inspected_node->layout_node(); + auto& element = static_cast(*m_inspected_node); + return element.get_pseudo_element_node(m_inspected_pseudo_element.value()); } static Node* find_common_ancestor(Node* a, Node* b) diff --git a/Userland/Libraries/LibWeb/DOM/Document.h b/Userland/Libraries/LibWeb/DOM/Document.h index 86aa2c6ba3..cacf78351a 100644 --- a/Userland/Libraries/LibWeb/DOM/Document.h +++ b/Userland/Libraries/LibWeb/DOM/Document.h @@ -136,9 +136,11 @@ public: Node* hovered_node() { return m_hovered_node.ptr(); } Node const* hovered_node() const { return m_hovered_node.ptr(); } - void set_inspected_node(Node*); + void set_inspected_node(Node*, Optional); Node* inspected_node() { return m_inspected_node.ptr(); } Node const* inspected_node() const { return m_inspected_node.ptr(); } + Layout::Node* inspected_layout_node(); + Layout::Node const* inspected_layout_node() const { return const_cast(this)->inspected_layout_node(); } Element* document_element(); Element const* document_element() const; @@ -494,6 +496,7 @@ private: JS::GCPtr m_style_sheets; JS::GCPtr m_hovered_node; JS::GCPtr m_inspected_node; + Optional m_inspected_pseudo_element; JS::GCPtr m_active_favicon; WeakPtr m_browsing_context; AK::URL m_url; diff --git a/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp b/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp index 7421982e7c..3766eb7d12 100644 --- a/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/InlinePaintable.cpp @@ -114,9 +114,7 @@ void InlinePaintable::paint(PaintContext& context, PaintPhase phase) const }); } - // FIXME: We check for a non-null dom_node(), since pseudo-elements have a null one and were getting - // highlighted incorrectly. A better solution will be needed if we want to inspect them too. - if (phase == PaintPhase::Overlay && layout_node().dom_node() && layout_node().document().inspected_node() == layout_node().dom_node()) { + if (phase == PaintPhase::Overlay && layout_node().document().inspected_layout_node() == &layout_node()) { // FIXME: This paints a double-thick border between adjacent fragments, where ideally there // would be none. Once we implement non-rectangular outlines for the `outline` CSS // property, we can use that here instead. diff --git a/Userland/Libraries/LibWeb/Painting/MarkerPaintable.cpp b/Userland/Libraries/LibWeb/Painting/MarkerPaintable.cpp index 106506478c..aeef6b50fd 100644 --- a/Userland/Libraries/LibWeb/Painting/MarkerPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/MarkerPaintable.cpp @@ -30,6 +30,8 @@ constexpr float sin_60_deg = 0.866025403f; void MarkerPaintable::paint(PaintContext& context, PaintPhase phase) const { + if (phase == PaintPhase::Overlay) + PaintableBox::paint(context, phase); if (phase != PaintPhase::Foreground) return; diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp index 4583936d0a..423d96fac7 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -169,7 +169,7 @@ void PaintableBox::paint(PaintContext& context, PaintPhase phase) const if (phase == PaintPhase::Overlay && should_clip_rect) context.painter().restore(); - if (phase == PaintPhase::Overlay && layout_box().dom_node() && layout_box().document().inspected_node() == layout_box().dom_node()) { + if (phase == PaintPhase::Overlay && layout_box().document().inspected_layout_node() == &layout_box()) { auto content_rect = absolute_rect(); auto margin_box = box_model().margin_box(); @@ -511,7 +511,7 @@ static void paint_text_fragment(PaintContext& context, Layout::TextNode const& t auto fragment_absolute_rect = fragment.absolute_rect(); auto fragment_absolute_device_rect = context.enclosing_device_rect(fragment_absolute_rect); - if (text_node.document().inspected_node() == &text_node.dom_node()) + if (text_node.document().inspected_layout_node() == &text_node) context.painter().draw_rect(fragment_absolute_device_rect.to_type(), Color::Magenta); auto text = text_node.text_for_rendering(); -- cgit v1.2.3