From d1d9d75ba8e9fb05605ef28143763271641ee590 Mon Sep 17 00:00:00 2001 From: Jis G Jacob Date: Tue, 12 May 2026 16:08:25 +0530 Subject: [PATCH] Atoll: drop lockscreen music player below widgets in canvas fallback The Spotify Canvas fallback layout previously centered the panel+artwork group on screenFrame.midY, so the enlarged artwork tile could push up into the row of circular widgets (battery, audio, AQI, weather). Clamp maxCenterY against the bottom edge of both LockScreenWeatherPanelManager.latestFrame and LockScreenTimerWidgetPanelManager.latestFrame, with a 20pt clearance, and guard against the clamp inverting via max(maxCenterY, minCenterY). The panel reflows through the existing .atollLockScreenPanelFrameDidChange notification, so the artwork overlay window follows the new panel position automatically. Signed-off-by: Jis G Jacob --- .../managers/LockScreenPanelManager.swift | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/DynamicIsland/managers/LockScreenPanelManager.swift b/DynamicIsland/managers/LockScreenPanelManager.swift index 5fab24c..e076fe7 100644 --- a/DynamicIsland/managers/LockScreenPanelManager.swift +++ b/DynamicIsland/managers/LockScreenPanelManager.swift @@ -329,8 +329,22 @@ class LockScreenPanelManager { let baseCenterY = screenFrame.midY let largestHalfHeight = max(artworkSide, panelSize.height) / 2 let minCenterY = screenFrame.minY + largestHalfHeight + 56 - let maxCenterY = screenFrame.maxY - largestHalfHeight - 84 - let centerY = min(max(baseCenterY, minCenterY), maxCenterY) + var maxCenterY = screenFrame.maxY - largestHalfHeight - 84 + + let widgetClearance: CGFloat = 20 + if let weatherFrame = LockScreenWeatherPanelManager.shared.latestFrame, + !weatherFrame.isEmpty { + let weatherTopConstrainedCenterY = weatherFrame.minY - widgetClearance - largestHalfHeight + maxCenterY = min(maxCenterY, weatherTopConstrainedCenterY) + } + if let timerFrame = LockScreenTimerWidgetPanelManager.shared.latestFrame, + !timerFrame.isEmpty { + let timerTopConstrainedCenterY = timerFrame.minY - widgetClearance - largestHalfHeight + maxCenterY = min(maxCenterY, timerTopConstrainedCenterY) + } + + let resolvedMaxCenterY = max(maxCenterY, minCenterY) + let centerY = min(max(baseCenterY, minCenterY), resolvedMaxCenterY) return NSRect( x: groupOriginX + artworkSide + spacing,