Swipe gesture tests don't work on macOS Sierra
authortimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 30 Mar 2017 01:05:58 +0000 (01:05 +0000)
committertimothy_horton@apple.com <timothy_horton@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 30 Mar 2017 01:05:58 +0000 (01:05 +0000)
https://bugs.webkit.org/show_bug.cgi?id=161675
<rdar://problem/23379930>

Reviewed by Darin Adler.

Tools:

* DumpRenderTree/mac/UIScriptControllerMac.mm:
(WTR::UIScriptController::platformPlayBackEventStream):
(WTR::UIScriptController::beginBackSwipe):
(WTR::UIScriptController::completeBackSwipe):
* TestRunnerShared/EventSerialization/mac/EventSerializerMac.h: Copied from Tools/DumpRenderTree/mac/UIScriptControllerMac.mm.
* TestRunnerShared/EventSerialization/mac/EventSerializerMac.mm: Added.
(eventIsOfType):
(eventIsOfTypes):
(eventIsOfGestureType):
(eventIsOfGestureTypes):
(+[EventSerializer dictionaryForEvent:relativeToTime:]):
(+[EventSerializer createEventForDictionary:inWindow:relativeToTime:]):
(+[EventSerializer playEventStream:inWindow:completionHandler:]):
* TestRunnerShared/EventSerialization/mac/SharedEventStreamsMac.h: Copied from Tools/WebKitTestRunner/mac/UIScriptControllerMac.mm.
* TestRunnerShared/EventSerialization/mac/SharedEventStreamsMac.mm: Added.
(beginSwipeBackEventStream):
(completeSwipeBackEventStream):
* TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
* TestRunnerShared/UIScriptContext/UIScriptController.cpp:
(WTR::UIScriptController::playBackEventStream):
(WTR::UIScriptController::beginBackSwipe):
(WTR::UIScriptController::completeBackSwipe):
(WTR::UIScriptController::platformPlayBackEventStream):
(WTR::UIScriptController::platformClearAllCallbacks): Deleted.
* TestRunnerShared/UIScriptContext/UIScriptController.h:
* TestRunnerShared/spi/CoreGraphicsSPI.h: Added.
* TestRunnerShared/spi/IOKitSPI.h: Renamed from Tools/WebKitTestRunner/ios/IOKitSPI.h.
* WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj:
* WebKitTestRunner/mac/UIScriptControllerMac.mm:
(WTR::playBackEvents):
(WTR::UIScriptController::beginBackSwipe):
(WTR::UIScriptController::completeBackSwipe):
(WTR::UIScriptController::platformPlayBackEventStream):

LayoutTests:

* platform/mac-wk2/TestExpectations:
* swipe/basic-cached-back-swipe-expected.txt:
* swipe/basic-cached-back-swipe.html:
* swipe/main-frame-pinning-requirement-expected.txt:
* swipe/main-frame-pinning-requirement.html:
* swipe/pushState-cached-back-swipe-expected.txt:
* swipe/pushState-cached-back-swipe.html:
* swipe/pushState-programmatic-back-while-swiping-crash-expected.txt:
* swipe/pushState-programmatic-back-while-swiping-crash.html:
* swipe/resources/swipe-test.js:
(measuredDurationShouldBeLessThan):
(startSwipeGesture):
(completeSwipeGesture):
(playEventStream):
(eventQueue.enqueueScrollEvent): Deleted.
(eventQueue.enqueueSwipeEvent): Deleted.
(eventQueue.hasPendingEvents): Deleted.
(eventQueue.callAfterEventDispatch): Deleted.
(eventQueue._processEventQueue): Deleted.
(eventQueue._processEventQueueSoon): Deleted.
* swipe/swipe-start-hysteresis-failures-expected.txt: Removed.
* swipe/swipe-start-hysteresis-failures.html: Removed.

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

35 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/mac-wk2/TestExpectations
LayoutTests/swipe/basic-cached-back-swipe-expected.txt
LayoutTests/swipe/basic-cached-back-swipe.html
LayoutTests/swipe/main-frame-pinning-requirement-expected.txt
LayoutTests/swipe/main-frame-pinning-requirement.html
LayoutTests/swipe/pushState-cached-back-swipe-expected.txt
LayoutTests/swipe/pushState-cached-back-swipe.html
LayoutTests/swipe/pushState-programmatic-back-while-swiping-crash-expected.txt
LayoutTests/swipe/pushState-programmatic-back-while-swiping-crash.html
LayoutTests/swipe/resources/swipe-test.js
LayoutTests/swipe/swipe-start-hysteresis-failures-expected.txt [deleted file]
LayoutTests/swipe/swipe-start-hysteresis-failures.html [deleted file]
Tools/ChangeLog
Tools/DumpRenderTree/mac/UIScriptControllerMac.mm
Tools/TestRunnerShared/EventSerialization/mac/EventSerializerMac.h [new file with mode: 0644]
Tools/TestRunnerShared/EventSerialization/mac/EventSerializerMac.mm [new file with mode: 0644]
Tools/TestRunnerShared/EventSerialization/mac/SharedEventStreamsMac.h [new file with mode: 0644]
Tools/TestRunnerShared/EventSerialization/mac/SharedEventStreamsMac.mm [new file with mode: 0644]
Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl
Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp
Tools/TestRunnerShared/UIScriptContext/UIScriptController.h
Tools/TestRunnerShared/spi/CoreGraphicsSPI.h [new file with mode: 0644]
Tools/TestRunnerShared/spi/IOKitSPI.h [moved from Tools/WebKitTestRunner/ios/IOKitSPI.h with 97% similarity]
Tools/WebKitTestRunner/EventSenderProxy.h
Tools/WebKitTestRunner/InjectedBundle/Bindings/EventSendingController.idl
Tools/WebKitTestRunner/InjectedBundle/EventSendingController.cpp
Tools/WebKitTestRunner/InjectedBundle/EventSendingController.h
Tools/WebKitTestRunner/InjectedBundle/ios/EventSenderProxyIOS.mm
Tools/WebKitTestRunner/TestController.cpp
Tools/WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj
Tools/WebKitTestRunner/efl/EventSenderProxyEfl.cpp
Tools/WebKitTestRunner/gtk/EventSenderProxyGtk.cpp
Tools/WebKitTestRunner/mac/EventSenderProxy.mm
Tools/WebKitTestRunner/mac/UIScriptControllerMac.mm

index 32b36fa..de18466 100644 (file)
@@ -1,3 +1,34 @@
+2017-03-29  Tim Horton  <timothy_horton@apple.com>
+
+        Swipe gesture tests don't work on macOS Sierra
+        https://bugs.webkit.org/show_bug.cgi?id=161675
+        <rdar://problem/23379930>
+
+        Reviewed by Darin Adler.
+
+        * platform/mac-wk2/TestExpectations:
+        * swipe/basic-cached-back-swipe-expected.txt:
+        * swipe/basic-cached-back-swipe.html:
+        * swipe/main-frame-pinning-requirement-expected.txt:
+        * swipe/main-frame-pinning-requirement.html:
+        * swipe/pushState-cached-back-swipe-expected.txt:
+        * swipe/pushState-cached-back-swipe.html:
+        * swipe/pushState-programmatic-back-while-swiping-crash-expected.txt:
+        * swipe/pushState-programmatic-back-while-swiping-crash.html:
+        * swipe/resources/swipe-test.js:
+        (measuredDurationShouldBeLessThan):
+        (startSwipeGesture):
+        (completeSwipeGesture):
+        (playEventStream):
+        (eventQueue.enqueueScrollEvent): Deleted.
+        (eventQueue.enqueueSwipeEvent): Deleted.
+        (eventQueue.hasPendingEvents): Deleted.
+        (eventQueue.callAfterEventDispatch): Deleted.
+        (eventQueue._processEventQueue): Deleted.
+        (eventQueue._processEventQueueSoon): Deleted.
+        * swipe/swipe-start-hysteresis-failures-expected.txt: Removed.
+        * swipe/swipe-start-hysteresis-failures.html: Removed.
+
 2017-03-29  Myles C. Maxfield  <mmaxfield@apple.com>
 
         Try to normalize variation ranges
index c0f5090..7a88e29 100644 (file)
@@ -542,12 +542,6 @@ webkit.org/b/162638 [ Sierra+ ] fast/scrolling/rtl-scrollbars-alternate-iframe-b
 # <rdar://problem/25063128>
 [ Sierra+ ] media/media-controls-drag-timeline-set-controls-property.html [ Pass Timeout ]
 
-# <rdar://problem/23379930> swipe tests crashing
-[ Sierra+ ] swipe/basic-cached-back-swipe.html [ Skip ]
-[ Sierra+ ] swipe/main-frame-pinning-requirement.html [ Skip ]
-[ Sierra+ ] swipe/pushState-cached-back-swipe.html [ Skip ]
-[ Sierra+ ] swipe/swipe-start-hysteresis-failures.html [ Skip ]
-
 # Hitting "The certificate for this server is invalid" loading error (not happening in WK1)
 webkit.org/b/160445 [ Sierra+ ] http/tests/security/contentSecurityPolicy/upgrade-insecure-requests/upgrade-insecure-fetch-in-worker.html [ Failure ]
 webkit.org/b/160445 [ Sierra+ ] http/tests/security/contentSecurityPolicy/upgrade-insecure-requests/upgrade-insecure-fetch-in-main-frame.html [ Failure ]
index e3d3e00..89decfd 100644 (file)
@@ -1,10 +1,6 @@
-swipe event (delta 0 0, phase 'maybegin')
-scroll event (delta 1 0, phase 'began')
-scroll event (delta 1 0, phase 'changed')
+startSwipeGesture
 didBeginSwipe
-swipe event (delta 1 0, phase 'changed')
-swipe event (delta 256 0, phase 'changed')
-swipe event (delta 0 0, phase 'ended')
+completeSwipeGesture
 willEndSwipe
 didEndSwipe
 didRemoveSwipeSnapshot
