swayidle icon indicating copy to clipboard operation
swayidle copied to clipboard

before-sleep not triggered when `systemd-suspend.service` or `suspend.target` triggered

Open NilsIrl opened this issue 4 years ago • 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.

NilsIrl avatar Feb 24 '20 20:02 NilsIrl

AFAIK the proper way to ask for suspend is systemctl suspend and it works fine with before-sleep for locking on 1.6.

duck-rh avatar Mar 03 '20 09:03 duck-rh

@duck-rh According to man systemctl the definition of systemctl suspend is that it runs systemctl start suspend.target, so what you recommend as the "proper way to suspend" is equivalent to what @NilsIrl is describing as a case where swaylock won't be run.

markstos avatar Nov 18 '20 15:11 markstos

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.

NilsIrl avatar Nov 18 '20 17:11 NilsIrl

@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.

duck-rh avatar Apr 28 '22 06:04 duck-rh

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 :thinking:

noahtallen avatar May 14 '22 01:05 noahtallen

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).

kennylevinsen avatar May 14 '22 08:05 kennylevinsen

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?)

noahtallen avatar May 14 '22 09:05 noahtallen

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:

  1. If I leave the computer alone, I want it first lock the screen and then a little later suspend.
  2. 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 ...

markstos avatar May 20 '22 14:05 markstos