Diff
Modified: trunk/LayoutTests/ChangeLog (206797 => 206798)
--- trunk/LayoutTests/ChangeLog 2016-10-05 00:15:39 UTC (rev 206797)
+++ trunk/LayoutTests/ChangeLog 2016-10-05 00:23:51 UTC (rev 206798)
@@ -1,3 +1,13 @@
+2016-10-04 Simon Fraser <[email protected]>
+
+ [iOS WK2] Make it possible for a test to describe a user gesture as a stream of events in JSON format
+ https://bugs.webkit.org/show_bug.cgi?id=162934
+
+ Reviewed by Dean Jackson.
+
+ * fast/events/ios/event-stream-single-tap-expected.txt: Added.
+ * fast/events/ios/event-stream-single-tap.html: Added.
+
2016-10-04 Chris Dumez <[email protected]>
Add support for KeyboardEvent.isComposing attribute
Added: trunk/LayoutTests/fast/events/ios/event-stream-single-tap-expected.txt (0 => 206798)
--- trunk/LayoutTests/fast/events/ios/event-stream-single-tap-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/events/ios/event-stream-single-tap-expected.txt 2016-10-05 00:23:51 UTC (rev 206798)
@@ -0,0 +1 @@
+PASS: received click.
Added: trunk/LayoutTests/fast/events/ios/event-stream-single-tap.html (0 => 206798)
--- trunk/LayoutTests/fast/events/ios/event-stream-single-tap.html (rev 0)
+++ trunk/LayoutTests/fast/events/ios/event-stream-single-tap.html 2016-10-05 00:23:51 UTC (rev 206798)
@@ -0,0 +1,86 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+
+<html>
+<meta name="viewport" content="initial-scale=1.0, width=device-width">
+<head>
+ <style>
+ #target {
+ height: 100px;
+ width: 100px;
+ background-color: gray;
+ }
+ </style>
+ <script>
+
+ if (window.testRunner) {
+ testRunner.dumpAsText();
+ testRunner.waitUntilDone();
+ }
+
+ function getUIScript(x, y)
+ {
+ return `
+ (function() {
+ var eventStream = {
+ events : [
+ {
+ inputType : "hand",
+ timeOffset : 0,
+ touches : [
+ {
+ inputType : "finger",
+ phase : "began",
+ id : 1,
+ x : ${x},
+ y : ${y}
+ }
+ ]
+ },
+ {
+ inputType : "hand",
+ timeOffset : 0.0005,
+ touches : [
+ {
+ inputType : "finger",
+ phase : "ended",
+ id : 1,
+ x : ${x},
+ y : ${y}
+ }
+ ]
+ },
+ ]
+ };
+
+ uiController.sendEventStream(JSON.stringify(eventStream), function() {
+ uiController.uiScriptComplete();
+ });
+ })();`
+ }
+
+ function handleClick()
+ {
+ document.getElementById("result").textContent = "PASS: received click.";
+ if (window.testRunner)
+ testRunner.notifyDone();
+ }
+
+ function runTest()
+ {
+ var target = document.getElementById("target");
+ target.addEventListener("click", handleClick, false);
+
+ if (!testRunner.runUIScript)
+ return;
+
+ testRunner.runUIScript(getUIScript(60, 60), function() {});
+ }
+
+ window.addEventListener("load", runTest, false);
+ </script>
+</head>
+<body>
+ <div id="target"></div>
+ <div id="result">FAIL: did not receive click event.</div>
+</body>
+</html>
Modified: trunk/Tools/ChangeLog (206797 => 206798)
--- trunk/Tools/ChangeLog 2016-10-05 00:15:39 UTC (rev 206797)
+++ trunk/Tools/ChangeLog 2016-10-05 00:23:51 UTC (rev 206798)
@@ -1,3 +1,38 @@
+2016-10-04 Simon Fraser <[email protected]>
+
+ [iOS WK2] Make it possible for a test to describe a user gesture as a stream of events in JSON format
+ https://bugs.webkit.org/show_bug.cgi?id=162934
+
+ Reviewed by Dean Jackson.
+
+ With this change, a test can describe a user gesture in an "event stream", which is
+ some JSON describing an array of events with their underlying touches. The added
+ test describes a single tap.
+
+ The implementation fires up an NSThread, and sleeps the thread between events to dispatch
+ them at close to real time.
+
+ In future, HIDEventGenerator could use this internally for all of the "compound" interactions.
+
+ * DumpRenderTree/ios/UIScriptControllerIOS.mm:
+ (WTR::UIScriptController::sendEventStream):
+ * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl:
+ * TestRunnerShared/UIScriptContext/UIScriptController.cpp:
+ (WTR::UIScriptController::sendEventStream):
+ * TestRunnerShared/UIScriptContext/UIScriptController.h:
+ * WebKitTestRunner/ios/HIDEventGenerator.h:
+ * WebKitTestRunner/ios/HIDEventGenerator.mm:
+ (transducerTypeFromString):
+ (phaseFromString):
+ (-[HIDEventGenerator eventMaskFromEventInfo:]):
+ (-[HIDEventGenerator touchFromEventInfo:]):
+ (-[HIDEventGenerator _createIOHIDEventWithInfo:]):
+ (-[HIDEventGenerator dispatchEventWithInfo:]):
+ (-[HIDEventGenerator eventDispatchThreadEntry:]):
+ (-[HIDEventGenerator sendEventStream:completionBlock:]):
+ * WebKitTestRunner/ios/UIScriptControllerIOS.mm:
+ (WTR::UIScriptController::sendEventStream):
+
2016-10-04 Megan Gardner <[email protected]>
Add Megan to contributor's list
Modified: trunk/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm (206797 => 206798)
--- trunk/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm 2016-10-05 00:15:39 UTC (rev 206797)
+++ trunk/Tools/DumpRenderTree/ios/UIScriptControllerIOS.mm 2016-10-05 00:23:51 UTC (rev 206798)
@@ -108,6 +108,10 @@
{
}
+void UIScriptController::sendEventStream(JSStringRef eventsJSON, JSValueRef callback)
+{
+}
+
void UIScriptController::typeCharacterUsingHardwareKeyboard(JSStringRef character, JSValueRef callback)
{
}
Modified: trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl (206797 => 206798)
--- trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl 2016-10-05 00:15:39 UTC (rev 206797)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl 2016-10-05 00:23:51 UTC (rev 206798)
@@ -49,6 +49,40 @@
void keyDownUsingHardwareKeyboard(DOMString character, object callback);
void keyUpUsingHardwareKeyboard(DOMString character, object callback);
+ // eventsJSON describes a series of user events in JSON form. For the keys, see HIDEventGenerator.mm.
+ // For example, this JSON describes a touch down followed by a touch up (i.e. a single tap).
+ // {
+ // "events" : [
+ // {
+ // "inputType" : "hand",
+ // "timeOffset" : 0,
+ // "touches" : [
+ // {
+ // "inputType" : "finger",
+ // "phase" : "began",
+ // "id" : 1,
+ // "x" : 100,
+ // "y" : 120
+ // }
+ // ]
+ // },
+ // {
+ // "inputType" : "hand",
+ // "timeOffset" : 0.002, // seconds relative to the first event
+ // "touches" : [
+ // {
+ // "inputType" : "finger",
+ // "phase" : "ended",
+ // "id" : 1,
+ // "x" : 100,
+ // "y" : 120
+ // }
+ // ]
+ // },
+ // ]
+ // }
+ void sendEventStream(DOMString eventsJSON, object callback);
+
// Equivalent of pressing the Done button in the form accessory bar.
void dismissFormAccessoryView();
Modified: trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp (206797 => 206798)
--- trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp 2016-10-05 00:15:39 UTC (rev 206797)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.cpp 2016-10-05 00:23:51 UTC (rev 206798)
@@ -180,6 +180,10 @@
{
}
+void UIScriptController::sendEventStream(JSStringRef eventsJSON, JSValueRef callback)
+{
+}
+
void UIScriptController::typeCharacterUsingHardwareKeyboard(JSStringRef, JSValueRef)
{
}
Modified: trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h (206797 => 206798)
--- trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h 2016-10-05 00:15:39 UTC (rev 206797)
+++ trunk/Tools/TestRunnerShared/UIScriptContext/UIScriptController.h 2016-10-05 00:23:51 UTC (rev 206798)
@@ -63,7 +63,9 @@
void stylusTapAtPoint(long x, long y, float azimuthAngle, float altitudeAngle, float pressure, JSValueRef callback);
void longPressAtPoint(long x, long y, JSValueRef callback);
-
+
+ void sendEventStream(JSStringRef eventsJSON, JSValueRef callback);
+
void typeCharacterUsingHardwareKeyboard(JSStringRef character, JSValueRef callback);
void keyDownUsingHardwareKeyboard(JSStringRef character, JSValueRef callback);
void keyUpUsingHardwareKeyboard(JSStringRef character, JSValueRef callback);
Modified: trunk/Tools/WebKitTestRunner/ios/HIDEventGenerator.h (206797 => 206798)
--- trunk/Tools/WebKitTestRunner/ios/HIDEventGenerator.h 2016-10-05 00:15:39 UTC (rev 206797)
+++ trunk/Tools/WebKitTestRunner/ios/HIDEventGenerator.h 2016-10-05 00:23:51 UTC (rev 206798)
@@ -27,6 +27,32 @@
#import <CoreGraphics/CGGeometry.h>
+// Keys for sendEventStream:completionBlock:.
+extern NSString* const TopLevelEventInfoKey;
+extern NSString* const HIDEventInputType;
+extern NSString* const HIDEventTimeOffsetKey;
+extern NSString* const HIDEventPhaseKey;
+extern NSString* const HIDEventTouchIDKey;
+extern NSString* const HIDEventPressureKey;
+extern NSString* const HIDEventXKey;
+extern NSString* const HIDEventYKey;
+extern NSString* const HIDEventTwistKey;
+extern NSString* const HIDEventMajorRadiusKey;
+extern NSString* const HIDEventMinorRadiusKey;
+extern NSString* const HIDEventTouchesKey;
+
+// Values for HIDEventInputType.
+extern NSString* const HIDEventInputTypeHand;
+extern NSString* const HIDEventInputTypeFinger;
+extern NSString* const HIDEventInputTypeStylus;
+
+// Values for HIDEventPhaseKey.
+extern NSString* const HIDEventPhaseBegan;
+extern NSString* const HIDEventPhaseMoved;
+extern NSString* const HIDEventPhaseEnded;
+extern NSString* const HIDEventPhaseCanceled;
+
+
@interface HIDEventGenerator : NSObject
+ (HIDEventGenerator *)sharedHIDEventGenerator;
@@ -56,6 +82,9 @@
- (void)pinchCloseWithStartPoint:(CGPoint)startLocation endPoint:(CGPoint)endLocation duration:(double)seconds completionBlock:(void (^)(void))completionBlock;
- (void)pinchOpenWithStartPoint:(CGPoint)startLocation endPoint:(CGPoint)endLocation duration:(double)seconds completionBlock:(void (^)(void))completionBlock;
+// Event stream
+- (void)sendEventStream:(NSDictionary *)eventInfo completionBlock:(void (^)(void))completionBlock;
+
- (void)markerEventReceived:(IOHIDEventRef)event;
// Keyboard
Modified: trunk/Tools/WebKitTestRunner/ios/HIDEventGenerator.mm (206797 => 206798)
--- trunk/Tools/WebKitTestRunner/ios/HIDEventGenerator.mm 2016-10-05 00:15:39 UTC (rev 206797)
+++ trunk/Tools/WebKitTestRunner/ios/HIDEventGenerator.mm 2016-10-05 00:23:51 UTC (rev 206798)
@@ -37,6 +37,28 @@
SOFT_LINK_PRIVATE_FRAMEWORK(BackBoardServices)
SOFT_LINK(BackBoardServices, BKSHIDEventSetDigitizerInfo, void, (IOHIDEventRef digitizerEvent, uint32_t contextID, uint8_t systemGestureisPossible, uint8_t isSystemGestureStateChangeEvent, CFStringRef displayUUID, CFTimeInterval initialTouchTimestamp, float maxForce), (digitizerEvent, contextID, systemGestureisPossible, isSystemGestureStateChangeEvent, displayUUID, initialTouchTimestamp, maxForce));
+NSString* const TopLevelEventInfoKey = @"events";
+NSString* const HIDEventInputType = @"inputType";
+NSString* const HIDEventTimeOffsetKey = @"timeOffset";
+NSString* const HIDEventTouchesKey = @"touches";
+NSString* const HIDEventPhaseKey = @"phase";
+NSString* const HIDEventTouchIDKey = @"id";
+NSString* const HIDEventPressureKey = @"pressure";
+NSString* const HIDEventXKey = @"x";
+NSString* const HIDEventYKey = @"y";
+NSString* const HIDEventTwistKey = @"twist";
+NSString* const HIDEventMajorRadiusKey = @"majorRadius";
+NSString* const HIDEventMinorRadiusKey = @"minorRadius";
+
+NSString* const HIDEventInputTypeHand = @"hand";
+NSString* const HIDEventInputTypeFinger = @"finger";
+NSString* const HIDEventInputTypeStylus = @"stylus";
+
+NSString* const HIDEventPhaseBegan = @"began";
+NSString* const HIDEventPhaseMoved = @"moved";
+NSString* const HIDEventPhaseEnded = @"ended";
+NSString* const HIDEventPhaseCanceled = @"canceled";
+
static const NSTimeInterval fingerLiftDelay = 0.05;
static const NSTimeInterval multiTapInterval = 0.15;
static const NSTimeInterval fingerMoveInterval = 0.016;
@@ -146,6 +168,130 @@
[self _sendHIDEvent:eventRef.get()];
}
+static IOHIDDigitizerTransducerType transducerTypeFromString(NSString * transducerTypeString)
+{
+ if ([transducerTypeString isEqualToString:HIDEventInputTypeHand])
+ return kIOHIDDigitizerTransducerTypeHand;
+
+ if ([transducerTypeString isEqualToString:HIDEventInputTypeFinger])
+ return kIOHIDDigitizerTransducerTypeFinger;
+
+ if ([transducerTypeString isEqualToString:HIDEventInputTypeStylus])
+ return kIOHIDDigitizerTransducerTypeStylus;
+
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+static UITouchPhase phaseFromString(NSString *string)
+{
+ if ([string isEqualToString:HIDEventPhaseBegan])
+ return UITouchPhaseBegan;
+
+ if ([string isEqualToString:HIDEventPhaseMoved])
+ return UITouchPhaseMoved;
+
+ if ([string isEqualToString:HIDEventPhaseEnded])
+ return UITouchPhaseEnded;
+
+ if ([string isEqualToString:HIDEventPhaseCanceled])
+ return UITouchPhaseCancelled;
+
+ return UITouchPhaseStationary;
+}
+
+- (IOHIDDigitizerEventMask)eventMaskFromEventInfo:(NSDictionary *)info
+{
+ NSArray *childEvents = info[HIDEventTouchesKey];
+ for (NSDictionary *touchInfo in childEvents) {
+ UITouchPhase phase = phaseFromString(touchInfo[HIDEventPhaseKey]);
+ // If there are any new or ended events, mask includes touch.
+ if (phase == UITouchPhaseBegan || phase == UITouchPhaseEnded || phase == UITouchPhaseCancelled)
+ return kIOHIDDigitizerEventTouch;
+ }
+
+ return 0;
+}
+
+// Returns 1 for all events where the fingers are on the glass (everything but enced and canceled).
+- (CFIndex)touchFromEventInfo:(NSDictionary *)info
+{
+ NSArray *childEvents = info[HIDEventTouchesKey];
+ for (NSDictionary *touchInfo in childEvents) {
+ UITouchPhase phase = phaseFromString(touchInfo[HIDEventPhaseKey]);
+ if (phase == UITouchPhaseBegan || phase == UITouchPhaseMoved || phase == UITouchPhaseStationary)
+ return 1;
+ }
+
+ return 0;
+}
+
+// FIXME: callers of _createIOHIDEventType could switch to this.
+- (IOHIDEventRef)_createIOHIDEventWithInfo:(NSDictionary *)info
+{
+ uint64_t machTime = mach_absolute_time();
+
+ IOHIDDigitizerEventMask eventMask = [self eventMaskFromEventInfo:info];
+
+ CFIndex range = 0;
+ // touch is 1 if a finger is down.
+ CFIndex touch = [self touchFromEventInfo:info];
+
+ IOHIDEventRef eventRef = IOHIDEventCreateDigitizerEvent(kCFAllocatorDefault, machTime,
+ transducerTypeFromString(info[HIDEventInputType]), // transducerType
+ 0, // index
+ 0, // identifier
+ eventMask, // event mask
+ 0, // button event
+ 0, // x
+ 0, // y
+ 0, // z
+ 0, // presure
+ 0, // twist
+ range, // range
+ touch, // touch
+ kIOHIDEventOptionNone);
+
+ IOHIDEventSetIntegerValue(eventRef, kIOHIDEventFieldDigitizerIsDisplayIntegrated, 1);
+
+ NSArray *childEvents = info[HIDEventTouchesKey];
+ for (NSDictionary *touchInfo in childEvents) {
+
+ IOHIDDigitizerEventMask childEventMask = 0;
+
+ UITouchPhase phase = phaseFromString(touchInfo[HIDEventPhaseKey]);
+ if (phase != UITouchPhaseCancelled && phase != UITouchPhaseBegan && phase != UITouchPhaseEnded)
+ childEventMask |= kIOHIDDigitizerEventPosition;
+
+ if (phase == UITouchPhaseBegan || phase == UITouchPhaseEnded || phase == UITouchPhaseCancelled)
+ childEventMask |= (kIOHIDDigitizerEventTouch | kIOHIDDigitizerEventRange);
+
+ if (phase == UITouchPhaseCancelled)
+ childEventMask |= kIOHIDDigitizerEventCancel;
+
+ IOHIDEventRef subEvent = IOHIDEventCreateDigitizerFingerEvent(kCFAllocatorDefault, machTime,
+ [touchInfo[HIDEventTouchIDKey] intValue], // index
+ 2, // identifier (which finger we think it is). FIXME: this should come from the data.
+ childEventMask,
+ [touchInfo[HIDEventXKey] floatValue],
+ [touchInfo[HIDEventYKey] floatValue],
+ 0, // z
+ [touchInfo[HIDEventPressureKey] floatValue],
+ [touchInfo[HIDEventTwistKey] floatValue],
+ touch, // range
+ touch, // touch
+ kIOHIDEventOptionNone);
+
+ IOHIDEventSetFloatValue(subEvent, kIOHIDEventFieldDigitizerMajorRadius, [touchInfo[HIDEventMajorRadiusKey] floatValue]);
+ IOHIDEventSetFloatValue(subEvent, kIOHIDEventFieldDigitizerMinorRadius, [touchInfo[HIDEventMinorRadiusKey] floatValue]);
+
+ IOHIDEventAppendEvent(eventRef, subEvent, 0);
+ CFRelease(subEvent);
+ }
+
+ return eventRef;
+}
+
- (IOHIDEventRef)_createIOHIDEventType:(HandEventType)eventType
{
BOOL isTouching = (eventType == HandEventTouched || eventType == HandEventMoved || eventType == HandEventChordChanged || eventType == StylusEventTouched || eventType == StylusEventMoved);
@@ -766,4 +912,62 @@
[self _sendMarkerHIDEventWithCompletionBlock:completionBlock];
}
+- (void)dispatchEventWithInfo:(NSDictionary *)eventInfo
+{
+ ASSERT([NSThread isMainThread]);
+
+ RetainPtr<IOHIDEventRef> eventRef = adoptCF([self _createIOHIDEventWithInfo:eventInfo]);
+ [self _sendHIDEvent:eventRef.get()];
+}
+
+- (void)eventDispatchThreadEntry:(NSDictionary *)threadData
+{
+ NSDictionary *eventStream = threadData[@"eventInfo"];
+ void (^completionBlock)() = threadData[@"completionBlock"];
+
+ NSArray *events = eventStream[TopLevelEventInfoKey];
+ if (!events.count) {
+ NSLog(@"No events found in event stream");
+ return;
+ }
+
+ CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
+
+ for (NSDictionary *eventInfo in events) {
+ NSTimeInterval eventRelativeTime = [eventInfo[HIDEventTimeOffsetKey] doubleValue];
+ CFAbsoluteTime targetTime = startTime + eventRelativeTime;
+
+ CFTimeInterval waitTime = targetTime - CFAbsoluteTimeGetCurrent();
+ if (waitTime > 0)
+ [NSThread sleepForTimeInterval:waitTime];
+
+ dispatch_async(dispatch_get_main_queue(), ^ {
+ [self dispatchEventWithInfo:eventInfo];
+ });
+ }
+
+ dispatch_async(dispatch_get_main_queue(), ^ {
+ [self _sendMarkerHIDEventWithCompletionBlock:completionBlock];
+ });
+}
+
+- (void)sendEventStream:(NSDictionary *)eventInfo completionBlock:(void (^)(void))completionBlock
+{
+ if (!eventInfo) {
+ NSLog(@"eventInfo is nil");
+ if (completionBlock)
+ completionBlock();
+ return;
+ }
+
+ NSDictionary* threadData = @{
+ @"eventInfo": [eventInfo copy],
+ @"completionBlock": [[completionBlock copy] autorelease]
+ };
+
+ NSThread *eventDispatchThread = [[[NSThread alloc] initWithTarget:self selector:@selector(eventDispatchThreadEntry:) object:threadData] autorelease];
+ eventDispatchThread.qualityOfService = NSQualityOfServiceUserInteractive;
+ [eventDispatchThread start];
+}
+
@end
Modified: trunk/Tools/WebKitTestRunner/ios/IOKitSPI.h (206797 => 206798)
--- trunk/Tools/WebKitTestRunner/ios/IOKitSPI.h 2016-10-05 00:15:39 UTC (rev 206797)
+++ trunk/Tools/WebKitTestRunner/ios/IOKitSPI.h 2016-10-05 00:23:51 UTC (rev 206798)
@@ -117,6 +117,8 @@
};
enum {
+ kIOHIDDigitizerTransducerTypeStylus = 0,
+ kIOHIDDigitizerTransducerTypeFinger = 2,
kIOHIDDigitizerTransducerTypeHand = 3
};
typedef uint32_t IOHIDDigitizerTransducerType;
Modified: trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm (206797 => 206798)
--- trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm 2016-10-05 00:15:39 UTC (rev 206797)
+++ trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm 2016-10-05 00:23:51 UTC (rev 206798)
@@ -35,6 +35,7 @@
#import "TestRunnerWKWebView.h"
#import "UIScriptContext.h"
#import <_javascript_Core/_javascript_Core.h>
+#import <_javascript_Core/OpaqueJSString.h>
#import <UIKit/UIKit.h>
#import <WebCore/FloatRect.h>
#import <WebKit/WKWebViewPrivate.h>
@@ -175,6 +176,24 @@
}];
}
+void UIScriptController::sendEventStream(JSStringRef eventsJSON, JSValueRef callback)
+{
+ unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
+
+ String jsonString = eventsJSON->string();
+ auto eventInfo = dynamic_objc_cast<NSDictionary>([NSJSONSerialization JSONObjectWithData:[(NSString *)jsonString dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]);
+ if (!eventInfo || ![eventInfo isKindOfClass:[NSDictionary class]]) {
+ WTFLogAlways("JSON is not convertible to a dictionary");
+ return;
+ }
+
+ [[HIDEventGenerator sharedHIDEventGenerator] sendEventStream:eventInfo completionBlock:^{
+ if (!m_context)
+ return;
+ m_context->asyncTaskComplete(callbackID);
+ }];
+}
+
void UIScriptController::dragFromPointToPoint(long startX, long startY, long endX, long endY, double durationSeconds, JSValueRef callback)
{
unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);