<feed xmlns='http://www.w3.org/2005/Atom'>
<title>dotfiles/dot_config/systemd/user/swayidle.service, branch master</title>
<subtitle>My linux config and rc files</subtitle>
<id>https://git.sommerfeld.dev/dotfiles/atom/dot_config/systemd/user/swayidle.service?h=master</id>
<link rel='self' href='https://git.sommerfeld.dev/dotfiles/atom/dot_config/systemd/user/swayidle.service?h=master'/>
<link rel='alternate' type='text/html' href='https://git.sommerfeld.dev/dotfiles/'/>
<updated>2026-05-29T10:18:15Z</updated>
<entry>
<title>refactor(suspend): gate suspend on AC, drop bespoke zellij inhibit</title>
<updated>2026-05-29T10:18:15Z</updated>
<author>
<name>sommerfeld</name>
<email>sommerfeld@sommerfeld.dev</email>
</author>
<published>2026-05-29T10:18:15Z</published>
<link rel='alternate' type='text/html' href='https://git.sommerfeld.dev/dotfiles/commit/?id=ec3734c5ef9fcfe97c21cd19f198ec779ab5f052'/>
<id>urn:sha1:ec3734c5ef9fcfe97c21cd19f198ec779ab5f052</id>
<content type='text'>
New, simpler suspend policy:

  AC plugged in   -&gt; never auto-suspends (lid close ignored, idle no-op)
  On battery only -&gt; lid close suspends, swayidle suspends at 30 min idle

This replaces the SSH/zellij-aware inhibit machinery with a rule that
matches the user's mental model: if you don't want the machine to
sleep, plug it in. Long-running tasks (builds, downloads, SSH
sessions, headless services) just need AC.

Changes:

* etc/systemd/logind.conf.d/20-lid-ac.conf: set
  HandleLidSwitchExternalPower=ignore so logind itself handles the AC
  case at the source. No userspace daemon, no race, no rate-limit risk.
* dot_local/bin/on-battery-suspend: tiny POSIX wrapper that exits 0
  when any /sys/class/power_supply/{AC,ADP}*/online == 1, else execs
  `systemctl suspend`.
* dot_config/systemd/user/swayidle.service: add
  `timeout 1800 on-battery-suspend`. Idle suspend now exists, but only
  when on battery.
* Delete zellij-inhibit-suspend.{path,service} + watcher script and
  remove the entry from systemd-units/user.txt. The .path
  re-trigger storm bug is moot because the whole mechanism is gone.

Manual suspends (sway XF86Sleep keybind, sway power submode `s`,
`systemctl suspend` over SSH) still always work regardless of AC --
explicit user intent wins.

Also drop /migrate-podman-to-btrfs.sh from .gitignore; the one-off
migration script has been deleted now that the user has switched their
podman storage to the btrfs driver.

On-host steps to apply:

  chezmoi apply -v
  systemctl --user daemon-reload
  systemctl --user reset-failed zellij-inhibit-suspend.service zellij-inhibit-suspend.path || true
  systemctl --user stop zellij-inhibit-suspend.path zellij-inhibit-suspend.service || true
  systemctl --user disable zellij-inhibit-suspend.path || true
  systemctl --user restart swayidle.service
  # logind drop-in is reloaded automatically by the etc deploy script.

Verify:

  systemctl status systemd-logind | grep -i lid
  loginctl show-session $XDG_SESSION_ID | grep -i lid
  # Unplug AC -&gt; close lid -&gt; should suspend.
  # Plug AC   -&gt; close lid -&gt; nothing happens.
</content>
</entry>
<entry>
<title>fix(sway): re-apply display layout on config reload, drop resume hook</title>
<updated>2026-05-13T12:43:38Z</updated>
<author>
<name>sommerfeld</name>
<email>sommerfeld@sommerfeld.dev</email>
</author>
<published>2026-05-13T12:43:38Z</published>
<link rel='alternate' type='text/html' href='https://git.sommerfeld.dev/dotfiles/commit/?id=2098f17c701b28ce2d0725a1e4837d628f4beb1d'/>
<id>urn:sha1:2098f17c701b28ce2d0725a1e4837d628f4beb1d</id>
<content type='text'>
Real cause of the silent switch back to side-by-side: sway reload
(Super+Shift+c or swaymsg reload) re-evaluates output config and
defaults to all-outputs-enabled-side-by-side, dropping the runtime
positions set by display-toggle.sh.

- sway config: `exec` -&gt; `exec_always` so the saved layout is
  re-applied on every reload, and use `apply` instead of `init` so
  user-chosen layouts (e.g. side-by-side picked deliberately) survive
  reloads. First boot still defaults to laptop-off via the script's
  state-file fallback.
- swayidle.service: drop the after-resume hook -- DPMS resume isn't
  what was breaking the layout, reload was. Less surface area.
</content>
</entry>
<entry>
<title>fix(sway): re-apply display layout on resume</title>
<updated>2026-05-13T12:43:37Z</updated>
<author>
<name>sommerfeld</name>
<email>sommerfeld@sommerfeld.dev</email>
</author>
<published>2026-05-13T12:43:37Z</published>
<link rel='alternate' type='text/html' href='https://git.sommerfeld.dev/dotfiles/commit/?id=9ed9bf58e5f21ab9295c306ac390e8873a771bee'/>
<id>urn:sha1:9ed9bf58e5f21ab9295c306ac390e8873a771bee</id>
<content type='text'>
After resume from suspend sway resets output config to defaults (both
monitors enabled side-by-side), so a laptop-off mode set before suspend
silently snapped back to side-by-side on wake. The display-watcher
script only reacts to changes in the count of connected externals, so
it doesn't notice this.

