hyprlock icon indicating copy to clipboard operation
hyprlock copied to clipboard

`systemctl suspend-then-hibernate` suspends before blur gets applied in hyprlock

Open KAGEYAM4 opened this issue 1 year ago • 25 comments
trafficstars

systemctl suspend-then-hibernate is too fast, and the blur dosen't get applied completely, its only applied 40% and the rest of blur gets applied after system resumes.

Is there a way to for hyprlock to say that it has completed its operation and system can suspend now. like inhibiting operation until its ready.

# BACKGROUND
background {
    monitor =
    path = screenshot
    blur_passes = 3
    contrast = 0.8916
    brightness = 0.8172
    vibrancy = 0.1696
    vibrancy_darkness = 0.0
}

# GENERAL
general {
    no_fade_in = false
    grace = 0
    disable_loading_bar = true
}

KAGEYAM4 avatar Mar 12 '24 14:03 KAGEYAM4

AFAIK, no

vaxerski avatar Mar 12 '24 15:03 vaxerski

@KAGEYAM4, i have another issue with lockscreen fades in after resume from suspend-then-hibernate I have hypridle set up, so it fires hyprlock after susptend-then-hibernate is started That way i came up with a hacky way by adding ExecStartPre=/bin/sleep 5 into /usr/lib/systemd/system/systemd-suspend-then-hibernate.service, which solves issue gradually fading in the lockscreen and then sleeping

mintyleaf avatar Apr 18 '24 10:04 mintyleaf

@mintyleaf Thanks you. you idea is good. This method is officially documented here https://wiki.archlinux.org/title/Power_management/Suspend_and_hibernate#Custom_systemd_units. I was trying to use it to sleep 5 and hyprlock. But i was getting into perminssion/variable issue.

Using your idea i will just create a unit/drop-in whose whole purpose would be too delay the sleep.

KAGEYAM4 avatar Apr 18 '24 11:04 KAGEYAM4

ExecStartPre=/bin/sleep 5 into /usr/lib/systemd/system/systemd-suspend-then-hibernate.service, which solves issue gradually fading in the lockscreen and then sleeping

Hope you did not actually edited /usr/lib/systemd/system/systemd-suspend-then-hibernate.service and it was just an exmple because this file will be overwritten when systemd will get new version over update. The better way for doing this would be to use https://wiki.archlinux.org/title/systemd#Drop-in_files.

KAGEYAM4 avatar Apr 18 '24 11:04 KAGEYAM4

@mintyleaf This is what i am using ->

/etc/systemd/system/root-suspend.service

[Unit]
Description=Local system suspend actions
Before=sleep.target

[Service]
Type=simple
ExecStartPre=-/usr/bin/sleep 1
ExecStart=-/usr/bin/true

[Install]
WantedBy=sleep.target

And then enable it using -> sudo systemctl enable root-suspend.service


Note->

  • For me 1 sec delay is enough for hyprlock to get fully applied
  • Disadvantage of using this unit file is that this delay is applied to every action like - suspend.target, hibernate.target, hybrid-sleep.target, or suspend-then-hibernate.target

KAGEYAM4 avatar Apr 18 '24 12:04 KAGEYAM4

@KAGEYAM4, btw the 1 sec delay is not enough for me, do you have fade in animation enabled? 5 secs is totally ok

Thanks for providing the service drop-in for a more robust way Editing suspend-then-hibernate itself is worth only as a proof of concept indeed

mintyleaf avatar Apr 18 '24 13:04 mintyleaf

i'd suggest to rename this issue and mention that hack in hyprwiki, as it affects to the whole purpose of fade in animation and user experience in general

mintyleaf avatar Apr 18 '24 14:04 mintyleaf

@KAGEYAM4, btw the 1 sec delay is not enough for me, do you have fade in animation enabled? 5 secs is totally ok

Yes it works perfectly for me, i think it may be because of different cpu. This is what i am using - https://github.com/end-4/dots-hyprland/blob/75e73896adab30573d9efd71d0656e8a409b4efd/.config/hypr/hyprlock/status.sh

i'd suggest to rename this issue and mention that hack in hyprwiki, as it affects to the whole purpose of fade in animation and user experience in general

I want to still find some better solution, like if there was a way for lockscreen-application to notify system that it has locked screen and systemd can sleep now because with current solution everyone has to add different delay.

I will try asking what other Desktop-Environment does to solve this.

KAGEYAM4 avatar Apr 18 '24 15:04 KAGEYAM4

@mintyleaf i think maybe i found one. @vaxerski can you please see maybe if this would work.

