Как правильно и программно запечатлеть вторую мышь или трекбол под 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
Другие вопросы по тегам