マウスとキーボード入力の監視

class=InputOnly, override_redirect=True なウィンドウを作成すると、非表示のウィンドウでマウス入力を取れる。非表示のウィンドウはフォーカスを持たないため、キー入力は別途 XGrabKeyboard を設定して監視する。マウス入力は XGrabPointer でも監視できるが、リスクが大きいので避ける。

#include <stdio.h>
#include <stdlib.h>
#include <X11/Xlib.h>
#include <X11/Intrinsic.h>

int main(int argc, char **argv)
{
    Display              *d;
    Window               w;
    long                 mask;
    XSetWindowAttributes attr;
    XEvent               e;

    /* イベント監視用ウィンドウを生成する */
    d = XOpenDisplay(NULL);
    w = XCreateWindow(d, DefaultRootWindow(d), 0, 0,
                      WidthOfScreen(DefaultScreenOfDisplay(d)),
                      HeightOfScreen(DefaultScreenOfDisplay(d)),
                      0, 0, InputOnly, CopyFromParent, 0L, NULL);

    /* ウィンドウマネージャの介入を抑止する */
    attr.override_redirect = True;
    XChangeWindowAttributes(d, w, CWOverrideRedirect, &attr);

    /* イベント処理 */
    XMapWindow(d, w);
    XGrabKeyboard(d, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
    mask = ButtonPressMask|ButtonReleaseMask|PointerMotionMask|KeyPress|KeyRelease;
    XSelectInput(d, w, mask);
    for (;;) {
        XNextEvent(d, &e);
        switch (e.type) {
        case KeyPress:
            fprintf(stderr, "KeyPress\n");
            break;
        case KeyRelease:
            fprintf(stderr, "KeyRelease\n");
            break;
        case ButtonPress:
            fprintf(stderr, "ButtonPress\n");
            break;
        case ButtonRelease:
            fprintf(stderr, "ButtonRelease\n");
            break;
        case MotionNotify:
            fprintf(stderr, "MotionNotify\n");
            break;
        default:
            break;
        }
    }
    XCloseDisplay(d);
    return 0;
}