| 1 | // Use the production resolver with a synthetic workspace. The fixture entry |
| 2 | // point never calls execute(), AX observation, activation, capture, or input. |
| 3 | #import <Cocoa/Cocoa.h> |
| 4 | @interface CUFixtureApplication : NSObject |
| 5 | @property pid_t processIdentifier; |
| 6 | @property NSString *localizedName; |
| 7 | @property NSString *bundleIdentifier; |
| 8 | @property(getter=isTerminated) BOOL terminated; |
| 9 | @end |
| 10 | @implementation CUFixtureApplication |
| 11 | @end |
| 12 | @interface CUFixtureWorkspace : NSObject |
| 13 | + (instancetype)sharedWorkspace; |
| 14 | - (NSArray *)runningApplications; |
| 15 | - (NSRunningApplication *)frontmostApplication; |
| 16 | @end |
| 17 | @implementation CUFixtureWorkspace |
| 18 | + (instancetype)sharedWorkspace { static id workspace; if(!workspace) workspace=[self new]; return workspace; } |
| 19 | - (NSArray *)runningApplications { |
| 20 | CUFixtureApplication *target=[CUFixtureApplication new], *front=[CUFixtureApplication new]; |
| 21 | target.processIdentifier=123; target.localizedName=@"Fixture"; target.bundleIdentifier=@"test.fixture"; |
| 22 | front.processIdentifier=999; front.localizedName=@"Other"; front.bundleIdentifier=@"test.other"; |
| 23 | return @[front,target]; |
| 24 | } |
| 25 | - (NSRunningApplication *)frontmostApplication { return (NSRunningApplication *)self.runningApplications[0]; } |
| 26 | @end |
| 27 | #define NSWorkspace CUFixtureWorkspace |
| 28 | #import <ApplicationServices/ApplicationServices.h> |
| 29 | static int fixturePosts=0, fixtureActivations=0; |
| 30 | static void fixturePost(CGEventTapLocation location, CGEventRef event) { fixturePosts++; } |
| 31 | static AXError fixtureSet(AXUIElementRef element, CFStringRef name, CFTypeRef value) { fixtureActivations++; return kAXErrorSuccess; } |
| 32 | #define CGEventPost fixturePost |
| 33 | #define AXUIElementSetAttributeValue fixtureSet |
| 34 | #define AXIsProcessTrusted() true |
| 35 | #define CU_TEST 1 |
| 36 | #define main unusedNativeMain |
| 37 | #include "../../src/backends/darwin-accessibility.m" |
| 38 | #undef main |
| 39 | #undef NSWorkspace |
| 40 | |
| 41 | int main(int argc, const char *argv[]) { @autoreleasepool { |
| 42 | if(argc!=2) return 2; |
| 43 | NSDictionary *request=[NSJSONSerialization JSONObjectWithData:[[NSString stringWithUTF8String:argv[1]] dataUsingEncoding:NSUTF8StringEncoding] options:0 error:nil]; |
| 44 | if([request[@"tool"] isEqual:@"inspect_pointer_guard"]) { |
| 45 | cuTestLockDir=request[@"args"][@"lock_dir"]; |
| 46 | NSString *refusal=nil; |
| 47 | @try { execute(@{@"tool":@"pointer_sequence",@"args":@{@"foreground_input":@YES,@"input_app_ref":@{@"pid":@123},@"steps":@[@{@"type":@1,@"x":@10,@"y":@10,@"button":@0}]}}); } |
| 48 | @catch(NSException *error) { refusal=error.reason; } |
| 49 | cuPrint(@{@"refusal":refusal?:NSNull.null,@"posts":@(fixturePosts),@"activations":@(fixtureActivations)}); |
| 50 | return 0; |
| 51 | } |
| 52 | if(![@[@"list_windows",@"get_app_state",@"resolve_element",@"window_info"] containsObject:request[@"tool"]]) return 2; |
| 53 | NSRunningApplication *app=resolve(request[@"args"][@"app_ref"]); |
| 54 | if(!app) { fputs("application not found\n",stderr); return 1; } |
| 55 | NSDictionary *receipt=@{@"found":@YES,@"pid":@(app.processIdentifier),@"name":app.localizedName,@"bundle_id":app.bundleIdentifier,@"windows":@[],@"elements":@[]}; |
| 56 | NSData *json=[NSJSONSerialization dataWithJSONObject:receipt options:0 error:nil]; |
| 57 | fwrite(json.bytes,1,json.length,stdout); fputc('\n',stdout); |
| 58 | return 0; |
| 59 | } } |
| 60 |