keyhook.c
changeset 17 e884dbb403cc
child 45 cf6a06f368e6
equal deleted inserted replaced
16:f5a7ede6c1f3 17:e884dbb403cc
       
     1 // !!! FIXME: this is X11 specific.  :(
       
     2 
       
     3 #include <stdio.h>
       
     4 #include <stdlib.h>
       
     5 #include <string.h>
       
     6 #include <pthread.h>
       
     7 #include <unistd.h>
       
     8 
       
     9 #include <X11/Xlib.h>
       
    10 #include <X11/Xlibint.h>
       
    11 #include <X11/extensions/record.h>
       
    12 
       
    13 #include "keyhook.h"
       
    14 
       
    15 static volatile int keyPressFlags = 0;
       
    16 static volatile int sawKeyCombo = 0;
       
    17 static void keyhookCallback(XPointer priv, XRecordInterceptData *data)
       
    18 {
       
    19     const xEvent *xev = (const xEvent *) data->data;
       
    20     if (data->category == XRecordFromServer)
       
    21     {
       
    22         const BYTE keycode = xev->u.u.detail;
       
    23         if (xev->u.u.type == KeyPress)
       
    24         {
       
    25             // !!! FIXME: don't hardcode these keycodes.
       
    26             if ((keycode == 64) && (keyPressFlags == 0))
       
    27                 keyPressFlags++;
       
    28             else if ((keycode == 133) && (keyPressFlags == 1))
       
    29                 keyPressFlags++;
       
    30             else if ((keycode == 51) && (keyPressFlags == 2))
       
    31             {
       
    32                 sawKeyCombo = 1;
       
    33                 keyPressFlags = 0;
       
    34             } // else if
       
    35             else
       
    36                 keyPressFlags = 0;
       
    37         } // if
       
    38         else if (xev->u.u.type == KeyRelease)
       
    39         {
       
    40             keyPressFlags = 0;
       
    41         } // else if
       
    42     } // if
       
    43 
       
    44     XRecordFreeData(data);
       
    45 } // keyhookCallback
       
    46 
       
    47 
       
    48 // every example I've seen needs two Display connections...one for the
       
    49 //  keyhook, and one to control it.
       
    50 static Display *ctrldpy = NULL;
       
    51 static Display *datadpy = NULL;
       
    52 static XRecordContext xrc = 0;
       
    53 
       
    54 int initKeyHook(void)
       
    55 {
       
    56     int major = 0;
       
    57     int minor = 0;
       
    58     XRecordRange *xrr = NULL;
       
    59     XRecordClientSpec xrcs = XRecordAllClients;
       
    60 
       
    61     if (ctrldpy)
       
    62         return 0;  // already initialized.
       
    63 
       
    64     ctrldpy = XOpenDisplay(NULL);
       
    65     if (!ctrldpy)
       
    66         goto failed;
       
    67 
       
    68     XSynchronize(ctrldpy, True);
       
    69 
       
    70     datadpy = XOpenDisplay(NULL);
       
    71     if (!datadpy)
       
    72         goto failed;
       
    73     else if (!XRecordQueryVersion(ctrldpy, &major, &minor))
       
    74         goto failed;
       
    75     else if ((xrr = XRecordAllocRange()) == NULL)
       
    76         goto failed;
       
    77 
       
    78     memset(xrr, '\0', sizeof (*xrr));
       
    79     xrr->device_events.first = KeyPress;
       
    80     xrr->device_events.last = KeyPress;
       
    81 
       
    82     if ((xrc = XRecordCreateContext(ctrldpy, 0, &xrcs, 1, &xrr, 1)) == 0)
       
    83         goto failed;
       
    84     else if (!XRecordEnableContextAsync(datadpy, xrc, keyhookCallback, NULL))
       
    85         goto failed;
       
    86 
       
    87     XFree(xrr);
       
    88     xrr = NULL;
       
    89 
       
    90     return 1;
       
    91 
       
    92 failed:
       
    93     deinitKeyHook();
       
    94     if (xrr) XFree(xrr);
       
    95 
       
    96     return 0;
       
    97 } // initKeyHook
       
    98 
       
    99 
       
   100 void deinitKeyHook(void)
       
   101 {
       
   102     if (ctrldpy)
       
   103     {
       
   104         if (xrc)
       
   105         {
       
   106             XRecordDisableContext(ctrldpy, xrc);
       
   107             XRecordFreeContext(ctrldpy, xrc);
       
   108         } // if
       
   109         XCloseDisplay(ctrldpy);
       
   110     } // if
       
   111 
       
   112     if (datadpy)
       
   113         XCloseDisplay(datadpy);
       
   114 
       
   115     ctrldpy = NULL;
       
   116     datadpy = NULL;
       
   117     xrc = 0;
       
   118     sawKeyCombo = 0;
       
   119     keyPressFlags = 0;
       
   120 } // deinitKeyHook
       
   121 
       
   122 
       
   123 int pumpKeyHook(void)
       
   124 {
       
   125     if (!datadpy)
       
   126         return 0;
       
   127 
       
   128     sawKeyCombo = 0;
       
   129     XRecordProcessReplies(datadpy);
       
   130     return sawKeyCombo;
       
   131 } // pumpKeyHook
       
   132 
       
   133 // end of keyhook.c ...
       
   134