Nowadays, many keyboard have additional, so called "multimedia" keys (e.g. to increase/decrease volume, write an email, etc...). On notebooks, keys for volume up/down/mute are the rule rather than the exception.
Those keys don't work out-of-the-box on Linux, or rather on X-Window (be it Xorg or XFree86).
Let's see how to make something useful out of those keys.
The problem
Those keys are very well supported from a hardware point-of-view. Pressing them does trigger input events in the kernel, and they are even received by X-Window.
But the problem is that you can only bind them to specific actions if they are mapped to a "
keysym" (key symbol). Examples of key symbols:
a,
8,
EuroSign,
Return,
Escape,
Home or
F10.
Key events are received as
keycodes (numeric values) by X-Window, mapped internally to keysyms and then X-Window (or KDE, or GNOME, or whatever) reacts to those X events (
KeyPress and
KeyRelease + the keysym) accordingly.
Those special keys on your keyboard don't work because although they send keycodes, they are
not mapped to any keysym.
The solution
Here is the plan:
- bind the currently unassigned keycodes to unused keysyms (e.g. F13, F14, ...)
- use xbindkeys or khotkeys (KDE) to execute commands (scripts, DCOP, ...) when those keys are pressed
To bind keycodes to keysyms, we are going to use
xmodmap.
xmodmap
xmodmap comes with X-Window, e.g. on SUSE Linux it's in the package
xorg-x11.
We're going to add keycode-to-keysym mappings in
~/.Xmodmap, which will be read by
xmodmap on X server startup (actually,
/etc/X11/xdm/Xsession and
/etc/X11/xinit/xinitrc run
xmodmap $HOME/.Xmodmap when that file exists).
Note that you don't have a
.Xmodmap file under your home directory by default (the system-wide
/usr/X11R6/lib/X11/Xmodmap is used, that itself is a symlink to
/etc/X11/Xmodmap).
The syntax of
~/.Xmodmap for assigning keycodes to keysyms is as follows:
keycode <keycode> = <keysym>
Here, for example, the for the keysyms
Return and
Home:
keycode 36 = Return
keycode 97 = Home
The format is very simple, but the most complicated part has to be done first: we have to find out the keycodes that are emitted by those special keys.
Finding the keycodes
To find out what keycodes are sent to X-Window by those special keys, we are going to use
xev, that is part of the core X-Window package as well (
xorg-x11 on SUSE Linux).
xev is a handy little tool that opens a window and traces all the X events that are triggered when your mouse is above that window.
It also tracks focus and mouse events that are of no interest to us in this case and that generate a lot of bloat. Start
xev as follows to only show the
KeyRelease events:
xev | grep -A2 --line-buffered '^KeyRelease' | sed -n '/keycode /s/^.*keycode \([0-9]*\).* (.*, \(.*\)).*$/\1 \2/p'
(just copy/paste that command on a shell and run it with your normal, non-root user)
When the
xev window appears, move your mouse above that window.
Then press one of those special keys on your keyboard, and you will see the appropriate keycode in the terminal window where you typed the command above, for example:
160 NoSymbol
174 NoSymbol
176 NoSymbol
Note that after pressing the key, you will most probably have to move your mouse around above the
xev window, as it seems to queue the X events and will only show the keycode after a few other X events have stacked up (
MotionNotify events in this case, doesn't matter, will be enough to flush out the event queue and the keycode will show up in the terminal).
Take good note of those numbers (
160,
174 and
176 in our example above) and with what keys they are associated. Note that the numbers from our example correspond to the "volume mute", "volume increase" and "volume decrease" special keys on a Dell notebook.
We're now finished with
xev, so you can terminate by typing
Control+C in the terminal where you entered the
xev | ... command above.
Back to xmodmap
Now that we have the keycodes, we can write them down in our very own
xmodmap configuration, namely in the file
~/.Xmodmap.
We just have to decide to which keysyms we shall map them. I would recommend to use keysyms that are usually not bound to any keys, like
F13,
F14, and so on.
In this example, we're going to bind the keycode
160 to the keysym
F13,
174 to
F14 and
176 to
F15.
Use your favorite text editor (
vim,
emacs,
kate,
nano, whatever) and put the corresponding lines in a file named
.Xmodmap (note the dot and the capital
X) under your home directory, like this:
keycode 160 = F13
keycode 174 = F14
keycode 176 = F15
Applying the xmodmap configuration
The
~/.Xmodmap file will automatically be interpreted by
xmodmap every time you start the X server with
startx or when you log into an X session using XDM/KDM/GDM.
But to avoid restarting our current X session, here is how to apply our configuration immediately:
xmodmap ~/.Xmodmap
KHotKeys
Now the keys can effectively be used in applications like KDE's
khotkeys, to be bound to commands or actions.
As an example, here is how to bind our new
F13 keysym to mute the sound volume, by sending a DCOP call to
kmix:
1) start the KDE Control Center (
kcontrol)
2) select "Regional & Accessibility"
3) select "Input Actions"
4) in the "General" tab, create a new action (using the "New Action" button), and give it a name in the "Action Name" text box (e.g. "mute volume")
5) still in the "General" tag, select "Keyboard Shortcut -> DCOP Call (simple)" for the "Action type":
6) go to the "Keyboard Shortcut" tab, click on the box that shows "None" and type the special key you want to assign to that action - as for our example, the box should then show "
F13"
7) go the the last tab, "DCOP Call Settings" and enter the following data:
* Remote application = kmix
* Remote object = Mixer0
* Called function = toggleMute
* Arguments 0
Then press the "OK" button and... we're done :)
If you want something that works with any window manager, have a look at
xbindkeys (
SUSE Linux RPMs of the latest xbindkeys version here)