Title: [136918] trunk
Revision
136918
Author
hay...@chromium.org
Date
2012-12-06 19:03:26 -0800 (Thu, 06 Dec 2012)

Log Message

Event's relatedTarget re-targeting does not occur for manually fired mouse events created by event.initMouseEvent().
https://bugs.webkit.org/show_bug.cgi?id=102681

Reviewed by Dimitri Glazkov.

Source/WebCore:

Make sure that event's relatedTarget re-targeting occurs for mouse
events created by event.initMouseEvent().  Since user-generated
mouse events can have a relatedTarget which is same to the target
node, the algorithm which calculates event's ancestors is also
updated so that ancestors are not shrunk wrongly.

Test: fast/events/dispatch-synthetic-mouseevent.html
      fast/dom/shadow/shadow-dom-event-dispatching.html

* dom/EventDispatcher.cpp:
(WebCore::EventRelatedTargetAdjuster::adjust):
* dom/MouseEvent.cpp:
(WebCore::MouseEventDispatchMediator::create):
(WebCore::MouseEventDispatchMediator::MouseEventDispatchMediator):
(WebCore::MouseEventDispatchMediator::dispatchEvent):
* dom/MouseEvent.h:
(WebCore::MouseEventDispatchMediator::isSyntheticMouseEvent):
(MouseEventDispatchMediator):
* dom/Node.cpp:
(WebCore::Node::dispatchEvent):

LayoutTests:

* fast/dom/shadow/shadow-dom-event-dispatching-expected.txt:
* fast/dom/shadow/shadow-dom-event-dispatching.html:
* fast/events/dispatch-synthetic-mouseevent-expected.txt: Added.
* fast/events/dispatch-synthetic-mouseevent.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (136917 => 136918)


--- trunk/LayoutTests/ChangeLog	2012-12-07 02:57:21 UTC (rev 136917)
+++ trunk/LayoutTests/ChangeLog	2012-12-07 03:03:26 UTC (rev 136918)
@@ -1,3 +1,15 @@
+2012-12-06  Hayato Ito  <hay...@chromium.org>
+
+        Event's relatedTarget re-targeting does not occur for manually fired mouse events created by event.initMouseEvent().
+        https://bugs.webkit.org/show_bug.cgi?id=102681
+
+        Reviewed by Dimitri Glazkov.
+
+        * fast/dom/shadow/shadow-dom-event-dispatching-expected.txt:
+        * fast/dom/shadow/shadow-dom-event-dispatching.html:
+        * fast/events/dispatch-synthetic-mouseevent-expected.txt: Added.
+        * fast/events/dispatch-synthetic-mouseevent.html: Added.
+
 2012-12-06  Kunihiko Sakamoto  <ksakam...@chromium.org>
 
         Disabled file input box stops a certain other div from being rendered

Modified: trunk/LayoutTests/fast/dom/shadow/shadow-dom-event-dispatching-expected.txt (136917 => 136918)


--- trunk/LayoutTests/fast/dom/shadow/shadow-dom-event-dispatching-expected.txt	2012-12-07 02:57:21 UTC (rev 136917)
+++ trunk/LayoutTests/fast/dom/shadow/shadow-dom-event-dispatching-expected.txt	2012-12-07 03:03:26 UTC (rev 136918)
@@ -435,6 +435,35 @@
      @shadow-root (target: non-used-fallback)
      @A (target: A)
      @top (target: A)
+
+
+Composed Shadow Tree will be:
+DIV	 id=sandbox
+	DIV	 id=top
+		DIV	 id=host
+			DIV	 id=div1
+			DIV	 id=div2
+
+
+  mouseout
+
+  mouseover
+     @div2 (target: div2) (related: div1)
+     @shadow-root (target: div2) (related: div1)
+
+
+Composed Shadow Tree will be:
+DIV	 id=sandbox
+	DIV	 id=top
+		DIV	 id=host
+			DIV	 id=div1
+
+
+  mouseout
+
+  mouseover
+     @div1 (target: div1) (related: div1)
+     @shadow-root (target: div1) (related: div1)
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/fast/dom/shadow/shadow-dom-event-dispatching.html (136917 => 136918)


