diff --git a/Libraries/LibHTML/DOM/HTMLElement.h b/Libraries/LibHTML/DOM/HTMLElement.h index 4e0c56beff..a366eb9ea0 100644 --- a/Libraries/LibHTML/DOM/HTMLElement.h +++ b/Libraries/LibHTML/DOM/HTMLElement.h @@ -6,4 +6,9 @@ class HTMLElement : public Element { public: HTMLElement(Document&, const String& tag_name); virtual ~HTMLElement() override; + + String title() const { return attribute("title"); } + +private: + virtual bool is_html_element() const final { return true; } }; diff --git a/Libraries/LibHTML/DOM/Node.cpp b/Libraries/LibHTML/DOM/Node.cpp index 5f527020b8..0126f4c13d 100644 --- a/Libraries/LibHTML/DOM/Node.cpp +++ b/Libraries/LibHTML/DOM/Node.cpp @@ -81,3 +81,10 @@ const HTMLAnchorElement* Node::enclosing_link_element() const return static_cast(this); return parent() ? parent()->enclosing_link_element() : nullptr; } + +const HTMLElement* Node::enclosing_html_element() const +{ + if (is_html_element()) + return static_cast(this); + return parent() ? parent()->enclosing_html_element() : nullptr; +} diff --git a/Libraries/LibHTML/DOM/Node.h b/Libraries/LibHTML/DOM/Node.h index 2096b0dafb..24bbf9f0ad 100644 --- a/Libraries/LibHTML/DOM/Node.h +++ b/Libraries/LibHTML/DOM/Node.h @@ -14,6 +14,7 @@ enum class NodeType : unsigned { }; class Document; +class HTMLElement; class HTMLAnchorElement; class ParentNode; class LayoutNode; @@ -39,6 +40,9 @@ public: const Document& document() const { return m_document; } const HTMLAnchorElement* enclosing_link_element() const; + const HTMLElement* enclosing_html_element() const; + + virtual bool is_html_element() const { return false; } protected: Node(Document&, NodeType); diff --git a/Libraries/LibHTML/HtmlView.cpp b/Libraries/LibHTML/HtmlView.cpp index ed3511e1fa..98e1cf98be 100644 --- a/Libraries/LibHTML/HtmlView.cpp +++ b/Libraries/LibHTML/HtmlView.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -90,8 +91,8 @@ void HtmlView::mousemove_event(GMouseEvent& event) auto result = m_layout_root->hit_test(event.position()); if (result.layout_node) { auto* node = result.layout_node->node(); + hovered_node_changed = node != m_document->hovered_node(); m_document->set_hovered_node(const_cast(node)); - hovered_node_changed = node == m_document->hovered_node(); if (node) { dbg() << "HtmlView: mousemove: " << node->tag_name() << "{" << node << "}"; if (auto* link = node->enclosing_link_element()) { @@ -99,8 +100,16 @@ void HtmlView::mousemove_event(GMouseEvent& event) } } } - if (hovered_node_changed) + if (hovered_node_changed) { update(); + auto* hovered_html_element = m_document->hovered_node() ? m_document->hovered_node()->enclosing_html_element() : nullptr; + if (hovered_html_element && !hovered_html_element->title().is_null()) { + auto screen_position = screen_relative_rect().location().translated(event.position()); + GApplication::the().show_tooltip(hovered_html_element->title(), screen_position.translated(4, 4)); + } else { + GApplication::the().hide_tooltip(); + } + } event.accept(); } @@ -113,8 +122,8 @@ void HtmlView::mousedown_event(GMouseEvent& event) auto result = m_layout_root->hit_test(event.position()); if (result.layout_node) { auto* node = result.layout_node->node(); + hovered_node_changed = node != m_document->hovered_node(); m_document->set_hovered_node(const_cast(node)); - hovered_node_changed = node == m_document->hovered_node(); if (node) { dbg() << "HtmlView: mousedown: " << node->tag_name() << "{" << node << "}"; if (auto* link = node->enclosing_link_element()) {