man logind.conf - InhibitDelayMaxSec ->

           Specifies the maximum time a system shutdown or sleep request is
           delayed due to an inhibitor lock of type "delay" being active before
           the inhibitor is ignored and the operation executes anyway. Defaults to 5.

When hyprlock start, it will create inhibit of type delay, and when hyprlock has fully painted the lockscreen it will release the lock.

I used systemd-inhibit --what=sleep --mode=delay sleep 1000 to create inhibit of type=delay, but it was run in different terminal, so not sure maybe it would be too late when hyprlock creates inhibit.

KAGEYAM4 avatar Apr 19 '24 12:04 KAGEYAM4

Should this issue be re-opened?

austinliuigi avatar Apr 26 '24 16:04 austinliuigi

I'll reopen, but prolly won't work on this, feel free to make a mr

vaxerski avatar Apr 26 '24 16:04 vaxerski

Would you prefer hyprlock or hypridle to grab the inhibitor lock? It seems more reasonable to me if hypridle does it, since (1) it already has sdbus as a dependency and (2) the inhibition only makes sense if hyprlock was triggered by an idle service.

What do you think?

austinliuigi avatar Apr 26 '24 20:04 austinliuigi

I dont mind but I fail to see how hypridle would know when hyprlock is done taking a screenshot and fading in

vaxerski avatar Apr 27 '24 15:04 vaxerski

Hypridle wouldn't be able to know, but it can use a delay type inhibitor, which would delay sleep for up to the time specified by the InhibitDelayMaxSec option in logind.conf, which the user can configure.

  • this is what swayidle does with the -w option

If hyprlock were to grab the inhibitor instead of hypridle, it could use a block type inhibitor, releasing it only once the fade-in is finished. This is nice since sleep is guaranteed to occur after hyprlock has faded in, without any variability from machine to machine or possible tinkering of delay times that the user needs to do. However, like mentioned above:

It seems more reasonable to me if hypridle does it, since (1) it already has sdbus as a dependency and (2) the inhibition only makes sense if hyprlock was triggered by an idle service.

Would you prefer hypridle or hyprlock to handle the inhibitor lock?

austinliuigi avatar May 09 '24 23:05 austinliuigi

Hypridle wouldn't be able to know, but it can use a delay type inhibitor, which would delay sleep for up to the time specified by the InhibitDelayMaxSec option in logind.conf, which the user can configure.

But with this we are back to depending on user to specify delay, which should be avoided.

If hyprlock were to grab the inhibitor instead of hypridle, it could use a block type inhibitor, releasing it only once the fade-in is finished. This is nice since sleep is guaranteed to occur after hyprlock has faded in, without any variability from machine to machine or possible tinkering of delay times that the user needs to do.

This would be best, but not sure about which one should be used - delay or block.

It seems more reasonable to me if hypridle does it, since (1) it already has sdbus as a dependency and (2) the inhibition only makes sense if hyprlock was triggered by an idle service.

(2) Maybe, but there are other cases too where a person dosen't use hypridle, for example who waana avoid idle daemon, because they specifically lock thes screen themselves ( hyprlock ; systemctl suspend ), or where someone usess different idle daemon ( maybe swayidle or something else in future ).

We should go with hyprlock triggring the inhibitor lock, the only problem that i think could happen is that - what if it's too late for hyprlock to create the inhibitor then we will have to go with hypridle creating the inhibitor.

KAGEYAM4 avatar May 10 '24 00:05 KAGEYAM4

what if it's too late for hyprlock to create the inhibitor then we will have to go with hypridle creating the inhibitor.

This is a good point. I tried explicity grabbing the inhibitor lock on the user-side by setting the following in hypridle.conf:

lock_cmd = pidof hyprlock || systemd-inhibit --what=sleep --mode=delay hyprlock

However, it failed with the error message:

Failed to inhibit: The operation inhibition has been requested for is already running

which shows that it is most like too late to grab the inhibitor lock in the command that hypridle executes.

austinliuigi avatar May 10 '24 01:05 austinliuigi

what if it's too late for hyprlock to create the inhibitor then we will have to go with hypridle creating the inhibitor.

This is a good point. I tried explicity grabbing the inhibitor lock on the user-side by setting the following in hypridle.conf:

lock_cmd = pidof hyprlock || systemd-inhibit --what=sleep --mode=delay hyprlock

However, it failed with the error message:

Failed to inhibit: The operation inhibition has been requested for is already running

which shows that it is most like too late to grab the inhibitor lock in the command that hypridle executes.

Let's just hope that in binary it will be fast enough.

KAGEYAM4 avatar May 10 '24 01:05 KAGEYAM4

