local brightness = require("hs.brightness") local caffeinate = require("hs.caffeinate") local timer = require("hs.timer") local eventtap = require("hs.eventtap") local host = require("hs.host") local distributednotifications = require("hs.distributednotifications") local pathwatcher = require("hs.pathwatcher")
-- 日志函数 localfunctionlogToFile(msg) local f = io.open(os.getenv("HOME") .. "/.hammerspoon/dim_debug.log", "a") if f then f:write(os.date("%Y-%m-%d %H:%M:%S") .. " - " .. msg .. "\n") f:close() end end logToFile("------ Init lua loaded / Config reloaded ------")
-- 允许 CLI 工具安装 hs.ipc.cliInstall()
-- 自动重载配置 localfunctionreloadConfig(files) local doReload = false for _,file inipairs(files) do if file:sub(-4) == ".lua"then doReload = true end end if doReload then logToFile("Auto-reloading config due to file change...") hs.reload() end end -- 注意:必须将 watcher 对象存为全局变量,否则会被 Lua 垃圾回收机制 (GC) 回收,导致监听失效! configWatcher = pathwatcher.new(os.getenv("HOME") .. "/.hammerspoon/", reloadConfig):start()
-- 配置参数 local delayBeforeDim = 0 * 60-- 进入屏保后等待开始降亮度的延迟时间(秒) local dimDuration = 5-- 从当前亮度降到 0 的总时长(秒) local steps = 2-- 分多少步降完(越大越平滑) local originalBrightness = nil local dimTimer = nil local delayTimer = nil local idleTimer = nil local lastIdleTime = nil local lastLockTime = 0 local isLocked = false
-- 不同 Hammerspoon 版本可用的唤醒屏幕 API 不一样;没有就跳过,避免 timer callback 中断 localfunctionwakeDisplayIfAvailable() if caffeinate.wakeDisplay then caffeinate.wakeDisplay() elseif caffeinate.wakeSystem then caffeinate.wakeSystem() end end
-- 停止所有计时器并恢复亮度 localfunctionrestoreBrightness(reason) logToFile("restoreBrightness called. Reason: " .. tostring(reason) .. ", originalBrightness: " .. tostring(originalBrightness)) if delayTimer then delayTimer:stop() delayTimer = nil end if dimTimer then dimTimer:stop() dimTimer = nil end if idleTimer then idleTimer:stop() idleTimer = nil lastIdleTime = nil end if originalBrightness then brightness.set(originalBrightness) originalBrightness = nil end end
-- 锁屏界面收不到按键事件,改用 idle time 变化判断是否有键盘/鼠标活动 localfunctionstartIdleWakeWatcher() if idleTimer then idleTimer:stop() end
if currentStep >= steps then dimTimer:stop() dimTimer = nil startIdleWakeWatcher() end end) end
-- 进入屏保时:根据延迟配置启动渐暗逻辑 localfunctiononScreensaverStart(triggerSource) logToFile("onScreensaverStart triggered by " .. tostring(triggerSource))
if isLocked then logToFile("onScreensaverStart ignored: already locked") return end isLocked = true lastLockTime = timer.secondsSinceEpoch()
-- 防止重复 restoreBrightness("onScreensaverStart")
if delayBeforeDim <= 0then startDimming() else delayTimer = timer.doAfter(delayBeforeDim, function() startDimming() end) end end
-- 退出屏保时:立刻恢复亮度 localfunctiononScreensaverStop(triggerSource) logToFile("onScreensaverStop triggered by " .. tostring(triggerSource)) ifnot isLocked then logToFile("onScreensaverStop ignored: not locked") return end isLocked = false restoreBrightness("onScreensaverStop") end