#Introduction to Hotkeys
On most modern Linux systems, the Desktop Environment (e.g. Gnome, KDE) handles hotkeys: mapping single keys, or keyboard combinations, to do certain things. Some common hotkey examples are:
- The “Mute Audio” key (available on most laptops) mutes the audio output.
Alt + Tabswitches between your open windows
Super + Topens up a terminal
If you don’t run a Desktop Environment and instead just run a window manager (e.g.
openbox) like me, you may find yourself configuring your own hotkeys. Since I run
sxhkd, the “simple X hotkey daemon,” (pro tip: it’s not simple) to manage my hotkeys.
Regardless of your setup, it’s sometimes annoying when you want to customize what a hotkey does, only to find out that some process is grabbing that hotkey and preventing you from using it.
#Error Messages in
An example of this hotkey conflict is shown when starting
Could not grab key 121 with modfield 0: the combination is already grabbed. Could not grab key 122 with modfield 0: the combination is already grabbed. Could not grab key 123 with modfield 16: the combination is already grabbed.
As it pretty clearly states, some other process has “already grabbed” some of the hotkeys you’re trying to use. Specifically, keycodes 121, 122, and 123, which just so happen to be my laptop’s volume keys. Later on we’ll talk about what a keycode means.
#Accessing Logs to Find the Processes
To find out which processes are grabbing which keys, we need to read some system logs. The log we’re looking for will be in different places depending on how your system is set up. It may be logged in one or both of these places:
#1. Xorg Log
If you’re running
X, you can check the
Xorg logs. To find the location of your
Xorg log, run:
$ lsof -c Xorg | grep ".log" Xorg 1234 user 7w REG 123,4 1234567 1234567 /home/user/.local/share/xorg/Xorg.0.log
Within the output, you should see a path like
/home/user/.local/share/xorg/Xorg.0.log. Once you have this path, you can watch updates to the log using
tail -f like so:
$ tail -f /home/user/.local/share/xorg/Xorg.0.log
In addition, you can pipe the output to
less to be able to search it, which may come in handy:
$ tail -f /home/user/.local/share/xorg/Xorg.0.log | less
If you’re on a system that uses the
systemd init system (most modern systems do), the information you’re looking for is logged using
journald. You can use
journalctl to access and read the journal:
$ journalctl -f
-f flag “continuously prints new entires as they are appended to the journal.” (
#Identifying the Keycode
You must know the keycode of the key in question. The easiest way to find the key’s keycode is using the
xev will open a blank, white window and record everything you press. Press the key you want to check (in my case it was my laptop’s “mute audio” key).
Once you’ve pressed the key, you will see output in the terminal running
xev that looks like this (you may have to scroll up):
KeyRelease event, serial 30, synthetic NO, window 0xc000001, root 0x1a2, subw 0x0, time 147487441, (-1333,-530), root:(590,562), state 0x0, keycode 121 (keysym 0x1008ff12, XF86AudioMute), same_screen YES, XLookupString gives 0 bytes: XFilterEvent returns: False
As stated in the output, the key is called
XF86AudioMute, and the keycode is
#Logging the Key Grabs
Whichever way you’ve chosen to read the logs, the information is the same. Now that you’ve opened and are watching the logs with either
tail -f or
journalctl -f, we need to fill the log with information on your system’s current key grabs.
There is a special key in
XF86LogGrabInfo that allows you to log all grab information about your keys. No keyboard has a physical
XF86LogGrabInfo key that you can press, so you have to simulate pressing it using
xdotool while at the same time simulating the key you want to press:
$ KEYCODE=121 $ xdotool keydown $KEYCODE; xdotool key XF86LogGrabInfo; xdotool keyup $KEYCODE
$KEYCODE contains the keycode we found earlier.
#Analyzing Logs to Identify Process
Now, look at your logs. Search for
activating key <keycode> where
<keycode> is the keycode you found earlier.
Hint: if you’re viewing the log in
less, you can hit
/to search for a string.
Active grab 0x41a0a67f (core) on device 'Virtual core keyboard' (3): [123456.123] client pid 2737 /usr/bin/kglobalaccel5 [123456.123] at 147059396 (from passive grab) (device frozen, state 6) [123456.123] core event mask 0x3 [123456.123] passive grab type 2, detail 0x79, activating key 121 [123456.123] owner-events true, kb 0 ptr 1, confine 0, cursor 0x0
In my example, the keycode I was looking for was
121, and it’s clear that
pid 2737 /usr/bin/kglobalaccel5 is the program that’s currently grabbing that key. You can do some research and see why the program is grabbing that key.
You can use this method to determine which pid’s/processes are grabbing your keys. For those of you that use
sxhkd, you may have to kill these processes in order to use those keys in a hotkey.