@@ -50,6 +50,74 @@ static void XCWSetErrorMessage(char **errorMessage, NSError *error) {
5050 return XCWCopyCString (string);
5151}
5252
53+ @interface XCWNativeAccessibilityThreadRunner : NSObject
54+ @end
55+
56+ @implementation XCWNativeAccessibilityThreadRunner
57+
58+ + (void )run {
59+ @autoreleasepool {
60+ NSThread .currentThread .name = @" com.simdeck.native-accessibility" ;
61+ NSRunLoop *runLoop = NSRunLoop .currentRunLoop ;
62+ [runLoop addPort: NSMachPort .port forMode: NSDefaultRunLoopMode ];
63+ while (!NSThread .currentThread .cancelled ) {
64+ @autoreleasepool {
65+ [runLoop runMode: NSDefaultRunLoopMode beforeDate: NSDate .distantFuture];
66+ }
67+ }
68+ }
69+ }
70+
71+ @end
72+
73+ @interface XCWNativeAccessibilitySnapshotRequest : NSObject
74+
75+ @property (nonatomic , copy ) NSString *udid;
76+ @property (nonatomic , assign ) BOOL hasPoint;
77+ @property (nonatomic , assign ) double x;
78+ @property (nonatomic , assign ) double y;
79+ @property (nonatomic , assign ) NSUInteger maxDepth;
80+ @property (nonatomic , assign ) char *result;
81+ @property (nonatomic , assign ) char *serializationError;
82+ @property (nonatomic , strong ) NSError *snapshotError;
83+
84+ - (void )performSnapshot ;
85+
86+ @end
87+
88+ @implementation XCWNativeAccessibilitySnapshotRequest
89+
90+ - (void )performSnapshot {
91+ @autoreleasepool {
92+ NSError *error = nil ;
93+ NSValue *pointValue = self.hasPoint ? [NSValue valueWithPoint: NSMakePoint (self .x, self .y)] : nil ;
94+ NSDictionary *snapshot = [XCWAccessibilityBridge accessibilitySnapshotForSimulatorUDID: self .udid
95+ atPoint: pointValue
96+ maxDepth: self .maxDepth
97+ error: &error];
98+ if (snapshot == nil ) {
99+ self.snapshotError = error;
100+ return ;
101+ }
102+ self.result = XCWJSONStringFromObject (snapshot, &_serializationError);
103+ }
104+ }
105+
106+ @end
107+
108+ static NSThread *XCWNativeAccessibilityThread (void ) {
109+ static NSThread *thread = nil ;
110+ static dispatch_once_t onceToken;
111+ dispatch_once (&onceToken, ^{
112+ thread = [[NSThread alloc ] initWithTarget: XCWNativeAccessibilityThreadRunner.class
113+ selector: @selector (run )
114+ object: nil ];
115+ thread.name = @" com.simdeck.native-accessibility" ;
116+ [thread start ];
117+ });
118+ return thread;
119+ }
120+
53121static xcw_native_owned_bytes XCWOwnedBytesFromData (NSData *data) {
54122 xcw_native_owned_bytes bytes = {0 };
55123 if (data.length == 0 ) {
@@ -458,17 +526,37 @@ xcw_native_owned_bytes xcw_native_screenshot_png(const char *udid, char **error_
458526
459527char *xcw_native_accessibility_snapshot (const char *udid, bool has_point, double x, double y, size_t max_depth, char **error_message) {
460528 @autoreleasepool {
461- NSError *error = nil ;
462- NSValue *pointValue = has_point ? [NSValue valueWithPoint: NSMakePoint (x, y)] : nil ;
463- NSDictionary *snapshot = [XCWAccessibilityBridge accessibilitySnapshotForSimulatorUDID: XCWStringFromCString (udid)
464- atPoint: pointValue
465- maxDepth: max_depth
466- error: &error];
467- if (snapshot == nil ) {
468- XCWSetErrorMessage (error_message, error);
529+ XCWNativeAccessibilitySnapshotRequest *request = [XCWNativeAccessibilitySnapshotRequest new ];
530+ request.udid = XCWStringFromCString (udid);
531+ request.hasPoint = has_point;
532+ request.x = x;
533+ request.y = y;
534+ request.maxDepth = max_depth;
535+
536+ NSThread *accessibilityThread = XCWNativeAccessibilityThread ();
537+ if (NSThread .currentThread == accessibilityThread) {
538+ [request performSnapshot ];
539+ } else {
540+ [request performSelector: @selector (performSnapshot )
541+ onThread: accessibilityThread
542+ withObject: nil
543+ waitUntilDone: YES
544+ modes: @[NSDefaultRunLoopMode ]];
545+ }
546+
547+ if (request.result != NULL ) {
548+ return request.result ;
549+ }
550+ if (request.serializationError != NULL ) {
551+ if (error_message != NULL ) {
552+ *error_message = request.serializationError ;
553+ } else {
554+ free (request.serializationError );
555+ }
469556 return NULL ;
470557 }
471- return XCWJSONStringFromObject (snapshot, error_message);
558+ XCWSetErrorMessage (error_message, request.snapshotError );
559+ return NULL ;
472560 }
473561}
474562
0 commit comments