From c3308429ff1922728e1bc24a397669ff764e3ad6 Mon Sep 17 00:00:00 2001 From: Franco Pellicciotti Date: Sat, 16 May 2026 11:10:16 -0400 Subject: [PATCH] The Menu Render Guard implemetned to prevent IPC errors after sleep/wake --- WindowManager.lua | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/WindowManager.lua b/WindowManager.lua index 8a14b66..d6a8071 100644 --- a/WindowManager.lua +++ b/WindowManager.lua @@ -34,6 +34,7 @@ obj.saveCountdown = obj.saveInterval obj.isRescued = false obj.isTransitioning = false obj.isRestoring = false +obj.isMenuUpdating = false -- Safety guard to prevent concurrent IPC menu rendering loops obj.wakeTimer = nil obj.lastScreenCount = #hs.screen.allScreens() obj.lastSavedTime = "Never" @@ -231,6 +232,10 @@ end local timerMenu = hs.menubar.new() 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 local screens = hs.screen.allScreens() timerMenu:setTitle(string.format("💠 %d:%02d", math.floor(obj.saveCountdown / 60), obj.saveCountdown % 60)) @@ -257,17 +262,25 @@ function updateMenu() end timerMenu:setMenu(menuTable) end + + obj.isMenuUpdating = false end 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 log("POWER: Sleep event.") 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.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 log("POWER: Wake event.") 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.clockTimer then obj.clockTimer:start() end if obj.wakeTimer then obj.wakeTimer:stop() end local currentScreens = #hs.screen.allScreens() @@ -285,6 +298,7 @@ obj.powerWatcher = hs.caffeinate.watcher.new(function(event) obj.isTransitioning = false obj.isRestoring = false obj.lastScreenCount = currentScreens + updateMenu() end end end):start()