120120static const NSUInteger DFKeyboardModifierCommand = 1 << 3 ;
121121static const NSUInteger DFKeyboardModifierCapsLock = 1 << 4 ;
122122
123- static NSString *DFSimulatorKitExecutablePath (void ) {
123+ static NSString *DFActiveDeveloperDirectory (void ) {
124124 const char *developerDir = getenv (" DEVELOPER_DIR" );
125125 if (developerDir != NULL && developerDir[0 ] != ' \0 ' ) {
126- return [[ NSString stringWithUTF8String: developerDir] stringByAppendingPathComponent: @" Library/PrivateFrameworks/SimulatorKit.framework/SimulatorKit " ];
126+ return [NSString stringWithUTF8String: developerDir];
127127 }
128128
129129 FILE *pipe = popen (" /usr/bin/xcode-select -p 2>/dev/null" , " r" );
133133 NSString *selected = [[NSString stringWithUTF8String: buffer] stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet ]];
134134 pclose (pipe);
135135 if (selected.length > 0 ) {
136- return [ selected stringByAppendingPathComponent: @" Library/PrivateFrameworks/SimulatorKit.framework/SimulatorKit " ] ;
136+ return selected;
137137 }
138138 } else {
139139 pclose (pipe);
140140 }
141141 }
142142
143+ return @" /Applications/Xcode.app/Contents/Developer" ;
144+ }
145+
146+ static NSString *DFSimulatorKitExecutablePath (void ) {
147+ NSString *developerDir = DFActiveDeveloperDirectory ();
148+ if (developerDir.length > 0 ) {
149+ return [developerDir stringByAppendingPathComponent: @" Library/PrivateFrameworks/SimulatorKit.framework/SimulatorKit" ];
150+ }
143151 return @" /Applications/Xcode.app/Contents/Developer/Library/PrivateFrameworks/SimulatorKit.framework/SimulatorKit" ;
144152}
145153
146154static NSInteger DFXcodeMajorVersion (void ) {
147- NSString *developerPath = nil ;
148- const char *developerDir = getenv (" DEVELOPER_DIR" );
149- if (developerDir != NULL && developerDir[0 ] != ' \0 ' ) {
150- developerPath = [NSString stringWithUTF8String: developerDir];
151- } else {
152- FILE *pipe = popen (" /usr/bin/xcode-select -p 2>/dev/null" , " r" );
153- if (pipe != NULL ) {
154- char buffer[PATH_MAX ] = {0 };
155- if (fgets (buffer, sizeof (buffer), pipe) != NULL ) {
156- developerPath = [[NSString stringWithUTF8String: buffer] stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet ]];
157- }
158- pclose (pipe);
159- }
160- }
155+ NSString *developerPath = DFActiveDeveloperDirectory ();
161156 if (developerPath.length == 0 ) {
162157 return 0 ;
163158 }
@@ -590,6 +585,103 @@ static id DFSendObject(id target, const char *selectorName) {
590585 return trimmed.length > 0 ? trimmed : nil ;
591586}
592587
588+ static id DFCreateCoreSimulatorServiceContext (NSError **error) {
589+ Class serviceContextClass = NSClassFromString (@" SimServiceContext" );
590+ if (serviceContextClass == Nil ) {
591+ if (error != NULL ) {
592+ *error = DFMakeError (
593+ DFPrivateSimulatorErrorCodeServiceContextFailed,
594+ @" CoreSimulator did not expose SimServiceContext in this Xcode runtime."
595+ );
596+ }
597+ return nil ;
598+ }
599+
600+ NSString *developerDir = DFActiveDeveloperDirectory ();
601+ NSError *serviceError = nil ;
602+ SEL sharedSelector = sel_registerName (" sharedServiceContextForDeveloperDir:error:" );
603+ if ([serviceContextClass respondsToSelector: sharedSelector]) {
604+ id serviceContext = ((id (*)(id , SEL , id , NSError **))objc_msgSend)(
605+ serviceContextClass,
606+ sharedSelector,
607+ developerDir,
608+ &serviceError
609+ );
610+ if (serviceContext != nil ) {
611+ return serviceContext;
612+ }
613+ DFLog (@" sharedServiceContextForDeveloperDir:error: failed for %@ : %@ " , developerDir, serviceError.localizedDescription ?: @" unknown error" );
614+ }
615+
616+ serviceError = nil ;
617+ SEL initSelector = sel_registerName (" initWithDeveloperDir:connectionType:error:" );
618+ id contextAlloc = ((id (*)(id , SEL ))objc_msgSend)(serviceContextClass, sel_registerName (" alloc" ));
619+ if (![contextAlloc respondsToSelector: initSelector]) {
620+ if (error != NULL ) {
621+ *error = DFMakeError (
622+ DFPrivateSimulatorErrorCodeServiceContextFailed,
623+ @" CoreSimulator did not expose a supported SimServiceContext initializer."
624+ );
625+ }
626+ return nil ;
627+ }
628+ id serviceContext = ((id (*)(id , SEL , id , long long , NSError **))objc_msgSend)(
629+ contextAlloc,
630+ initSelector,
631+ developerDir,
632+ 0LL ,
633+ &serviceError
634+ );
635+ if (serviceContext == nil && error != NULL ) {
636+ *error = serviceError ?: DFMakeError (
637+ DFPrivateSimulatorErrorCodeServiceContextFailed,
638+ [NSString stringWithFormat: @" Unable to create a CoreSimulator service context for %@ ." , developerDir]
639+ );
640+ }
641+ return serviceContext;
642+ }
643+
644+ static NSArray *DFFlattenCoreSimulatorDevices (id devicesPayload) {
645+ if ([devicesPayload isKindOfClass: [NSArray class ]]) {
646+ return devicesPayload;
647+ }
648+ if ([devicesPayload isKindOfClass: [NSSet class ]]) {
649+ return [devicesPayload allObjects ];
650+ }
651+ if ([devicesPayload isKindOfClass: [NSDictionary class ]]) {
652+ NSMutableArray *devices = [NSMutableArray array ];
653+ for (id value in [(NSDictionary *)devicesPayload allValues ]) {
654+ [devices addObjectsFromArray: DFFlattenCoreSimulatorDevices (value)];
655+ }
656+ return devices;
657+ }
658+ return @[];
659+ }
660+
661+ static NSArray *DFCoreSimulatorDevicesForDeviceSet (id deviceSet) {
662+ SEL availableSelector = sel_registerName (" availableDevices" );
663+ if ([deviceSet respondsToSelector: availableSelector]) {
664+ NSArray *availableDevices = DFFlattenCoreSimulatorDevices (((id (*)(id , SEL ))objc_msgSend)(deviceSet, availableSelector));
665+ if (availableDevices.count > 0 ) {
666+ return availableDevices;
667+ }
668+ }
669+
670+ SEL devicesSelector = sel_registerName (" devices" );
671+ if ([deviceSet respondsToSelector: devicesSelector]) {
672+ return DFFlattenCoreSimulatorDevices (((id (*)(id , SEL ))objc_msgSend)(deviceSet, devicesSelector));
673+ }
674+ return @[];
675+ }
676+
677+ static NSString *DFUDIDForCoreSimulatorDevice (id device) {
678+ id deviceUDID = DFSendObject (device, " UDID" );
679+ if ([deviceUDID respondsToSelector: sel_registerName (" UUIDString" )]) {
680+ return DFSendObject (deviceUDID, " UUIDString" );
681+ }
682+ return [deviceUDID description ];
683+ }
684+
593685static id DFAllocInitRect (Class cls, NSRect rect) {
594686 id instance = ((id (*)(id , SEL ))objc_msgSend)(cls, sel_registerName (" alloc" ));
595687 return ((id (*)(id , SEL , NSRect ))objc_msgSend)(instance, sel_registerName (" initWithFrame:" ), rect);
@@ -2565,26 +2657,8 @@ - (nullable instancetype)initWithUDID:(NSString *)udid
25652657 dispatch_queue_set_specific (_callbackQueue, DFPrivateSimulatorCallbackQueueKey, (void *)DFPrivateSimulatorCallbackQueueKey, NULL );
25662658 [self updateStatus: [NSString stringWithFormat: @" Starting private CoreSimulator attach for %@ " , udid]];
25672659
2568- Class serviceContextClass = NSClassFromString (@" SimServiceContext" );
2569- if (serviceContextClass == Nil ) {
2570- if (error != NULL ) {
2571- *error = DFMakeError (
2572- DFPrivateSimulatorErrorCodeServiceContextFailed,
2573- @" CoreSimulator did not expose SimServiceContext in this Xcode runtime."
2574- );
2575- }
2576- return nil ;
2577- }
2578-
25792660 NSError *serviceError = nil ;
2580- id contextAlloc = ((id (*)(id , SEL ))objc_msgSend)(serviceContextClass, sel_registerName (" alloc" ));
2581- _serviceContext = ((id (*)(id , SEL , id , long long , NSError **))objc_msgSend)(
2582- contextAlloc,
2583- sel_registerName (" initWithDeveloperDir:connectionType:error:" ),
2584- nil ,
2585- 0LL ,
2586- &serviceError
2587- );
2661+ _serviceContext = DFCreateCoreSimulatorServiceContext (&serviceError);
25882662 if (_serviceContext == nil ) {
25892663 if (error != NULL ) {
25902664 *error = serviceError ?: DFMakeError (
@@ -2607,13 +2681,9 @@ - (nullable instancetype)initWithUDID:(NSString *)udid
26072681 return nil ;
26082682 }
26092683
2610- NSArray *devices = DFSendObject (deviceSet, " devices " );
2684+ NSArray *devices = DFCoreSimulatorDevicesForDeviceSet (deviceSet);
26112685 for (id candidate in devices) {
2612- id deviceUDID = DFSendObject (candidate, " UDID" );
2613- NSString *candidateUDID = [deviceUDID respondsToSelector: sel_registerName (" UUIDString" )]
2614- ? DFSendObject (deviceUDID, " UUIDString" )
2615- : [deviceUDID description ];
2616- if ([candidateUDID isEqualToString: udid]) {
2686+ if ([DFUDIDForCoreSimulatorDevice (candidate) isEqualToString: udid]) {
26172687 _device = candidate;
26182688 break ;
26192689 }
@@ -2894,8 +2964,17 @@ - (nullable instancetype)initWithUDID:(NSString *)udid
28942964 _displayView = [[NSView alloc ] initWithFrame: NSMakeRect (0 , 0 , 430 , 932 )];
28952965 _displayView.wantsLayer = YES ;
28962966 }
2897- [self updateStatus: @" Waiting for IOSurface callback" ];
2898- [self activateDisplayIfNeeded ];
2967+ [self updateStatus: @" Waiting for direct CoreSimulator IOSurface callback" ];
2968+ NSDate *directFrameDeadline = [NSDate dateWithTimeIntervalSinceNow: 1.0 ];
2969+ while (_latestPixelBuffer == nil && [directFrameDeadline timeIntervalSinceNow ] > 0 ) {
2970+ DFSpinRunLoop (0.05 );
2971+ }
2972+ if (_latestPixelBuffer == nil ) {
2973+ [self updateStatus: @" Direct CoreSimulator frames unavailable; attaching SimulatorKit fallback display" ];
2974+ [self activateDisplayIfNeeded ];
2975+ } else {
2976+ DFLog (@" Using direct CoreSimulator screen callbacks without activating SimulatorKit fallback display." );
2977+ }
28992978
29002979 DFSpinRunLoop (0.25 );
29012980 return self;
0 commit comments