Ever wanted to bind some command to a key or mouse button of your choosing? Yes? Good, because that’s what I’m going to show you in this tutorial. The whole thing is very straightforward, so the list of things needed is rather short:

  • A system with X11 - The stuff I’m showing here should generally work on any X11-based graphical environment
  • xbindkyes - For actual execution of your mapped commands
  • xautomation - For simulating key presses from the console; provides xte

Both xbindkeys and xautomation should be available in your OS’s repositories.

Defining xbindkeys configs

xbindkeys will look for your mappings in a file named .xbindkeysrc in your home directory. The syntax of xbindkeys is pretty simple with each binding definition being just two lines:

# execute some_command whenever a "some + three + keys" shortcut is pressed
"some_command"
    some + three + keys

# You can also activate your mappings on key release events by adding an extra
# "Release" key to your combination

# Say "Caps Lock!" on CapsLock release
"espeak 'Caps Lock!'"
    Caps_Lock + Release

But I don’t know what my key is called!

Fear not, xbindkeys has you covered. Just run xbindkeys -k, focus on the window created by the program and press the key you want to map. If you want to capture more than one, use xbindkeys -mk. Here’s a sample output for the gesture button on my Logitech MX Master mouse:

$ xbindkeys -k
Press combination of keys or/and click under the window.
You can use one of the two lines after "NoCommand"
in $HOME/.xbindkeysrc to bind a key.
"(Scheme function)"
    m:0x1c + c:172
    Control+Alt+Mod2 + Tab

Huh, it seems to just send Ctrl+Alt+Tab! :upside_down_face:

Both lines below "(Scheme function)" refer to the very same key combination - just choose whichever you like more.

:information_source: Note:

Mod2 means “Modifier 2” and basically refers to Num Lock. You can safely omit it when copying the key to your config.

With your key name no longer being a secret, you can use it to define your own mapping rules in the format I described above.

Example

My own key mapping needs aren’t too big. The ~/.xbindkeysrc I’m using covers only some media keys and screenshot bindings, making it a simple example:

# The dbus-send part controls Spotify (which wouldn't listen to standard media
# keys for some reason)

# Ctrl + Scroll Lock => play/pause
"xte 'key XF86AudioPlay'; dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause"
    Control + Scroll_Lock

# Ctrl + PrtScr => previous song
"xte 'key XF86AudioPrev'; dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Previous"
    Control + Print

# Ctrl + PauseBreak => next song
"xte 'key XF86AudioNext'; dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Next"
    Control + Pause

# Screenshots (BTW check out scrot, it's a really awesome and simple screenshot
# program)

# PrtScr => screenshot
"scrot screenshot.png"
    Print

# Menu => screenshot with area selection
"scrot -s screenshot.png"
    Menu + Release

xte is a program for simulating keypresses in X11, while Menu refers to that “right-click equivalent” key found between your right Windows key and Control. At first Menu wasn’t willing to cooperate, but in the end, Release finally got it to work.

Testing

To check how your config behaves, xbindkeys offers a non-daemon mode which will exit as soon as you hit Ctrl+C:

xbindkeys -n

If you happen to have an instance of xbindkeys already running, kill it before starting any more.

Activating the bindings on system startup

Unfortunately, xbindkeys doesn’t run automatically on startup. The easiest way to fix this is to use your desktop environment’s autostart capabilities. In i3 - my window manager of choice - you’d just need to add one line to your ~/.i3/config file:

exec "xbindkeys"

Questions?

Feel free ask them in the comments or see the xbindkeys manpage.