index cf7f75c..871a2bc 100644 (file)
@@ -6,28 +6,10 @@ html {
 </style>
 <script src="resources/swipe-test.js"></script>
 <script>
-function startSwipeGesture()
-{
-    eventSender.mouseMoveTo(100, 100);
-
-    eventQueue.enqueueSwipeEvent(0, 0, 'maybegin');
-    eventQueue.enqueueScrollEvent(1, 0, 'began');
-    eventQueue.enqueueScrollEvent(1, 0, 'changed');
-}
-
-function completeSwipeGesture()
-{
-    eventQueue.enqueueSwipeEvent(1, 0, 'changed');
-    eventQueue.enqueueSwipeEvent(256, 0, 'changed');
-    eventQueue.enqueueSwipeEvent(0, 0, 'ended');
-}
-
 function didBeginSwipeCallback()
 {
     log("didBeginSwipe");
 
-    shouldBe(false, eventQueue.hasPendingEvents(), "Event queue should be empty. Both scroll events should be required to start the swipe because of the swipe-start hysteresis.");
-
     completeSwipeGesture();
 }
 
@@ -42,7 +24,6 @@ function didEndSwipeCallback()
 {
     log("didEndSwipe");
 
-    shouldBe(0, eventQueue.hasPendingEvents(), "Event queue should be empty. The swipe isn't complete until we see the end of the gesture.");
     startMeasuringDuration("snapshotRemoval");
 }
 
index 6359740..ce76681 100644 (file)
@@ -1,23 +1,8 @@
-swipe event (delta 0 0, phase 'maybegin')
-scroll event (delta 10 0, phase 'began')
-scroll event (delta 10 0, phase 'changed')
-scroll event (delta 10 0, phase 'changed')
-scroll event (delta 10 0, phase 'changed')
-scroll event (delta 10 0, phase 'changed')
-scroll event (delta 10 0, phase 'changed')
-scroll event (delta 10 0, phase 'changed')
-scroll event (delta 10 0, phase 'changed')
-scroll event (delta 10 0, phase 'changed')
-scroll event (delta 10 0, phase 'changed')
-scroll event (delta 10 0, phase 'changed')
-scroll event (delta 0 0, phase 'ended')
-swipe event (delta 0 0, phase 'maybegin')
-scroll event (delta 1 0, phase 'began')
-scroll event (delta 10 0, phase 'changed')
+startSwipeGesture
+completeSwipeGesture
+startSwipeGesture
 didBeginSwipe
-swipe event (delta 1 0, phase 'changed')
-swipe event (delta 256 0, phase 'changed')
-swipe event (delta 0 0, phase 'ended')
+completeSwipeGesture
 willEndSwipe
 didEndSwipe
 didRemoveSwipeSnapshot
index 6215544..a369b82 100644 (file)
@@ -6,48 +6,24 @@ html {
 </style>
 <script src="resources/swipe-test.js"></script>
 <script>
-function startSwipeGesture()
-{
-    eventSender.mouseMoveTo(100, 100);
 
+function runTest()
+{
     // The first swipe should fail because we're scrolled to the middle of the document
     // and this is all a single gesture. We can only start swipes if we *begin*
     // pinned to the edge.
-    eventQueue.enqueueSwipeEvent(0, 0, 'maybegin');
-    eventQueue.enqueueScrollEvent(10, 0, 'began');
-    eventQueue.enqueueScrollEvent(10, 0, 'changed');
-    eventQueue.enqueueScrollEvent(10, 0, 'changed');
-    eventQueue.enqueueScrollEvent(10, 0, 'changed');
-    eventQueue.enqueueScrollEvent(10, 0, 'changed');
-    eventQueue.enqueueScrollEvent(10, 0, 'changed');
-    eventQueue.enqueueScrollEvent(10, 0, 'changed');
-    eventQueue.enqueueScrollEvent(10, 0, 'changed');
-    eventQueue.enqueueScrollEvent(10, 0, 'changed');
-    eventQueue.enqueueScrollEvent(10, 0, 'changed');
-    eventQueue.enqueueScrollEvent(10, 0, 'changed');
-    eventQueue.enqueueScrollEvent(0, 0, 'ended');
-
-    eventQueue.callAfterEventDispatch(function () {
-        testRunner.clearTestRunnerCallbacks();
-        testRunner.installDidBeginSwipeCallback(didBeginSwipeCallback);
-        testRunner.installWillEndSwipeCallback(willEndSwipeCallback);
-        testRunner.installDidEndSwipeCallback(didEndSwipeCallback);
-        testRunner.installDidRemoveSwipeSnapshotCallback(didRemoveSwipeSnapshotCallback);
+    startSwipeGesture(function () {
+        completeSwipeGesture(function () {
+            testRunner.clearTestRunnerCallbacks();
+            testRunner.installDidBeginSwipeCallback(didBeginSwipeCallback);
+            testRunner.installWillEndSwipeCallback(willEndSwipeCallback);
+            testRunner.installDidEndSwipeCallback(didEndSwipeCallback);
+            testRunner.installDidRemoveSwipeSnapshotCallback(didRemoveSwipeSnapshotCallback);    
 
-        setTimeout(function () {
             // The second swipe should succeed because we are now scrolled to the left edge.
-            eventQueue.enqueueSwipeEvent(0, 0, 'maybegin');
-            eventQueue.enqueueScrollEvent(1, 0, 'began');
-            eventQueue.enqueueScrollEvent(10, 0, 'changed');
-        }, 0);
-    })
-}
-
-function completeSwipeGesture()
-{
-    eventQueue.enqueueSwipeEvent(1, 0, 'changed');
-    eventQueue.enqueueSwipeEvent(256, 0, 'changed');
-    eventQueue.enqueueSwipeEvent(0, 0, 'ended');
+            startSwipeGesture(function () { completeSwipeGesture(); });
+        });
+    });
 }
 
 function didBeginSwipeNotReachedCallback()
@@ -58,10 +34,6 @@ function didBeginSwipeNotReachedCallback()
 function didBeginSwipeCallback()
 {
     log("didBeginSwipe");
-
-    shouldBe(false, eventQueue.hasPendingEvents(), "Event queue should be empty. Both scroll events should be required to start the swipe because of the swipe-start hysteresis.");
-
-    completeSwipeGesture();
 }
 
 function willEndSwipeCallback()
@@ -75,7 +47,6 @@ function didEndSwipeCallback()
 {
     log("didEndSwipe");
 
-    shouldBe(0, eventQueue.hasPendingEvents(), "Event queue should be empty. The swipe isn't complete until we see the end of the gesture.");
     startMeasuringDuration("snapshotRemoval");
 }
 
@@ -121,8 +92,9 @@ window.onload = function () {
     }
 
     // Second page loaded.
-    window.scrollTo(1000, 0);
-    startSwipeGesture();
+    window.scrollTo(100, 0);
+
+    runTest();
 };
 </script>
 </head>
index e3d3e00..89decfd 100644 (file)
@@ -1,10 +1,6 @@
-swipe event (delta 0 0, phase 'maybegin')
-scroll event (delta 1 0, phase 'began')
-scroll event (delta 1 0, phase 'changed')
+startSwipeGesture
 didBeginSwipe
-swipe event (delta 1 0, phase 'changed')
-swipe event (delta 256 0, phase 'changed')
-swipe event (delta 0 0, phase 'ended')
+completeSwipeGesture
 willEndSwipe
 didEndSwipe
 didRemoveSwipeSnapshot
index 56dada4..9a8dc9d 100644 (file)
@@ -6,28 +6,11 @@ html {
 </style>
 <script src="resources/swipe-test.js"></script>
 <script>
-function startSwipeGesture()
-{
-    eventSender.mouseMoveTo(100, 100);
-
-    eventQueue.enqueueSwipeEvent(0, 0, 'maybegin');
-    eventQueue.enqueueScrollEvent(1, 0, 'began');
-    eventQueue.enqueueScrollEvent(1, 0, 'changed');
-}
-
-function completeSwipeGesture()
-{
-    eventQueue.enqueueSwipeEvent(1, 0, 'changed');
-    eventQueue.enqueueSwipeEvent(256, 0, 'changed');
-    eventQueue.enqueueSwipeEvent(0, 0, 'ended');
-}
 
 function didBeginSwipeCallback()
 {
     log("didBeginSwipe");
 
-    shouldBe(false, eventQueue.hasPendingEvents(), "Event queue should be empty. Both scroll events should be required to start the swipe because of the swipe-start hysteresis.");
-
     completeSwipeGesture();
 }
 
@@ -42,7 +25,6 @@ function didEndSwipeCallback()
 {
     log("didEndSwipe");
 
-    shouldBe(0, eventQueue.hasPendingEvents(), "Event queue should be empty. The swipe isn't complete until we see the end of the gesture.");
     startMeasuringDuration("snapshotRemoval");
 }
 
index dc34e92..0050755 100644 (file)
@@ -1,7 +1,4 @@
-swipe event (delta 0 0, phase 'maybegin')
-scroll event (delta 1 0, phase 'began')
-scroll event (delta 1 0, phase 'changed')
-swipe event (delta 1 0, phase 'changed')
-swipe event (delta 256 0, phase 'changed')
-swipe event (delta 0 0, phase 'ended')
+playEventStream
+playEventStream
+completeSwipeGesture
 
index 36ef39f..3f87a03 100644 (file)
@@ -6,37 +6,67 @@ html {
 </style>
 <script src="resources/swipe-test.js"></script>
 <script>
-function startSwipeGesture()
+function runTest()
 {
-    eventSender.mouseMoveTo(100, 100);
-
-    eventQueue.enqueueSwipeEvent(0, 0, 'maybegin');
-    eventQueue.enqueueScrollEvent(1, 0, 'began');
-    
-    eventQueue.callAfterEventDispatch(goBack);
+    playEventStream(`[{
+        "relativeTimeMS" : 0,
+        "kCGEventScrollGestureFlagBits" : 1,
+        "kCGEventGestureHIDType" : 6,
+        "kCGSEventTypeField" : 29,
+        "kCGEventGesturePhase" : 128,
+        "windowLocation" : "{400, 300}"
+      },
+      {
+        "relativeTimeMS" : 8,
+        "kCGEventGestureHIDType" : 61,
+        "kCGSEventTypeField" : 29,
+        "kCGEventGestureStartEndSeriesType" : 6,
+        "windowLocation" : "{0, 0}"
+      },
+      {
+        "kCGEventGestureHIDType" : 6,
+        "relativeTimeMS" : 8,
+        "windowLocation" : "{400, 300}",
+        "kCGEventGesturePhase" : 1,
+        "kCGEventScrollGestureFlagBits" : 1,
+        "kCGSEventTypeField" : 29,
+        "kCGEventGestureScrollX" : 2
+      },
+      {
+        "relativeTimeMS" : 8,
+        "windowLocation" : "{400, 300}",
+        "kCGScrollWheelEventScrollPhase" : 1,
+        "kCGScrollWheelEventIsContinuous" : 1,
+        "kCGScrollWheelEventPointDeltaAxis2" : 1,
+        "kCGSEventTypeField" : 22
+      }]`, goBack);
 }
 
 function goBack()
 {
     window.history.back();
 
-    eventQueue.callAfterEventDispatch(continueSwipeGesture);
+    setTimeout(continueTest, 0);
 }
 
-function continueSwipeGesture()
+function continueTest()
 {
-    eventQueue.enqueueScrollEvent(1, 0, 'changed');
-
-    eventQueue.callAfterEventDispatch(completeSwipeGesture);
+    playEventStream(`[
+      {
+        "relativeTimeMS" : 0,
+        "windowLocation" : "{400, 300}",
+        "kCGScrollWheelEventScrollPhase" : 1,
+        "kCGScrollWheelEventIsContinuous" : 1,
+        "kCGScrollWheelEventPointDeltaAxis2" : 20,
+        "kCGSEventTypeField" : 22
+      }]`, function () {
+        completeTest();
+      });
 }
 
-function completeSwipeGesture()
+function completeTest()
 {
-    eventQueue.enqueueSwipeEvent(1, 0, 'changed');
-    eventQueue.enqueueSwipeEvent(256, 0, 'changed');
-    eventQueue.enqueueSwipeEvent(0, 0, 'ended');
-
-    eventQueue.callAfterEventDispatch(testComplete);
+    completeSwipeGesture(testComplete);
 }
 
 function didBeginSwipeCallback()
@@ -79,7 +109,7 @@ window.onload = function () {
         updateContent();
 
         setTimeout(function () {
-            startSwipeGesture();
+            runTest();
         }, 0);
     }, 0);
 };
index dd8e900..0c2365d 100644 (file)
@@ -1,50 +1,3 @@
-var eventQueue = {
-    enqueueScrollEvent: function (x, y, phase) {
-        this._queue.push(function () {
-            log("scroll event (delta " + x + " " + y + ", phase '" + phase + "')");
-            window.eventSender.mouseScrollByWithWheelAndMomentumPhases(x, y, phase, 'none');
-        });
-        this._processEventQueueSoon();
-    },
-
-    enqueueSwipeEvent: function (x, y, phase) {
-        this._queue.push(function () {
-            log("swipe event (delta " + x + " " + y + ", phase '" + phase + "')");
-            window.eventSender.swipeGestureWithWheelAndMomentumPhases(x, y, phase, 'none');
-        });
-        this._processEventQueueSoon();
-    },
-
-    hasPendingEvents: function () {
-        return this._queue.length != 0;
-    },
-
-    callAfterEventDispatch: function (callback) {
-        var interval = setInterval(function () { 
-            if (!eventQueue.hasPendingEvents()) {
-                clearInterval(interval);
-                callback();
-            }
-        }, 0);
-    },
-
-    _queue: [],
-
-    _processEventQueue: function () {
-        if (!this._queue.length)
-            return;
-
-        var item = this._queue.shift();
-        item();
-        this._processEventQueueSoon();
-    },
-
-    _processEventQueueSoon: function () {
-        clearTimeout(this._processingTimeout);
-        this._processingTimeout = setTimeout(this._processEventQueue.bind(this), 0);
-    }
-}
-
 function shouldBe(expected, actual, message)
 {
     if (expected != actual)
@@ -84,4 +37,37 @@ function measuredDurationShouldBeLessThan(key, timeInMS, message)
     var duration = Date.now() - window.localStorage[key + "swipeStartTime"];
     if (duration >= timeInMS)
         log("Failure. " + message + " (expected: " + timeInMS + ", actual: " + duration + ")");
-}
\ No newline at end of file
+}
+
+function startSwipeGesture(callback)
+{
+    log("startSwipeGesture");
+    testRunner.runUIScript(`
+    (function() {
+        uiController.beginBackSwipe(function() {
+            uiController.uiScriptComplete();
+        });
+    })();`, callback || function () {});
+}
+
+function completeSwipeGesture(callback)
+{
+    log("completeSwipeGesture");
+    testRunner.runUIScript(`
+    (function() {
+        uiController.completeBackSwipe(function() {
+            uiController.uiScriptComplete();
+        });
+    })();`, callback || function () {});
+}
+
+function playEventStream(stream, callback)
+{
+    log("playEventStream");
+    testRunner.runUIScript(`
+    (function() {
+        uiController.playBackEventStream(\`${stream}\`, function() {
+            uiController.uiScriptComplete();
+        });
+    })();`, callback || function () {});
+}
diff --git a/LayoutTests/swipe/swipe-start-hysteresis-failures-expected.txt b/LayoutTests/swipe/swipe-start-hysteresis-failures-expected.txt
deleted file mode 100644 (file)
index 5a480a9..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-swipe event (delta 0 0, phase 'maybegin')
-scroll event (delta 1 0, phase 'began')
-scroll event (delta 0 0, phase 'changed')
-scroll event (delta 0 0, phase 'ended')
-swipe event (delta 0 0, phase 'maybegin')
-scroll event (delta 2 2, phase 'began')
-scroll event (delta 0 0, phase 'changed')
-scroll event (delta 0 0, phase 'ended')
-swipe event (delta 0 0, phase 'maybegin')
-scroll event (delta 0 2, phase 'began')
-scroll event (delta 0 0, phase 'changed')
-scroll event (delta 0 0, phase 'ended')
-swipe event (delta 0 0, phase 'maybegin')
-scroll event (delta 1 0, phase 'began')
-scroll event (delta 0 2, phase 'changed')
-scroll event (delta 0 0, phase 'ended')
-swipe event (delta 0 0, phase 'maybegin')
-scroll event (delta 3 1, phase 'began')
-scroll event (delta 0 0, phase 'changed')
-scroll event (delta 0 0, phase 'ended')
-swipe event (delta 0 0, phase 'ended')
-
diff --git a/LayoutTests/swipe/swipe-start-hysteresis-failures.html b/LayoutTests/swipe/swipe-start-hysteresis-failures.html
deleted file mode 100644 (file)
index e75e67b..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-<head>
-<style>
-html {
-    font-size: 32pt;
-}
-</style>
-<script src="resources/swipe-test.js"></script>
-<script>
-function doShortSwipeGesture()
-{
-    eventSender.mouseMoveTo(100, 100);
-
-    // Total delta of 10, 0; should not be enough to start a swipe.
-    eventQueue.enqueueSwipeEvent(0, 0, 'maybegin');
-    eventQueue.enqueueScrollEvent(1, 0, 'began');
-    eventQueue.enqueueScrollEvent(0, 0, 'changed');
-    eventQueue.enqueueScrollEvent(0, 0, 'ended');
-
-    eventQueue.callAfterEventDispatch(doDiagonalSwipeGesture);
-}
-
-function doDiagonalSwipeGesture()
-{
-    // Total delta of 20, 20; this is ordinarily sufficient magnitude to start a swipe,
-    // but is too diagonal to start a swipe.
-    eventQueue.enqueueSwipeEvent(0, 0, 'maybegin');
-    eventQueue.enqueueScrollEvent(2, 2, 'began');
-    eventQueue.enqueueScrollEvent(0, 0, 'changed');
-    eventQueue.enqueueScrollEvent(0, 0, 'ended');
-
-    eventQueue.callAfterEventDispatch(doVerticalSwipeGesture);
-}
-
-function doVerticalSwipeGesture()
-{
-    // Total delta of 0, 20; this is ordinarily sufficient magnitude to start a swipe,
-    // but is completely vertical, so we won't start a swipe.
-    eventQueue.enqueueSwipeEvent(0, 0, 'maybegin');
-    eventQueue.enqueueScrollEvent(0, 2, 'began');
-    eventQueue.enqueueScrollEvent(0, 0, 'changed');
-    eventQueue.enqueueScrollEvent(0, 0, 'ended');
-
-    eventQueue.callAfterEventDispatch(doHorizontalThenVerticalSwipeGesture);
-}
-
-function doHorizontalThenVerticalSwipeGesture()
-{
-    // Total delta of 10, 20; this is ordinarily sufficient magnitude to start a swipe,
-    // but is too vertical, so we won't start a swipe.
-    eventQueue.enqueueSwipeEvent(0, 0, 'maybegin');
-    eventQueue.enqueueScrollEvent(1, 0, 'began');
-    eventQueue.enqueueScrollEvent(0, 2, 'changed');
-    eventQueue.enqueueScrollEvent(0, 0, 'ended');
-
-    eventQueue.callAfterEventDispatch(doRegularSwipeGesture);
-}
-
-function doRegularSwipeGesture()
-{
-    // Swap in a different callback that makes sure we *do* reach didBeginSwipe.
-    testRunner.clearTestRunnerCallbacks();
-    var sawDidBeginSwipe = false;
-    testRunner.installDidBeginSwipeCallback(function () {
-        sawDidBeginSwipe = true;
-        // Need a swipe-end event to clean up.
-        eventQueue.enqueueSwipeEvent(0, 0, 'ended');
-    });
-
-    testRunner.installDidRemoveSwipeSnapshotCallback(function () {
-        shouldBe(true, sawDidBeginSwipe, "The last gesture should start a swipe, because it is sufficient magnitude and in the correct direction.")
-        testComplete();
-    });
-
-    // Total delta of 30, 10; this should start a swipe as usual.
-    eventQueue.enqueueSwipeEvent(0, 0, 'maybegin');
-    eventQueue.enqueueScrollEvent(3, 1, 'began');
-    eventQueue.enqueueScrollEvent(0, 0, 'changed');
-    eventQueue.enqueueScrollEvent(0, 0, 'ended');
-}
-
-function didBeginSwipeNotReachedCallback()
-{
-    log("Failure. Should never begin a swipe, because all of the attempted swipes should fail due to the swipe-start hysteresis.");
-}
-
-function isFirstPage()
-{
-    return window.location.href.indexOf("second") == -1;
-}
-
-window.onload = function () {
-    if (!window.eventSender || !window.testRunner) {
-        document.body.innerHTML = "This test must be run in WebKitTestRunner.";
-        return;
-    }
-
-    document.body.innerHTML = isFirstPage() ? "first" : "second";
-
-    if (isFirstPage()) {
-        initializeSwipeTest();
-
-        testRunner.installDidBeginSwipeCallback(didBeginSwipeNotReachedCallback);
-
-        testRunner.overridePreference("WebKitUsesPageCachePreferenceKey", 1);
-        testRunner.dumpAsText();
-        testRunner.waitUntilDone();
-
-        setTimeout(function () { 
-            window.location.href = window.location.href + "?second";
-        }, 0);
-        return;
-    }
-
-    doShortSwipeGesture();
-};
-</script>
-</head>
-<body>
-</body>
\ No newline at end of file
index 97023cd..1314139 100644 (file)
@@ -1,3 +1,45 @@
+2017-03-29  Tim Horton  <timothy_horton@apple.com>
+
+        Swipe gesture tests don't work on macOS Sierra
+        https://bugs.webkit.org/show_bug.cgi?id=161675
+        <rdar://problem/23379930>
+
+        Reviewed by Darin Adler.
+
+        * DumpRenderTree/mac/UIScriptControllerMac.mm:
+        (WTR::UIScriptController::platformPlayBackEventStream):
+        (WTR::UIScriptController::beginBackSwipe):
+        (WTR::UIScriptController::completeBackSwipe):
+        * TestRunnerShared/EventSerialization/mac/EventSerializerMac.h: Copied from Tools/DumpRenderTree/mac/UIScriptControllerMac.mm.
+        * TestRunnerShared/EventSerialization/mac/EventSerializerMac.mm: Added.
+        (eventIsOfType):
+        (eventIsOfTypes):
+        (eventIsOfGestureType):
+        (eventIsOfGestureTypes):
+        (+[EventSerializer dictionaryForEvent:relativeToTime:]):
+        (+[EventSerializer createEventForDictionary:inWindow:relativeToTime:]):
+        (+[EventSerializer playEventStream:inWindow:completionHandler:]):
+        * TestRunnerShared/EventSerialization/mac/SharedEventStreamsMac.h: Copied from Tools/WebKitTestRunner/mac/UIScriptControllerMac.mm.
+        * TestRunnerShared/EventSerialization/mac/SharedEventStreamsMac.mm: Added.
+        (beginSwipeBackEventStream):
+        (completeSwipeBackEventStream):
+        * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
+        * TestRunnerShared/UIScriptContext/UIScriptController.cpp:
+        (WTR::UIScriptController::playBackEventStream):
+        (WTR::UIScriptController::beginBackSwipe):
+        (WTR::UIScriptController::completeBackSwipe):
+        (WTR::UIScriptController::platformPlayBackEventStream):
+        (WTR::UIScriptController::platformClearAllCallbacks): Deleted.
+        * TestRunnerShared/UIScriptContext/UIScriptController.h:
+        * TestRunnerShared/spi/CoreGraphicsSPI.h: Added.
+        * TestRunnerShared/spi/IOKitSPI.h: Renamed from Tools/WebKitTestRunner/ios/IOKitSPI.h.
+        * WebKitTestRunner/WebKitTestRunner.xcodeproj/project.pbxproj:
+        * WebKitTestRunner/mac/UIScriptControllerMac.mm:
+        (WTR::playBackEvents):
+        (WTR::UIScriptController::beginBackSwipe):
+        (WTR::UIScriptController::completeBackSwipe):
+        (WTR::UIScriptController::platformPlayBackEventStream):
+
 2017-03-29  Jonathan Bedard  <jbedard@apple.com>
 
         webkitpy: Robust test clean-up
index e2f0f5e..7eccba7 100644 (file)
@@ -136,6 +136,18 @@ void UIScriptController::addViewToWindow(JSValueRef callback)
     });
 }
 
