我正在使用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