LibWeb: Defer updating hovered node until end of mouse event handling

Updating the hovered node may fire events, and so we can't assume the
layout and paintable nodes we've found via hit testing will be valid
after doing it.
This commit is contained in:
Andreas Kling 2025-08-02 14:56:57 +02:00 committed by Andreas Kling
commit b60d465029
Notes: github-actions[bot] 2025-08-05 09:30:55 +00:00

View file

@ -608,6 +608,10 @@ EventResult EventHandler::handle_mousedown(CSSPixelPoint viewport_position, CSSP
GC::Ref<DOM::Document> document = *m_navigable->active_document(); GC::Ref<DOM::Document> document = *m_navigable->active_document();
GC::Ptr<DOM::Node> node; GC::Ptr<DOM::Node> node;
ScopeGuard update_hovered_node_guard = [&node, &document] {
document->set_hovered_node(node);
};
{ {
GC::Ptr<Painting::Paintable> paintable; GC::Ptr<Painting::Paintable> paintable;
if (auto result = target_for_mouse_position(viewport_position); result.has_value()) if (auto result = target_for_mouse_position(viewport_position); result.has_value())
@ -620,7 +624,6 @@ EventResult EventHandler::handle_mousedown(CSSPixelPoint viewport_position, CSSP
VERIFY(pointer_events != CSS::PointerEvents::None); VERIFY(pointer_events != CSS::PointerEvents::None);
node = dom_node_for_event_dispatch(*paintable); node = dom_node_for_event_dispatch(*paintable);
document->set_hovered_node(node);
if (paintable->wants_mouse_events()) { if (paintable->wants_mouse_events()) {
if (paintable->handle_mousedown({}, viewport_position, button, modifiers) == Painting::Paintable::DispatchEventOfSameName::No) if (paintable->handle_mousedown({}, viewport_position, button, modifiers) == Painting::Paintable::DispatchEventOfSameName::No)
@ -745,18 +748,25 @@ EventResult EventHandler::handle_mousemove(CSSPixelPoint viewport_position, CSSP
start_index = result->index_in_node; start_index = result->index_in_node;
} }
GC::Ptr<DOM::Node> node;
ScopeGuard update_hovered_node_guard = [&node, &document] {
document.set_hovered_node(node);
};
GC::Ptr<HTML::HTMLAnchorElement const> hovered_link_element; GC::Ptr<HTML::HTMLAnchorElement const> hovered_link_element;
if (paintable) { if (paintable) {
if (paintable->wants_mouse_events()) { if (paintable->wants_mouse_events()) {
document.set_hovered_node(paintable->dom_node()); if (paintable->handle_mousemove({}, viewport_position, buttons, modifiers) == Painting::Paintable::DispatchEventOfSameName::No) {
if (paintable->handle_mousemove({}, viewport_position, buttons, modifiers) == Painting::Paintable::DispatchEventOfSameName::No) node = paintable->dom_node();
return EventResult::Cancelled; return EventResult::Cancelled;
}
// FIXME: It feels a bit aggressive to always update the cursor like this. // FIXME: It feels a bit aggressive to always update the cursor like this.
m_navigable->page().client().page_did_request_cursor_change(Gfx::StandardCursor::None); m_navigable->page().client().page_did_request_cursor_change(Gfx::StandardCursor::None);
} }
auto node = dom_node_for_event_dispatch(*paintable); node = dom_node_for_event_dispatch(*paintable);
if (node && is<HTML::HTMLIFrameElement>(*node)) { if (node && is<HTML::HTMLIFrameElement>(*node)) {
if (auto content_navigable = static_cast<HTML::HTMLIFrameElement&>(*node).content_navigable()) if (auto content_navigable = static_cast<HTML::HTMLIFrameElement&>(*node).content_navigable())
@ -775,7 +785,6 @@ EventResult EventHandler::handle_mousemove(CSSPixelPoint viewport_position, CSSP
GC::Ptr<Layout::Node> layout_node; GC::Ptr<Layout::Node> layout_node;
bool found_parent_element = parent_element_for_event_dispatch(*paintable, node, layout_node); bool found_parent_element = parent_element_for_event_dispatch(*paintable, node, layout_node);
hovered_node_changed = node.ptr() != document.hovered_node(); hovered_node_changed = node.ptr() != document.hovered_node();
document.set_hovered_node(node);
if (found_parent_element) { if (found_parent_element) {
hovered_link_element = node->enclosing_link_element(); hovered_link_element = node->enclosing_link_element();
if (hovered_link_element) if (hovered_link_element)