я использую libevdev
(обертка вокруг evdev
) Хватать (libevdev_grab
) и убрать (libevdev_grab
) устройство с сенсорной панелью на моем ноутбуке Linux; если касание начинается в определенной области сенсорной панели, я беру его и выполняю следующие движения, а затем отпускаю, когда палец отпущен. Однако, когда я хватаю после того, как палец опущен, и убираю после того, как палец отпущен, к 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
Задача ещё не решена.
Других решений пока нет …