How to properly use XGrabKey to get a program hotkey

cheshirekow cheshirekow at gmail.com
Wed Oct 27 11:56:13 PDT 2010


Hello,

My goal is to have a program that sleeps in the background but can be 
activated by the user via some "hotkey". From digging around the Xlib 
manual and the Xlib O'reilly manual, I gather that the correct way to to 
this is with XGrabKey. However my understanding of the process is 
incorrect as a simple proof of concept does not work.

My understanding is that if I call XGrabKey with the root window as the 
grab_window, and owner_events false, then whenever my hotkey is pressed 
the event will be sent *only* to the root window. If I then select 
KeyPress events from the root window, and then listen for X events, I 
should get a key press event when the hotkey is pressed. I've pasted a 
minimal example below.

What I expect is that when the program is run, regardless of what window 
has focus, if Ctrl+Shift+K is pressed, my program should output "Hot key 
pressed!" in the console, and then terminate.

Furthermore, it is my understanding that if the XGrabKey fails, the 
default error handler will display a message, and since it does not I am 
assuming that the call succeeds.

Obviously, my understanding is flawed somehow. Can anyone point me in 
the right direction?

Thanks,

Josh





#include <iostream>
#include <X11/Xlib.h>
#include <X11/Xutil.h>


using namespace std;


int main()
{
     Display*    dpy     = XOpenDisplay(0);
     Window      root    = DefaultRootWindow(dpy);
     XEvent      ev;

     unsigned int    modifiers       = ControlMask | ShiftMask;
     int             keycode         = XKeysymToKeycode(dpy,XK_K);
     Window          grab_window     =  root;
     Bool            owner_events    = False;
     int             pointer_mode    = GrabModeAsync;
     int             keyboard_mode   = GrabModeAsync;

     XGrabKey(dpy, keycode, modifiers, grab_window, owner_events, 
pointer_mode,
              keyboard_mode);

     XSelectInput(dpy, root, KeyPressMask);
     while(true)
     {
         bool shouldQuit = false;
         XNextEvent(dpy, &ev);
         switch(ev.type)
         {
             case KeyPress:
                 cout << "Hot key pressed!" << endl;	
                 XUngrabKey(dpy,keycode,modifiers,grab_window);
                 shouldQuit = true;

             default:
                 break;
         }

         if(shouldQuit)
             break;
     }

     XCloseDisplay(dpy);
     return 0;
}



More information about the xorg mailing list