perf: prevent random freezes of the ui (#563)

timers were on the main thread, creating indeterministic freezes
This commit is contained in:
Louis Pontoise authored and lwouis committed 2020-09-08 23:29:32 +09:00
1 parent 7b304903ee
commit e208da91da
4 files changed
+25 -15

No files matched your search

+5
View File
@@ -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 {
+17 -13
View File
@@ -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) {
+1
View File
@@ -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()
@@ -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()