Manually block sleep and screen locking for N minutes

Hello, I have my plasma desktop at work configured to enable the screensaver after just one minute. This is intended to increase the security of my computer by avoiding a “walk away” vulnerability. In truth, it just prevents my colleagues from taking over my Slack account and promising to buy cake for the office. :sweat_smile:

Occasionally, I will be doing a less interactive activity like reading a long article or sitting beside someone and discussing the contents on my screen without actually touching the mouse or keyboard.

For these scenarios, it would be great to be able to disable my screensaver for some number of minutes. Maybe just some predetermined values like 15 minutes, 30 minutes, 1 hour.

Currently, the only option is to disable the screensaver “forever” by checking the “Manually block sleep and screen locking” checkbox. And I often forget that I have ticked this box until I walk away from my computer and return surprised to see it still unlocked.

image

Is this something that the PowerDevil utility could easily support?

System inhibition (which is essentially what the PowerDevil “manually block” feature does) is pretty easy to script. Maybe all you need is a command to request inhibition for how long you want, and then have some UI button to trigger it?

The command systemd-inhibit allows you to inhibit idle sleep (or a few other power management conditions) while another command is running. The specific command you want to run is probably something like this:

systemd-inhibit --what=idle:sleep  sleep 300

Which means: run the command sleep 300 and inhibit the idle timer or the sleep feature until that command ends. The command sleep 300 means “wait 300 seconds and then exit”. If you run this, you can see the effect in the PowerDevil widget:

image

This is not very informative, but that is because we didn’t specify the details that PowerDevil wants to display - namely the “who”, “what”, and “why” flags for systemd-inhibit (see the explanation by typing man:systemd-inhibit in krunner or main menu), and there are other missing features that you may want, such as - triggering with a GUI, knowing how long until the timer runs out, etc.

So, for exercise, I made this little script (attached at the end) that manages the unsleeping time for you. I’ve set it up as a widget on the desktop using the 3rd-party Command Output widget (also get it from the “Get New Widgets” button in the widgets menu) and it works like this:

  1. Configure the display command:

  1. Configure the click action command:

Then, when not blocking, it just shows the text “Not blocking”:

image

Click on it and a dialog box opens:

image

After selecting something and clicking “OK”, it starts blocking and you get a count down:

image

Here is the script - save it in a directory in your path (for example ~/.bin or ~/.local/bin) as unsleep-time and give it “execute” permission:

#!/bin/bash -e

QUERY=
REMOVE=
ASK=
TIME_SPEC=
CLIARGS=( "" "$@" ) # OPTIND is 1 based
while [ "$OPTIND" -lt "${#CLIARGS[*]}" ]; do
	if getopts "rqh?" OPT; then
		case $OPT in
		h|\?) echo "$0 <-q|-r|TIME-SPEC>" >&2; exit 5;;
		q) QUERY=yes;;
		r) REMOVE=yes;;
		esac
	else
		TIME_SPEC="${CLIARGS[$OPTIND]}"
		OPTIND=$(( $OPTIND + 1 ))
	fi
done

if [ -n "$QUERY" ]; then
	pid="$(systemd-inhibit --list | awk '$1=="unsleep-time"{print$4}')"
	if [ -z "$pid" ]; then
		echo "Not blocking"
		exit 0
	fi
	running=$(ps h -p "$pid" -o etimes)
	sleep_for="$(ps h -p "$pid" -o cmd | awk '{print$NF}')"
	remaining=$(( sleep_for - running ))
	printf "Blocking for %dm %02ds\n" $(( remaining / 60 )) $(( remaining % 60 ))
elif [ -n "$REMOVE" ]; then
	pid="$(systemd-inhibit --list | awk '$1=="unsleep-time"{print$4}')"
	if [ -n "$pid" ]; then
		kill "$pid"
	fi
else
	if [ -z "$TIME_SPEC" ]; then
		if which kdialog 2>&1 >/dev/null; then
			TIME_SPEC="$(kdialog --slider "Inhibit idle sleep for how many minutes?" "1" "15" "1" || true)min"
		else
			TIME_SPEC="5min"
		fi
	fi
	until="$(date -d "$TIME_SPEC" +%s)"
	sleep_for=$(( $until - $(date +%s) ))
	systemd-inhibit --what=idle:sleep --who=unsleep-time --why="Unsleeping for $TIME_SPEC" sleep "$sleep_for"
fi

So, this is a bit heavy handed but I like bash scripting :grin: A more “plasmay” approach will be to just create a standalone widget that implements the functionality directly using the PowerDevil DBus API, but that is too much for me at this time of night…

2 Likes

I recommend filing this wish on Bugzilla to inform the developers. From the description and guss77’s example, it appears to be straight forward to implement.