@@ -442,6 +442,59 @@ int enable_grid_app_switcher(RemoteCall *proc) {
442442 return 0 ;
443443}
444444
445+ static uint64_t get_main_window (RemoteCall *proc) {
446+ if (!proc) return 0 ;
447+
448+ uint64_t clsUIApplication = remote_getClass (proc, " UIApplication" );
449+ if (!clsUIApplication) return 0 ;
450+
451+ uint64_t selSharedApp = remote_sel (proc, " sharedApplication" );
452+ uint64_t app = remote_msg (proc, clsUIApplication, selSharedApp, 0 , 0 , 0 , 0 );
453+ if (!app) return 0 ;
454+
455+ uint64_t selKeyWindow = remote_sel (proc, " keyWindow" );
456+ uint64_t selWindows = remote_sel (proc, " windows" );
457+ uint64_t selCount = remote_sel (proc, " count" );
458+ uint64_t selObjAtIdx = remote_sel (proc, " objectAtIndex:" );
459+
460+ uint64_t window = remote_msg (proc, app, selKeyWindow, 0 , 0 , 0 , 0 );
461+ if (window) return window;
462+
463+ uint64_t windows = remote_msg (proc, app, selWindows, 0 , 0 , 0 , 0 );
464+ if (windows) {
465+ uint64_t count = remote_msg (proc, windows, selCount, 0 , 0 , 0 , 0 );
466+ for (uint64_t i = 0 ; i < count && i < 10 ; i++) {
467+ uint64_t w = remote_msg (proc, windows, selObjAtIdx, i, 0 , 0 , 0 );
468+ if (w) return w;
469+ }
470+ }
471+
472+ uint64_t selConnectedScenes = remote_sel (proc, " connectedScenes" );
473+ uint64_t scenes = remote_msg (proc, app, selConnectedScenes, 0 , 0 , 0 , 0 );
474+ if (scenes) {
475+ uint64_t selAllObjects = remote_sel (proc, " allObjects" );
476+ uint64_t sceneArray = remote_msg (proc, scenes, selAllObjects, 0 , 0 , 0 , 0 );
477+ if (sceneArray) {
478+ uint64_t scCount = remote_msg (proc, sceneArray, selCount, 0 , 0 , 0 , 0 );
479+ for (uint64_t i = 0 ; i < scCount && i < 5 ; i++) {
480+ uint64_t scene = remote_msg (proc, sceneArray, selObjAtIdx, i, 0 , 0 , 0 );
481+ if (scene) {
482+ uint64_t sceneWindows = remote_msg (proc, scene, selWindows, 0 , 0 , 0 , 0 );
483+ if (sceneWindows) {
484+ uint64_t wCount = remote_msg (proc, sceneWindows, selCount, 0 , 0 , 0 , 0 );
485+ for (uint64_t j = 0 ; j < wCount && j < 10 ; j++) {
486+ uint64_t w = remote_msg (proc, sceneWindows, selObjAtIdx, j, 0 , 0 , 0 );
487+ if (w) return w;
488+ }
489+ }
490+ }
491+ }
492+ }
493+ }
494+
495+ return 0 ;
496+ }
497+
445498static uint64_t get_main_window_scene (RemoteCall *proc) {
446499 if (!proc) return 0 ;
447500 uint64_t selMainWindowScene = remote_sel (proc, " mainWindowScene" );
@@ -456,29 +509,18 @@ static uint64_t get_main_window_scene(RemoteCall *proc) {
456509 }
457510 }
458511
512+ uint64_t window = get_main_window (proc);
513+ if (window) {
514+ uint64_t selWindowScene = remote_sel (proc, " windowScene" );
515+ uint64_t scene = remote_msg (proc, window, selWindowScene, 0 , 0 , 0 , 0 );
516+ if (scene) return scene;
517+ }
518+
459519 uint64_t clsUIApplication = remote_getClass (proc, " UIApplication" );
460520 if (clsUIApplication) {
461521 uint64_t selSharedApp = remote_sel (proc, " sharedApplication" );
462522 uint64_t app = remote_msg (proc, clsUIApplication, selSharedApp, 0 ,0 ,0 ,0 );
463523 if (app) {
464- uint64_t selKeyWindow = remote_sel (proc, " keyWindow" );
465- uint64_t selWindows = remote_sel (proc, " windows" );
466- uint64_t selFirstObj = remote_sel (proc, " firstObject" );
467- uint64_t selWindowScene = remote_sel (proc, " windowScene" );
468-
469- uint64_t window = remote_msg (proc, app, selKeyWindow, 0 ,0 ,0 ,0 );
470- if (!window) {
471- uint64_t windows = remote_msg (proc, app, selWindows, 0 ,0 ,0 ,0 );
472- if (windows) {
473- window = remote_msg (proc, windows, selFirstObj, 0 ,0 ,0 ,0 );
474- }
475- }
476-
477- if (window) {
478- uint64_t scene = remote_msg (proc, window, selWindowScene, 0 ,0 ,0 ,0 );
479- if (scene) return scene;
480- }
481-
482524 uint64_t selConnectedScenes = remote_sel (proc, " connectedScenes" );
483525 uint64_t selAnyObject = remote_sel (proc, " anyObject" );
484526 uint64_t scenes = remote_msg (proc, app, selConnectedScenes, 0 ,0 ,0 ,0 );
@@ -505,67 +547,90 @@ int enable_debug_overlay(RemoteCall *proc) {
505547 return -1 ;
506548 }
507549
508- uint64_t selAddGestureRecognizer = remote_sel (proc, " addGestureRecognizer:" );
509- uint64_t selHandleActivation = remote_sel (proc, " _handleActivationGesture:" );
510550 uint64_t selInit = remote_sel (proc, " init" );
511- uint64_t selInitWithTargetAction = remote_sel (proc, " initWithTarget:action:" );
512- uint64_t selMainHandler = remote_sel (proc, " mainHandler" );
513551 uint64_t selOverlay = remote_sel (proc, " overlay" );
552+ uint64_t selPrepare = remote_sel (proc, " prepareDebuggingOverlay" );
514553 uint64_t selPerform = remote_sel (proc, " performSelectorOnMainThread:withObject:waitUntilDone:" );
515- uint64_t selSetNumberOfTapsRequired = remote_sel (proc, " setNumberOfTapsRequired:" );
516- uint64_t selSetWindowScene = remote_sel (proc, " setWindowScene:" );
517- uint64_t selSharedApplication = remote_sel (proc, " sharedApplication" );
518- uint64_t selStatusBar = remote_sel (proc, " statusBarForEmbeddedDisplay" );
519554
520- // Swizzle -[UIDebuggingInformationOverlay init] to -[UIWindow init] to bypass internal check
555+ // 1. Swizzle -[UIDebuggingInformationOverlay init] to -[UIWindow init] to bypass internal check
521556 uint64_t methodWindowInit = RemoteArbCall (proc, class_getInstanceMethod , clsUIWindow, selInit);
522557 uint64_t methodOverlayInit = RemoteArbCall (proc, class_getInstanceMethod , clsDebugOverlayWindow, selInit);
523558 uint64_t impWindowInit = RemoteArbCall (proc, method_getImplementation , methodWindowInit);
524559 if (methodOverlayInit && impWindowInit) {
525560 RemoteArbCall (proc, method_setImplementation , methodOverlayInit, impWindowInit);
526561 }
562+
563+ // 2. Call +[UIDebuggingInformationOverlay prepareDebuggingOverlay] to prevent UIDebuggingInformationOverlayNotPrepared exception
564+ remote_msg (proc, clsDebugOverlayWindow, selPerform, selPrepare, 0 , 1 , 0 );
527565
528- // Set windowScene
529- uint64_t mainWindowScene = get_main_window_scene (proc);
530- remote_msg (proc, clsDebugOverlayWindow, selPerform, selOverlay, 0 , 1 , 0 ); // init window
566+ // 3. Get or allocate overlay window
567+ remote_msg (proc, clsDebugOverlayWindow, selPerform, selOverlay, 0 , 1 , 0 );
531568 uint64_t debugOverlay = remote_msg (proc, clsDebugOverlayWindow, selOverlay, 0 , 0 , 0 , 0 );
569+ if (!debugOverlay) {
570+ debugOverlay = RemoteArbCall (proc, objc_alloc, clsDebugOverlayWindow);
571+ if (debugOverlay) {
572+ debugOverlay = remote_msg (proc, debugOverlay, selInit, 0 , 0 , 0 , 0 );
573+ }
574+ }
575+
576+ // 4. Set windowScene
577+ uint64_t mainWindowScene = get_main_window_scene (proc);
532578 if (debugOverlay && mainWindowScene) {
579+ uint64_t selSetWindowScene = remote_sel (proc, " setWindowScene:" );
533580 remote_msg (proc, debugOverlay, selPerform, selSetWindowScene, mainWindowScene, 1 , 0 );
534581 }
535582
583+ // 5. Show overlay window immediately
536584 if (debugOverlay) {
585+ uint64_t selSetHidden = remote_sel (proc, " setHidden:" );
586+ uint64_t selMakeKeyAndVisible = remote_sel (proc, " makeKeyAndVisible" );
537587 uint64_t selToggle = remote_sel (proc, " toggleVisibility" );
588+
589+ remote_msg (proc, debugOverlay, selPerform, selSetHidden, 0 , 1 , 0 );
590+ remote_msg (proc, debugOverlay, selPerform, selMakeKeyAndVisible, 0 , 1 , 0 );
538591 remote_msg (proc, debugOverlay, selPerform, selToggle, 0 , 1 , 0 );
539592 }
540593
541- // register gesture recognizer to status bar or key window
594+ // 6. Register gesture recognizer to status bar and main window
542595 if (clsDebugOverlayHandler && clsUITapGestureRecognizer) {
596+ uint64_t selMainHandler = remote_sel (proc, " mainHandler" );
597+ uint64_t selSharedInstance = remote_sel (proc, " sharedInstance" );
543598 uint64_t target = remote_msg (proc, clsDebugOverlayHandler, selMainHandler, 0 , 0 , 0 , 0 );
599+ if (!target) {
600+ target = remote_msg (proc, clsDebugOverlayHandler, selSharedInstance, 0 , 0 , 0 , 0 );
601+ }
602+
544603 if (target) {
545- uint64_t doubleTapGesture = RemoteArbCall (proc, objc_alloc, clsUITapGestureRecognizer);
546- doubleTapGesture = remote_msg (proc, doubleTapGesture, selInitWithTargetAction, target, selHandleActivation, 0 , 0 );
547- remote_msg (proc, doubleTapGesture, selSetNumberOfTapsRequired, 2 , 0 , 0 , 0 );
548-
549- uint64_t app = remote_msg (proc, clsUIApplication, selSharedApplication, 0 , 0 , 0 , 0 );
550- uint64_t targetView = 0 ;
604+ uint64_t selInitWithTargetAction = remote_sel (proc, " initWithTarget:action:" );
605+ uint64_t selHandleActivation = remote_sel (proc, " _handleActivationGesture:" );
606+ uint64_t selSetNumberOfTapsRequired = remote_sel (proc, " setNumberOfTapsRequired:" );
607+ uint64_t selAddGesture = remote_sel (proc, " addGestureRecognizer:" );
608+
609+ // Gesture 1: Status bar double tap
610+ uint64_t app = remote_msg (proc, clsUIApplication, remote_sel (proc, " sharedApplication" ), 0 , 0 , 0 , 0 );
611+ uint64_t statusBar = 0 ;
551612 if (app) {
552- targetView = remote_msg (proc, app, selStatusBar, 0 , 0 , 0 , 0 );
553- if (!targetView) {
554- uint64_t selKeyWindow = remote_sel (proc, " keyWindow" );
555- targetView = remote_msg (proc, app, selKeyWindow, 0 , 0 , 0 , 0 );
556- }
557- if (!targetView) {
558- uint64_t selWindows = remote_sel (proc, " windows" );
559- uint64_t windows = remote_msg (proc, app, selWindows, 0 , 0 , 0 , 0 );
560- if (windows) {
561- targetView = remote_msg (proc, windows, remote_sel (proc, " firstObject" ), 0 , 0 , 0 , 0 );
562- }
563- }
613+ statusBar = remote_msg (proc, app, remote_sel (proc, " statusBarForEmbeddedDisplay" ), 0 , 0 , 0 , 0 );
614+ }
615+ if (statusBar) {
616+ uint64_t sbGesture = RemoteArbCall (proc, objc_alloc, clsUITapGestureRecognizer);
617+ sbGesture = remote_msg (proc, sbGesture, selInitWithTargetAction, target, selHandleActivation, 0 , 0 );
618+ remote_msg (proc, sbGesture, selSetNumberOfTapsRequired, 2 , 0 , 0 , 0 );
619+ remote_msg (proc, statusBar, selPerform, selAddGesture, sbGesture, 1 , 0 );
620+ RemoteArbCall (proc, objc_release, sbGesture);
564621 }
565- if (targetView) {
566- remote_msg (proc, targetView, selPerform, selAddGestureRecognizer, doubleTapGesture, 1 , 0 );
622+
623+ // Gesture 2: Main window 2-finger double tap
624+ uint64_t mainWindow = get_main_window (proc);
625+ if (mainWindow) {
626+ uint64_t winGesture = RemoteArbCall (proc, objc_alloc, clsUITapGestureRecognizer);
627+ winGesture = remote_msg (proc, winGesture, selInitWithTargetAction, target, selHandleActivation, 0 , 0 );
628+ remote_msg (proc, winGesture, selSetNumberOfTapsRequired, 2 , 0 , 0 , 0 );
629+ uint64_t selSetTouches = remote_sel (proc, " setNumberOfTouchesRequired:" );
630+ remote_msg (proc, winGesture, selSetTouches, 2 , 0 , 0 , 0 );
631+ remote_msg (proc, mainWindow, selPerform, selAddGesture, winGesture, 1 , 0 );
632+ RemoteArbCall (proc, objc_release, winGesture);
567633 }
568- RemoteArbCall (proc, objc_release, doubleTapGesture);
569634 }
570635 }
571636
0 commit comments