Hammerspoon / hammerspoon

Staggeringly powerful macOS desktop automation with Lua
http://www.hammerspoon.org
MIT License
11.9k stars 578 forks source link

Caffeinate: prevents sleep when system is locked, too. #2314

Open toothbrush opened 4 years ago

toothbrush commented 4 years ago

Hello, first post here, so please bear with me. I'm a new (and very happy) Hammerspoon user. I've configured Caffeinate as follows, from the examples:

caffeine = hs.menubar.new()

function setCaffeineDisplay(state)
  if state then
    caffeine:setTitle("wake")
  else
    caffeine:setTitle("sleep")
  end
end

function caffeineClicked()
  setCaffeineDisplay(hs.caffeinate.toggle("displayIdle"))
end

if caffeine then
  caffeine:setClickCallback(caffeineClicked)
  hs.caffeinate.set("displayIdle", true, true)
  setCaffeineDisplay(hs.caffeinate.get("displayIdle"))
end

The behaviour i expect is the same as when using old-style Caffeine.app, namely that it will indefinitely keep my screen on while i'm logged in, but when i "Lock" my computer, it'll allow it to go to sleep. Especially on battery, this is important. Hammerspoon seems to keep the computer awake when it's locked, too, which is not what i want.

Is this something wrong with Caffeinate's behaviour, or would i need to remember to "uncaffeinate" every time i want to lock my system? I'm all for automating things, so if that's the case, does anyone have a suggestion for how to make this process automatic? Thanks!

toothbrush commented 4 years ago

For others who might run into a similar issue, my current (extremely hacky) workaround is to listen for lock events and temporarily disable Caffeinate. Full code below: 🐉🐲

caffeine = hs.menubar.new()

-- Always caffeinate on startup.
shouldCaffeinate = true

function setCaffeineDisplay(state)
  if state then
    caffeine:setTitle("foo")
  else
    caffeine:setTitle("blop")
  end
end

function setCaffeine(state)
  hs.caffeinate.set("displayIdle", state, true)
  setCaffeineDisplay(state)
end

function caffeineClicked()
  shouldCaffeinate = not shouldCaffeinate
  setCaffeine(shouldCaffeinate)
end

if caffeine then
  caffeine:setClickCallback(caffeineClicked)
  setCaffeine(shouldCaffeinate)
end

local pow = hs.caffeinate.watcher
local log = hs.logger.new("caffeine", 'verbose')

local function on_pow(event)
  local name = "?"
  for key,val in pairs(pow) do
    if event == val then name = key end
  end
  log.f("caffeinate event %d => %s", event, name)
  if event == pow.screensDidUnlock
    or event == pow.screensaverDidStop
  then
    log.i("Screen awakened!")
    -- Restore Caffeinated state:
    setCaffeine(shouldCaffeinate)
    return
  end
  if event == pow.screensDidLock
    or event == pow.screensaverDidStart
  then
    log.i("Screen locked.")
    setCaffeine(false)
    return
  end
end

-- Listen for power events, callback on_pow().
pow.new(on_pow):start()
log.i("Started.")

Credit goes to Tony Finch from whom i stole and adapted the above.