--- trunk/LayoutTests/fast/dom/shadow/shadow-dom-event-dispatching.html	2012-12-07 02:57:21 UTC (rev 136917)
+++ trunk/LayoutTests/fast/dom/shadow/shadow-dom-event-dispatching.html	2012-12-07 03:03:26 UTC (rev 136918)
@@ -378,6 +378,58 @@
     debugDispatchedEvent('click');
 }
 
+function testEventsFiredManually()
+{
+    sandbox.innerHTML = '';
+    sandbox.appendChild(
+        createDOM('div', {'id': 'top'},
+                  createDOM('div', {'id': 'host'},
+                            createShadowRoot(
+                                createDOM('div', {'id': 'div1'}),
+                                createDOM('div', {'id': 'div2'})))));
+
+    addEventListeners(['top', 'host', 'host/', 'host/div1', 'host/div2']);
+    getNodeInShadowTreeStack('host/').id = 'shadow-root';
+    showSandboxTree();
+
+    var div1 = getNodeInShadowTreeStack('host/div1');
+    var div2 = getNodeInShadowTreeStack('host/div2');
+
+    clearEventRecords();
+    var event = document.createEvent("MouseEvents");
+    event.initMouseEvent("mouseover", true, false, window,
+                         0, 10, 10, 10, 10, false, false, false, false, 0, div1);
+    div2.dispatchEvent(event);
+
+    debugDispatchedEvent('mouseout');
+    debugDispatchedEvent('mouseover');
+}
+
+function testEventsFiredManuallyWithRelatedTargetSameToTarget()
+{
+    sandbox.innerHTML = '';
+    sandbox.appendChild(
+        createDOM('div', {'id': 'top'},
+                  createDOM('div', {'id': 'host'},
+                            createShadowRoot(
+                                createDOM('div', {'id': 'div1'})))));
+
+    addEventListeners(['top', 'host', 'host/', 'host/div1']);
+    getNodeInShadowTreeStack('host/').id = 'shadow-root';
+    showSandboxTree();
+
+    var div1 = getNodeInShadowTreeStack('host/div1');
+
+    clearEventRecords();
+    var event = document.createEvent("MouseEvents");
+    event.initMouseEvent("mouseover", true, false, window,
+                         0, 10, 10, 10, 10, false, false, false, false, 0, div1);
+    div1.dispatchEvent(event);
+
+    debugDispatchedEvent('mouseout');
+    debugDispatchedEvent('mouseover');
+}
+
 function test()
 {
     if (window.testRunner)
@@ -393,6 +445,8 @@
     testEventsOnMultipleShadowRoots();
     testEventsOnNonDistributedNodes();
     testEventsOnFallbackElements();
+    testEventsFiredManually();
+    testEventsFiredManuallyWithRelatedTargetSameToTarget();
 }
 
 test();

Added: trunk/LayoutTests/fast/events/dispatch-synthetic-mouseevent-expected.txt (0 => 136918)


--- trunk/LayoutTests/fast/events/dispatch-synthetic-mouseevent-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/events/dispatch-synthetic-mouseevent-expected.txt	2012-12-07 03:03:26 UTC (rev 136918)
@@ -0,0 +1,10 @@
+Tests to ensure that dblclick event is not fired.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+click event is fired.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/events/dispatch-synthetic-mouseevent.html (0 => 136918)


--- trunk/LayoutTests/fast/events/dispatch-synthetic-mouseevent.html	                        (rev 0)
+++ trunk/LayoutTests/fast/events/dispatch-synthetic-mouseevent.html	2012-12-07 03:03:26 UTC (rev 136918)
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<p id="description"></p>
+<div id='top'>
+</div>
+<pre id="console"></pre>
+<script>
+description("Tests to ensure that dblclick event is not fired.");
+
+function clickHandler(event)
+{
+    debug('click event is fired.');
+}
+
+function dblclickHandler(event)
+{
+    testFailed('dblclick event should not be fired.');
+}
+
+function test()
+{
+    if (window.testRunner)
+        testRunner.dumpAsText();
+
+    var node = document.getElementById('top');
+    node.addEventListener('click', clickHandler, false);
+    node.addEventListener('dblclick', dblclickHandler, false);
+
+    var event = document.createEvent("MouseEvents");
+    var details = 2;
+    event.initMouseEvent("click", true, false, window,
+                         details, 10, 10, 10, 10, false, false, false, false, 0, null);
+    node.dispatchEvent(event);
+}
+
+test();
+</script>
+<script src=""
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (136917 => 136918)


