Pointer lock events should be delivered directly to the target element
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 3 Feb 2017 21:56:43 +0000 (21:56 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 3 Feb 2017 21:56:43 +0000 (21:56 +0000)
https://bugs.webkit.org/show_bug.cgi?id=167134
rdar://problem/30268004

Patch by Jeremy Jones <jeremyj@apple.com> on 2017-02-03
Reviewed by Dean Jackson.

Source/WebCore:

pointer-lock/mouse-event-delivery.html: Enabled for mac, added wheel event tests.

When pointer is locked on an element, route mouse events directly to the target element, instead of
doing the normal event disptach.

* page/EventHandler.cpp:
(WebCore::EventHandler::handleMousePressEvent):
(WebCore::EventHandler::handleMouseDoubleClickEvent):
(WebCore::EventHandler::handleMouseMoveEvent):
(WebCore::EventHandler::handleMouseReleaseEvent):
(WebCore::EventHandler::handleMouseForceEvent):
(WebCore::EventHandler::handleWheelEvent):
* page/PointerLockController.cpp:
(WebCore::PointerLockController::isLocked): Added.
(WebCore::PointerLockController::dispatchLockedWheelEvent): Added.
* page/PointerLockController.h:

LayoutTests:

The pointer-lock/mouse-event-delivery.html test is modified to explicitly move the mouse pointer to a valid
location before sending mouse actions. Without this, the test infrastructure doesn't know that the pointer
is over the web view and doesn't deliver events.

The pointer-lock/mouse-event-delivery.html is also modified to explicitly wait for the delivery of the
wheel event before continuing with the test. This prevents flakeyness with the order the events are received.

Added code to test for wheel events.

* platform/mac/TestExpectations: enabled test.
* pointer-lock/mouse-event-delivery.html:
* pointer-lock/mouse-event-delivery-expected.txt:

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

LayoutTests/ChangeLog
LayoutTests/platform/mac/TestExpectations
LayoutTests/pointer-lock/mouse-event-delivery-expected.txt
LayoutTests/pointer-lock/mouse-event-delivery.html
Source/WebCore/ChangeLog
Source/WebCore/page/EventHandler.cpp
Source/WebCore/page/PointerLockController.cpp
Source/WebCore/page/PointerLockController.h

index 6a244ad..6d73123 100644 (file)
@@ -1,3 +1,24 @@
+2017-02-03  Jeremy Jones  <jeremyj@apple.com>
+
+        Pointer lock events should be delivered directly to the target element
+        https://bugs.webkit.org/show_bug.cgi?id=167134
+        rdar://problem/30268004
+
+        Reviewed by Dean Jackson.
+
+        The pointer-lock/mouse-event-delivery.html test is modified to explicitly move the mouse pointer to a valid
+        location before sending mouse actions. Without this, the test infrastructure doesn't know that the pointer
+        is over the web view and doesn't deliver events.
+
+        The pointer-lock/mouse-event-delivery.html is also modified to explicitly wait for the delivery of the 
+        wheel event before continuing with the test. This prevents flakeyness with the order the events are received.
+
+        Added code to test for wheel events.
+
+        * platform/mac/TestExpectations: enabled test.
+        * pointer-lock/mouse-event-delivery.html:
+        * pointer-lock/mouse-event-delivery-expected.txt:
+
 2017-02-03  Yoav Weiss  <yoav@yoav.ws>
 
         Avoid evicting link preload resources when parsing is done.
index ec3a4ec..f554da4 100644 (file)
@@ -280,7 +280,6 @@ fast/events/platform-wheelevent-paging-y-in-scrolling-page.html
 # Pointer Lock can only check some of the API at the moment.
 pointer-lock/bug90391-move-then-window-open-crash.html
 pointer-lock/locked-element-iframe-removed-from-dom.html
-pointer-lock/mouse-event-delivery.html
 pointer-lock/pointerlockchange-event-on-lock-lost.html
 pointer-lock/pointerlockchange-pointerlockerror-events.html
 pointer-lock/pointerlockelement-null-when-pending.html
index 7565e9f..7f5459c 100644 (file)
@@ -5,11 +5,17 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 PASS document.onpointerlockchange event received.
 PASS document.pointerLockElement is targetdiv1
+     With a lock in place send a wheel event.
+PASS event type: wheel, target: target1, received on: target1
+PASS event type: wheel, target: target1, received on: body
      With a lock in place send a click.
 PASS event type: mousedown, target: target1, received on: target1
 PASS event type: mousedown, target: target1, received on: body
 PASS document.onpointerlockchange event received.
 PASS document.pointerLockElement is targetdiv2
+     With a lock in place send a wheel event.
+PASS event type: wheel, target: target2, received on: target2
+PASS event type: wheel, target: target2, received on: body
      With a lock in place send a click.
 PASS event type: mousedown, target: target2, received on: target2
 PASS event type: mousedown, target: target2, received on: body
index e5b9c49..11fd10e 100644 (file)
     function eventExpected(e) {
       testPassed("event type: " + e.type + ", target: " + e.target.id + ", received on: " + e.currentTarget.id);
     }
+    function eventExpectedThenNextStep(e) {
+      testPassed("event type: " + e.type + ", target: " + e.target.id + ", received on: " + e.currentTarget.id);
+      doNextStep();
+    }
 
     todo = [
         function () {
             // doNextStep() called by onpointerlockchange handler.
         },
         function () {
+            debug("     With a lock in place send a wheel event.")
+            targetdiv1.onwheel = eventExpectedThenNextStep;
+            targetdiv2.onwheel = eventNotExpected;
+            document.body.onwheel = eventExpected;
+            if (window.eventSender) {
+                window.eventSender.mouseMoveTo(20,20);
+                window.eventSender.leapForward(1000);
+                window.eventSender.mouseScrollBy(0,10);
+            }
+        },
+        function () {
             debug("     With a lock in place send a click.")
             targetdiv1.onmousedown = eventExpected;
             targetdiv2.onmousedown = eventNotExpected;
             // doNextStep() called by onpointerlockchange handler.
         },
         function () {
+            debug("     With a lock in place send a wheel event.")
+            targetdiv1.onwheel = eventNotExpected;
+            targetdiv2.onwheel = eventExpected;
+            document.body.onwheel = eventExpected;
+            if (window.eventSender) {
+                window.eventSender.leapForward(1000);
+                window.eventSender.mouseScrollBy(0,10);
+            }
+            doNextStep();
+        },
+        function () {
             debug("     With a lock in place send a click.")
             targetdiv1.onmousedown = eventNotExpected;
             targetdiv2.onmousedown = eventExpected;
index b50f55f..bf8899c 100644 (file)
@@ -1,3 +1,28 @@
+2017-02-03  Jeremy Jones  <jeremyj@apple.com>
+
+        Pointer lock events should be delivered directly to the target element
+        https://bugs.webkit.org/show_bug.cgi?id=167134
+        rdar://problem/30268004
+
+        Reviewed by Dean Jackson.
+
+        pointer-lock/mouse-event-delivery.html: Enabled for mac, added wheel event tests.
+
+        When pointer is locked on an element, route mouse events directly to the target element, instead of 
+        doing the normal event disptach.
+
+        * page/EventHandler.cpp:
+        (WebCore::EventHandler::handleMousePressEvent):
+        (WebCore::EventHandler::handleMouseDoubleClickEvent):
+        (WebCore::EventHandler::handleMouseMoveEvent):
+        (WebCore::EventHandler::handleMouseReleaseEvent):
+        (WebCore::EventHandler::handleMouseForceEvent):
+        (WebCore::EventHandler::handleWheelEvent):
+        * page/PointerLockController.cpp:
+        (WebCore::PointerLockController::isLocked): Added.
+        (WebCore::PointerLockController::dispatchLockedWheelEvent): Added.
+        * page/PointerLockController.h:
+
 2017-02-03  Yoav Weiss  <yoav@yoav.ws>
 
         Avoid evicting link preload resources when parsing is done.
index 03d483b..a81f55f 100644 (file)
@@ -1621,6 +1621,13 @@ bool EventHandler::handleMousePressEvent(const PlatformMouseEvent& platformMouse
         return true;
     }
 
+#if ENABLE(POINTER_LOCK)
+    if (m_frame.page()->pointerLockController().isLocked()) {
+        m_frame.page()->pointerLockController().dispatchLockedMouseEvent(platformMouseEvent, eventNames().mousedownEvent);
+        return true;
+    }
+#endif
+
     if (m_frame.mainFrame().pageOverlayController().handleMouseEvent(platformMouseEvent))
         return true;
 
@@ -1761,6 +1768,13 @@ bool EventHandler::handleMouseDoubleClickEvent(const PlatformMouseEvent& platfor
 
     UserGestureIndicator gestureIndicator(ProcessingUserGesture, m_frame.document());
 
+#if ENABLE(POINTER_LOCK)
+    if (m_frame.page()->pointerLockController().isLocked()) {
+        m_frame.page()->pointerLockController().dispatchLockedMouseEvent(platformMouseEvent, eventNames().mouseupEvent);
+        return true;
+    }
+#endif
+
     // We get this instead of a second mouse-up 
     m_mousePressed = false;
     setLastKnownMousePosition(platformMouseEvent);
@@ -1855,7 +1869,14 @@ bool EventHandler::handleMouseMoveEvent(const PlatformMouseEvent& platformMouseE
 
     Ref<Frame> protectedFrame(m_frame);
     RefPtr<FrameView> protector(m_frame.view());
-    
+
+#if ENABLE(POINTER_LOCK)
+    if (m_frame.page()->pointerLockController().isLocked()) {
+        m_frame.page()->pointerLockController().dispatchLockedMouseEvent(platformMouseEvent, eventNames().mousemoveEvent);
+        return true;
+    }
+#endif
+
     setLastKnownMousePosition(platformMouseEvent);
 
     if (m_hoverTimer.isActive())
@@ -1989,6 +2010,13 @@ bool EventHandler::handleMouseReleaseEvent(const PlatformMouseEvent& platformMou
 
     m_frame.selection().setCaretBlinkingSuspended(false);
 
+#if ENABLE(POINTER_LOCK)
+    if (m_frame.page()->pointerLockController().isLocked()) {
+        m_frame.page()->pointerLockController().dispatchLockedMouseEvent(platformMouseEvent, eventNames().mouseupEvent);
+        return true;
+    }
+#endif
+
     if (m_frame.mainFrame().pageOverlayController().handleMouseEvent(platformMouseEvent))
         return true;
 
@@ -2067,6 +2095,17 @@ bool EventHandler::handleMouseForceEvent(const PlatformMouseEvent& event)
     Ref<Frame> protectedFrame(m_frame);
     RefPtr<FrameView> protector(m_frame.view());
 
+#if ENABLE(POINTER_LOCK)
+    if (m_frame.page()->pointerLockController().isLocked()) {
+        m_frame.page()->pointerLockController().dispatchLockedMouseEvent(event, eventNames().webkitmouseforcechangedEvent);
+        if (event.type() == PlatformEvent::MouseForceDown)
+            m_frame.page()->pointerLockController().dispatchLockedMouseEvent(event, eventNames().webkitmouseforcedownEvent);
+        if (event.type() == PlatformEvent::MouseForceUp)
+            m_frame.page()->pointerLockController().dispatchLockedMouseEvent(event, eventNames().webkitmouseforceupEvent);
+        return true;
+    }
+#endif
+
     setLastKnownMousePosition(event);
 
     HitTestRequest::HitTestRequestType hitType = HitTestRequest::DisallowUserAgentShadowContent | HitTestRequest::Active;
@@ -2672,6 +2711,13 @@ bool EventHandler::handleWheelEvent(const PlatformWheelEvent& event)
     if (!view)
         return false;
 
+#if ENABLE(POINTER_LOCK)
+    if (m_frame.page()->pointerLockController().isLocked()) {
+        m_frame.page()->pointerLockController().dispatchLockedWheelEvent(event);
+        return true;
+    }
+#endif
+
     m_isHandlingWheelEvent = true;
     setFrameWasScrolledByUser();
 
index 26b3cbf..ded552e 100644 (file)
@@ -123,6 +123,11 @@ void PointerLockController::documentDetached(Document& document)
     }
 }
 
+bool PointerLockController::isLocked() const
+{
+    return m_element && !m_lockPending;
+}
+
 bool PointerLockController::lockPending() const
 {
     return m_lockPending;
@@ -175,6 +180,14 @@ void PointerLockController::dispatchLockedMouseEvent(const PlatformMouseEvent& e
         m_element->dispatchMouseEvent(event, eventNames().clickEvent, event.clickCount());
 }
 
+void PointerLockController::dispatchLockedWheelEvent(const PlatformWheelEvent& event)
+{
+    if (!m_element || !m_element->document().frame())
+        return;
+
+    m_element->dispatchWheelEvent(event);
+}
+
 void PointerLockController::clearElement()
 {
     m_lockPending = false;
index 13d161f..5021ae9 100644 (file)
@@ -35,6 +35,7 @@ class Element;
 class Document;
 class Page;
 class PlatformMouseEvent;
+class PlatformWheelEvent;
 class VoidCallback;
 
 class PointerLockController {
@@ -48,6 +49,7 @@ public:
     void requestPointerUnlockAndForceCursorVisible();
     void elementRemoved(Element&);
     void documentDetached(Document&);
+    bool isLocked() const;
     WEBCORE_EXPORT bool lockPending() const;
     WEBCORE_EXPORT Element* element() const;
 
@@ -55,6 +57,7 @@ public:
     WEBCORE_EXPORT void didNotAcquirePointerLock();
     WEBCORE_EXPORT void didLosePointerLock();
     void dispatchLockedMouseEvent(const PlatformMouseEvent&, const AtomicString& eventType);
+    void dispatchLockedWheelEvent(const PlatformWheelEvent&);
 
 private:
     void clearElement();