Grab the key in X11

本文是搜集网上的资料整理而成的。

方法1:

#include <X11/Xlib.h>
#include <stdio.h>
main()
{
  Window root;
  XEvent e;
  int F2,F3,F4,F5,F6;
   
  // Open the display
  Display *dpy = XOpenDisplay(0);
  if (!dpy)return;
  // Get the root window -- so keys will be global
  root = DefaultRootWindow(dpy);
   
  F2 = XKeysymToKeycode(dpy, XStringToKeysym("F2"));
  F3 = XKeysymToKeycode(dpy, XStringToKeysym("F3"));
  F4 = XKeysymToKeycode(dpy, XStringToKeysym("F4"));
  F5 = XKeysymToKeycode(dpy, XStringToKeysym("F5"));
  F6 = XKeysymToKeycode(dpy, XStringToKeysym("F6"));
   
  // register the keys
  XGrabKey(dpy, F2, 0, root, True, GrabModeAsync, GrabModeAsync);
  XGrabKey(dpy, F3, 0, root, True, GrabModeAsync, GrabModeAsync);
  XGrabKey(dpy, F4, 0, root, True, GrabModeAsync, GrabModeAsync);
  XGrabKey(dpy, F5, 0, root, True, GrabModeAsync, GrabModeAsync);
  XGrabKey(dpy, F6, 0, root, True, GrabModeAsync, GrabModeAsync);
   
  // wait for events
  for(;;) {
  XNextEvent(dpy, &e);
  if (e.type == KeyPress){
  if (e.xkey.keycode == F4)
  break;
  else{
  if (e.xkey.keycode == F2)printf("F2!!!\n");
  else if (e.xkey.keycode == F3)printf("F3!!!\n");
  else if (e.xkey.keycode == F5)printf("F5!!!\n");
  else if (e.xkey.keycode == F6)printf("F6!!!\n");
  }
  }
  }
  // clean up
  XUngrabKey(dpy, F2, 0, root);
  XUngrabKey(dpy, F3, 0, root);
  XUngrabKey(dpy, F4, 0, root);
  XUngrabKey(dpy, F5, 0, root);
  XUngrabKey(dpy, F6, 0, root);
}

方法2:

#include <X11/Xlib.h>
#include <X11/extensions/record.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <glib-2.0/glib.h>


static gboolean stop_thread = FALSE;
static Display* dpy = 0;
static XRecordContext rc;
static pthread_t thread;

GMainLoop *main_loop;


void* intercept_key_thread(void* data);
void key_pressed_cb(XPointer arg, XRecordInterceptData *d);

int main(int argc, char *argv[])
{

	pthread_create(&thread, NULL, intercept_key_thread, NULL);

	main_loop = g_main_loop_new (NULL, FALSE);  
   
	g_main_loop_run (main_loop);  
	g_main_loop_unref (main_loop);  
	return 0;
}

void* intercept_key_thread(void* data) {
  XRecordClientSpec rcs;
  XRecordRange* rr;
  dpy = XOpenDisplay(0);

  if (!(rr = XRecordAllocRange())) {
    fprintf(stderr, "XRecordAllocRange error\n");
    exit(1);
  }
  rr->device_events.first = KeyPress;
  rr->device_events.last = MotionNotify;
  rcs = XRecordAllClients;

  if (!(rc = XRecordCreateContext(dpy, 0, &rcs, 1, &rr, 1))) {
    fprintf(stderr, "XRecordCreateContext error\n");
    exit(1);
  }
  XFree(rr);
  if (!XRecordEnableContext(dpy, rc, key_pressed_cb, data)) {
    fprintf(stderr, "XRecordEnableContext error\n");
    exit(1);
  }
  return 0;
}


void stop_intercept_key_thread(void) {
  void* result;
  stop_thread = TRUE;
  if (0 != pthread_join(thread, &result)) {
    fprintf(stderr, "pthread_join error\n");
    exit(1);
  }
}


void key_pressed_cb(XPointer arg, XRecordInterceptData *d) {
  if (stop_thread) {
    if (!XRecordDisableContext(dpy, rc)) {
      fprintf(stderr, "XRecordDisableContext error\n");
      exit(1);
    }
    if (!XRecordFreeContext(dpy, rc)) {
      fprintf(stderr, "XRecordFreeContext error\n");
      exit(1);
    }
    pthread_exit(0);
  }

  if (d->category != XRecordFromServer) return;
  unsigned char type = ((unsigned char*)d->data)[0] & 0x7F;
  unsigned char keycode = ((unsigned char*)d->data)[1];
  if (type == KeyPress) {
		printf("key: %d\n", keycode);
  }
}

编译方法:

gcc file.c  `pkg-config --cflags --libs  glib-2.0` -lpthread -lX11 -lXtst

方法3:

/**
 * 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;
    }
}


References:

1. https://github.com/Aitjcize/Qwertickle/blob/master/src/qwertickle.c

2. http://incise.org/tinywm.html

3. http://jouyouyun.is-programmer.com/posts/42193.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值