feat: stop checking screen-recording permission after launch (#5202)

closes #5202

the permission check was expensive for the os, leading to higher energy usage, thus more battery drain
This commit is contained in:
lwouis committed 2026-01-15 15:47:33 +01:00
1 parent 149e3a5026
commit f481d22b75
3 files changed
+6 -22

No files matched your search

+6 -17
View File
@@ -15,20 +15,22 @@ class SystemPermissions {
private static func checkPermissionsOnTimer() { private static func checkPermissionsOnTimer() {
AccessibilityPermission.update() AccessibilityPermission.update()
ScreenRecordingPermission.update() if !preStartupPermissionsPassed || App.app.permissionsWindow.isVisible {
ScreenRecordingPermission.update()
}
Logger.debug { "accessibility:\(AccessibilityPermission.status) screenRecording:\(ScreenRecordingPermission.status)" }
if !preStartupPermissionsPassed { if !preStartupPermissionsPassed {
checkPermissionsPreStartup() checkPermissionsPreStartup()
} else { } else {
checkPermissionsPostStartup() checkPermissionsPostStartup()
} }
DispatchQueue.main.async { DispatchQueue.main.async {
Menubar.togglePermissionCallout(ScreenRecordingPermission.status == .skipped) Menubar.togglePermissionCallout(ScreenRecordingPermission.status != .granted)
App.app.permissionsWindow.updatePermissionViews() App.app.permissionsWindow.updatePermissionViews()
} }
} }
private static func checkPermissionsPreStartup() { private static func checkPermissionsPreStartup() {
Logger.info { "accessibility:\(AccessibilityPermission.status) screenRecording:\(ScreenRecordingPermission.status)" }
if AccessibilityPermission.status != .notGranted && ScreenRecordingPermission.status != .notGranted { if AccessibilityPermission.status != .notGranted && ScreenRecordingPermission.status != .notGranted {
DispatchQueue.main.async { DispatchQueue.main.async {
preStartupPermissionsPassed = true preStartupPermissionsPassed = true
@@ -44,22 +46,10 @@ class SystemPermissions {
} }
private static func checkPermissionsPostStartup() { private static func checkPermissionsPostStartup() {
Logger.debug { "accessibility:\(AccessibilityPermission.status) screenRecording:\(ScreenRecordingPermission.status)" }
if AccessibilityPermission.status == .notGranted { if AccessibilityPermission.status == .notGranted {
Logger.error { "Accessibility permission revoked while AltTab was running; restarting" } Logger.error { "Accessibility permission revoked while AltTab was running; restarting" }
DispatchQueue.main.async { App.app.restart() } DispatchQueue.main.async { App.app.restart() }
} }
if ScreenRecordingPermission.status == .notGranted {
// permission check may yield a false negative during wake-up; we restart after 2 negative checks
if ScreenRecordingPermission.flakyCounter >= 2 {
Logger.error { "Screen-recording permission revoked while AltTab was running (checked 2 times); restarting" }
DispatchQueue.main.async { App.app.restart() }
} else {
ScreenRecordingPermission.flakyCounter += 1
}
} else {
ScreenRecordingPermission.flakyCounter = 0
}
} }
static func setInfrequentTimer() { static func setInfrequentTimer() {
@@ -67,7 +57,7 @@ class SystemPermissions {
} }
static func setFrequentTimer() { static func setFrequentTimer() {
timer.schedule(deadline: .now() + 0.5, repeating: 0.5, leeway: .milliseconds(500)) timer.schedule(deadline: .now(), repeating: 0.5, leeway: .milliseconds(500))
} }
private static func setImmediateTimer() { private static func setImmediateTimer() {
@@ -91,7 +81,6 @@ class AccessibilityPermission {
class ScreenRecordingPermission { class ScreenRecordingPermission {
static var status = PermissionStatus.notGranted static var status = PermissionStatus.notGranted
static var flakyCounter = 0
@discardableResult @discardableResult
static func update() -> PermissionStatus { static func update() -> PermissionStatus {
-3
View File
@@ -4,7 +4,6 @@ class Menubar {
static var statusItem: NSStatusItem! static var statusItem: NSStatusItem!
static var menu: NSMenu! static var menu: NSMenu!
static var permissionCalloutMenuItems: [NSMenuItem]? static var permissionCalloutMenuItems: [NSMenuItem]?
static var isShowingPermissionCallout = false
static func addMenuItem(_ title: String, _ action: Selector, _ keyEquivalent: String, _ symbolName: String?, _ color: NSColor? = nil) { static func addMenuItem(_ title: String, _ action: Selector, _ keyEquivalent: String, _ symbolName: String?, _ color: NSColor? = nil) {
let item = menu.addItem(withTitle: title, action: action, keyEquivalent: keyEquivalent) let item = menu.addItem(withTitle: title, action: action, keyEquivalent: keyEquivalent)
@@ -42,8 +41,6 @@ class Menubar {
// NSMenuItem.isHidden isn't reliable with custom views. We add/remove to hide/show these items // NSMenuItem.isHidden isn't reliable with custom views. We add/remove to hide/show these items
static func togglePermissionCallout(_ show: Bool) { static func togglePermissionCallout(_ show: Bool) {
guard isShowingPermissionCallout != show else { return }
isShowingPermissionCallout = show
permissionCalloutMenuItems?.enumerated().forEach { offset, element in permissionCalloutMenuItems?.enumerated().forEach { offset, element in
if show && !menu.items.contains(element) { if show && !menu.items.contains(element) {
menu.insertItem(element, at: offset) menu.insertItem(element, at: offset)
@@ -17,14 +17,12 @@ class PermissionsWindow: NSWindow {
guard !isVisible else { return } guard !isVisible else { return }
Logger.debug { "" } Logger.debug { "" }
SystemPermissions.setFrequentTimer() SystemPermissions.setFrequentTimer()
updatePermissionViews()
center() center()
App.shared.activate(ignoringOtherApps: true) App.shared.activate(ignoringOtherApps: true)
makeKeyAndOrderFront(nil) makeKeyAndOrderFront(nil)
} }
func updatePermissionViews() { func updatePermissionViews() {
guard isVisible else { return }
accessibilityView.updatePermissionStatus(AccessibilityPermission.status) accessibilityView.updatePermissionStatus(AccessibilityPermission.status)
if #available(macOS 10.15, *) { if #available(macOS 10.15, *) {
screenRecordingView.updatePermissionStatus(ScreenRecordingPermission.status) screenRecordingView.updatePermissionStatus(ScreenRecordingPermission.status)