Window Managers like i3, Awesome, Xmonad, Sway etc etc are great. But it does feel like reinventing the wheel sometimes with basic features that come included with full desktop environments.
As life starts to show hints that it might finally be returning to relative normal soon and we all brush up on our social skills and personal hygiene. I find myself thinking that it might be useful to have my screen auto-lock after a set period whilst I’m out and about.
There are already a couple of options for this, such as Xscreensaver but I don’t want a bloated screensaver, I just want to trigger a custom lock screen I’ve already built in AwesomeWM.
I figured I may as well document how I did it, so here we go.
First thing to do is to ascertain how long the user has been idle. Fortunately this is relatively easy with Xprintidle, so let’s use that:
#!/bin/bash IDLE_TIME="$(xprintidle)" MAX_IDLE="180000" # 3 minutes echo "Idle time is: $IDLE_TIME" [ "$IDLE_TIME" -gt "$MAX_IDLE" ] && $(echo "lock_screen_show()" | awesome-client) || exit 0
This nice simple script I’ve called
idle-check checks whether the idle time (in ms) is greater than the timeout. If it is, it calls the
lock_screen_show function I have defined in my Awesome config.
Good start, but the big problem with this is that when I’m watching a video for example, I don’t want the script to trigger. We’ll solve that in the next step.
Let’s create another script to check if a fullscreen application is running. We can do this using a combination of
#!/bin/bash root_geo="$(xwininfo -root | grep geometry)" [ "$(xwininfo -id $(xdotool getactivewindow) | grep geometry)" = "$root_geo" ] && echo "1" || echo "0"
This script gets the resolution of the screen (
root_geo) and uses
xdotool to get the currently active window before comparing the geometry of said window to the max resolution. If they match, we know the currently active application is in fullscreen mode.
We can simply return 1 to represent fullscreen and 0 otherwise.
Now that we have this set up, we can add it to the check in our initial script:
#!/bin/bash IDLE_TIME="$(xprintidle)" MAX_IDLE="180000" # 3 minutes echo "Idle time is: $IDLE_TIME" + echo "Fullscreen status is: $(is_fullscreen)" - [ "$IDLE_TIME" -gt "$MAX_IDLE" ] && $(echo "lock_screen_show()" | awesome-client) || exit 0 + [ "$IDLE_TIME" -gt "$MAX_IDLE" ] && [ "$(is_fullscreen)" -eq "0" ] && $(echo "lock_screen_show()" | awesome-client) || exit 0
is_fullscreen is the name of our other script.
Almost there. We now have a script which, when run will check the idle time and, if greater than the specified timeout (and no fullscreen app is running) it will call the lock function.
The only thing left to do is run this script on an interval to constantly poll the status. To do this with cron just append
* * * * * /path/to/your/script using
crontab-e. However I’m going to be using Systemd timers, which I’ll detail in the next step.
Create a service file in
~/.config/systemd/user called something like
idle-check.service with the following:
[Unit] Description=Check if user has been idle for more than 3 minutes and lock the screen After=multi-user.target [Service] Environment=DISPLAY=:0 ExecStart=/path/to/your/idle-check/script [Install] WantedBy=basic.target
Then, create a timer to activate this service at the same location (e.g.
[Unit] Description=Run idle check every minute [Timer] OnBootSec=2min OnCalendar=*-*-* *:*:00 Unit=idle-check.service [Install] WantedBy=basic.target
Enable it with
systemd --user enable idle-check.timer and you’re good to go!