+void UIScriptController::beginBackSwipe(JSValueRef callback)
+{
+}
+
+void UIScriptController::completeBackSwipe(JSValueRef callback)
+{
+}
+
+void UIScriptController::platformPlayBackEventStream(JSStringRef, JSValueRef)
+{
+}
+
 }
 
 #endif // PLATFORM(MAC)
diff --git a/Tools/TestRunnerShared/EventSerialization/mac/EventSerializerMac.h b/Tools/TestRunnerShared/EventSerialization/mac/EventSerializerMac.h
new file mode 100644 (file)
index 0000000..2cd2d55
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if PLATFORM(MAC)
+
+#import <AppKit/AppKit.h>
+#import <wtf/BlockPtr.h>
+#import <wtf/RetainPtr.h>
+
+@interface EventSerializer : NSObject
+
++ (NSDictionary *)dictionaryForEvent:(CGEventRef)event relativeToTime:(CGEventTimestamp)referenceTimestamp;
+
++ (RetainPtr<CGEventRef>)createEventForDictionary:(NSDictionary *)dict inWindow:(NSWindow *)window relativeToTime:(CGEventTimestamp)referenceTimestamp;
+
+@end
+
+@interface EventStreamPlayer : NSObject {
+    RetainPtr<NSMutableArray *> _remainingEventDictionaries;
+    RetainPtr<NSWindow *> _window;
+    BlockPtr<void ()> _completionHandler;
+    uint64_t _startTime;
+}
+
++ (void)playStream:(NSArray<NSDictionary *> *)eventDicts window:(NSWindow *)window completionHandler:(void(^)())completionHandler;
+
+@end
+
+#endif
diff --git a/Tools/TestRunnerShared/EventSerialization/mac/EventSerializerMac.mm b/Tools/TestRunnerShared/EventSerialization/mac/EventSerializerMac.mm
new file mode 100644 (file)
index 0000000..e675396
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "EventSerializerMac.h"
+
+#if PLATFORM(MAC)
+
+#import "CoreGraphicsSPI.h"
+#import "IOKitSPI.h"
+#import <algorithm>
+#import <mach/mach_time.h>
+#import <wtf/RetainPtr.h>
+
+#define MOUSE_EVENT_TYPES \
+    (CGSEventType)kCGEventLeftMouseDown, \
+    (CGSEventType)kCGEventLeftMouseUp, \
+    (CGSEventType)kCGEventRightMouseDown, \
+    (CGSEventType)kCGEventRightMouseUp, \
+    (CGSEventType)kCGEventMouseMoved, \
+    (CGSEventType)kCGEventLeftMouseDragged, \
+    (CGSEventType)kCGEventRightMouseDragged, \
+    (CGSEventType)kCGEventOtherMouseDown, \
+    (CGSEventType)kCGEventOtherMouseUp, \
+    (CGSEventType)kCGEventOtherMouseDragged
+
+#define KEY_EVENT_TYPES \
+    (CGSEventType)kCGEventKeyDown, \
+    (CGSEventType)kCGEventKeyUp, \
+    (CGSEventType)kCGEventFlagsChanged
+
+#define GESTURE_EVENT_TYPES \
+    kCGSEventGesture, \
+    kCGSEventFluidTouchGesture, \
+    kCGSEventDockControl
+
+bool eventIsOfType(CGEventRef event, CGSEventType type)
+{
+    return (CGSEventType)CGEventGetType(event) == type;
+}
+
+bool eventIsOfTypes(CGEventRef) { return false; }
+
+template<typename ... Types>
+bool eventIsOfTypes(CGEventRef event, CGSEventType first, Types ... rest)
+{
+    return eventIsOfType(event, first) || eventIsOfTypes(event, rest...);
+}
+
+bool eventIsOfGestureType(CGEventRef event, IOHIDEventType type)
+{
+    return (IOHIDEventType)CGEventGetIntegerValueField(event, kCGEventGestureHIDType) == type;
+}
+
+bool eventIsOfGestureTypes(CGEventRef) { return false; }
+
+template<typename ... Types>
+bool eventIsOfGestureTypes(CGEventRef event, IOHIDEventType first, Types ... rest)
+{
+    if (!eventIsOfTypes(event, GESTURE_EVENT_TYPES))
+        return false;
+    return eventIsOfGestureType(event, first) || eventIsOfGestureTypes(event, rest...);
+}
+
+#define FOR_EACH_CGEVENT_INTEGER_FIELD(macro) \
+    macro(true, kCGSEventTypeField) \
+    \
+    macro(eventIsOfTypes(rawEvent, kCGSEventScrollWheel, kCGSEventZoom), kCGScrollWheelEventDeltaAxis1) \
+    macro(eventIsOfTypes(rawEvent, kCGSEventScrollWheel, kCGSEventZoom), kCGScrollWheelEventDeltaAxis2) \
+    macro(eventIsOfTypes(rawEvent, kCGSEventScrollWheel, kCGSEventZoom), kCGScrollWheelEventDeltaAxis3) \
+    macro(eventIsOfTypes(rawEvent, kCGSEventScrollWheel, kCGSEventZoom), kCGScrollWheelEventIsContinuous) \
+    macro(eventIsOfTypes(rawEvent, kCGSEventScrollWheel, kCGSEventZoom), kCGScrollWheelEventMomentumPhase) \
+    macro(eventIsOfTypes(rawEvent, kCGSEventScrollWheel, kCGSEventZoom), kCGScrollWheelEventPointDeltaAxis1) \
+    macro(eventIsOfTypes(rawEvent, kCGSEventScrollWheel, kCGSEventZoom), kCGScrollWheelEventPointDeltaAxis2) \
+    macro(eventIsOfTypes(rawEvent, kCGSEventScrollWheel, kCGSEventZoom), kCGScrollWheelEventPointDeltaAxis3) \
+    macro(eventIsOfTypes(rawEvent, kCGSEventScrollWheel, kCGSEventZoom), kCGScrollWheelEventScrollCount) \
+    macro(eventIsOfTypes(rawEvent, kCGSEventScrollWheel, kCGSEventZoom), kCGScrollWheelEventScrollPhase) \
+    \
+    macro(eventIsOfTypes(rawEvent, MOUSE_EVENT_TYPES), kCGMouseEventButtonNumber) \
+    macro(eventIsOfTypes(rawEvent, MOUSE_EVENT_TYPES), kCGMouseEventClickState) \
+    macro(eventIsOfTypes(rawEvent, MOUSE_EVENT_TYPES), kCGMouseEventDeltaX) \
+    macro(eventIsOfTypes(rawEvent, MOUSE_EVENT_TYPES), kCGMouseEventDeltaY) \
+    macro(eventIsOfTypes(rawEvent, MOUSE_EVENT_TYPES), kCGMouseEventSubtype) \
+    macro(eventIsOfTypes(rawEvent, MOUSE_EVENT_TYPES), kCGMouseEventNumber) \
+    \
+    macro(eventIsOfTypes(rawEvent, KEY_EVENT_TYPES), kCGKeyboardEventAutorepeat) \
+    macro(eventIsOfTypes(rawEvent, KEY_EVENT_TYPES), kCGKeyboardEventKeyboardType) \
+    macro(eventIsOfTypes(rawEvent, KEY_EVENT_TYPES), kCGKeyboardEventKeycode) \
+    \
+    macro(eventIsOfTypes(rawEvent, GESTURE_EVENT_TYPES), kCGEventGestureHIDType) \
+    macro(eventIsOfTypes(rawEvent, GESTURE_EVENT_TYPES), kCGEventGestureBehavior) \
+    macro(eventIsOfTypes(rawEvent, GESTURE_EVENT_TYPES), kCGEventGestureFlavor) \
+    macro(eventIsOfTypes(rawEvent, GESTURE_EVENT_TYPES), kCGEventGestureMask) \
+    macro(eventIsOfTypes(rawEvent, GESTURE_EVENT_TYPES), kCGEventGesturePhase) \
+    macro(eventIsOfTypes(rawEvent, GESTURE_EVENT_TYPES), kCGEventGestureStage) \
+    \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeScroll), kCGEventScrollGestureFlagBits) \
+    \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeNavigationSwipe), kCGEventSwipeGestureFlagBits) \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeNavigationSwipe), kCGEventGestureSwipeMask) \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeNavigationSwipe), kCGEventGestureSwipeMotion) \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeNavigationSwipe), kCGEventGestureSwipeValue) \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeNavigationSwipe), kCGEventGestureFlavor) \
+    \
+    macro(eventIsOfGestureTypes(rawEvent, kCGHIDEventTypeGestureStarted, kCGHIDEventTypeGestureEnded), kCGEventGestureStartEndSeriesType)
+
+#define FOR_EACH_CGEVENT_DOUBLE_FIELD(macro) \
+    macro(eventIsOfTypes(rawEvent, GESTURE_EVENT_TYPES), kCGEventGestureProgress) \
+    \
+    macro(eventIsOfTypes(rawEvent, MOUSE_EVENT_TYPES), kCGMouseEventPressure) \
+    \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeZoom), kCGEventGestureZoomDeltaX) \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeZoom), kCGEventGestureZoomDeltaY) \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeZoom), kCGEventGestureZoomValue) \
+    \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeRotation), kCGEventGestureRotationValue) \
+    \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeScroll), kCGEventGestureScrollX) \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeScroll), kCGEventGestureScrollY) \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeScroll), kCGEventGestureScrollZ) \
+    \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeNavigationSwipe), kCGEventGestureSwipePositionX) \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeNavigationSwipe), kCGEventGestureSwipePositionY) \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeNavigationSwipe), kCGEventGestureSwipeProgress) \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeNavigationSwipe), kCGEventGestureSwipeVelocityX) \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeNavigationSwipe), kCGEventGestureSwipeVelocityY) \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeNavigationSwipe), kCGEventGestureSwipeVelocityZ) \
+    \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeForce), kCGEventTransitionProgress) \
+    macro(eventIsOfGestureType(rawEvent, kIOHIDEventTypeForce), kCGEventStagePressure)
+
+#define LOAD_INTEGER_FIELD_FROM_EVENT(eventTypeFilter, field) \
+^ { \
+    if (!(eventTypeFilter)) \
+        return; \
+    int64_t value = CGEventGetIntegerValueField(rawEvent, field); \
+    int64_t plainValue = CGEventGetIntegerValueField(rawPlainEvent, field); \
+    if (value != plainValue) \
+        dict[@#field] = @(value); \
+}();
+
+#define LOAD_DOUBLE_FIELD_FROM_EVENT(eventTypeFilter, field) \
+^ { \
+    if (!(eventTypeFilter)) \
+        return; \
+    double value = CGEventGetDoubleValueField(rawEvent, field); \
+    if (!isnan(value)) { \
+        double plainValue = CGEventGetDoubleValueField(rawPlainEvent, field); \
+        if (fabs(value - plainValue) >= FLT_EPSILON) \
+            dict[@#field] = @(value); \
+    } \
+}();
+
+#define STORE_INTEGER_FIELD_TO_EVENT(eventTypeFilter, field) \
+^ { \
+    if (!(eventTypeFilter)) \
+        return; \
+    NSNumber *value = dict[@#field]; \
+    if (value) \
+        CGEventSetIntegerValueField(rawEvent, field, value.unsignedLongLongValue); \
+}();
+
+#define STORE_DOUBLE_FIELD_TO_EVENT(eventTypeFilter, field) \
+^ { \
+    if (!(eventTypeFilter)) \
+        return; \
+    NSNumber *value = dict[@#field]; \
+    if (value) \
+        CGEventSetDoubleValueField(rawEvent, field, value.doubleValue); \
+}();
+
+@implementation EventSerializer
+
++ (NSDictionary *)dictionaryForEvent:(CGEventRef)rawEvent relativeToTime:(CGEventTimestamp)referenceTimestamp
+{
+    RetainPtr<CGEventRef> plainEvent = adoptCF(CGEventCreate(NULL));
+    CGEventRef rawPlainEvent = plainEvent.get();
+
+    NSMutableDictionary *dict = [[[NSMutableDictionary alloc] init] autorelease];
+
+    FOR_EACH_CGEVENT_INTEGER_FIELD(LOAD_INTEGER_FIELD_FROM_EVENT);
+    FOR_EACH_CGEVENT_DOUBLE_FIELD(LOAD_DOUBLE_FIELD_FROM_EVENT);
+
+    CGEventTimestamp timestamp = CGEventGetTimestamp(rawEvent);
+    dict[@"relativeTimeMS"] = @(std::max(static_cast<double>(timestamp - referenceTimestamp) / NSEC_PER_MSEC, 0.0));
+
+    CGSEventType eventType = (CGSEventType)CGEventGetIntegerValueField(rawEvent, kCGSEventTypeField);
+    if (eventType == kCGSEventGesture || eventType == kCGSEventFluidTouchGesture || eventType == kCGSEventDockControl) {
+        if (CGEventGetIntegerValueField(rawEvent, kCGEventGestureIsPreflight)) {
+            dict[@"kCGEventGestureIsPreflight"] = @YES;
+            dict[@"kCGEventGesturePreflightProgress"] = @(CGEventGetDoubleValueField(rawEvent, kCGEventGesturePreflightProgress));
+        }
+    }
+
+    dict[@"windowLocation"] = NSStringFromPoint(NSPointFromCGPoint(CGEventGetWindowLocation(rawEvent)));
+
+    auto flags = static_cast<CGEventFlags>(CGEventGetFlags(rawEvent) & ~NX_NONCOALSESCEDMASK);
+    auto plainFlags = static_cast<CGEventFlags>(CGEventGetFlags(rawPlainEvent) & ~NX_NONCOALSESCEDMASK);
+    if (flags != plainFlags)
+        dict[@"flags"] = @(flags);
+
+    return dict;
+}
+
++ (RetainPtr<CGEventRef>)createEventForDictionary:(NSDictionary *)dict inWindow:(NSWindow *)window relativeToTime:(CGEventTimestamp)referenceTimestamp
+{
+    RetainPtr<CGEventRef> event = adoptCF(CGEventCreate(NULL));
+    CGEventRef rawEvent = event.get();
+
+    FOR_EACH_CGEVENT_INTEGER_FIELD(STORE_INTEGER_FIELD_TO_EVENT);
+    FOR_EACH_CGEVENT_DOUBLE_FIELD(STORE_DOUBLE_FIELD_TO_EVENT);
+
+    if (dict[@"relativeTimeMS"])
+        CGEventSetTimestamp(event.get(), referenceTimestamp + static_cast<CGEventTimestamp>(([dict[@"relativeTimeMS"] doubleValue] * NSEC_PER_MSEC)));
+
+    if ([dict[@"kCGEventGestureIsPreflight"] boolValue]) {
+        CGEventSetIntegerValueField(rawEvent, kCGEventGestureIsPreflight, 1);
+        CGEventSetDoubleValueField(rawEvent, kCGEventGesturePreflightProgress, [dict[@"kCGEventGesturePreflightProgress"] doubleValue]);
+    }
+
+    if (dict[@"windowLocation"]) {
+        CGPoint windowLocation = NSPointToCGPoint(NSPointFromString(dict[@"windowLocation"]));
+        CGEventSetWindowLocation(rawEvent, windowLocation);
+
+        NSPoint screenPoint = [window convertRectToScreen:NSMakeRect(windowLocation.x, windowLocation.y, 1, 1)].origin;
+        CGEventSetLocation(rawEvent, CGPointMake(screenPoint.x, NSScreen.screens.firstObject.frame.size.height - screenPoint.y));
+    }
+
+    if (dict[@"flags"])
+        CGEventSetFlags(rawEvent, static_cast<CGEventFlags>([dict[@"flags"] unsignedLongLongValue]));
+
+    CGEventSetIntegerValueField(rawEvent, kCGSEventWindowIDField, window.windowNumber);
+
+    return event;
+}
+
+@end
+
+@implementation EventStreamPlayer
+
+const float eventDispatchTimerRate = 1. / 120.;
+
++ (void)playStream:(NSArray<NSDictionary *> *)eventDicts window:(NSWindow *)window completionHandler:(void(^)())completionHandler
+{
+    RetainPtr<EventStreamPlayer> player = adoptNS([[EventStreamPlayer alloc] init]);
+
+    player->_remainingEventDictionaries = adoptNS([eventDicts mutableCopy]);
+    player->_window = window;
+
+    if (completionHandler)
+        player->_completionHandler = makeBlockPtr(completionHandler);
+
+    player->_startTime = mach_absolute_time();
+
+    [NSTimer scheduledTimerWithTimeInterval:eventDispatchTimerRate target:player.get() selector:@selector(playbackTimerFired:) userInfo:nil repeats:YES];
+}
+
+- (void)playbackTimerFired:(NSTimer *)timer
+{
+    auto removeList = adoptNS([[NSMutableArray alloc] init]);
+    NSEvent *nsEvent = nil;
+    for (id eventDict in _remainingEventDictionaries.get()) {
+        RetainPtr<CGEventRef> event = [EventSerializer createEventForDictionary:eventDict inWindow:_window.get() relativeToTime:_startTime];
+        if (CGEventGetTimestamp(event.get()) < mach_absolute_time()) {
+            nsEvent = [NSEvent eventWithCGEvent:event.get()];
+            [NSApp postEvent:nsEvent atStart:NO];
+            [removeList addObject:eventDict];
+        }
+    }
+    [_remainingEventDictionaries removeObjectsInArray:removeList.get()];
+
+    if ([_remainingEventDictionaries count])
+        return;
+
+#if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
+    NSEventType applicationDefinedEventType = NSEventTypeApplicationDefined;
+#else
+    NSEventType applicationDefinedEventType = NSApplicationDefined;
+#endif
+    [NSApp postEvent:[NSEvent otherEventWithType:applicationDefinedEventType location:NSZeroPoint modifierFlags:0 timestamp:0 windowNumber:0 context:0 subtype:0 data1:42 data2:0] atStart:NO];
+    // Block until we send the last event we posted.
+    while (true) {
+        NSEvent *nextEvent = [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate dateWithTimeIntervalSinceNow:eventDispatchTimerRate] inMode:NSDefaultRunLoopMode dequeue:YES];
+        if (nextEvent.type == applicationDefinedEventType && nextEvent.data1 == 42)
+            break;
+        if (nextEvent)
+            [NSApp sendEvent:nextEvent];
+    }
+
+    if (_completionHandler)
+        _completionHandler();
+
+    [timer invalidate];
+}
+
+@end
+
+#endif
diff --git a/Tools/TestRunnerShared/EventSerialization/mac/SharedEventStreamsMac.h b/Tools/TestRunnerShared/EventSerialization/mac/SharedEventStreamsMac.h
new file mode 100644 (file)
index 0000000..e3d826a
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if PLATFORM(MAC)
+
+@class NSString;
+
+NSString *beginSwipeBackEventStream();
+NSString *completeSwipeBackEventStream();
+
+#endif
diff --git a/Tools/TestRunnerShared/EventSerialization/mac/SharedEventStreamsMac.mm b/Tools/TestRunnerShared/EventSerialization/mac/SharedEventStreamsMac.mm
new file mode 100644 (file)
index 0000000..1824059
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import "config.h"
+#import "SharedEventStreamsMac.h"
+
+#if PLATFORM(MAC)
+
+#define QUOTE(...) @(#__VA_ARGS__)
+
+NSString *beginSwipeBackEventStream()
+{
+    return QUOTE([
+        {
+            "relativeTimeMS" : 0,
+            "kCGEventScrollGestureFlagBits" : 1,
+            "kCGEventGestureHIDType" : 6,
+            "kCGSEventTypeField" : 29,
+            "kCGEventGesturePhase" : 128,
+            "windowLocation" : "{400, 300}"
+        },
+        {
+            "relativeTimeMS" : 8,
+            "kCGEventGestureHIDType" : 61,
+            "kCGSEventTypeField" : 29,
+            "kCGEventGestureStartEndSeriesType" : 6,
+            "windowLocation" : "{400, 300}"
+        },
+        {
+            "kCGEventGestureHIDType" : 6,
+            "relativeTimeMS" : 8,
+            "windowLocation" : "{400, 300}",
+            "kCGEventGesturePhase" : 1,
+            "kCGEventScrollGestureFlagBits" : 1,
+            "kCGSEventTypeField" : 29,
+            "kCGEventGestureScrollX" : 2
+        },
+        {
+            "relativeTimeMS" : 8,
+            "windowLocation" : "{400, 300}",
+            "kCGScrollWheelEventScrollPhase" : 1,
+            "kCGScrollWheelEventIsContinuous" : 1,
+            "kCGScrollWheelEventPointDeltaAxis2" : 1,
+            "kCGSEventTypeField" : 22
+        },
+        {
+            "kCGEventGestureHIDType" : 6,
+            "relativeTimeMS" : 17,
+            "windowLocation" : "{400, 300}",
+            "kCGEventGestureScrollY" : 1,
+            "kCGEventGesturePhase" : 2,
+            "kCGEventScrollGestureFlagBits" : 1,
+            "kCGSEventTypeField" : 29,
+            "kCGEventGestureScrollX" : 12
+        },
+        {
+            "kCGScrollWheelEventPointDeltaAxis1" : 1,
+            "relativeTimeMS" : 17,
+            "kCGScrollWheelEventScrollPhase" : 2,
+            "kCGScrollWheelEventIsContinuous" : 1,
+            "kCGScrollWheelEventPointDeltaAxis2" : 4,
+            "windowLocation" : "{400, 300}",
+            "kCGSEventTypeField" : 22
+        },
+        {
+            "kCGEventGestureHIDType" : 6,
+            "relativeTimeMS" : 25,
+            "windowLocation" : "{400, 300}",
+            "kCGEventGestureScrollY" : 2,
+            "kCGEventGesturePhase" : 2,
+            "kCGEventScrollGestureFlagBits" : 1,
+            "kCGSEventTypeField" : 29,
+            "kCGEventGestureScrollX" : 23
+        },
+        {
+            "kCGScrollWheelEventDeltaAxis2" : 1,
+            "kCGScrollWheelEventPointDeltaAxis1" : 1,
+            "relativeTimeMS" : 25,
+            "kCGScrollWheelEventIsContinuous" : 1,
+            "kCGScrollWheelEventScrollPhase" : 2,
+            "kCGScrollWheelEventPointDeltaAxis2" : 11,
+            "windowLocation" : "{400, 300}",
+            "kCGSEventTypeField" : 22
+        },
+        {
+            "kCGEventGestureHIDType" : 6,
+            "relativeTimeMS" : 33,
+            "windowLocation" : "{400, 300}",
+            "kCGEventGestureScrollY" : 2,
+            "kCGEventGesturePhase" : 2,
+            "kCGEventScrollGestureFlagBits" : 1,
+            "kCGSEventTypeField" : 29,
+            "kCGEventGestureScrollX" : 28
+        },
+        {
+            "kCGScrollWheelEventDeltaAxis2" : 2,
+            "kCGScrollWheelEventPointDeltaAxis1" : 1,
+            "relativeTimeMS" : 33,
+            "kCGScrollWheelEventIsContinuous" : 1,
+            "kCGScrollWheelEventScrollPhase" : 2,
+            "kCGScrollWheelEventPointDeltaAxis2" : 16,
+            "windowLocation" : "{400, 300}",
+            "kCGSEventTypeField" : 22
+        },
+        {
+            "kCGEventGestureHIDType" : 6,
+            "relativeTimeMS" : 41,
+            "windowLocation" : "{400, 300}",
+            "kCGEventGestureScrollY" : 1,
+            "kCGEventGesturePhase" : 2,
+            "kCGEventScrollGestureFlagBits" : 1,
+            "kCGSEventTypeField" : 29,
+            "kCGEventGestureScrollX" : 35
+        },
+        {
+            "kCGScrollWheelEventDeltaAxis2" : 2,
+            "kCGScrollWheelEventPointDeltaAxis1" : 1,
+            "relativeTimeMS" : 41,
+            "kCGScrollWheelEventIsContinuous" : 1,
+            "kCGScrollWheelEventScrollPhase" : 2,
+            "kCGScrollWheelEventPointDeltaAxis2" : 24,
+            "windowLocation" : "{400, 300}",
+            "kCGSEventTypeField" : 22
+        },
+        {
+            "kCGEventGestureHIDType" : 6,
+            "relativeTimeMS" : 49,
+            "windowLocation" : "{400, 300}",
+            "kCGEventGestureScrollY" : -1,
+            "kCGEventGesturePhase" : 2,
+            "kCGEventScrollGestureFlagBits" : 1,
+            "kCGSEventTypeField" : 29,
+            "kCGEventGestureScrollX" : 45
+        },
+        {
+            "kCGScrollWheelEventScrollCount" : 1,
+            "kCGScrollWheelEventDeltaAxis2" : 4,
+            "kCGScrollWheelEventPointDeltaAxis1" : -1,
+            "relativeTimeMS" : 49,
+            "kCGScrollWheelEventIsContinuous" : 1,
+            "kCGScrollWheelEventScrollPhase" : 2,
+            "kCGScrollWheelEventPointDeltaAxis2" : 37,
+            "windowLocation" : "{400, 300}",
+            "kCGSEventTypeField" : 22
+        },
+        {
+            "kCGEventGestureHIDType" : 6,
+            "relativeTimeMS" : 57,
+            "windowLocation" : "{400, 300}",
+            "kCGEventGestureScrollY" : -3,
+            "kCGEventGesturePhase" : 2,
+            "kCGEventScrollGestureFlagBits" : 1,
+            "kCGSEventTypeField" : 29,
+            "kCGEventGestureScrollX" : 57
+        },
+        {
+            "kCGScrollWheelEventScrollCount" : 1,
+            "kCGScrollWheelEventDeltaAxis2" : 5,
+            "kCGScrollWheelEventPointDeltaAxis1" : -1,
+            "relativeTimeMS" : 57,
+            "kCGScrollWheelEventIsContinuous" : 1,
+            "kCGScrollWheelEventScrollPhase" : 2,
+            "kCGScrollWheelEventPointDeltaAxis2" : 54,
+            "windowLocation" : "{400, 300}",
+            "kCGSEventTypeField" : 22
+        },
+        {
+            "kCGEventGestureHIDType" : 6,
+            "relativeTimeMS" : 65,
+            "windowLocation" : "{400, 300}",
+            "kCGEventGestureScrollY" : -5,
+            "kCGEventGesturePhase" : 2,
+            "kCGEventScrollGestureFlagBits" : 1,
+            "kCGSEventTypeField" : 29,
+            "kCGEventGestureScrollX" : 81
+        },
+        {
+            "kCGScrollWheelEventScrollCount" : 1,
+            "kCGScrollWheelEventDeltaAxis2" : 9,
+            "kCGScrollWheelEventPointDeltaAxis1" : -2,
+            "relativeTimeMS" : 65,
+            "kCGScrollWheelEventIsContinuous" : 1,
+            "kCGScrollWheelEventScrollPhase" : 2,
+            "kCGScrollWheelEventPointDeltaAxis2" : 92,
+            "windowLocation" : "{400, 300}",
+            "kCGSEventTypeField" : 22
+        },
+    ]);
+}
+
+NSString *completeSwipeBackEventStream()
+{
+    return QUOTE([
+        {
+            "kCGEventGestureHIDType" : 6,
+            "relativeTimeMS" : 73,
+            "windowLocation" : "{400, 300}",
+            "kCGEventGestureScrollY" : -3,
+            "kCGEventGesturePhase" : 2,
+            "kCGEventScrollGestureFlagBits" : 1,
+            "kCGSEventTypeField" : 29,
+            "kCGEventGestureScrollX" : 75
+        },
+        {
+            "kCGScrollWheelEventScrollCount" : 1,
+            "kCGScrollWheelEventDeltaAxis2" : 11,
+            "kCGScrollWheelEventPointDeltaAxis1" : -1,
+            "relativeTimeMS" : 73,
+            "kCGScrollWheelEventIsContinuous" : 1,
+            "kCGScrollWheelEventScrollPhase" : 2,
+            "kCGScrollWheelEventPointDeltaAxis2" : 106,
+            "windowLocation" : "{400, 300}",
+            "kCGSEventTypeField" : 22
+        },
+        {
+            "kCGEventGestureHIDType" : 6,
+            "relativeTimeMS" : 81,
+            "windowLocation" : "{400, 300}",
+            "kCGEventGestureScrollY" : -3,
+            "kCGEventGesturePhase" : 2,
+            "kCGEventScrollGestureFlagBits" : 1,
+            "kCGSEventTypeField" : 29,
+            "kCGEventGestureScrollX" : 85
+        },
+        {
+            "kCGScrollWheelEventScrollCount" : 1,
+            "kCGScrollWheelEventDeltaAxis2" : 13,
+            "kCGScrollWheelEventPointDeltaAxis1" : -1,
+            "relativeTimeMS" : 81,
+            "kCGScrollWheelEventIsContinuous" : 1,
+            "kCGScrollWheelEventScrollPhase" : 2,
+            "kCGScrollWheelEventPointDeltaAxis2" : 127,
+            "windowLocation" : "{400, 300}",
+            "kCGSEventTypeField" : 22
+        },
+        {
+            "kCGEventGestureHIDType" : 6,
+            "relativeTimeMS" : 89,
+            "windowLocation" : "{400, 300}",
+            "kCGEventGestureScrollY" : -1,
+            "kCGEventGesturePhase" : 2,
+            "kCGEventScrollGestureFlagBits" : 1,
+            "kCGSEventTypeField" : 29,
+            "kCGEventGestureScrollX" : 91
+        },
+        {
+            "kCGScrollWheelEventScrollCount" : 1,
+            "kCGScrollWheelEventDeltaAxis2" : 14,
+            "kCGScrollWheelEventPointDeltaAxis1" : -1,
+            "relativeTimeMS" : 89,
+            "kCGScrollWheelEventIsContinuous" : 1,
+            "kCGScrollWheelEventScrollPhase" : 2,
+            "kCGScrollWheelEventPointDeltaAxis2" : 139,
+            "windowLocation" : "{400, 300}",
+            "kCGSEventTypeField" : 22
+        },
+        {
+            "kCGEventGestureHIDType" : 6,
+            "relativeTimeMS" : 97,
+            "windowLocation" : "{400, 300}",
+            "kCGEventGestureScrollY" : 2,
+            "kCGEventGesturePhase" : 2,
+            "kCGEventScrollGestureFlagBits" : 1,
+            "kCGSEventTypeField" : 29,
+            "kCGEventGestureScrollX" : 136
+        },
+        {
+            "kCGScrollWheelEventScrollCount" : 1,
+            "kCGScrollWheelEventDeltaAxis2" : 20,
+            "kCGScrollWheelEventPointDeltaAxis1" : 1,
+            "relativeTimeMS" : 97,
+            "kCGScrollWheelEventIsContinuous" : 1,
+            "kCGScrollWheelEventScrollPhase" : 2,
+            "kCGScrollWheelEventPointDeltaAxis2" : 204,
+            "windowLocation" : "{400, 300}",
+            "kCGSEventTypeField" : 22
+        },
+        {
+            "kCGEventGestureHIDType" : 6,
+            "relativeTimeMS" : 105,
+            "windowLocation" : "{400, 300}",
+            "kCGEventGestureScrollY" : 5,
+            "kCGEventGesturePhase" : 2,
+            "kCGEventScrollGestureFlagBits" : 1,
+            "kCGSEventTypeField" : 29,
+            "kCGEventGestureScrollX" : 92
+        },
+        {
+            "kCGScrollWheelEventScrollCount" : 1,
+            "kCGScrollWheelEventDeltaAxis2" : 14,
+            "kCGScrollWheelEventPointDeltaAxis1" : 2,
+            "relativeTimeMS" : 105,
+            "kCGScrollWheelEventIsContinuous" : 1,
+            "kCGScrollWheelEventScrollPhase" : 2,
+            "kCGScrollWheelEventPointDeltaAxis2" : 136,
+            "windowLocation" : "{400, 300}",
+            "kCGSEventTypeField" : 22
+        },
+        {
+            "kCGEventGestureHIDType" : 6,
+            "relativeTimeMS" : 113,
+            "windowLocation" : "{400, 300}",
+            "kCGEventGestureScrollY" : 14,
+            "kCGEventGesturePhase" : 2,
+            "kCGEventScrollGestureFlagBits" : 1,
+            "kCGSEventTypeField" : 29,
+            "kCGEventGestureScrollX" : 133
+        },
+        {
+            "kCGScrollWheelEventScrollPhase" : 2,
+            "kCGScrollWheelEventPointDeltaAxis2" : 192,
+            "kCGSEventTypeField" : 22,
+            "kCGScrollWheelEventDeltaAxis1" : 1,
+            "kCGScrollWheelEventIsContinuous" : 1,
+            "relativeTimeMS" : 113,
+            "kCGScrollWheelEventScrollCount" : 1,
+            "kCGScrollWheelEventDeltaAxis2" : 19,
+            "windowLocation" : "{400, 300}",
+            "kCGScrollWheelEventPointDeltaAxis1" : 7
+        },
+        {
+            "relativeTimeMS" : 121,
+            "kCGEventScrollGestureFlagBits" : 1,
+            "kCGEventGestureHIDType" : 6,
+            "kCGSEventTypeField" : 29,
+            "kCGEventGesturePhase" : 4,
+            "windowLocation" : "{400, 300}"
+        },
+        {
+            "relativeTimeMS" : 121,
+            "kCGEventGestureHIDType" : 62,
+            "kCGSEventTypeField" : 29,
+            "kCGEventGestureStartEndSeriesType" : 6,
+            "windowLocation" : "{400, 300}"
+        },
+        {
+            "kCGScrollWheelEventScrollCount" : 1,
+            "relativeTimeMS" : 139,
+            "windowLocation" : "{400, 300}",
+            "kCGSEventTypeField" : 22,
+            "kCGScrollWheelEventScrollPhase" : 4,
+            "kCGScrollWheelEventIsContinuous" : 1
+        }
+    ]);
+}
+
+#endif
index c4c3f27..f66ae15 100644 (file)
@@ -162,6 +162,11 @@ interface UIScriptController {
     //  }
     void sendEventStream(DOMString eventsJSON, object callback);
 
+    void beginBackSwipe(object callback);
+    void completeBackSwipe(object callback);
+
+    void playBackEventStream(DOMString eventStream, object callback);
+
     // Equivalent of pressing the Done button in the form accessory bar.
     void dismissFormAccessoryView();
 
index c7aecb3..612c9e2 100644 (file)
@@ -194,6 +194,11 @@ JSObjectRef UIScriptController::contentsOfUserInterfaceItem(JSStringRef interfac
 }
 #endif
 
+void UIScriptController::playBackEventStream(JSStringRef stream, JSValueRef callback)
+{
+    platformPlayBackEventStream(stream, callback);
+}
+
 #if !PLATFORM(IOS)
 void UIScriptController::touchDownAtPoint(long x, long y, long touchCount, JSValueRef)
 {
@@ -418,6 +423,18 @@ void UIScriptController::insertText(JSStringRef, int, int)
 {
 }
 
+void UIScriptController::beginBackSwipe(JSValueRef callback)
+{
+}
+
+void UIScriptController::completeBackSwipe(JSValueRef callback)
+{
+}
+
+void UIScriptController::platformPlayBackEventStream(JSStringRef, JSValueRef)
+{
+}
+
 #endif
 
 void UIScriptController::uiScriptComplete(JSStringRef result)
index db24ef5..46c28b1 100644 (file)
@@ -95,6 +95,9 @@ public:
     void immediateScrollToOffset(long x, long y);
     void immediateZoomToScale(double scale);
 
+    void beginBackSwipe(JSValueRef callback);
+    void completeBackSwipe(JSValueRef callback);
+
     void setDidStartFormControlInteractionCallback(JSValueRef);
     JSValueRef didStartFormControlInteractionCallback() const;
 
@@ -122,6 +125,8 @@ public:
     void setDidEndScrollingCallback(JSValueRef);
     JSValueRef didEndScrollingCallback() const;
 
+    void playBackEventStream(JSStringRef stream, JSValueRef callback);
+
     double zoomScale() const;
     double minimumZoomScale() const;
     double maximumZoomScale() const;
@@ -166,6 +171,7 @@ private:
     void platformSetDidHideKeyboardCallback();
     void platformSetDidEndScrollingCallback();
     void platformClearAllCallbacks();
+    void platformPlayBackEventStream(JSStringRef, JSValueRef);
 
     JSClassRef wrapperClass() final;
 
diff --git a/Tools/TestRunnerShared/spi/CoreGraphicsSPI.h b/Tools/TestRunnerShared/spi/CoreGraphicsSPI.h
new file mode 100644 (file)
index 0000000..e75be07
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#import <wtf/Platform.h>
+
+#if USE(APPLE_INTERNAL_SDK)
+
+#import <CoreGraphics/CGEventPrivate.h>
+#import <CoreGraphics/CGSEvent.h>
+
+#else
+
+WTF_EXTERN_C_BEGIN
+
+static const CGEventField kCGSEventWindowIDField = (CGEventField)51;
+static const CGEventField kCGSEventTypeField = (CGEventField)55;
+static const CGEventField kCGEventGestureHIDType = (CGEventField)110;
+static const CGEventField kCGEventGestureIsPreflight = (CGEventField)111;
+static const CGEventField kCGEventGestureZoomValue = (CGEventField)113;
+static const CGEventField kCGEventGestureRotationValue = (CGEventField)114;
+static const CGEventField kCGEventGestureSwipeValue = (CGEventField)115;
+static const CGEventField kCGEventGesturePreflightProgress = (CGEventField)116;
+static const CGEventField kCGEventGestureStartEndSeriesType = (CGEventField)117;
+static const CGEventField kCGEventGestureScrollX = (CGEventField)118;
+static const CGEventField kCGEventGestureScrollY = (CGEventField)119;
+static const CGEventField kCGEventGestureScrollZ = (CGEventField)120;
+static const CGEventField kCGEventGestureSwipeMotion = (CGEventField)123;
+static const CGEventField kCGEventGestureSwipeProgress = (CGEventField)124;
+static const CGEventField kCGEventGestureSwipePositionX = (CGEventField)125;
+static const CGEventField kCGEventGestureSwipePositionY = (CGEventField)126;
+static const CGEventField kCGEventGestureSwipeVelocityX = (CGEventField)129;
+static const CGEventField kCGEventGestureSwipeVelocityY = (CGEventField)130;
+static const CGEventField kCGEventGestureSwipeVelocityZ = (CGEventField)131;
+static const CGEventField kCGEventGesturePhase = (CGEventField)132;
+static const CGEventField kCGEventGestureMask = (CGEventField)133;
+static const CGEventField kCGEventGestureSwipeMask = (CGEventField)134;
+static const CGEventField kCGEventScrollGestureFlagBits = (CGEventField)135;
+static const CGEventField kCGEventSwipeGestureFlagBits = (CGEventField)136;
+static const CGEventField kCGEventGestureFlavor = (CGEventField)138;
+static const CGEventField kCGEventGestureZoomDeltaX = (CGEventField)139;
+static const CGEventField kCGEventGestureZoomDeltaY = (CGEventField)140;
+static const CGEventField kCGEventGestureProgress = (CGEventField)142;
+static const CGEventField kCGEventGestureStage = (CGEventField)143;
+static const CGEventField kCGEventGestureBehavior = (CGEventField)144;
+static const CGEventField kCGEventTransitionProgress = (CGEventField)147;
+static const CGEventField kCGEventStagePressure = (CGEventField)148;
+
+enum {
+    kCGSEventScrollWheel = 22,
+    kCGSEventZoom = 28,
+    kCGSEventGesture = 29,
+    kCGSEventDockControl = 30,
+    kCGSEventFluidTouchGesture = 31,
+};
+typedef uint32_t CGSEventType;
+
+enum {
+    kCGHIDEventTypeGestureStarted = 61,
+    kCGHIDEventTypeGestureEnded = 62,
+};
+typedef uint32_t CGSHIDEventType;
+
+CGPoint CGEventGetWindowLocation(CGEventRef);
+void CGEventSetWindowLocation(CGEventRef, CGPoint);
+
+WTF_EXTERN_C_END
+
+#endif // USE(APPLE_INTERNAL_SDK)
similarity index 97%
rename from Tools/WebKitTestRunner/ios/IOKitSPI.h
rename to Tools/TestRunnerShared/spi/IOKitSPI.h
index 787cc9f..73e4b6e 100644 (file)
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef IOKitSPI_h
-#define IOKitSPI_h
+#pragma once
 
 #import <wtf/Platform.h>
 
-#if PLATFORM(IOS)
-
 #if USE(APPLE_INTERNAL_SDK)
 
 #import <IOKit/hid/IOHIDEvent.h>
@@ -89,7 +86,13 @@ enum {
     kIOHIDEventTypeNULL,
     kIOHIDEventTypeVendorDefined,
     kIOHIDEventTypeKeyboard = 3,
+    kIOHIDEventTypeRotation = 5,
+    kIOHIDEventTypeScroll = 6,
+    kIOHIDEventTypeZoom = 8,
     kIOHIDEventTypeDigitizer = 11,
+    kIOHIDEventTypeNavigationSwipe = 16,
+    kIOHIDEventTypeForce = 32,
+
 };
 typedef uint32_t IOHIDEventType;
 
@@ -198,7 +201,3 @@ enum {
 WTF_EXTERN_C_END
 
 #endif // USE(APPLE_INTERNAL_SDK)
-
-#endif // PLATFORM(IOS)
-
-#endif // IOKitSPI_h
index 70d9401..24f27b2 100644 (file)
@@ -71,7 +71,6 @@ public:
     void mouseMoveTo(double x, double y);
     void mouseScrollBy(int x, int y);
     void mouseScrollByWithWheelAndMomentumPhases(int x, int y, int phase, int momentum);
-    void swipeGestureWithWheelAndMomentumPhases(int x, int y, int phase, int momentum);
     void continuousMouseScrollBy(int x, int y, bool paged);
 
     void leapForward(int milliseconds);
index f3280bb..d5b8038 100644 (file)
@@ -34,7 +34,6 @@ interface EventSendingController {
     void mouseForceChanged(double force);
     void mouseScrollBy(long x, long y);
     void mouseScrollByWithWheelAndMomentumPhases(long x, long y, DOMString phase, DOMString momentum);
-    void swipeGestureWithWheelAndMomentumPhases(long x, long y, DOMString phase, DOMString momentum);
     void continuousMouseScrollBy(long x, long y, optional boolean paged);
     object contextClick();
     void scheduleAsynchronousClick();
index f81982c..9a0ff65 100644 (file)
@@ -483,38 +483,6 @@ void EventSendingController::mouseScrollByWithWheelAndMomentumPhases(int x, int
     WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get());
 }
 
-void EventSendingController::swipeGestureWithWheelAndMomentumPhases(int x, int y, JSStringRef phaseStr, JSStringRef momentumStr)
-{
-    WKRetainPtr<WKStringRef> EventSenderMessageName(AdoptWK, WKStringCreateWithUTF8CString("EventSender"));
-    WKRetainPtr<WKMutableDictionaryRef> EventSenderMessageBody(AdoptWK, WKMutableDictionaryCreate());
-
-    WKRetainPtr<WKStringRef> subMessageKey(AdoptWK, WKStringCreateWithUTF8CString("SubMessage"));
-    WKRetainPtr<WKStringRef> subMessageName(AdoptWK, WKStringCreateWithUTF8CString("SwipeGestureWithWheelAndMomentumPhases"));
-    WKDictionarySetItem(EventSenderMessageBody.get(), subMessageKey.get(), subMessageName.get());
-
-    WKRetainPtr<WKStringRef> xKey(AdoptWK, WKStringCreateWithUTF8CString("X"));
-    WKRetainPtr<WKDoubleRef> xRef(AdoptWK, WKDoubleCreate(x));
-    WKDictionarySetItem(EventSenderMessageBody.get(), xKey.get(), xRef.get());
-
-    WKRetainPtr<WKStringRef> yKey(AdoptWK, WKStringCreateWithUTF8CString("Y"));
-    WKRetainPtr<WKDoubleRef> yRef(AdoptWK, WKDoubleCreate(y));
-    WKDictionarySetItem(EventSenderMessageBody.get(), yKey.get(), yRef.get());
-
-    uint64_t phase = cgEventPhaseFromString(phaseStr);
-    uint64_t momentum = cgEventMomentumPhaseFromString(momentumStr);
-
-    WKRetainPtr<WKStringRef> phaseKey(AdoptWK, WKStringCreateWithUTF8CString("Phase"));
-    WKRetainPtr<WKUInt64Ref> phaseRef(AdoptWK, WKUInt64Create(phase));
-    WKDictionarySetItem(EventSenderMessageBody.get(), phaseKey.get(), phaseRef.get());
-
-    WKRetainPtr<WKStringRef> momentumKey(AdoptWK, WKStringCreateWithUTF8CString("Momentum"));
-    WKRetainPtr<WKUInt64Ref> momentumRef(AdoptWK, WKUInt64Create(momentum));
-    WKDictionarySetItem(EventSenderMessageBody.get(), momentumKey.get(), momentumRef.get());
-
-    WKBundlePageForceRepaint(InjectedBundle::singleton().page()->page()); // Triggers a scrolling tree commit.
-    WKBundlePagePostMessage(InjectedBundle::singleton().page()->page(), EventSenderMessageName.get(), EventSenderMessageBody.get());
-}
-
 void EventSendingController::continuousMouseScrollBy(int x, int y, bool paged)
 {
     WKRetainPtr<WKStringRef> EventSenderMessageName(AdoptWK, WKStringCreateWithUTF8CString("EventSender"));
index 3eb8129..2254b34 100644 (file)
@@ -52,7 +52,6 @@ public:
     void mouseForceChanged(double force);
     void mouseScrollBy(int x, int y);
     void mouseScrollByWithWheelAndMomentumPhases(int x, int y, JSStringRef phase, JSStringRef momentum);
-    void swipeGestureWithWheelAndMomentumPhases(int x, int y, JSStringRef phase, JSStringRef momentum);
     void continuousMouseScrollBy(int x, int y, bool paged);
     JSValueRef contextClick();
     void leapForward(int milliseconds);
index ac54a1c..cab3f18 100644 (file)
@@ -103,11 +103,6 @@ void EventSenderProxy::mouseScrollByWithWheelAndMomentumPhases(int x, int y, int
     // Write me.
 }
 
-void EventSenderProxy::swipeGestureWithWheelAndMomentumPhases(int, int, int, int)
-{
-    // Write me.
-}
-
 void EventSenderProxy::continuousMouseScrollBy(int x, int y, bool paged)
 {
     // Write me.
index 37654ba..9b709e3 100644 (file)
@@ -1315,23 +1315,6 @@ void TestController::didReceiveMessageFromInjectedBundle(WKStringRef messageName
             return;
         }
 
-        if (WKStringIsEqualToUTF8CString(subMessageName, "SwipeGestureWithWheelAndMomentumPhases")) {
-            WKRetainPtr<WKStringRef> xKey = adoptWK(WKStringCreateWithUTF8CString("X"));
-            double x = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, xKey.get())));
-
-            WKRetainPtr<WKStringRef> yKey = adoptWK(WKStringCreateWithUTF8CString("Y"));
-            double y = WKDoubleGetValue(static_cast<WKDoubleRef>(WKDictionaryGetItemForKey(messageBodyDictionary, yKey.get())));
-
-            WKRetainPtr<WKStringRef> phaseKey = adoptWK(WKStringCreateWithUTF8CString("Phase"));
-            int phase = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, phaseKey.get()))));
-            WKRetainPtr<WKStringRef> momentumKey = adoptWK(WKStringCreateWithUTF8CString("Momentum"));
-            int momentum = static_cast<int>(WKUInt64GetValue(static_cast<WKUInt64Ref>(WKDictionaryGetItemForKey(messageBodyDictionary, momentumKey.get()))));
-
-            m_eventSenderProxy->swipeGestureWithWheelAndMomentumPhases(x, y, phase, momentum);
-
-            return;
-        }
-
         ASSERT_NOT_REACHED();
     }
 
