Как правильно и программно запечатлеть вторую мышь или трекбол под Linux X?
Я проектирую и внедряю экспериментальное приложение с графическим интерфейсом. Я хочу, чтобы мои пользователи могли одновременно использовать обе руки для взаимодействия с приложением. В качестве примера представьте GIMP и вторую мышь (трекбол) в левой (другой) руке: вы можете перемещаться, перемещать, поворачивать или масштабировать изображение левой рукой, одновременно рисуя / редактируя точечные точки, линии или фигуры с правой рукой в то же время. В 2000–2002 годах я провел несколько экспериментов с двумя мышами: одна с интерфейсом PS2 (USB), а другая с последовательным интерфейсом RS232. В настоящее время, много лет спустя, я возвращаюсь к этой древней идее с современным программным обеспечением и современными (USB) устройствами ввода.
В идеальном случае моя цель - подключить вторую систему мыши (или трекбол) к системе GNU/ Linux с X и затем иметь возможность:
- (1.) Продолжайте использовать основную мышь в качестве основного указателя X по умолчанию.
- (2.) Программный доступ / чтение событий от второй мыши.
- (3.) Получите события от второй мыши отдельно (различимым образом) от основной мыши.
- (4.) Иметь возможность "потреблять" события от второй мыши, чтобы при каждом запуске моей программы вторая мышь не влияла на главный указатель.
- (5.) Предпочтительно, чтобы вторая мышь была захвачена только тогда, когда окно GUI моей программы имеет фокус.
- (6.) Предпочтительно, полное решение не должно зависеть от других пакетов или библиотек, таких как, например, gpm. Тем не менее, это не проблема, если (какие-либо) правила udev требуются, так как конечный пользователь должен был бы установить мою программу в любом случае.
- (7.) Предпочтительно, чтобы решение не нуждалось в каких-либо дополнительных привилегиях или разрешениях, таких как, например, добавление пользователя в группу "ввода".
Я потратил более 6 часов на поиски подсказок в Интернете, но, к сожалению, я не слишком далеко зашел за какое-то "грязное" частичное решение с несколькими недостатками:
- (A.) Добавьте пользователя в группу "вход".
- (B.) Захват событий от второй мыши, как в примере программы ниже.
- (C.) Открытая точка: посмотрите дальше, как "потреблять" события от второй мыши?
- (D.) Справиться с глобальным захватом (не только окно с фокусом) и другими проблемами?
...
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/input.h>
int main(int argc, char **argv)
{
int ret=1; /* Program's return value; 0=success. */
int fd; /* File descriptor (handler) */
struct input_event ev;
if (argc != 2) {
printf("Usage:\n rdinpdev <device>\n"
"Print events from an input device.\n"
);
}
else {
fd = open(argv[1], O_RDONLY);
printf("open returned %d\n",fd);
if(fd >= 0) {
ret=0;
while(1) {
read(fd, &ev, sizeof(struct input_event));
printf("value %d, type %d, code %d\n",ev.value,ev.type,ev.code);
}
}
}
return ret;
}
1 ответ
Краткий ответ: Расширение устройства ввода X
Несколько более длинный ответ: у X есть концепция основных устройств ввода, которые обычно представляют собой клавиатуру и мышь, и дополнительные устройства ввода, которые можно запрашивать с помощью расширения, упомянутого выше. Эти альтернативные входы могут генерировать события, если вы их попросите.
Вот небольшой фрагмент кода, который перечислит все устройства ввода:
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/extensions/XInput.h>
int main (int argc, char *argv[])
{
Display *d = XOpenDisplay (0);
if (!d)
{
printf ("Failed to open display.\n");
return 1;
}
int i, num;
XDeviceInfo *dev;
dev = XListInputDevices (d, &num);
printf ("Found %d input devices:\n", num);
for (i = 0; i < num; i++)
{
printf (" name: %s; classes: %d; use: %d\n", dev[i].name, dev[i].num_classes, dev[i].use);
}
XCloseDisplay (d);
return 0;
}
Makefile:
second-input: second-input.o
$(CC) -o $@ $< -lX11 -lXi
.o:.c
$(CC) -g -o $@ $<
У меня есть планшет для рисования Wacom, подключенный к моей системе, но этот код перечисляет еще больше, некоторые из которых я не ожидал:
Found 10 input devices:
name: Virtual core pointer; classes: 2; use: 0
name: Virtual core keyboard; classes: 1; use: 1
name: Virtual core XTEST pointer; classes: 2; use: 4
name: Virtual core XTEST keyboard; classes: 1; use: 3
name: Power Button; classes: 1; use: 3
name: Power Button; classes: 1; use: 3
name: USB Mouse ; classes: 2; use: 4
name: Wacom Volito Pen; classes: 0; use: 2
name: UVC Camera (046d:081d); classes: 1; use: 3
name: AT Translated Set 2 keyboard; classes: 1; use: 3