--- trunk/Source/WebCore/ChangeLog	2012-12-07 02:57:21 UTC (rev 136917)
+++ trunk/Source/WebCore/ChangeLog	2012-12-07 03:03:26 UTC (rev 136918)
@@ -1,3 +1,31 @@
+2012-12-06  Hayato Ito  <hay...@chromium.org>
+
+        Event's relatedTarget re-targeting does not occur for manually fired mouse events created by event.initMouseEvent().
+        https://bugs.webkit.org/show_bug.cgi?id=102681
+
+        Reviewed by Dimitri Glazkov.
+
+        Make sure that event's relatedTarget re-targeting occurs for mouse
+        events created by event.initMouseEvent().  Since user-generated
+        mouse events can have a relatedTarget which is same to the target
+        node, the algorithm which calculates event's ancestors is also
+        updated so that ancestors are not shrunk wrongly.
+
+        Test: fast/events/dispatch-synthetic-mouseevent.html
+              fast/dom/shadow/shadow-dom-event-dispatching.html
+
+        * dom/EventDispatcher.cpp:
+        (WebCore::EventRelatedTargetAdjuster::adjust):
+        * dom/MouseEvent.cpp:
+        (WebCore::MouseEventDispatchMediator::create):
+        (WebCore::MouseEventDispatchMediator::MouseEventDispatchMediator):
+        (WebCore::MouseEventDispatchMediator::dispatchEvent):
+        * dom/MouseEvent.h:
+        (WebCore::MouseEventDispatchMediator::isSyntheticMouseEvent):
+        (MouseEventDispatchMediator):
+        * dom/Node.cpp:
+        (WebCore::Node::dispatchEvent):
+
 2012-12-06  Kunihiko Sakamoto  <ksakam...@chromium.org>
 
         Disabled file input box stops a certain other div from being rendered

Modified: trunk/Source/WebCore/dom/EventDispatcher.cpp (136917 => 136918)


