Operational security rule 1 - and probably 2, 3 and then some - is to say nothing. We divulge enough information as it is and there's no need to make it any easier for a would-be attacker or opportunist of fortune. For a variety of reasons, many of which are not directly a result of security-mindedness, we resist providing information to strangers. This is good. Neither should your computer. To that end, it's a good idea to have a screensaver/locker!
Initially after installing i3, there's no screen locker set up (though i3 does ship with such software). It's also quite possible you've discovered that during some activities, like watching full-screen videos, your screen dims, or goes to sleep. In this tutorial we'll install a screensaver/locker called xscreensaver, and write a small script to detect full screen and prevent your screen from going dark! We'll improve our security and our general computing experience at the same time!
Setting Up xscreensaver:
To start, we'll need to install it:
$ sudo apt update
$ sudo apt install xscreensaver
In order for to start xscreensaver when i3 loads, we need to add an invocation to i3's config. Add the following like to your i3 config, which by default is at ~/.config/i3/config
, to silently start it in the background:
exec --no-startup-id xscreensaver -no-splash
While we're at it, why don't we also set up a key combination to lock the screen. I like CRTL + ALT + L for this, but you can set to to whatever you'd like by substituting other keys in the pattern. Add something like the following to your i3 config:
bindsym $mod+Control+l exec xscreensaver-command -lock
To configure xscreensaver, you can run the following in a terminal to open the setting/configuration window:
$ xscreensaver-demo
Changing any settings will create a configuration file at ~/.xscreensaver
.
Okay, xscreensaver is all set. Now let's address full-screen apps.
Detecting Full-Screen Windows:
The assumption here is that quite often full-screen apps will be things that aren't accompanied by user interaction. While watching a full-screen youtube video, you don't usually type things or move the mouse. Many default Linux set ups won't take this into account, and so enable power-saving strategies when you don't want them to. Let's write a little script that detects full screen, and prevents the problem!
The basic idea of our script will be to get a hold of the properties of each active window, and see if any of them include the full-screen state, _NET_WM_STATE_FULLSCREEN:
#!/bin/bash
checkFullScreen()
{
# Loop over all windows:
# Create an array of windows by setting IFS to the list separation value:
IFS=', ' read -r -a ar <<< $(xprop -root _NET_CLIENT_LIST_STACKING);
# Window objects start at offset 4. 50 should be more than enough:
for w in {4..50}; do
w_id=${ar[$w]};
# If it exists:
if [[ $w_id ]]; then
# Get all props of that window, and check for FULL:
if xprop -id $w_id | grep -q FULL; then
# Report if detected, and return true:
echo 'FULL SCREEN DETECTED!';
return 0;
fi
fi
done
return 1; # return false
}
# Constantly check for full screen:
while true; do
if checkFullScreen; then
# Reset screensaver countdown w/ -deactivate flag (suggested in docs):
xscreensaver-command -deactivate
fi
# Wait some time:
sleep 1;
done
Though it could certainly be improved upon (please do!), it get's the job done!
In order to run it, save it somewhere (mine's in ~/scripts/check_fs.sh) and then make it executable:
$ vi ~/scripts/check_fs.sh
$ chmod +x ~/scripts/check_fs.sh
$ ./scripts/check_fs.sh
Then try opening something in full screen.
Generic Anti-Dimming Measures:
It may be that what works to prevent dimming and blanking on some set ups doesn't work on others. For instance, while on a vanilla install of i3 over Mint with xscreensaver running, the call in the script above to 'deactivate' xscreensaver is sufficient to stop dimming. On Debian 10 installed with no desktop environment, it does not.
A much more generic method to prevent dimming that will work across many set ups is to simulate input of some kind. We can do this with xdotool.
Install:
$ sudo apt install xdotool
Then we can simulate some input activity as follows:
$ xdotool key VoidSymbol
In my original use, I'd moved the mouse by an offset of 0, but as suggested in this post on the issue, using VoidSymbol I think is much cleaner!
Replacing the xscreensaver-command -deactivate
line with the above xdotool line should produce the desired result!
Optimizations:
There are a couple of minor optimizations we can make to improve the experience. First, calling checkFullScreen()
every second is overkill. Instead, set the number of seconds to something just smaller than the shortest possible time your power settings will wait before dimming your screen. In my case, my screen will dim after 120 seconds, so my script checks for full screen every 110 seconds.
Second, there may be applications that, for whatever reason, run in full screen but shouldn't prevent dimming. I often run one or more virtual machines in full screen, and I don't want them to prevent dimming. To remedy this issue, we can create an "ignore" array, which checkFullScreen can compare full-screen windows against before returning true:
#!/bin/bash
# Ignore Strings:
ignore_list=("VMWARE");
checkFullScreen()
{
# Loop over all windows:
IFS=', ' read -r -a ar <<< $(xprop -root _NET_CLIENT_LIST_STACKING);
# Window objects start at offset 4. 50 should be more than enough:
for w in {4..50}; do
w_id=${ar[$w]};
# If it exists:
if [[ $w_id ]]; then
# Get all props of that window, and check for FULL:
w_info="$(xprop -id $w_id)";
if echo $w_info | grep -q FULL; then
# Loop over ignore array:
for ignore in "${ignore_list[@]}"; do
# If FULL found, and not in ignore list, ret 0:
if ! echo $w_info | grep -iq $ignore; then
echo "FOUND FULLSCREEN";
return 0; # return true
else
echo "IGNORING $ignore";
fi
done
return 1; # return false
fi
fi
done
return 1; # return false
}
# Constantly check for full screen:
while true; do
if checkFullScreen; then
# Reset screensaver countdown w/ -deactivate flag (suggested in docs):
#xscreensaver-command -deactivate
xdotool key VoidSymbol
fi
# Wait some time:
sleep 110;
done
Running Our Script in the Background:
In order to constantly check for full-screen apps, we need to have the script running all the time. We can do this the same way we started xscreensaver, by adding an exec line to our i3 config like so:
exec --no-startup-id ~/temp/check_fs.sh > /dev/null
We can silence the script's output by piping it into /dev/null
. Alternatively, we could simply stop the script from writing anything on stdout, but it's sometimes useful for debugging.
With all of these changes in place, we're ready to start using our new setup. Restart i3 for the changes to all take effect!