diff --git a/TargetBridge-Receiver/TBReceiverC/src/main.c b/TargetBridge-Receiver/TBReceiverC/src/main.c index f334413..4d23345 100644 --- a/TargetBridge-Receiver/TBReceiverC/src/main.c +++ b/TargetBridge-Receiver/TBReceiverC/src/main.c @@ -1855,6 +1855,14 @@ static void build_display_host(char *buf, size_t bufsz, const char *ip_fallback, int main(int argc, char **argv) { int fullscreen = 1; for (int i = 1; i < argc; i++) { + if (strcmp(argv[i], "--permission-status") == 0) { + printf( + "TB_PERMISSION_STATUS:screen_recording=0:accessibility=%d:input_monitoring=%d\n", + tb_receiver_accessibility_trusted(), + tb_receiver_input_monitoring_trusted() + ); + return 0; + } if (strcmp(argv[i], "--windowed") == 0) fullscreen = 0; } diff --git a/TargetBridge-Sender/TBDisplaySender/TBDisplaySenderApp.swift b/TargetBridge-Sender/TBDisplaySender/TBDisplaySenderApp.swift index 5457c13..a96a66a 100644 --- a/TargetBridge-Sender/TBDisplaySender/TBDisplaySenderApp.swift +++ b/TargetBridge-Sender/TBDisplaySender/TBDisplaySenderApp.swift @@ -1,13 +1,31 @@ import AppKit +import ApplicationServices +import Darwin import SwiftUI @main struct TBDisplaySenderApp: App { - @StateObject private var service = TBDisplaySenderService.shared - private let statusItemController = TBDisplaySenderStatusItemController(service: TBDisplaySenderService.shared) + @StateObject private var service: TBDisplaySenderService + private let statusItemController: TBDisplaySenderStatusItemController @MainActor init() { + // This probe is intentionally handled before constructing the shared + // service. The Setup Assistant can inspect the exact installed binary + // without opening a window, starting capture or attaching a display. + if CommandLine.arguments.contains("--permission-status") { + let screenRecording = CGPreflightScreenCaptureAccess() ? 1 : 0 + let accessibility = AXIsProcessTrusted() ? 1 : 0 + let inputMonitoring = CGPreflightListenEventAccess() ? 1 : 0 + print("TB_PERMISSION_STATUS:screen_recording=\(screenRecording):accessibility=\(accessibility):input_monitoring=\(inputMonitoring)") + fflush(stdout) + Darwin.exit(EXIT_SUCCESS) + } + + let sharedService = TBDisplaySenderService.shared + _service = StateObject(wrappedValue: sharedService) + statusItemController = TBDisplaySenderStatusItemController(service: sharedService) + // LaunchAgent automation must not depend on SwiftUI restoring or showing // the main window on a headless Mac. TBSenderAutomation.handleLaunchArguments(CommandLine.arguments)