before-sleep not triggered when `systemd-suspend.service` or `suspend.target` triggered
NilsIrl opened this issue ยท 8 comments
swayidle version: 1.6
$ swayidle -w before-sleep 'swaylock -f'
$ systemctl start systemd-suspend.service
$ systemctl start suspend.target
In both of these cases, swaylock
won't be run.
AFAIK the proper way to ask for suspend is systemctl suspend
and it works fine with before-sleep for locking on 1.6.
For context, the reason I had this problem was that I wanted a timer to trigger a suspend, or something like that, which is why I wanted to directly use suspend.target
.
@markstos my bad, thanks for correcting me. So the only difference I can think of is that systemctl suspend
is asynchronous, probably similar to using --no-block
, but that should not affect the swayidle hook.
I just checked and polkit does not allow me to start a target as a user but systemctl suspend
is ok. Not sure if @NilsIrl triggered the suspend as root or user though.
Anyway that was a 2020 problem so maybe this is not a problem anymore.
This is an issue for me. I'm specifically using deep sleep (e.g. suspend to RAM), and I believe it was working with non-deep sleep.
Here's my config:
exec swayidle -w \
timeout 300 'systemctl suspend"' \
resume 'swaymsg "output * dpms on"' \
before-sleep 'swaylock -C ~/.config/swaylock/config' \
lock 'swaylock -C ~/.config/swaylock/config'
bindsym --release $mod+Escape exec systemctl suspend
My idea was to trigger systemctl suspend, which would then (theoretically) trigger swaylock. The short cut at least seemed to work when it was non-deep sleep ๐ค
You can get swayidle to trigger lock by sending SIGUSR1 to it, then wait a moment before suspend. Alternatively start swaylock directly before suspending (not sure how multiple swaylock instances behave these days).
As for why swayidle doesn't trigger, if it's on our end then it could be a problem servicing sd-bus (e.g. we only dispatch on readable socket but sd-bus already read into a buffer).
I went with the route of triggering swaylock before doing anything else:
### Idle configuration
exec swayidle -w \
timeout 300 'swaylock' \
timeout 301 'systemctl suspend' \
after-resume 'swaymsg "output * dpms on"' \
before-sleep 'swaylock' \
lock 'swaylock'
bindsym --release $mod+Escape exec 'swaylock'
(Also noting that swaylock is daemonized in its config file.)
I could also bind the shortcut to exec swaylock && systemctl suspend
.
That said, I was also curious, is it necessary to run systemctl suspend
manually after the timeout? (Or does swayidle tell systemctl behind the scenes that the system is idle?)
I have created swayidle.service
and installed it in ~/.config/systemd/user/
, then enabled and started with systemctl --user enable --now swayidle
:
[Unit]
Description=Swayidle to trigger idle actions
Documentation=man:swayidle(1)
PartOf=sway-session.target
After=sway-session.service
[Service]
Type=simple
ExecStart=/usr/bin/swayidle -w \
timeout 600 '\
swaylock --ignore-empty-password \
--image /path/to/wallpaper.jpg' \
timeout 900 'swaymsg "output * dpms off"' \
resume 'swaymsg "output * dpms on"' \
timeout 1800 'systemctl suspend' \
timeout 30 'if pgrep swaylock; then swaymsg "output * dpms off"; fi' \
resume 'if pgrep swaylock; then swaymsg "output * dpms on"; fi' \
before-sleep \
"swaylock --ignore-empty-password \
--image /path/to/wallpaper.jpg"
[Install]
WantedBy=sway-session.target
It seems to work pretty well, but it seems like sometimes I have to unlock the session multiple times with correct passwords after I wake the system. I think I see why now. I want to cover two cases:
- If I leave the computer alone, I want it first lock the screen and then a little later suspend.
- If I explicitly suspend the computer, I want the screen locked then, too.
It looks like in the case where I leave the computer alone, it's running swaylock twice: once due to the timeout and a second time due to the suspend!
It looks like @noahtallen is following the same pattern. I checked the swaylock
man page and didn't find an option to not lock the screen if it's already locked, which it seems like what is needed here. Or I need a bit of extra shell code to run swaylock if it's already running like if !pgrep swaylock; then ...