Alright, I could make a PR but I would like to get @vaxerski's opinion on whether it should be done in hyprlock or hypridle

austinliuigi avatar May 11 '24 15:05 austinliuigi

likely idle

vaxerski avatar May 11 '24 20:05 vaxerski

Hypridle wouldn't be able to know, but it can use a delay type inhibitor, which would delay sleep for up to the time specified by the InhibitDelayMaxSec option in logind.conf, which the user can configure. This is what swayidle does with the -w option

So if this get implemented in hypridle, will user have to configure InhibitDelayMaxSec option in logind.conf?

If yes, is it right to just set a value for InhibitDelayMaxSec based on hyprlock? Like i don't know the usecase currently but i would like to keep it at default 5 sec, so that other applicaton that depend on this default behaviour works correctly.

if this was configurable by command-line, then those who have mutiple systems will have change flag based of that cpu performance.

Locking is job of hyprlock and it has make sure that lock-screen was painted completely before suspend and other events.

KAGEYAM4 avatar May 11 '24 20:05 KAGEYAM4

you can make it default 5 and configurable

vaxerski avatar May 12 '24 02:05 vaxerski

Can we relly have something dynamic. No configuration on user end for the amount of sec to delay to lockscreen to wait completely.

In sway they are using fork/daemonizing behavior of swaylock to check if lock completed or not ->

static void cmd_exec(char *param) {
	swayidle_log(LOG_DEBUG, "Cmd exec %s", param);
	pid_t pid = fork();
	if (pid == 0) {
		if (!state.wait) {
			pid = fork();
		}
		if (pid == 0) {
			sigset_t set;
			sigemptyset(&set);
			sigprocmask(SIG_SETMASK, &set, NULL);
			signal(SIGINT, SIG_DFL);
			signal(SIGTERM, SIG_DFL);
			signal(SIGUSR1, SIG_DFL);


			char *const cmd[] = { "sh", "-c", param, NULL, };
			execvp(cmd[0], cmd);
			swayidle_log_errno(LOG_ERROR, "execve failed!");
			exit(1);
		} else if (pid < 0) {
			swayidle_log_errno(LOG_ERROR, "fork failed");
			exit(1);
		}
		exit(0);
	} else if (pid < 0) {
		swayidle_log_errno(LOG_ERROR, "fork failed");
	} else {
		swayidle_log(LOG_DEBUG, "Spawned process %s", param);
		if (state.wait) {
			swayidle_log(LOG_DEBUG, "Blocking until process exits");
		}
		int status = 0;
		waitpid(pid, &status, 0);
		if (state.wait && WIFEXITED(status)) {
			swayidle_log(LOG_DEBUG, "Process exit status: %d", WEXITSTATUS(status));
		}
	}
}
  • state.wait is -w commandline of swayidle.
  • swaylock -f daemonizes the process.

KAGEYAM4 avatar May 12 '24 04:05 KAGEYAM4

I am asking in there IRC for there rationale of using this method, here's the commit by the way - https://github.com/swaywm/swayidle/commit/5b653e8fbf8c4f33b45068e04576101b1bf73cce

Found it, will have to go through them -> https://github.com/swaywm/sway/pull/3382 https://github.com/swaywm/sway/issues/3119

Edit - so after reading them, they just went with fork/wait method. These was one mention of how xss-lock works ->

 -l, --tranfer-sleep-lock

    Allow the locker process to inherit the file descriptor that represents the delay lock obtained from the login manager.
The corresponding index will be made available in the environment variable $XSS_SLEEP_LOCK_FD; 
this will only be set if the reason for locking is that the system is preparing to go to sleep.
The locker should close this file descriptor to indicate it is ready.

KAGEYAM4 avatar May 12 '24 04:05 KAGEYAM4

That seems like the way to go, thanks for looking into it. So to make sure we're on the same page:

  • hypridle can optionally block until commands that it spawns terminate
    • uses delay type inhibitor lock
  • hyprlock can optionally daemonize (detach from controlling terminal) after it fades in
    • this can effectively act as a signal to hypridle that it is finished since the original (non-forked) process that hypridle spawned terminates

austinliuigi avatar May 12 '24 05:05 austinliuigi

  • hypridle can optionally block until commands that it spawns terminate

Because this behaviou would be for before_sleep_cmd, can this create problem in case like this - before_sleep_cmd = loginctl lock-session & playerctl pause & some-other-command. In this case the if we use forking/daemonize - would it work?

KAGEYAM4 avatar May 12 '24 07:05 KAGEYAM4

fixed in https://github.com/hyprwm/hypridle/pull/122

KAGEYAM4 avatar Feb 06 '25 13:02 KAGEYAM4