From 34e435b400e183215f4a223332ab9d327b484dcf Mon Sep 17 00:00:00 2001 From: Hariharan Mudaliar Date: Wed, 10 Dec 2025 23:59:11 +0530 Subject: [PATCH] HotFix: Lock Screen Widget positioning issue --- .../managers/LockScreenPanelManager.swift | 37 +++++++++++++++++++ ...LockScreenReminderWidgetPanelManager.swift | 33 ++++++++++++++++- .../LockScreenTimerWidgetManager.swift | 33 ++++++++++++++++- .../LockScreenWeatherPanelManager.swift | 33 ++++++++++++++++- 4 files changed, 133 insertions(+), 3 deletions(-) diff --git a/DynamicIsland/managers/LockScreenPanelManager.swift b/DynamicIsland/managers/LockScreenPanelManager.swift index 56bb800..7875aaa 100644 --- a/DynamicIsland/managers/LockScreenPanelManager.swift +++ b/DynamicIsland/managers/LockScreenPanelManager.swift @@ -30,9 +30,12 @@ class LockScreenPanelManager { private(set) var latestFrame: NSRect? private let panelAnimator = LockScreenPanelAnimator() private var hideTask: Task? + private var screenChangeObserver: NSObjectProtocol? + private var workspaceObservers: [NSObjectProtocol] = [] private init() { print("[\(timestamp())] LockScreenPanelManager: initialized") + registerScreenChangeObservers() } private func timestamp() -> String { @@ -41,6 +44,27 @@ class LockScreenPanelManager { return formatter.string(from: Date()) } + private func registerScreenChangeObservers() { + screenChangeObserver = NotificationCenter.default.addObserver( + forName: NSApplication.didChangeScreenParametersNotification, + object: nil, + queue: .main + ) { [weak self] _ in + self?.handleScreenGeometryChange(reason: "screen-parameters") + } + + let workspaceCenter = NSWorkspace.shared.notificationCenter + let wakeObserver = workspaceCenter.addObserver( + forName: NSWorkspace.screensDidWakeNotification, + object: nil, + queue: .main + ) { [weak self] _ in + self?.handleScreenGeometryChange(reason: "screens-did-wake") + } + + workspaceObservers = [wakeObserver] + } + func showPanel() { print("[\(timestamp())] LockScreenPanelManager: showPanel") @@ -197,6 +221,19 @@ class LockScreenPanelManager { } } + private func handleScreenGeometryChange(reason: String) { + guard let window = panelWindow else { return } + guard window.isVisible || panelAnimator.isPresented else { return } + guard let screen = NSScreen.main else { return } + + let screenFrame = screen.frame + collapsedFrame = collapsedFrame(for: screenFrame) + updatePanelSize(expanded: isPanelExpanded, additionalHeight: currentAdditionalHeight, animated: false) + LockScreenTimerWidgetManager.shared.notifyMusicPanelFrameChanged(animated: false) + + print("[\(timestamp())] LockScreenPanelManager: realigned window due to \(reason)") + } + private func collapsedFrame(for screenFrame: NSRect) -> NSRect { let collapsedSize = LockScreenMusicPanel.collapsedSize let originX = screenFrame.midX - (collapsedSize.width / 2) diff --git a/DynamicIsland/managers/LockScreenReminderWidgetPanelManager.swift b/DynamicIsland/managers/LockScreenReminderWidgetPanelManager.swift index 27a0a8f..7b5d0f4 100644 --- a/DynamicIsland/managers/LockScreenReminderWidgetPanelManager.swift +++ b/DynamicIsland/managers/LockScreenReminderWidgetPanelManager.swift @@ -9,12 +9,16 @@ final class LockScreenReminderWidgetPanelManager { private var window: NSWindow? private var hasDelegated = false + private var screenChangeObserver: NSObjectProtocol? + private var workspaceObservers: [NSObjectProtocol] = [] var isVisible: Bool { window?.isVisible == true } - private init() {} + private init() { + registerScreenChangeObservers() + } func show(with snapshot: LockScreenReminderWidgetSnapshot) { render(snapshot: snapshot, makeVisible: true) @@ -130,5 +134,32 @@ final class LockScreenReminderWidgetPanelManager { return NSRect(x: originX, y: proposedY, width: size.width, height: size.height) } + + private func registerScreenChangeObservers() { + screenChangeObserver = NotificationCenter.default.addObserver( + forName: NSApplication.didChangeScreenParametersNotification, + object: nil, + queue: .main + ) { [weak self] _ in + self?.handleScreenGeometryChange(reason: "screen-parameters") + } + + let workspaceCenter = NSWorkspace.shared.notificationCenter + let wakeObserver = workspaceCenter.addObserver( + forName: NSWorkspace.screensDidWakeNotification, + object: nil, + queue: .main + ) { [weak self] _ in + self?.handleScreenGeometryChange(reason: "screens-did-wake") + } + + workspaceObservers = [wakeObserver] + } + + private func handleScreenGeometryChange(reason: String) { + guard window?.isVisible == true else { return } + refreshPosition(animated: false) + print("LockScreenReminderWidgetPanelManager: realigned window due to \(reason)") + } } diff --git a/DynamicIsland/managers/LockScreenTimerWidgetManager.swift b/DynamicIsland/managers/LockScreenTimerWidgetManager.swift index c71716a..ccfb6e4 100644 --- a/DynamicIsland/managers/LockScreenTimerWidgetManager.swift +++ b/DynamicIsland/managers/LockScreenTimerWidgetManager.swift @@ -102,8 +102,12 @@ final class LockScreenTimerWidgetPanelManager { private let animator = LockScreenTimerWidgetAnimator() private var hideTask: Task? private(set) var latestFrame: NSRect? + private var screenChangeObserver: NSObjectProtocol? + private var workspaceObservers: [NSObjectProtocol] = [] - private init() {} + private init() { + registerScreenChangeObservers() + } func showWidget() { guard let screen = NSScreen.main else { return } @@ -248,4 +252,31 @@ final class LockScreenTimerWidgetPanelManager { let raw = Defaults[.lockScreenTimerVerticalOffset] return min(max(raw, -160), 160) } + + private func registerScreenChangeObservers() { + screenChangeObserver = NotificationCenter.default.addObserver( + forName: NSApplication.didChangeScreenParametersNotification, + object: nil, + queue: .main + ) { [weak self] _ in + self?.handleScreenGeometryChange(reason: "screen-parameters") + } + + let workspaceCenter = NSWorkspace.shared.notificationCenter + let wakeObserver = workspaceCenter.addObserver( + forName: NSWorkspace.screensDidWakeNotification, + object: nil, + queue: .main + ) { [weak self] _ in + self?.handleScreenGeometryChange(reason: "screens-did-wake") + } + + workspaceObservers = [wakeObserver] + } + + private func handleScreenGeometryChange(reason: String) { + guard window?.isVisible == true else { return } + refreshPosition(animated: false) + print("LockScreenTimerWidgetPanelManager: realigned window due to \(reason)") + } } diff --git a/DynamicIsland/managers/LockScreenWeatherPanelManager.swift b/DynamicIsland/managers/LockScreenWeatherPanelManager.swift index f4112f9..9ae3c08 100644 --- a/DynamicIsland/managers/LockScreenWeatherPanelManager.swift +++ b/DynamicIsland/managers/LockScreenWeatherPanelManager.swift @@ -13,8 +13,12 @@ final class LockScreenWeatherPanelManager { private(set) var latestFrame: NSRect? private var lastSnapshot: LockScreenWeatherSnapshot? private var lastContentSize: CGSize? + private var screenChangeObserver: NSObjectProtocol? + private var workspaceObservers: [NSObjectProtocol] = [] - private init() {} + private init() { + registerScreenChangeObservers() + } func show(with snapshot: LockScreenWeatherSnapshot) { render(snapshot: snapshot, makeVisible: true) @@ -122,4 +126,31 @@ final class LockScreenWeatherPanelManager { window.setFrame(targetFrame, display: true) } } + + private func registerScreenChangeObservers() { + screenChangeObserver = NotificationCenter.default.addObserver( + forName: NSApplication.didChangeScreenParametersNotification, + object: nil, + queue: .main + ) { [weak self] _ in + self?.handleScreenGeometryChange(reason: "screen-parameters") + } + + let workspaceCenter = NSWorkspace.shared.notificationCenter + let wakeObserver = workspaceCenter.addObserver( + forName: NSWorkspace.screensDidWakeNotification, + object: nil, + queue: .main + ) { [weak self] _ in + self?.handleScreenGeometryChange(reason: "screens-did-wake") + } + + workspaceObservers = [wakeObserver] + } + + private func handleScreenGeometryChange(reason: String) { + guard window?.isVisible == true else { return } + refreshPositionForOffsets(animated: false) + print("LockScreenWeatherPanelManager: realigned window due to \(reason)") + } }