Parcourir la source

LibWeb: Try harder to find a suitable DOM node for mouse event dispatch

Since our hit testing mechanism gives you the Paintable under the mouse
cursor, we can't just give up if that paintable doesn't have a
corresponding DOM node. That meant that generated content like pseudo-
elements didn't generate mouse events at all.

Fix this by making a dom_node_for_event_dispatch() helper function that
finds a suitable DOM node when given a paintable. This first cut is very
naive, and there's probably more we should do, but we have to start
somewhere. :^)
Andreas Kling il y a 2 ans
Parent
commit
29c6aabf49
1 fichiers modifiés avec 16 ajouts et 15 suppressions
  1. 16 15
      Userland/Libraries/LibWeb/Page/EventHandler.cpp

+ 16 - 15
Userland/Libraries/LibWeb/Page/EventHandler.cpp

@@ -23,6 +23,17 @@
 
 namespace Web {
 
+static JS::GCPtr<DOM::Node> dom_node_for_event_dispatch(Painting::Paintable const& paintable)
+{
+    if (auto node = paintable.mouse_event_target())
+        return node;
+    if (auto node = paintable.dom_node())
+        return node;
+    if (auto* layout_parent = paintable.layout_node().parent())
+        return layout_parent->dom_node();
+    return nullptr;
+}
+
 static Gfx::StandardCursor cursor_css_to_gfx(Optional<CSS::Cursor> cursor)
 {
     if (!cursor.has_value()) {
@@ -147,9 +158,7 @@ bool EventHandler::handle_mousewheel(Gfx::IntPoint const& position, unsigned but
     if (paintable) {
         paintable->handle_mousewheel({}, position, buttons, modifiers, wheel_delta_x, wheel_delta_y);
 
-        JS::GCPtr<DOM::Node> node = paintable->mouse_event_target();
-        if (!node)
-            node = paintable->dom_node();
+        auto node = dom_node_for_event_dispatch(*paintable);
 
         if (node) {
             // FIXME: Support wheel events in nested browsing contexts.
@@ -211,9 +220,7 @@ bool EventHandler::handle_mouseup(Gfx::IntPoint const& position, unsigned button
     }
 
     if (paintable) {
-        JS::GCPtr<DOM::Node> node = paintable->mouse_event_target();
-        if (!node)
-            node = paintable->dom_node();
+        auto node = dom_node_for_event_dispatch(*paintable);
 
         if (node) {
             if (is<HTML::HTMLIFrameElement>(*node)) {
@@ -328,9 +335,7 @@ bool EventHandler::handle_mousedown(Gfx::IntPoint const& position, unsigned butt
         // FIXME: Handle other values for pointer-events.
         VERIFY(pointer_events != CSS::PointerEvents::None);
 
-        node = paintable->mouse_event_target();
-        if (!node)
-            node = paintable->dom_node();
+        node = dom_node_for_event_dispatch(*paintable);
         document->set_hovered_node(node);
 
         if (paintable->wants_mouse_events()) {
@@ -434,9 +439,7 @@ bool EventHandler::handle_mousemove(Gfx::IntPoint const& position, unsigned butt
                 page->client().page_did_request_cursor_change(Gfx::StandardCursor::None);
         }
 
-        JS::GCPtr<DOM::Node> node = paintable->mouse_event_target();
-        if (!node)
-            node = paintable->dom_node();
+        auto node = dom_node_for_event_dispatch(*paintable);
 
         if (node && is<HTML::HTMLIFrameElement>(*node)) {
             if (auto* nested_browsing_context = static_cast<HTML::HTMLIFrameElement&>(*node).nested_browsing_context())
@@ -543,9 +546,7 @@ bool EventHandler::handle_doubleclick(Gfx::IntPoint const& position, unsigned bu
     if (pointer_events == CSS::PointerEvents::None)
         return false;
 
-    JS::GCPtr<DOM::Node> node = paintable->mouse_event_target();
-    if (!node)
-        node = paintable->dom_node();
+    auto node = dom_node_for_event_dispatch(*paintable);
 
     if (paintable->wants_mouse_events()) {
         // FIXME: Handle double clicks.