C语言 获取鼠标按钮状态非阻塞Linux

bnl4lu3b  于 2023-02-15  发布在  Linux
关注(0)|答案(2)|浏览(106)

我正在尝试写一个游戏插件,我需要读取鼠标按钮的状态,而不是阻止或“吃掉”事件。直接阅读/dev/input不是一个选项,因为根访问。我更接近我需要的是下面的代码:

#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>

int main (int argc, char **argv)
{
Display *display;
XEvent ev;

display = XOpenDisplay(NULL);
Window window = RootWindow(display, XDefaultScreen(display));

XSelectInput(display, window, ButtonPressMask | ButtonReleaseMask);
XGrabButton(display, Button1, AnyModifier, window, False, ButtonPressMask | ButtonReleaseMask, GrabModeSync, GrabModeAsync, None, None);

while(1) {

XAllowEvents(display, ReplayPointer, CurrentTime);
    if(XCheckTypedEvent(display, ButtonPress ,&ev))
    {
        printf("Button pressed\n");
    }
    else if(XCheckTypedEvent(display, ButtonRelease ,&ev))
    {
        printf("Button relised\n");
    }

}

return 0;
}

问题是,通过设置GrabModeSync并使用XAllowEvents和ReplayPointer,我可以传递事件,但我只得到ButtonPress。ButtonRelease从未被捕获,但我需要它。GrabModeAsync捕获两个事件,但“吃掉”点击。有人能建议一个解决方案吗?10 x

ux6nzvsh

ux6nzvsh1#

对于任何人谁可能会绊倒到这个职位,而寻找类似的问题解决方案,这里是什么为我工作.

#include <stdio.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>

static void select_events(Display *dpy, Window win)
{
    XIEventMask evmasks[1];
    unsigned char mask1[(XI_LASTEVENT + 7)/8];

    memset(mask1, 0, sizeof(mask1));

    /* select for button and key events from all master devices */
    XISetMask(mask1, XI_RawButtonPress);
    XISetMask(mask1, XI_RawButtonRelease);

    evmasks[0].deviceid = XIAllMasterDevices;
    evmasks[0].mask_len = sizeof(mask1);
    evmasks[0].mask = mask1;

    XISelectEvents(dpy, win, evmasks, 1);
    XFlush(dpy);
}

int main(){
Display *dpy;
XEvent ev;
XIEvent *xi_event;
XIRawEvent *xev;

XGenericEventCookie *cookie = &ev.xcookie;
dpy = XOpenDisplay(NULL);
select_events(dpy, DefaultRootWindow(dpy));
    int count = 0;
    while(1){
       if (XCheckTypedEvent(dpy, GenericEvent ,&ev)){

        if (cookie->type != GenericEvent ||
            !XGetEventData(dpy, cookie)){
            continue;
            }

        xi_event = (XIEvent *) cookie->data;
        xev = (XIRawEvent *) xi_event;
        switch (cookie->evtype) {
            case XI_RawButtonPress:
                printf("Button pressed %d %d\n", xev->detail, ++count);
                break;
            case XI_RawButtonRelease:
                printf("Button released %d %d\n", xev->detail, count);
                break;
            }

        XFreeEventData(dpy, cookie);
        }
    }

    return 1;
}
fnx2tebb

fnx2tebb2#

谢谢你的解决方案,但它沉重地加载了我的处理器。所以我发现它是如何在xinput test命令:https://github.com/freedesktop/xorg-xinput/blob/master/src/test.c

#include "xinput.h"
#include <string.h>

#define INVALID_EVENT_TYPE  -1

static int           motion_type = INVALID_EVENT_TYPE;
static int           button_press_type = INVALID_EVENT_TYPE;
static int           button_release_type = INVALID_EVENT_TYPE;
static int           key_press_type = INVALID_EVENT_TYPE;
static int           key_release_type = INVALID_EVENT_TYPE;
static int           proximity_in_type = INVALID_EVENT_TYPE;
static int           proximity_out_type = INVALID_EVENT_TYPE;

