Compare commits
3 Commits
4b1d6808c9
...
3c9c03b64b
| Author | SHA1 | Date | |
|---|---|---|---|
| 3c9c03b64b | |||
| 11ed9b80bc | |||
| c3308429ff |
@@ -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()
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"windows" : [
|
||||||
|
{
|
||||||
|
"x" : 0,
|
||||||
|
"winTitle" : "francop - Gitea: Git with a cup of tea - Google Chrome",
|
||||||
|
"y" : 30,
|
||||||
|
"appName" : "Google Chrome",
|
||||||
|
"h" : 957,
|
||||||
|
"w" : 1920,
|
||||||
|
"bundleID" : "com.google.Chrome"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x" : 2883,
|
||||||
|
"winTitle" : "raycast-scripts — -zsh — 120×30",
|
||||||
|
"y" : 25,
|
||||||
|
"appName" : "Terminal",
|
||||||
|
"h" : 499,
|
||||||
|
"w" : 860,
|
||||||
|
"bundleID" : "com.apple.Terminal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x" : 2879,
|
||||||
|
"winTitle" : "francop — -zsh — 120×30",
|
||||||
|
"y" : 528,
|
||||||
|
"appName" : "Terminal",
|
||||||
|
"h" : 499,
|
||||||
|
"w" : 860,
|
||||||
|
"bundleID" : "com.apple.Terminal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x" : 2670,
|
||||||
|
"winTitle" : "lab-status.py — raycast-scripts — Untracked",
|
||||||
|
"y" : 366,
|
||||||
|
"appName" : "Code",
|
||||||
|
"h" : 714,
|
||||||
|
"w" : 1170,
|
||||||
|
"bundleID" : "com.microsoft.VSCode"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x" : 0,
|
||||||
|
"winTitle" : "mouseJiggle.lua — .hammerspoon — Modified",
|
||||||
|
"y" : 30,
|
||||||
|
"appName" : "Code",
|
||||||
|
"h" : 956,
|
||||||
|
"w" : 1920,
|
||||||
|
"bundleID" : "com.microsoft.VSCode"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x" : 1920,
|
||||||
|
"winTitle" : "AFFiNE",
|
||||||
|
"y" : 0,
|
||||||
|
"appName" : "AFFiNE",
|
||||||
|
"h" : 1080,
|
||||||
|
"w" : 960,
|
||||||
|
"bundleID" : "pro.affine.app"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"x" : 392,
|
||||||
|
"winTitle" : "Bluetooth",
|
||||||
|
"y" : 168,
|
||||||
|
"appName" : "System Settings",
|
||||||
|
"h" : 671,
|
||||||
|
"w" : 723,
|
||||||
|
"bundleID" : "com.apple.systempreferences"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"screenCount" : 3,
|
||||||
|
"saveTime" : "2026-05-16 04:21:57",
|
||||||
|
"mode" : "Docked"
|
||||||
|
}
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
{
|
|
||||||
"screenCount" : 3,
|
|
||||||
"windows" : [
|
|
||||||
{
|
|
||||||
"x" : -952,
|
|
||||||
"bundleID" : "com.apple.finder",
|
|
||||||
"y" : 159,
|
|
||||||
"appName" : "Finder",
|
|
||||||
"h" : 492,
|
|
||||||
"w" : 920,
|
|
||||||
"winTitle" : "raycast-scripts"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"x" : 2070,
|
|
||||||
"bundleID" : "com.raycast.macos",
|
|
||||||
"y" : 121,
|
|
||||||
"appName" : "Raycast",
|
|
||||||
"h" : 319,
|
|
||||||
"w" : 1000,
|
|
||||||
"winTitle" : "Settings"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"x" : 1986,
|
|
||||||
"bundleID" : "com.google.GeminiMacOS",
|
|
||||||
"y" : 110,
|
|
||||||
"appName" : "Gemini",
|
|
||||||
"h" : 536,
|
|
||||||
"w" : 1002,
|
|
||||||
"winTitle" : "Gemini — Hammerspoon Menu Bar Icon Troubleshooting"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"x" : 0,
|
|
||||||
"bundleID" : "com.google.Chrome",
|
|
||||||
"y" : 39,
|
|
||||||
"appName" : "Google Chrome",
|
|
||||||
"h" : 957,
|
|
||||||
"w" : 1920,
|
|
||||||
"winTitle" : "francop - Dashboard - Gitea: Git with a cup of tea - Google Chrome"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"x" : 2794,
|
|
||||||
"bundleID" : "com.apple.Terminal",
|
|
||||||
"y" : 131,
|
|
||||||
"appName" : "Terminal",
|
|
||||||
"h" : 499,
|
|
||||||
"w" : 860,
|
|
||||||
"winTitle" : "francop — -zsh — 120×30"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"x" : 0,
|
|
||||||
"bundleID" : "com.microsoft.VSCode",
|
|
||||||
"y" : 30,
|
|
||||||
"appName" : "Code",
|
|
||||||
"h" : 957,
|
|
||||||
"w" : 1920,
|
|
||||||
"winTitle" : "init.lua — .hammerspoon"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"saveTime" : "2026-05-15 22:26:48",
|
|
||||||
"mode" : "Docked"
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,7 @@ local LOCKOUT_DURATION = 3.0 -- Cooldown duration (seconds) before allowed to
|
|||||||
|
|
||||||
-- Asymmetrical Thresholds
|
-- Asymmetrical Thresholds
|
||||||
local SPEED_TO_ENABLE = 115.0 -- Slightly lower: easier to turn ON
|
local SPEED_TO_ENABLE = 115.0 -- Slightly lower: easier to turn ON
|
||||||
local SPEED_TO_DISABLE = 150.0 -- Slightly higher: harder to accidentally turn OFF
|
local SPEED_TO_DISABLE = 140.0 -- Slightly higher: harder to accidentally turn OFF
|
||||||
|
|
||||||
-- Focusdim Global Hotkey Configuration from your settings
|
-- Focusdim Global Hotkey Configuration from your settings
|
||||||
local FOCUS_DIM_MODS = { "ctrl", "alt", "shift", "cmd" }
|
local FOCUS_DIM_MODS = { "ctrl", "alt", "shift", "cmd" }
|
||||||
|
|||||||
Reference in New Issue
Block a user