- Add an 'apply' mode to display-toggle.sh that reads the saved state
  and applies it (no toggle, no notification).
- Wire it into swayidle's after-resume directive.
</content>
</entry>
<entry>
<title>style(swaylock): pure black background</title>
<updated>2026-05-13T12:43:37Z</updated>
<author>
<name>sommerfeld</name>
<email>sommerfeld@sommerfeld.dev</email>
</author>
<published>2026-05-13T12:43:37Z</published>
<link rel='alternate' type='text/html' href='https://git.sommerfeld.dev/dotfiles/commit/?id=03164e770e040b54fc69e355c6c977e8ffb013eb'/>
<id>urn:sha1:03164e770e040b54fc69e355c6c977e8ffb013eb</id>
<content type='text'>
</content>
</entry>
<entry>
<title>fix(swayidle): screen off at 5min, lock 30s later, lock on suspend</title>
<updated>2026-05-13T12:43:36Z</updated>
<author>
<name>sommerfeld</name>
<email>sommerfeld@sommerfeld.dev</email>
</author>
<published>2026-05-13T12:43:36Z</published>
<link rel='alternate' type='text/html' href='https://git.sommerfeld.dev/dotfiles/commit/?id=efbdb49c07fd0023a8db599965d596ebb662ef87'/>
<id>urn:sha1:efbdb49c07fd0023a8db599965d596ebb662ef87</id>
<content type='text'>
</content>
</entry>
<entry>
<title>refactor(swayidle): drop bespoke post-resume grace script</title>
<updated>2026-05-13T12:43:36Z</updated>
<author>
<name>sommerfeld</name>
<email>sommerfeld@sommerfeld.dev</email>
</author>
<published>2026-05-13T12:43:36Z</published>
<link rel='alternate' type='text/html' href='https://git.sommerfeld.dev/dotfiles/commit/?id=54662c8b95ce260ad0a8718e14850c96a66242ef'/>
<id>urn:sha1:54662c8b95ce260ad0a8718e14850c96a66242ef</id>
<content type='text'>
Replaces the resume-lock-grace.sh + after-resume hook from the previous
commit with the simpler observation that sway already provides a wake
grace for free: it pauses the idle counter during suspend and resets it
on the first input event post-resume, so the existing timeout 300 lock
naturally gives ~5min to interact before locking. Just dropping the
before-sleep lock is enough; the script and after-resume directive were
overcomplicating it.
</content>
</entry>
<entry>
<title>feat(sway): browser-aware idle inhibits + post-resume lock grace</title>
<updated>2026-05-13T12:43:36Z</updated>
<author>
<name>sommerfeld</name>
<email>sommerfeld@sommerfeld.dev</email>
</author>
<published>2026-05-13T12:43:36Z</published>
<link rel='alternate' type='text/html' href='https://git.sommerfeld.dev/dotfiles/commit/?id=d7fac4bbf607a894219065dc9b87f6d495d9ebab'/>
<id>urn:sha1:d7fac4bbf607a894219065dc9b87f6d495d9ebab</id>
<content type='text'>
Two related session-idle improvements:

1. ScreenSaver inhibit bridge. Browsers (LibreWolf/Chromium flatpaks)
   ask the session not to idle via the legacy
   org.freedesktop.ScreenSaver D-Bus API during video calls and
   fullscreen video; swayidle only honors logind's BlockInhibited
   property. Add inhibridge as a user unit to translate the former
   into the latter, so e.g. a Google Meet tab now keeps the screen
   from locking, dimming and (downstream) suspending.

2. Post-resume grace period. Locking on before-sleep meant every wake
   demanded the password even for a quick check. Replace with:
     before-sleep -&gt; only pause media
     after-resume -&gt; resume-lock-grace.sh 30
   The grace script runs a one-shot swayidle that locks iff the user
   stays idle for 30s after the wake, with a watchdog that exits as
   soon as swaylock comes up (or after a hard cap) so it never lingers
   alongside the main swayidle. The 5-min main idle-lock and explicit
   loginctl lock-session paths are unchanged.
</content>
</entry>
<entry>
<title>refactor(sway): manage swayidle as a user unit; drop logind override</title>
<updated>2026-05-13T12:43:11Z</updated>
<author>
<name>sommerfeld</name>
<email>sommerfeld@sommerfeld.dev</email>
</author>
<published>2026-05-13T12:43:11Z</published>
<link rel='alternate' type='text/html' href='https://git.sommerfeld.dev/dotfiles/commit/?id=456aa855b4348a8aa8b4a6679d5edfffdb235452'/>
<id>urn:sha1:456aa855b4348a8aa8b4a6679d5edfffdb235452</id>
<content type='text'>
- New dot_config/systemd/user/swayidle.service, pulled in by
  sway-session.target alongside mako/display-watcher/poweralertd. Same
  lifetime as the rest of the session: starts after graphical-session,
  restarts on failure, stops on logout.
- Drop the swayidle exec from sway config (was unmanaged background
  process with no restart, no logging hookup).
- Revert etc/systemd/logind.conf overrides: swayidle handles idle-lock
  directly via Wayland ext-idle-notifier, so the logind IdleAction
  belt-and-suspenders is redundant. Run just etc-reset
  /etc/systemd/logind.conf on the host to restore pristine.
</content>
</entry>
</feed>
