I teach a lecture on object-oriented programming in Java, and I spend a lot of time writing code in my favorite terminal editor, kakoune, in front of my class. My students asked me to find a utility that I like for displaying the keys that I press so that they can learn the commands and shortcuts that I use.
After searching for a good application for a while, I found screenkey
, which is available in the default Debian repositories. It creates a nice banner across the screen that displays recently pressed keys. It like it because it shows a history (for a short time) instead of simply the keys being pressed now. This should allow students to write down patterns for their future reference.
I was thrilled with screenkey
until the first time that I unlocked my machine while it was running. Once my lock screen cleared, I was greeted with my password displayed in plaintext on the screen.
I suppose that screenkey
has access to the input even while the screen is locked. I don’t know enough X internals to know why. In any event, I resolved that screenkey should automatically be killed if/when my screen locks.
I’m currently running GNOME, so I spent some time looking for how to execute a hook on lock in GNOME. Sadly, there isn’t any official support for that (at least, not that I could find). Instead, I found this AskUbuntu question that gave me the hint that I needed. Apparently, dbus
sends an event when the screen is locked. I can write a script that listens for that event and takes an action when it occurs. After some experimentation, I came up with the following script:
#!/bin/bash dbus-monitor --session "interface='org.gnome.ScreenSaver'" | \ ( while true do read X if echo "$X" | grep "interface=org.gnome.ScreenSaver" &> /dev/null; then pkill screenkey &> /dev/null fi done )
It simply looks for dbus
messages that contain the member=Lock
attribute (which are always issued when the screen is locked) and kills all instances of screenkey
. You would think that the argument to dbus-monitor
would filter down to only the requested events, but the pipe to grep
is actually necessary in order to only trigger this when a screen-saving-related message appears on the bus. This worked well for me, but I had to launch it manually. To make it launch on login I had to create a GNOME (well XDG, but whatever) autostart desktop file at ~/.config/autostart/lock-hook.desktop
that looks like this:
[Desktop Entry] Name=Lock Hook Type=Application Comment=A script to run custom commands on screen lock Exec=/home/chris/.local/bin/lock-hook.sh
I had to spend some time with the official spec to get all of the required keys in place, but we got there eventually. Once I moved the script above to the path referenced in the desktop file, this setup worked flawlessly.
I can now launch screenkey
with the assurance that it will be dead as soon as I lock the screen. It might be better to do with this a userspace systemd
service (so that it would restart itself automatically if it somehow crashed), but this setup works for now.
Many thanks to Andrew Thorp for his help with the Xorg suspension process and a tip about the .config/autostart/
directory.
Image Credit: Stefan Lins
Image License: CC BY-NC 2.0