抓住触摸板事件设备导致指针跳转

时间:2018-06-27 23:13:19

标签: c++ linux x11 evdev

我正在使用libevdev(在evdev周围包装)在Linux笔记本电脑上抓取(libevdev_grab)和取消(libevdev_grab)触摸板设备;如果触摸从触摸板的某个区域开始,我将抓住它并处理以下动作,然后在释放手指时将其释放。但是,当我在手指放下后抓紧手指,并在松开手指后松开手指时,到X服务器时,好像放下了一根手指,并且从未松开过。因此,下次用户放下手指时,X服务器会将其视为先前事件的延续,并相应地移动指针。

是否有办法告诉X服务器好像已经释放了手指,以便下次手指放下时,它不会将新的手指事件与先前的手指事件相关联?

编辑,添加最小样本以重现该问题:

每次您用手指触摸触摸板时,下面的程序都会抓住指针,而当您松开手指时,将取消对指针的拨动。请注意,如果在点x上点击(触摸并释放),然后触摸或点击点y,则指针的移动就像您将手指从点x移到y一样。这是我要解决的问题。当x和y之间的时间增量较小时,就会发生这种情况。

#include <fcntl.h>
#include <iostream>
#include <libevdev/libevdev-uinput.h>
#include <libevdev/libevdev.h>
#include <poll.h>
#include <zconf.h>

int fd;
libevdev *inputDevice;
pollfd pollyFd;

bool fingerDown;

// sets inputDevice to the first device found that supports EV_ABS events
bool findInputDevice() {
    const std::string prefix = "/dev/input/event";
    int i = 0;

    while (true) {
        std::string pathString = prefix + std::to_string(i++);
        const char *path = pathString.c_str();

        fd = open(path, O_RDONLY);
        if (fd == -1) {
            fprintf(stderr, "Unable to open event file %d, %s\n", i, path);
            fprintf(stderr, "Unable to find touch device, iterated %d devices\n", i);
            return false;
        }
        if (libevdev_new_from_fd(fd, &inputDevice) != 0)
            fprintf(stderr, "Unable to open libevdev device from fd %d, device %d\n", fd, i);
        if (libevdev_has_event_type(inputDevice, EV_ABS))
            return true;
        libevdev_free(inputDevice);
        close(fd);
    }
}

void readEvents() {
    input_event event;
    while (poll(&pollyFd, 1, 10)) {
        read(fd, &event, sizeof(input_event));

        if (event.type == EV_KEY && event.code == BTN_TOUCH)
            fingerDown = (bool) event.value;
    }
}

int main() {
    if (getuid() != 0)
        fprintf(stderr, "Need root, run with sudo\n");

    if (!findInputDevice())
        return 0;

    pollyFd.fd = fd;
    pollyFd.events = POLLIN;

    while (true) {
        readEvents();
        if (fingerDown)
            libevdev_grab(inputDevice, LIBEVDEV_GRAB);
        else
            libevdev_grab(inputDevice, LIBEVDEV_UNGRAB);
    }

    libevdev_free(inputDevice);
    close(fd);
}

要编译和运行它,需要安装libevdev-dev软件包

请注意,该程序将使您的触摸板无法使用,因此请确保拥有另一个指针输入设备或能够使用键盘将其终止。

g++ main.cpp -I/usr/include/libevdev-1.0 -levdev

0 个答案:

没有答案