index 21e4e6e..0b214ab 100644 (file)
                29A8FCDD145F0337009045A6 /* JSAccessibilityTextMarkerRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 29A8FCE1345E7021006AA5A6 /* JSAccessibilityTextMarkerRange.cpp */; };
                29A8FCE2145F037B009045A6 /* AccessibilityTextMarkerRange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 29A8FCE1145F037B009045A6 /* AccessibilityTextMarkerRange.cpp */; };
                29A8FCE5145F0464009045A6 /* AccessibilityTextMarkerRangeMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 29A8FCE4145F0464009045A6 /* AccessibilityTextMarkerRangeMac.mm */; };
+               2DB6187E1D7D58D400978D19 /* CoreGraphicsSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DB6187D1D7D58D400978D19 /* CoreGraphicsSPI.h */; };
+               2DD4C49A1D6E7D3B0007379C /* EventSerializerMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DD4C4981D6E7D3B0007379C /* EventSerializerMac.h */; };
+               2DD4C49B1D6E7D3B0007379C /* EventSerializerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2DD4C4991D6E7D3B0007379C /* EventSerializerMac.mm */; };
+               2DFA98481D7F70CF00AFF2C9 /* SharedEventStreamsMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 2DFA98461D7F70CF00AFF2C9 /* SharedEventStreamsMac.h */; };
+               2DFA98491D7F70CF00AFF2C9 /* SharedEventStreamsMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2DFA98471D7F70CF00AFF2C9 /* SharedEventStreamsMac.mm */; };
                2E34C90018B68808000067BB /* WebKitTestRunnerInjectedBundle.bundle in Copy Plug-Ins */ = {isa = PBXBuildFile; fileRef = BC25186211D15D54002EBC01 /* WebKitTestRunnerInjectedBundle.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
                2E63ED8A1891AD7E002A7AFC /* AccessibilityControllerIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E63ED751891ACE9002A7AFC /* AccessibilityControllerIOS.mm */; };
                2E63ED8B1891AD7E002A7AFC /* AccessibilityTextMarkerIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2E63ED771891ACE9002A7AFC /* AccessibilityTextMarkerIOS.mm */; };
                0FEB90A31905BC6A000FDBF3 /* CrashReporterInfo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = CrashReporterInfo.mm; path = cocoa/CrashReporterInfo.mm; sourceTree = "<group>"; };
                0FEBF8581BB61DF20028722D /* HIDEventGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HIDEventGenerator.h; sourceTree = "<group>"; };
                0FEBF8591BB61DF20028722D /* HIDEventGenerator.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = HIDEventGenerator.mm; sourceTree = "<group>"; };
-               0FEBF85B1BB62A370028722D /* IOKitSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IOKitSPI.h; sourceTree = "<group>"; };
+               0FEBF85B1BB62A370028722D /* IOKitSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = IOKitSPI.h; path = ../TestRunnerShared/spi/IOKitSPI.h; sourceTree = "<group>"; };
                0FEBF85C1BB62D460028722D /* UIKitSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = UIKitSPI.h; sourceTree = "<group>"; };
                1A3326051B75396500F89F62 /* TestOptions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TestOptions.h; sourceTree = "<group>"; };
                1CA211C71BCA107300B2101F /* FontWithFeatures.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = FontWithFeatures.otf; sourceTree = "<group>"; };
                29A8FCE1345E7021006AA5A6 /* JSAccessibilityTextMarkerRange.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSAccessibilityTextMarkerRange.cpp; sourceTree = "<group>"; };
                29A8FCE1345E7021006AA5A7 /* JSAccessibilityTextMarkerRange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSAccessibilityTextMarkerRange.h; sourceTree = "<group>"; };
                29A8FCE4145F0464009045A6 /* AccessibilityTextMarkerRangeMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AccessibilityTextMarkerRangeMac.mm; sourceTree = "<group>"; };
+               2DB6187D1D7D58D400978D19 /* CoreGraphicsSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CoreGraphicsSPI.h; path = ../TestRunnerShared/spi/CoreGraphicsSPI.h; sourceTree = "<group>"; };
                2DCE2CD11B84524500C7F832 /* TestControllerCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = TestControllerCocoa.mm; path = cocoa/TestControllerCocoa.mm; sourceTree = "<group>"; };
+               2DD4C4981D6E7D3B0007379C /* EventSerializerMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = EventSerializerMac.h; path = mac/EventSerializerMac.h; sourceTree = "<group>"; };
+               2DD4C4991D6E7D3B0007379C /* EventSerializerMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = EventSerializerMac.mm; path = mac/EventSerializerMac.mm; sourceTree = "<group>"; };
+               2DFA98461D7F70CF00AFF2C9 /* SharedEventStreamsMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SharedEventStreamsMac.h; path = mac/SharedEventStreamsMac.h; sourceTree = "<group>"; };
+               2DFA98471D7F70CF00AFF2C9 /* SharedEventStreamsMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = SharedEventStreamsMac.mm; path = mac/SharedEventStreamsMac.mm; sourceTree = "<group>"; };
                2E63ED751891ACE9002A7AFC /* AccessibilityControllerIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AccessibilityControllerIOS.mm; sourceTree = "<group>"; };
                2E63ED761891ACE9002A7AFC /* AccessibilityNotificationHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AccessibilityNotificationHandler.h; sourceTree = "<group>"; };
                2E63ED771891ACE9002A7AFC /* AccessibilityTextMarkerIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AccessibilityTextMarkerIOS.mm; sourceTree = "<group>"; };
                0F73B5471BA782FE004B3EF4 /* UIScriptContext */ = {
                        isa = PBXGroup;
                        children = (
+                               2DB6187F1D7D598800978D19 /* spi */,
                                0F73B54B1BA78350004B3EF4 /* Bindings */,
+                               2DD4C4971D6E7D3B0007379C /* Event Serialization */,
                                0F73B54E1BA78954004B3EF4 /* Derived Sources */,
                                0F18E6DD1D6B9AAF0027E547 /* UIScriptContext.cpp */,
                                0F18E6DE1D6B9AAF0027E547 /* UIScriptContext.h */,
                        name = Accessibility;
                        sourceTree = "<group>";
                };
+               2DB6187F1D7D598800978D19 /* spi */ = {
+                       isa = PBXGroup;
+                       children = (
+                               2DB6187D1D7D58D400978D19 /* CoreGraphicsSPI.h */,
+                               0FEBF85B1BB62A370028722D /* IOKitSPI.h */,
+                       );
+                       name = spi;
+                       sourceTree = "<group>";
+               };
+               2DD4C4971D6E7D3B0007379C /* Event Serialization */ = {
+                       isa = PBXGroup;
+                       children = (
+                               2DFA984A1D7F79E000AFF2C9 /* mac */,
+                       );
+                       name = "Event Serialization";
+                       path = ../TestRunnerShared/EventSerialization;
+                       sourceTree = "<group>";
+               };
+               2DFA984A1D7F79E000AFF2C9 /* mac */ = {
+                       isa = PBXGroup;
+                       children = (
+                               2DD4C4981D6E7D3B0007379C /* EventSerializerMac.h */,
+                               2DD4C4991D6E7D3B0007379C /* EventSerializerMac.mm */,
+                               2DFA98461D7F70CF00AFF2C9 /* SharedEventStreamsMac.h */,
+                               2DFA98471D7F70CF00AFF2C9 /* SharedEventStreamsMac.mm */,
+                       );
+                       name = mac;
+                       sourceTree = "<group>";
+               };
                2E63ED741891ACE9002A7AFC /* ios */ = {
                        isa = PBXGroup;
                        children = (
                        children = (
                                0FEBF8581BB61DF20028722D /* HIDEventGenerator.h */,
                                0FEBF8591BB61DF20028722D /* HIDEventGenerator.mm */,
-                               0FEBF85B1BB62A370028722D /* IOKitSPI.h */,
                                2EE52D131890A9FB0010ED21 /* PlatformWebViewIOS.mm */,
                                2EE52D141890A9FB0010ED21 /* TestControllerIOS.mm */,
                                0FEBF85C1BB62D460028722D /* UIKitSPI.h */,
                        isa = PBXHeadersBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               2DB6187E1D7D58D400978D19 /* CoreGraphicsSPI.h in Headers */,
                                0F73B5521BA78968004B3EF4 /* JSUIScriptController.h in Headers */,
+                               2DFA98481D7F70CF00AFF2C9 /* SharedEventStreamsMac.h in Headers */,
+                               2DD4C49A1D6E7D3B0007379C /* EventSerializerMac.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                0F73B5511BA78968004B3EF4 /* JSUIScriptController.cpp in Sources */,
                                0F18E7181D6BC4560027E547 /* JSWrapper.cpp in Sources */,
                                A185103C1B9AE0FE00744AEB /* Options.cpp in Sources */,
+                               2DD4C49B1D6E7D3B0007379C /* EventSerializerMac.mm in Sources */,
                                A18510401B9AE13100744AEB /* PixelDumpSupport.cpp in Sources */,
                                A18510411B9AE13800744AEB /* TestController.cpp in Sources */,
+                               2DFA98491D7F70CF00AFF2C9 /* SharedEventStreamsMac.mm in Sources */,
                                A185103B1B9AE0E200744AEB /* TestControllerCocoa.mm in Sources */,
                                31DA8A3D1E7205CC00E1DF2F /* IOSLayoutTestCommunication.cpp in Sources */,
                                A18510421B9AE13E00744AEB /* TestInvocation.cpp in Sources */,
index 5fef029..c1e82f8 100644 (file)
@@ -399,11 +399,6 @@ void EventSenderProxy::mouseScrollByWithWheelAndMomentumPhases(int x, int y, int
     mouseScrollBy(x, y);
 }
 
-void EventSenderProxy::swipeGestureWithWheelAndMomentumPhases(int, int, int, int)
-{
-    notImplemented();
-}
-
 void EventSenderProxy::leapForward(int milliseconds)
 {
     if (m_eventQueue.isEmpty())
index 3b1b41b..9a320ff 100644 (file)
@@ -468,11 +468,6 @@ void EventSenderProxy::mouseScrollByWithWheelAndMomentumPhases(int x, int y, int
     mouseScrollBy(x, y);
 }
 
-void EventSenderProxy::swipeGestureWithWheelAndMomentumPhases(int, int, int, int)
-{
-    notImplemented();
-}
-
 void EventSenderProxy::leapForward(int milliseconds)
 {
     if (m_eventQueue.isEmpty())
index ee4eb0c..790f635 100644 (file)
 - (void)_postDelayed;
 @end
 
-#if defined(__LP64__)
-struct WKTRCGSEventRecord {
-    char offset1[150];
-    uint8_t phase;
-    char offset2[13];
-    float deltaX;
-    float deltaY;
-    char offset3[76];
-} __attribute__((packed));
-#endif
-
 @interface EventSenderSyntheticEvent : NSEvent {
 @public
     NSPoint _eventSender_locationInWindow;
@@ -71,11 +60,6 @@ struct WKTRCGSEventRecord {
     short _eventSender_subtype;
     NSEventType _eventSender_type;
     NSWindow *_eventSender_window;
-
-
-#if defined(__LP64__)
-    WKTRCGSEventRecord _eventSender_cgsEventRecord;
-#endif
 }
 
 - (id)initPressureEventAtLocation:(NSPoint)location globalLocation:(NSPoint)globalLocation stage:(NSInteger)stage pressure:(float)pressure stageTransition:(float)stageTransition phase:(NSEventPhase)phase time:(NSTimeInterval)time eventNumber:(NSInteger)eventNumber window:(NSWindow *)window;
@@ -168,13 +152,6 @@ struct WKTRCGSEventRecord {
     return false;
 }
 
-#if defined(__LP64__)
-- (WKTRCGSEventRecord)_cgsEventRecord
-{
-    return _eventSender_cgsEventRecord;
-}
-#endif
-
 - (NSWindow *)window
 {
     return _eventSender_window;
@@ -907,50 +884,4 @@ void EventSenderProxy::mouseScrollByWithWheelAndMomentumPhases(int x, int y, int
     }
 }
 
-static NSEventPhase nsEventPhaseFromCGEventPhase(int phase)
-{
-    switch (phase) {
-    case 0: // kCGSGesturePhaseNone
-        return NSEventPhaseNone;
-    case 1: // kCGSGesturePhaseBegan
-        return NSEventPhaseBegan;
-    case 2: // kCGSGesturePhaseChanged
-        return NSEventPhaseChanged;
-    case 4: // kCGSGesturePhaseEnded
-        return NSEventPhaseEnded;
-    case 8: // kCGSGesturePhaseCancelled
-        return NSEventPhaseCancelled;
-    case 128: // kCGSGesturePhaseMayBegin
-        return NSEventPhaseMayBegin;
-    }
-
-    ASSERT_NOT_REACHED();
-    return NSEventPhaseNone;
-}
-
-void EventSenderProxy::swipeGestureWithWheelAndMomentumPhases(int x, int y, int phase, int momentum)
-{
-    RetainPtr<EventSenderSyntheticEvent> event = adoptNS([[EventSenderSyntheticEvent alloc] init]);
-
-    // "mayBegin" a swipe is actually a scroll wheel event.
-    event->_eventSender_type = (phase == 128) ? NSEventTypeScrollWheel : NSEventTypeGesture;
-    event->_eventSender_subtype = 6; // kIOHIDEventTypeScroll
-    event->_eventSender_locationInWindow = NSMakePoint(m_position.x, m_position.y);
-    event->_eventSender_location = ([m_testController->mainWebView()->platformWindow() convertRectToScreen:NSMakeRect(m_position.x, m_position.y, 1, 1)].origin);
-    event->_eventSender_phase = nsEventPhaseFromCGEventPhase(phase);
-    event->_eventSender_momentumPhase = nsEventPhaseFromCGEventPhase(momentum);
-    event->_eventSender_timestamp = absoluteTimeForEventTime(currentEventTime());
-    event->_eventSender_eventNumber = ++eventNumber;
-
-#if defined(__LP64__)
-    event->_eventSender_cgsEventRecord.phase = phase;
-    event->_eventSender_cgsEventRecord.deltaX = (float)x;
-    event->_eventSender_cgsEventRecord.deltaY = (float)y;
-#else
-    NSLog(@"Synthetic swipe gestures are not implemented for 32-bit WebKitTestRunner.");
-#endif
-
-    [NSApp sendEvent:event.get()];
-}
-
 } // namespace WTR
index 9e65909..801674e 100644 (file)
 #import "config.h"
 #import "UIScriptController.h"
 
+#import "EventSerializerMac.h"
+#import "PlatformWebView.h"
+#import "SharedEventStreamsMac.h"
+#import "TestController.h"
 #import "PlatformWebView.h"
 #import "StringFunctions.h"
 #import "TestController.h"
@@ -188,4 +192,39 @@ void UIScriptController::addViewToWindow(JSValueRef callback)
 #endif
 }
 
+static void playBackEvents(UIScriptContext *context, NSString *eventStream, JSValueRef callback)
+{
+    NSError *error = nil;
+    NSArray *eventDicts = [NSJSONSerialization JSONObjectWithData:[eventStream dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&error];
+
+    if (error) {
+        NSLog(@"ERROR: %@", error);
+        return;
+    }
+
+    unsigned callbackID = context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
+
+    NSWindow *window = [TestController::singleton().mainWebView()->platformView() window];
+
+    [EventStreamPlayer playStream:eventDicts window:window completionHandler:^ {
+        context->asyncTaskComplete(callbackID);
+    }];
+}
+
+void UIScriptController::beginBackSwipe(JSValueRef callback)
+{
+    playBackEvents(m_context, beginSwipeBackEventStream(), callback);
+}
+
+void UIScriptController::completeBackSwipe(JSValueRef callback)
+{
+    playBackEvents(m_context, completeSwipeBackEventStream(), callback);
+}
+
+void UIScriptController::platformPlayBackEventStream(JSStringRef eventStream, JSValueRef callback)
+{
+    RetainPtr<CFStringRef> stream = adoptCF(JSStringCopyCFString(kCFAllocatorDefault, eventStream));
+    playBackEvents(m_context, (NSString *)stream.get(), callback);
+}
+
 } // namespace WTR