mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-05-01 16:58:52 +00:00
LibHTML+Browser: Show target URL of hovered links in Browser statusbar
HtmlView will now invoke the on_link_hover hook when the cursor enters or leaves a DOM node that has an enclosing link element. This patch also updates the meaning of Node::enclosing_link_element() to find the nearest HTMLAnchorElementAncestor *with an href attribute*.
This commit is contained in:
parent
73af2f8d02
commit
884ae80699
Notes:
sideshowbarker
2024-07-19 11:37:36 +09:00
Author: https://github.com/awesomekling
Commit: 884ae80699
6 changed files with 31 additions and 4 deletions
|
@ -105,6 +105,10 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
auto statusbar = GStatusBar::construct(widget);
|
auto statusbar = GStatusBar::construct(widget);
|
||||||
|
|
||||||
|
html_widget->on_link_hover = [&](auto& href) {
|
||||||
|
statusbar->set_text(href);
|
||||||
|
};
|
||||||
|
|
||||||
ResourceLoader::the().on_load_counter_change = [&] {
|
ResourceLoader::the().on_load_counter_change = [&] {
|
||||||
if (ResourceLoader::the().pending_loads() == 0) {
|
if (ResourceLoader::the().pending_loads() == 0) {
|
||||||
statusbar->set_text("");
|
statusbar->set_text("");
|
||||||
|
|
|
@ -31,6 +31,7 @@ public:
|
||||||
|
|
||||||
virtual String tag_name() const final { return m_tag_name; }
|
virtual String tag_name() const final { return m_tag_name; }
|
||||||
|
|
||||||
|
bool has_attribute(const String& name) const { return !attribute(name).is_null(); }
|
||||||
String attribute(const String& name) const;
|
String attribute(const String& name) const;
|
||||||
void set_attribute(const String& name, const String& value);
|
void set_attribute(const String& name, const String& value);
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,11 @@ Node::~Node()
|
||||||
|
|
||||||
const HTMLAnchorElement* Node::enclosing_link_element() const
|
const HTMLAnchorElement* Node::enclosing_link_element() const
|
||||||
{
|
{
|
||||||
return first_ancestor_of_type<HTMLAnchorElement>();
|
for (auto* node = this; node; node = node->parent()) {
|
||||||
|
if (is<HTMLAnchorElement>(*node) && to<HTMLAnchorElement>(*node).has_attribute("href"))
|
||||||
|
return to<HTMLAnchorElement>(node);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const HTMLElement* Node::enclosing_html_element() const
|
const HTMLElement* Node::enclosing_html_element() const
|
||||||
|
@ -76,3 +80,11 @@ void Node::invalidate_style()
|
||||||
});
|
});
|
||||||
document().schedule_style_update();
|
document().schedule_style_update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Node::is_link() const
|
||||||
|
{
|
||||||
|
auto* enclosing_link = enclosing_link_element();
|
||||||
|
if (!enclosing_link)
|
||||||
|
return false;
|
||||||
|
return enclosing_link->has_attribute("href");
|
||||||
|
}
|
||||||
|
|
|
@ -75,6 +75,8 @@ public:
|
||||||
|
|
||||||
void invalidate_style();
|
void invalidate_style();
|
||||||
|
|
||||||
|
bool is_link() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Node(Document&, NodeType);
|
Node(Document&, NodeType);
|
||||||
|
|
||||||
|
|
|
@ -142,16 +142,18 @@ void HtmlView::mousemove_event(GMouseEvent& event)
|
||||||
|
|
||||||
bool hovered_node_changed = false;
|
bool hovered_node_changed = false;
|
||||||
bool is_hovering_link = false;
|
bool is_hovering_link = false;
|
||||||
|
bool was_hovering_link = m_document->hovered_node() && m_document->hovered_node()->is_link();
|
||||||
auto result = layout_root()->hit_test(to_content_position(event.position()));
|
auto result = layout_root()->hit_test(to_content_position(event.position()));
|
||||||
|
const HTMLAnchorElement* hovered_link_element = nullptr;
|
||||||
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();
|
||||||
m_document->set_hovered_node(const_cast<Node*>(node));
|
m_document->set_hovered_node(const_cast<Node*>(node));
|
||||||
if (node) {
|
if (node) {
|
||||||
if (auto* link = node->enclosing_link_element()) {
|
hovered_link_element = node->enclosing_link_element();
|
||||||
UNUSED_PARAM(link);
|
if (hovered_link_element) {
|
||||||
#ifdef HTML_DEBUG
|
#ifdef HTML_DEBUG
|
||||||
dbg() << "HtmlView: hovering over a link to " << link->href();
|
dbg() << "HtmlView: hovering over a link to " << hovered_link_element->href();
|
||||||
#endif
|
#endif
|
||||||
is_hovering_link = true;
|
is_hovering_link = true;
|
||||||
}
|
}
|
||||||
|
@ -169,6 +171,11 @@ void HtmlView::mousemove_event(GMouseEvent& event)
|
||||||
GApplication::the().hide_tooltip();
|
GApplication::the().hide_tooltip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (is_hovering_link != was_hovering_link) {
|
||||||
|
if (on_link_hover) {
|
||||||
|
on_link_hover(hovered_link_element ? m_document->complete_url(hovered_link_element->href()).to_string() : String());
|
||||||
|
}
|
||||||
|
}
|
||||||
event.accept();
|
event.accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ public:
|
||||||
void set_should_show_line_box_borders(bool value) { m_should_show_line_box_borders = value; }
|
void set_should_show_line_box_borders(bool value) { m_should_show_line_box_borders = value; }
|
||||||
|
|
||||||
Function<void(const String&)> on_link_click;
|
Function<void(const String&)> on_link_click;
|
||||||
|
Function<void(const String&)> on_link_hover;
|
||||||
Function<void(const String&)> on_title_change;
|
Function<void(const String&)> on_title_change;
|
||||||
Function<void(const URL&)> on_load_start;
|
Function<void(const URL&)> on_load_start;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue