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()) {