--- trunk/Source/WebCore/dom/EventDispatcher.cpp	2012-12-07 02:57:21 UTC (rev 136917)
+++ trunk/Source/WebCore/dom/EventDispatcher.cpp	2012-12-07 03:03:26 UTC (rev 136918)
@@ -62,6 +62,9 @@
 
 void EventRelatedTargetAdjuster::adjust(Vector<EventContext>& ancestors)
 {
+    // Synthetic mouse events can have a relatedTarget which is identical to the target.
+    bool targetIsIdenticalToToRelatedTarget = (m_node.get() == m_relatedTarget.get());
+
     Vector<EventTarget*> relatedTargetStack;
     TreeScope* lastTreeScope = 0;
     for (AncestorChainWalker walker(m_relatedTarget.get()); walker.get(); walker.parent()) {
@@ -93,7 +96,12 @@
             iter->setRelatedTarget(adjustedRelatedTarget);
         }
         lastTreeScope = scope;
-        if (iter->target() == adjustedRelatedTarget) {
+        if (targetIsIdenticalToToRelatedTarget) {
+            if (m_node->treeScope()->rootNode() == iter->node()) {
+                ancestors.shrink(iter + 1 - ancestors.begin());
+                break;
+            }
+        } else if (iter->target() == adjustedRelatedTarget) {
             // Event dispatching should be stopped here.
             ancestors.shrink(iter - ancestors.begin());
             break;

Modified: trunk/Source/WebCore/dom/MouseEvent.cpp (136917 => 136918)


--- trunk/Source/WebCore/dom/MouseEvent.cpp	2012-12-07 02:57:21 UTC (rev 136917)
+++ trunk/Source/WebCore/dom/MouseEvent.cpp	2012-12-07 03:03:26 UTC (rev 136918)
@@ -209,13 +209,13 @@
     }
 }
 
-PassRefPtr<MouseEventDispatchMediator> MouseEventDispatchMediator::create(PassRefPtr<MouseEvent> mouseEvent)
+PassRefPtr<MouseEventDispatchMediator> MouseEventDispatchMediator::create(PassRefPtr<MouseEvent> mouseEvent, MouseEventType mouseEventType)
 {
-    return adoptRef(new MouseEventDispatchMediator(mouseEvent));
+    return adoptRef(new MouseEventDispatchMediator(mouseEvent, mouseEventType));
 }
 
-MouseEventDispatchMediator::MouseEventDispatchMediator(PassRefPtr<MouseEvent> mouseEvent)
-    : EventDispatchMediator(mouseEvent)
+MouseEventDispatchMediator::MouseEventDispatchMediator(PassRefPtr<MouseEvent> mouseEvent, MouseEventType mouseEventType)
+    : EventDispatchMediator(mouseEvent), m_mouseEventType(mouseEventType)
 {
 }
 
@@ -226,12 +226,19 @@
 
 bool MouseEventDispatchMediator::dispatchEvent(EventDispatcher* dispatcher) const
 {
+    if (isSyntheticMouseEvent()) {
+        dispatcher->adjustRelatedTarget(event(), event()->relatedTarget());
+        return dispatcher->dispatchEvent(event());
+    }
+
     if (dispatcher->node()->disabled()) // Don't even send DOM events for disabled controls..
         return false;
 
     if (event()->type().isEmpty())
         return true; // Shouldn't happen.
 
+    ASSERT(!event()->target() || event()->target() != event()->relatedTarget());
+
     EventTarget* relatedTarget = event()->relatedTarget();
     dispatcher->adjustRelatedTarget(event(), relatedTarget);
 
@@ -240,6 +247,7 @@
 
     if (event()->type() != eventNames().clickEvent || event()->detail() != 2)
         return !swallowEvent;
+
     // Special case: If it's a double click event, we also send the dblclick event. This is not part
     // of the DOM specs, but is used for compatibility with the _ondblclick_="" attribute. This is treated
     // as a separate event in other DOM-compliant browsers like Firefox, and so we do the same.

Modified: trunk/Source/WebCore/dom/MouseEvent.h (136917 => 136918)


--- trunk/Source/WebCore/dom/MouseEvent.h	2012-12-07 02:57:21 UTC (rev 136917)
+++ trunk/Source/WebCore/dom/MouseEvent.h	2012-12-07 03:03:26 UTC (rev 136918)
@@ -115,13 +115,16 @@
 
 class MouseEventDispatchMediator : public EventDispatchMediator {
 public:
-    static PassRefPtr<MouseEventDispatchMediator> create(PassRefPtr<MouseEvent>);
+    enum MouseEventType { SyntheticMouseEvent, NonSyntheticMouseEvent};
+    static PassRefPtr<MouseEventDispatchMediator> create(PassRefPtr<MouseEvent>, MouseEventType = NonSyntheticMouseEvent);
 
 private:
-    explicit MouseEventDispatchMediator(PassRefPtr<MouseEvent>);
+    explicit MouseEventDispatchMediator(PassRefPtr<MouseEvent>, MouseEventType);
     MouseEvent* event() const;
 
     virtual bool dispatchEvent(EventDispatcher*) const;
+    bool isSyntheticMouseEvent() const { return m_mouseEventType == SyntheticMouseEvent; }
+    MouseEventType m_mouseEventType;
 };
 
 inline MouseEvent* toMouseEvent(Event* event)

Modified: trunk/Source/WebCore/dom/Node.cpp (136917 => 136918)


--- trunk/Source/WebCore/dom/Node.cpp	2012-12-07 02:57:21 UTC (rev 136917)
+++ trunk/Source/WebCore/dom/Node.cpp	2012-12-07 03:03:26 UTC (rev 136918)
@@ -2481,6 +2481,8 @@
 
 bool Node::dispatchEvent(PassRefPtr<Event> event)
 {
+    if (event->isMouseEvent())
+        return EventDispatcher::dispatchEvent(this, MouseEventDispatchMediator::create(adoptRef(toMouseEvent(event.leakRef())), MouseEventDispatchMediator::SyntheticMouseEvent));
     return EventDispatcher::dispatchEvent(this, EventDispatchMediator::create(event));
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to