C++ – Use X11 on Linux to grab events on a specific key

Use X11 on Linux to grab events on a specific key… here is a solution to the problem.

Use X11 on Linux to grab events on a specific key

I’m writing a program in C++ to implement OS X’s keyboard backlighting on a MacBook Pro running a Linux distribution. So far, it turns on the backlight on startup, turns it off if keyboard and mouse events are not registered within 20 seconds, and of course, turns it on again when there are events registered. The next thing I need the program to do is capture the keys on the keyboard backlit up/down keys, but I’m not sure how to handle this.

I’m currently using XScreenSaverQueryInfo to get idle time for keyboard and mouse events, so using the X11 API method will do. I’ve done a lot of Google searches but haven’t found a method that I’m sure can use. The problem I’ve seen in many of the methods I’ve found is that they use keycodes to identify keys, but I don’t think this is a viable solution because the program should work with any keyboard layout available.

Any ideas on the methods and APIs I should use? What works best?

Greetings,

Solution

The general way to do this is to use XGrabKey(). It uses the keycode, but instead of hardcoding the keycode, you get it using XKeysymToKeycode(). More correctly, you also want to redo the fetch when you receive MappingNotify (XMappingEvent). (Note that MappingNotify, not MapNotify.) If these keys don’t have a keycode – the old X version may not have, but hopefully the newer X.org version has one – then you just have to hardwire the keycode. This won’t be very robust or portable, but it will probably work for everyone on Linux using the same hardware model.

Ready key fetching is global, so if you try XGrabKey() and something else has already fetched that key, you’ll get an X error – quit the program by default. Another quirk of XGrabKey() is that it gets keys using an exact set of modifiers. For example, to process NumLock at the same time, you need to fetch twice. See also Global Hotkey with X11/Xlib

In a normal Linux setup (if you want to get such functionality in an upstream project), the desktop environment doesn’t want many separate applications vying for keys and getting errors. So there will be some central coordination point, such as a window manager or a special daemon that may perform all the binds as needed and forward commands to other processes. So, if you’re trying to integrate your functionality into a release by default, you might want to look at the same upstream code that patches other special keys.

Another thing to note is the Xkb API, which is much more complex. There are some brain-draining ways to get keys using XKB, but I don’t know what good it is to go that route.

Related Problems and Solutions