The Menu Render Guard implemetned to prevent IPC errors after sleep/wake
This commit is contained in:
@@ -34,6 +34,7 @@ obj.saveCountdown = obj.saveInterval
|
|||||||
obj.isRescued = false
|
obj.isRescued = false
|
||||||
obj.isTransitioning = false
|
obj.isTransitioning = false
|
||||||
obj.isRestoring = false
|
obj.isRestoring = false
|
||||||
|
obj.isMenuUpdating = false -- Safety guard to prevent concurrent IPC menu rendering loops
|
||||||
obj.wakeTimer = nil
|
obj.wakeTimer = nil
|
||||||
obj.lastScreenCount = #hs.screen.allScreens()
|
obj.lastScreenCount = #hs.screen.allScreens()
|
||||||
obj.lastSavedTime = "Never"
|
obj.lastSavedTime = "Never"
|
||||||
@@ -231,6 +232,10 @@ end
|
|||||||
local timerMenu = hs.menubar.new()
|
local timerMenu = hs.menubar.new()
|
||||||
|
|
||||||
function updateMenu()
|
function updateMenu()
|
||||||
|
-- Safety Guard: Bail if update is already running from a previous thread block
|
||||||
|
if obj.isMenuUpdating then return end
|
||||||
|
obj.isMenuUpdating = true
|
||||||
|
|
||||||
if timerMenu then
|
if timerMenu then
|
||||||
local screens = hs.screen.allScreens()
|
local screens = hs.screen.allScreens()
|
||||||
timerMenu:setTitle(string.format("💠 %d:%02d", math.floor(obj.saveCountdown / 60), obj.saveCountdown % 60))
|
timerMenu:setTitle(string.format("💠 %d:%02d", math.floor(obj.saveCountdown / 60), obj.saveCountdown % 60))
|
||||||
@@ -257,17 +262,25 @@ function updateMenu()
|
|||||||
end
|
end
|
||||||
timerMenu:setMenu(menuTable)
|
timerMenu:setMenu(menuTable)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
obj.isMenuUpdating = false
|
||||||
end
|
end
|
||||||
|
|
||||||
obj.powerWatcher = hs.caffeinate.watcher.new(function(event)
|
obj.powerWatcher = hs.caffeinate.watcher.new(function(event)
|
||||||
if event == hs.caffeinate.watcher.systemWillSleep or event == hs.caffeinate.watcher.screensDidSleep or event == hs.caffeinate.watcher.screensDidLock then
|
if event == hs.caffeinate.watcher.systemWillSleep or event == hs.caffeinate.watcher.screensDidSleep or event == hs.caffeinate.watcher.screensDidLock then
|
||||||
log("POWER: Sleep event.")
|
log("POWER: Sleep event.")
|
||||||
obj.isTransitioning = true
|
obj.isTransitioning = true
|
||||||
|
-- Stop both timers entirely so they don't fire or stack requests while suspended
|
||||||
if obj.autoSaveTimer then obj.autoSaveTimer:stop() end
|
if obj.autoSaveTimer then obj.autoSaveTimer:stop() end
|
||||||
|
if obj.clockTimer then obj.clockTimer:stop() end
|
||||||
elseif event == hs.caffeinate.watcher.systemDidWake or event == hs.caffeinate.watcher.screensDidWake or event == hs.caffeinate.watcher.screensDidUnlock then
|
elseif event == hs.caffeinate.watcher.systemDidWake or event == hs.caffeinate.watcher.screensDidWake or event == hs.caffeinate.watcher.screensDidUnlock then
|
||||||
log("POWER: Wake event.")
|
log("POWER: Wake event.")
|
||||||
obj.saveCountdown = obj.saveInterval
|
obj.saveCountdown = obj.saveInterval
|
||||||
|
obj.isMenuUpdating = false -- Explicitly clean guard flag upon waking up
|
||||||
|
|
||||||
|
-- Safely start timers up only after wakeup initialization
|
||||||
if obj.autoSaveTimer then obj.autoSaveTimer:start() end
|
if obj.autoSaveTimer then obj.autoSaveTimer:start() end
|
||||||
|
if obj.clockTimer then obj.clockTimer:start() end
|
||||||
if obj.wakeTimer then obj.wakeTimer:stop() end
|
if obj.wakeTimer then obj.wakeTimer:stop() end
|
||||||
|
|
||||||
local currentScreens = #hs.screen.allScreens()
|
local currentScreens = #hs.screen.allScreens()
|
||||||
@@ -285,6 +298,7 @@ obj.powerWatcher = hs.caffeinate.watcher.new(function(event)
|
|||||||
obj.isTransitioning = false
|
obj.isTransitioning = false
|
||||||
obj.isRestoring = false
|
obj.isRestoring = false
|
||||||
obj.lastScreenCount = currentScreens
|
obj.lastScreenCount = currentScreens
|
||||||
|
updateMenu()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end):start()
|
end):start()
|
||||||
|
|||||||
Reference in New Issue
Block a user