diff --git a/src/logic/BackgroundWork.swift b/src/logic/BackgroundWork.swift index 05cd974c..1f9425f6 100644 --- a/src/logic/BackgroundWork.swift +++ b/src/logic/BackgroundWork.swift @@ -8,6 +8,7 @@ class BackgroundWork { static var crashReportsQueue: DispatchQueue! static var accessibilityEventsThread: BackgroundThreadWithRunLoop! static var mouseEventsThread: BackgroundThreadWithRunLoop! + static var systemPermissionsThread: BackgroundThreadWithRunLoop! // we cap concurrent tasks to .processorCount to avoid thread explosion on the .global queue static let globalSemaphore = DispatchSemaphore(value: ProcessInfo.processInfo.processorCount) @@ -21,6 +22,10 @@ class BackgroundWork { accessibilityEventsThread = BackgroundThreadWithRunLoop("accessibilityEventsThread", .userInteractive) mouseEventsThread = BackgroundThreadWithRunLoop("mouseEventsThread", .userInteractive) } + + static func startSystemPermissionThread() { + systemPermissionsThread = BackgroundThreadWithRunLoop("systemPermissionsThread", .utility) + } } extension DispatchQueue { diff --git a/src/logic/SystemPermissions.swift b/src/logic/SystemPermissions.swift index 34675114..a5fc0673 100644 --- a/src/logic/SystemPermissions.swift +++ b/src/logic/SystemPermissions.swift @@ -42,12 +42,13 @@ class SystemPermissions { } static func observePermissionsPostStartup() { - timer = Timer.scheduledTimer(withTimeInterval: 5, repeats: true, block: { _ in + timer = Timer(timeInterval: 5, repeats: true, block: { _ in if !(accessibilityIsGranted() && screenRecordingIsGranted()) { App.app.restart() } }) timer.tolerance = 4.9 + CFRunLoopAddTimer(BackgroundWork.systemPermissionsThread.runLoop, timer, .defaultMode) } static func observePermissionsPreStartup(_ startupBlock: @escaping () -> Void) { @@ -55,23 +56,26 @@ class SystemPermissions { // this call triggers the permission prompt, however it's the only way to force the app to be listed with a checkbox SLSRequestScreenCaptureAccess() } - timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { _ in + timer = Timer(timeInterval: 0.1, repeats: true) { _ in let accessibility = accessibilityIsGranted() let screenRecording = screenRecordingIsGranted() - if accessibility && screenRecording { - permissionsWindow.close() - timer.invalidate() - startupBlock() - } else { - if accessibility != permissionsWindow.accessibilityView.isPermissionGranted { - permissionsWindow.accessibilityView.updatePermissionStatus(accessibility) - } - if #available(OSX 10.15, *), screenRecording != permissionsWindow.screenRecordingView.isPermissionGranted { - permissionsWindow.screenRecordingView.updatePermissionStatus(screenRecording) + DispatchQueue.main.async { + if accessibility && screenRecording { + permissionsWindow.close() + timer.invalidate() + startupBlock() + } else { + if accessibility != permissionsWindow.accessibilityView.isPermissionGranted { + permissionsWindow.accessibilityView.updatePermissionStatus(accessibility) + } + if #available(OSX 10.15, *), screenRecording != permissionsWindow.screenRecordingView.isPermissionGranted { + permissionsWindow.screenRecordingView.updatePermissionStatus(screenRecording) + } } } - }) + } timer.tolerance = 0.09 + CFRunLoopAddTimer(BackgroundWork.systemPermissionsThread.runLoop, timer, .defaultMode) } static func ensurePermissionsAreGranted(_ continueAppStartup: @escaping () -> Void) { diff --git a/src/ui/App.swift b/src/ui/App.swift index c75d2014..ccc36b60 100644 --- a/src/ui/App.swift +++ b/src/ui/App.swift @@ -41,6 +41,7 @@ class App: AppCenterApplication, NSApplicationDelegate { PFMoveToApplicationsFolderIfNecessary() #endif AXUIElement.setGlobalTimeout() + BackgroundWork.startSystemPermissionThread() SystemPermissions.ensurePermissionsAreGranted { [weak self] in guard let self = self else { return } BackgroundWork.start() diff --git a/src/ui/permission-window/PermissionsWindow.swift b/src/ui/permission-window/PermissionsWindow.swift index 548b580a..bcbf6def 100644 --- a/src/ui/permission-window/PermissionsWindow.swift +++ b/src/ui/permission-window/PermissionsWindow.swift @@ -4,8 +4,8 @@ class PermissionsWindow: NSWindow, NSWindowDelegate { var accessibilityView: PermissionView! var screenRecordingView: PermissionView! - override init(contentRect: NSRect, styleMask style: StyleMask, backing backingStoreType: BackingStoreType, defer flag: Bool) { - super.init(contentRect: .zero, styleMask: style, backing: backingStoreType, defer: flag) + convenience init() { + self.init(contentRect: .zero, styleMask: [.titled, .miniaturizable, .closable], backing: .buffered, defer: false) delegate = self setupWindow() setupView()