click event does not dispatch to parent when child target stops hit testing after...
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 17 Jul 2017 19:14:12 +0000 (19:14 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 17 Jul 2017 19:14:12 +0000 (19:14 +0000)
https://bugs.webkit.org/show_bug.cgi?id=174564
<rdar://problem/33340234>

Reviewed by Simon Fraser.

Source/WebCore:

As per [1], if the mouse down node and the mouse release node differ, then we are supposed to
fire the click event at their common ancestor, if such node exists. This patch implements this
logic. This also aligns our behavior with Blink.

[1] https://w3c.github.io/uievents/#events-mouseevent-event-order

Test: fast/events/mouse-click-different-mouseDown-mouseUp-nodes.html

* page/EventHandler.cpp:
(WebCore::targetNodeForClickEvent):

LayoutTests:

Add layout test coverage.

* fast/events/mouse-click-different-mouseDown-mouseUp-nodes-expected.txt: Added.
* fast/events/mouse-click-different-mouseDown-mouseUp-nodes.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@219568 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/events/mouse-click-different-mouseDown-mouseUp-nodes-expected.txt [new file with mode: 0644]
LayoutTests/fast/events/mouse-click-different-mouseDown-mouseUp-nodes.html [new file with mode: 0644]
LayoutTests/platform/ios/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/page/EventHandler.cpp

index bf991f6ca53fb8111f8e0cf6d02a1979e9cc9e37..cadbf6c0b3c7cffdc3999edacc70592bab87bfcd 100644 (file)
@@ -1,3 +1,16 @@
+2017-07-17  Chris Dumez  <cdumez@apple.com>
+
+        click event does not dispatch to parent when child target stops hit testing after mousedown
+        https://bugs.webkit.org/show_bug.cgi?id=174564
+        <rdar://problem/33340234>
+
+        Reviewed by Simon Fraser.
+
+        Add layout test coverage.
+
+        * fast/events/mouse-click-different-mouseDown-mouseUp-nodes-expected.txt: Added.
+        * fast/events/mouse-click-different-mouseDown-mouseUp-nodes.html: Added.
+
 2017-07-17  Antoine Quint  <graouts@apple.com>
 
         REGRESSION: order of AirPlay and volume controls is inconsistent between <audio> and <video>
diff --git a/LayoutTests/fast/events/mouse-click-different-mouseDown-mouseUp-nodes-expected.txt b/LayoutTests/fast/events/mouse-click-different-mouseDown-mouseUp-nodes-expected.txt
new file mode 100644 (file)
index 0000000..e96c15a
--- /dev/null
@@ -0,0 +1,11 @@
+Tests that the click event is fired at the common ancestor if the mouseDown / mouseUp nodes differ.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS parentGotClickEvent is true
+PASS childGotClickEvent is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/events/mouse-click-different-mouseDown-mouseUp-nodes.html b/LayoutTests/fast/events/mouse-click-different-mouseDown-mouseUp-nodes.html
new file mode 100644 (file)
index 0000000..eccbb1b
--- /dev/null
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../resources/js-test.js"></script>
+<style>
+    div {
+        position: absolute;
+        top: 0;
+        left: 0;
+        width: 100%;
+        height: 100%;
+    }
+
+    .button {
+        background-color: blue;
+    }
+
+    .icon {
+        background-color: black;
+    }
+
+    .button:active .icon {
+        transform: scale(0.25);
+    }
+</style>
+</head>
+<body>
+<div id="parentDiv" class="button" onclick="alert('clicked')">
+    <div id="childDiv" class="icon"></div>
+</div>
+<script>
+description("Tests that the click event is fired at the common ancestor if the mouseDown / mouseUp nodes differ.");
+jsTestIsAsync = true;
+
+parentGotClickEvent = false;
+childGotClickEvent = false;
+
+document.getElementById("parentDiv").onclick = function() {
+    parentGotClickEvent = true;
+};
+
+document.getElementById("childDiv").onclick = function() {
+    childGotClickEvent = true;
+};
+
+onload = function() {
+    if (window.eventSender) {
+        eventSender.mouseMoveTo(10, 300);
+        eventSender.mouseDown();
+        eventSender.mouseUp();    
+    }
+
+    setTimeout(function() {
+        shouldBeTrue("parentGotClickEvent");
+        shouldBeFalse("childGotClickEvent");
+        finishJSTest();
+    }, 0);
+}
+</script>
+</body>
+</html>
index 973d5eae9407bf76d90371522db5de3c21f2902d..6be7c408ac4da1ecb2034d4844d2192dd78fbc42 100644 (file)
@@ -387,6 +387,7 @@ fast/forms/range/disabled-while-dragging.html [ Skip ]
 fast/forms/range/range-drag-when-toggled-disabled.html [ Skip ]
 fast/media/video-element-in-details-collapse.html [ Skip ]
 fast/frames/user-gesture-timestamp-propagation.html [ Failure ]
+fast/events/mouse-click-different-mouseDown-mouseUp-nodes.html [ Skip ]
 
 # The file-wrapper part of <attachment> is not yet working on iOS
 fast/attachment/attachment-type-attribute.html [ Skip ]
index e8f1113a088248928263a7ccb8cc6cfebc47ebae..bf4926c41719a84d18629b3fe3ff147eaad04b9a 100644 (file)
@@ -1,3 +1,22 @@
+2017-07-17  Chris Dumez  <cdumez@apple.com>
+
+        click event does not dispatch to parent when child target stops hit testing after mousedown
+        https://bugs.webkit.org/show_bug.cgi?id=174564
+        <rdar://problem/33340234>
+
+        Reviewed by Simon Fraser.
+
+        As per [1], if the mouse down node and the mouse release node differ, then we are supposed to
+        fire the click event at their common ancestor, if such node exists. This patch implements this
+        logic. This also aligns our behavior with Blink.
+
+        [1] https://w3c.github.io/uievents/#events-mouseevent-event-order
+
+        Test: fast/events/mouse-click-different-mouseDown-mouseUp-nodes.html
+
+        * page/EventHandler.cpp:
+        (WebCore::targetNodeForClickEvent):
+
 2017-07-17  Brady Eidson  <beidson@apple.com>
 
         WKHTTPCookieStore observing only works on the default cookie store.
index e97842980d5193cddfcc63bd06789974c9a567d0..617b325a30cd77e8658cf22c5c4d15cb960220f6 100644 (file)
@@ -70,6 +70,7 @@
 #include "PlatformKeyboardEvent.h"
 #include "PlatformWheelEvent.h"
 #include "PluginDocument.h"
+#include "Range.h"
 #include "RenderFrameSet.h"
 #include "RenderLayer.h"
 #include "RenderListBox.h"
@@ -1999,6 +2000,12 @@ static Node* targetNodeForClickEvent(Node* mousePressNode, Node* mouseReleaseNod
     if (mousePressNode == mouseReleaseNode)
         return mouseReleaseNode;
 
+    // If mousePressNode and mouseReleaseNode differ, we should fire the event at their common ancestor if there is one.
+    if (&mousePressNode->document() == &mouseReleaseNode->document()) {
+        if (auto* commonAncestor = Range::commonAncestorContainer(mousePressNode, mouseReleaseNode))
+            return commonAncestor;
+    }
+
     Element* mouseReleaseShadowHost = mouseReleaseNode->shadowHost();
     if (mouseReleaseShadowHost && mouseReleaseShadowHost == mousePressNode->shadowHost()) {
         // We want to dispatch the click to the shadow tree host element to give listeners the illusion that the