static int
register_events(Display     *dpy,
        XDeviceInfo *info,
        char        *dev_name,
        Bool        handle_proximity)
{
    int         number = 0; /* number of events registered */
    XEventClass     event_list[7];
    int         i;
    XDevice     *device;
    Window      root_win;
    unsigned long   screen;
    XInputClassInfo *ip;

    screen = DefaultScreen(dpy);
    root_win = RootWindow(dpy, screen);

    device = XOpenDevice(dpy, info->id);

    if (!device) {
    fprintf(stderr, "unable to open device '%s'\n", dev_name);
    return 0;
    }

    if (device->num_classes > 0) {
    for (ip = device->classes, i=0; i<info->num_classes; ip++, i++) {
        switch (ip->input_class) {
        case KeyClass:
        DeviceKeyPress(device, key_press_type, event_list[number]); number++;
        DeviceKeyRelease(device, key_release_type, event_list[number]); number++;
        break;

        case ButtonClass:
        DeviceButtonPress(device, button_press_type, event_list[number]); number++;
        DeviceButtonRelease(device, button_release_type, event_list[number]); number++;
        break;

        case ValuatorClass:
        DeviceMotionNotify(device, motion_type, event_list[number]); number++;
        if (handle_proximity) {
            ProximityIn(device, proximity_in_type, event_list[number]); number++;
            ProximityOut(device, proximity_out_type, event_list[number]); number++;
        }
        break;

        default:
        fprintf(stderr, "unknown class\n");
        break;
        }
    }

    if (XSelectExtensionEvent(dpy, root_win, event_list, number)) {
        fprintf(stderr, "error selecting extended events\n");
        return 0;
    }
    }
    return number;
}

static void
print_events(Display    *dpy)
{
    XEvent        Event;

    setvbuf(stdout, NULL, _IOLBF, 0);

    while(1) {
    XNextEvent(dpy, &Event);

    if (Event.type == motion_type) {
        int loop;
        XDeviceMotionEvent *motion = (XDeviceMotionEvent *) &Event;

        printf("motion ");

        for(loop=0; loop<motion->axes_count; loop++) {
        printf("a[%d]=%d ", motion->first_axis + loop, motion->axis_data[loop]);
        }
        printf("\n");
    } else if ((Event.type == button_press_type) ||
           (Event.type == button_release_type)) {
        int loop;
        XDeviceButtonEvent *button = (XDeviceButtonEvent *) &Event;

        printf("button %s %d ", (Event.type == button_release_type) ? "release" : "press  ",
           button->button);

        for(loop=0; loop<button->axes_count; loop++) {
        printf("a[%d]=%d ", button->first_axis + loop, button->axis_data[loop]);
        }
        printf("\n");
    } else if ((Event.type == key_press_type) ||
           (Event.type == key_release_type)) {
        int loop;
        XDeviceKeyEvent *key = (XDeviceKeyEvent *) &Event;

        printf("key %s %d ", (Event.type == key_release_type) ? "release" : "press  ",
           key->keycode);

        for(loop=0; loop<key->axes_count; loop++) {
        printf("a[%d]=%d ", key->first_axis + loop, key->axis_data[loop]);
        }
        printf("\n");
    } else if ((Event.type == proximity_out_type) ||
           (Event.type == proximity_in_type)) {
        int loop;
        XProximityNotifyEvent *prox = (XProximityNotifyEvent *) &Event;

        printf("proximity %s ", (Event.type == proximity_in_type) ? "in " : "out");

        for(loop=0; loop<prox->axes_count; loop++) {
        printf("a[%d]=%d ", prox->first_axis + loop, prox->axis_data[loop]);
        }
        printf("\n");
    }
    else {
        printf("what's that %d\n", Event.type);
    }
    }
}

int
test(Display    *display,
     int    argc,
     char   *argv[],
     char   *name,
     char   *desc)
{
    XDeviceInfo     *info;

    if (argc != 1 && argc != 2) {
    fprintf(stderr, "usage: xinput %s %s\n", name, desc);
    return EXIT_FAILURE;
    } else {
    Bool    handle_proximity = False;
    int idx = 0;

    if (argc == 2) {
        if (strcmp("-proximity", argv[0]) != 0) {
        fprintf(stderr, "usage: xinput %s %s\n", name, desc);
        return EXIT_FAILURE;
        }
        handle_proximity = 1;
        idx = 1;
    }

    info = find_device_info(display, argv[idx], True);

    if (!info) {
        fprintf(stderr, "unable to find device '%s'\n", argv[idx]);
        return EXIT_FAILURE;
    } else {
        if (register_events(display, info, argv[idx], handle_proximity)) {
        print_events(display);
        }
        else {
        fprintf(stderr, "no event registered...\n");
        return EXIT_FAILURE;
        }
    }
    }
    return EXIT_FAILURE;
}

相关问题