XRecord 示例

jouyouyun posted @ 2013年12月26日 12:41 in xrecord with tags xrecord , 3297 阅读

最近做但按键绑定,用到了 XRecord。但其的示例程序很难找,故在此记录一下,以便日后温习。

XRecord 是 xlib 的一个扩展,在 xtest 扩展中。下面的程序主要监听按键与鼠标事件,其它的事件可以根据需要添加。

/**
 * Author:      jouyouyun <jouyouwen717@gmail.com>
 * Maintainer:  jouyouyun <jouyouwen717@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 **/

#include <glib.h>
#include <X11/Xlib.h>
#include <X11/extensions/record.h>

static void event_cb (XPointer user_data, XRecordInterceptData *hook);

int main (int argc, char *argv[])
{
    Display *ctrl_disp = XOpenDisplay(NULL);
    Display *data_disp = XOpenDisplay(NULL);

    if ( !ctrl_disp || !data_disp ) {
        g_warning ("Unable to connect to X11 display!");
        return -1;
    }

    gint major, minor, dummy;

    if ( !XQueryExtension (ctrl_disp, "XTEST", &major, &minor, &dummy) ) {
        g_warning ("XTest extension missing!");
        return -1;
    }

    if ( !XRecordQueryVersion (ctrl_disp, &major, &minor) ) {
        g_warning ("Failed to obtain xrecord version!");
        return -1;
    }

    XSynchronize(ctrl_disp, True);
    XFlush (ctrl_disp);

    XRecordRange *range = XRecordAllocRange ();
    /*
     * 设定事件监听的范围
     * 监听 first ~ last 之间的事件
     */
    range->device_events.first = KeyPress;
    range->device_events.last = ButtonRelease;

    XRecordClientSpec spec = XRecordAllClients;
    XRecordContext context = XRecordCreateContext (
                                 data_disp, 0, &spec, 1, &range, 1 );

    if ( !context ) {
        g_warning ("Failed to create context!");
        return -1;
    }

    if ( !XRecordEnableContext(data_disp, context, event_cb, NULL) ) {
        g_warning ("Failed to enable context!");
        return -1;
    }

    /*
    if ( !XRecordEnableContextAsync (data_disp, context, event_cb, NULL) ) {
        g_warning ("Failed to enable context!");
        return -1;
    }

    XRecordProcessReplies (data_disp);
    */

    XRecordDisableContext(data_disp, context);
    XRecordFreeContext (data_disp, context);
    XFree(range);

    XCloseDisplay (data_disp);
    XCloseDisplay (ctrl_disp);
    return 0;
}

static void
event_cb (XPointer user_data, XRecordInterceptData *hook)
{
    if ( hook->category != XRecordFromServer ) {
        g_warning ("Data not from server!");
        return;
    }

    int event_type = hook->data[0];
    KeyCode keycode = hook->data[1];
    g_print ("Intercepted event type: %d, code: %d\n",
             event_type, keycode);

    switch (event_type) {
        case KeyPress:
            g_print ("key press event!\n");
            break;

        case KeyRelease:
            g_print ("key release event!\n");
            break;

        case ButtonPress:
            g_print ("button press event!\n");
            break;

        case ButtonRelease:
            g_print ("button release event!\n");
            break;

        default:
            /* FIXME: other events grab */
            break;
    }
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter