mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
Atoll: clear lock screen widgets faster on unlock
- Add session-active and CGSession poll fallbacks for unlock detection - Force weather panel alpha to 0 before orderOut for instant hide Signed-off-by: Jis G Jacob <studiokeys@blissroms.org>
This commit is contained in:
parent
854eb3e4bd
commit
3829627dbd
2 changed files with 61 additions and 4 deletions
|
|
@ -48,6 +48,7 @@ class LockScreenManager: ObservableObject {
|
||||||
private var debounceIdleTask: Task<Void, Never>?
|
private var debounceIdleTask: Task<Void, Never>?
|
||||||
private var collapseTask: Task<Void, Never>?
|
private var collapseTask: Task<Void, Never>?
|
||||||
private var postUnlockMusicHUDTask: Task<Void, Never>?
|
private var postUnlockMusicHUDTask: Task<Void, Never>?
|
||||||
|
private var lockStatePollTask: Task<Void, Never>?
|
||||||
|
|
||||||
// MARK: - Helpers
|
// MARK: - Helpers
|
||||||
|
|
||||||
|
|
@ -65,9 +66,11 @@ class LockScreenManager: ObservableObject {
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
DistributedNotificationCenter.default().removeObserver(self)
|
DistributedNotificationCenter.default().removeObserver(self)
|
||||||
|
NSWorkspace.shared.notificationCenter.removeObserver(self)
|
||||||
debounceIdleTask?.cancel()
|
debounceIdleTask?.cancel()
|
||||||
collapseTask?.cancel()
|
collapseTask?.cancel()
|
||||||
postUnlockMusicHUDTask?.cancel()
|
postUnlockMusicHUDTask?.cancel()
|
||||||
|
lockStatePollTask?.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Setup
|
// MARK: - Setup
|
||||||
|
|
@ -89,6 +92,17 @@ class LockScreenManager: ObservableObject {
|
||||||
object: nil
|
object: nil
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Fallback: macOS sometimes delays `com.apple.screenIsUnlocked`, leaving
|
||||||
|
// lock-screen widgets visible after the user-perceived unlock.
|
||||||
|
// The workspace session-active notification typically fires earlier; the
|
||||||
|
// guard at the top of `screenUnlocked` makes the call idempotent.
|
||||||
|
NSWorkspace.shared.notificationCenter.addObserver(
|
||||||
|
self,
|
||||||
|
selector: #selector(screenUnlocked),
|
||||||
|
name: NSWorkspace.sessionDidBecomeActiveNotification,
|
||||||
|
object: nil
|
||||||
|
)
|
||||||
|
|
||||||
print("LockScreenManager: ✅ Observers registered for lock/unlock events")
|
print("LockScreenManager: ✅ Observers registered for lock/unlock events")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -141,6 +155,8 @@ class LockScreenManager: ObservableObject {
|
||||||
print("[\(timestamp())] LockScreenManager: ⏭️ Lock icon disabled in settings")
|
print("[\(timestamp())] LockScreenManager: ⏭️ Lock icon disabled in settings")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startLockStatePolling()
|
||||||
|
|
||||||
print("[\(timestamp())] LockScreenManager: ✅ Lock screen activated")
|
print("[\(timestamp())] LockScreenManager: ✅ Lock screen activated")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -156,6 +172,7 @@ class LockScreenManager: ObservableObject {
|
||||||
lastUpdated = Date()
|
lastUpdated = Date()
|
||||||
updateIdleState(locked: false)
|
updateIdleState(locked: false)
|
||||||
isLocked = false
|
isLocked = false
|
||||||
|
stopLockStatePolling()
|
||||||
postUnlockMusicHUDTask?.cancel()
|
postUnlockMusicHUDTask?.cancel()
|
||||||
shouldDelayPostUnlockMusicHUD = Defaults[.enableLockScreenLiveActivity]
|
shouldDelayPostUnlockMusicHUD = Defaults[.enableLockScreenLiveActivity]
|
||||||
|
|
||||||
|
|
@ -207,6 +224,44 @@ class LockScreenManager: ObservableObject {
|
||||||
print("[\(self.timestamp())] LockScreenManager: ✅ Lock screen deactivated")
|
print("[\(self.timestamp())] LockScreenManager: ✅ Lock screen deactivated")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Lock State Polling
|
||||||
|
|
||||||
|
// Defensive fallback against late/missed `com.apple.screenIsUnlocked` and
|
||||||
|
// `NSWorkspace.sessionDidBecomeActiveNotification` notifications, which
|
||||||
|
// macOS sometimes delivers well after the user-perceived unlock — leaving
|
||||||
|
// lock-screen widgets visible for an extra moment. While we believe we are
|
||||||
|
// locked, poll the canonical session-lock state and fire `screenUnlocked()`
|
||||||
|
// the moment the OS flips. The handler's duplicate-event guard makes this
|
||||||
|
// safe to call alongside any later-arriving notification.
|
||||||
|
private static func isSessionScreenLocked() -> Bool {
|
||||||
|
guard let session = CGSessionCopyCurrentDictionary() as? [String: Any] else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return session["CGSSessionScreenIsLocked"] as? Bool ?? false
|
||||||
|
}
|
||||||
|
|
||||||
|
private func startLockStatePolling() {
|
||||||
|
lockStatePollTask?.cancel()
|
||||||
|
lockStatePollTask = Task { [weak self] in
|
||||||
|
while !Task.isCancelled {
|
||||||
|
try? await Task.sleep(for: .milliseconds(500))
|
||||||
|
if Task.isCancelled { return }
|
||||||
|
await MainActor.run {
|
||||||
|
guard let self, self.isLocked else { return }
|
||||||
|
if !Self.isSessionScreenLocked() {
|
||||||
|
print("[\(self.timestamp())] LockScreenManager: 🔓 Polling detected unlock ahead of notification")
|
||||||
|
self.screenUnlocked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func stopLockStatePolling() {
|
||||||
|
lockStatePollTask?.cancel()
|
||||||
|
lockStatePollTask = nil
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Idle State Management
|
// MARK: - Idle State Management
|
||||||
|
|
||||||
/// Copy EXACT logic from ScreenRecordingManager
|
/// Copy EXACT logic from ScreenRecordingManager
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,10 @@ final class LockScreenWeatherPanelManager {
|
||||||
|
|
||||||
func hide() {
|
func hide() {
|
||||||
guard let window else { return }
|
guard let window else { return }
|
||||||
|
window.alphaValue = 0
|
||||||
window.orderOut(nil)
|
window.orderOut(nil)
|
||||||
window.contentView = nil
|
window.contentView = nil
|
||||||
|
window.alphaValue = 1
|
||||||
latestFrame = nil
|
latestFrame = nil
|
||||||
lastSnapshot = nil
|
lastSnapshot = nil
|
||||||
lastContentSize = nil
|
lastContentSize = nil
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue