XSendEvent不起作用

时间:2016-01-10 10:07:11

标签: c++ ubuntu x11

我正在尝试根据this示例及其后面的评论发送X事件:

#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <cstdio>
#include <iostream>
#include <string>
#include <unistd.h>
// #include <X11/extensions/XTest.h> // Uncomment to use XTestFakeKeyEvent()

// The key code to be sent.
// A full list of available codes can be found in /usr/include/X11/keysymdef.h
#define KEYCODE XK_Down

// Function to create an X11 keyboard event
// http://www.doctort.org/adam/nerd-notes/x11-fake-keypress-event.html
XKeyEvent createKeyEvent(Display *display, Window &win, Window &winRoot,
                         bool press, int keycode, int modifiers) {
    XKeyEvent event;

    event.display = display;
    event.window = win;
    event.root = winRoot;
    event.subwindow = None;
    event.time = CurrentTime;
    event.x = 1;
    event.y = 1;
    event.x_root = 1;
    event.y_root = 1;
    event.same_screen = True;
    event.keycode = XKeysymToKeycode(display, keycode);
    event.state = modifiers;

    if (press)
        event.type = KeyPress;
    else
        event.type = KeyRelease;

    return event;
}

int main() {
    // Obtain the X11 display.
    Display *display = XOpenDisplay(0);
    if (display == NULL) return -1;

    // Get the root window for the current display.
    Window winRoot = XDefaultRootWindow(display);

    // Find the window which has the current keyboard focus.
    Window winFocus;
    int revert;
    XGetInputFocus(display, &winFocus, &revert);

    // Send a fake key press event to the window.
    XKeyEvent event =
        createKeyEvent(display, winFocus, winRoot, true, KEYCODE, 0);
    int res = XSendEvent(event.display, event.window, True, KeyPressMask,
                         (XEvent *)&event);
    // int res =
    //     XTestFakeKeyEvent(event.display, event.keycode, True, CurrentTime);
    std::cout << ((res != 0) ? std::string("Sent successfully")
                             : std::string("Sending failed")) << std::endl;
    sleep(1);
    if (XPending(display))
        std::cout << "Got it!" << std::endl;
    else
        std::cout << "It's lost..." << std::endl;
    // Done.
    XCloseDisplay(display);
    return 0;
}

根据输出,无论我使用XSendEvent还是XTestFakeKeyEvent(注释掉的代码),事件都会被发送,然后会丢失。我正在使用Ubuntu 14.04下的gcc 4.8.2编译代码。缺少什么?

1 个答案:

答案 0 :(得分:3)

为了接收事件,X11应用程序通常需要注册对它们的兴趣。这是通过XSelectInput函数完成的:

XSelectInput(display, winFocus, KeyPressMask|KeyReleaseMask); 

告诉X11此客户希望接收与winFocus相关联的按键和密钥释放事件。