удалить / переписать / сгенерировать события клавиатуры под Linux - PullRequest
7 голосов
/ 23 сентября 2010

Я бы хотел подключить, перехватить и сгенерировать события клавиатуры (make / break) в Linux, прежде чем они будут доставлены в какое-либо приложение.Точнее, я хочу обнаруживать шаблоны в ключевом потоке событий и иметь возможность отбрасывать / вставлять события в поток в зависимости от обнаруженных шаблонов.

Я видел несколько связанных вопросов по SO, но:

  • либо они имеют дело только с тем, как добраться до ключевых событий (регистраторы ключей и т. Д.), А не с тем, как манипулировать их распространением (они только слушают, но не перехватывают / генерируют).
  • или они используют пассивные / активные захваты в X (подробнее об этом ниже).

Небольшой DSL

Я объясняю проблему ниже, но чтобы ее решитьнемного более компактный и понятный, сначала небольшое определение DSL.

  • A_: для клавиши make (нажмите) A
  • A^: для клавиши A break (release)
  • A^->[C_,C^,U_,U^]: на A^ отправить комбо make / break для C и затем U дальше по цепочке обработки (и, наконец, в приложение).Если нет ->, то ничего не отправляется (но внутреннее состояние может быть изменено для обнаружения последующих событий).
  • $X: выполнить произвольное действие.Это может быть отправка некоторой настраиваемой последовательности событий клавиш (например, C-x C-s для emacs) или выполнение функции.Если я могу отправлять только ключевые события, этого будет достаточно, поскольку я могу затем обрабатывать их в диспетчере окон в зависимости от того, какое приложение активно.

Описание проблемы

Хорошо,поэтому в этой записи обозначены шаблоны, которые я хочу обнаружить, и какие события я хочу передать по цепочке обработки.

  1. A_, A^->[A_,A^]: expl.см. выше, обратите внимание, что отправка происходит A^.
  2. A_, B_, A^->[A_,A^], B^->[B_,B^]: в основном то же, что и 1., но перекрывающиеся события не изменяют поток обработки.
  3. A_, B_, B^->[$X], A^:если произошел полный взлом / разрыв ключа (B), в то время как удерживался другой ключ (A), выполняется X (см. выше), и разрыв A сбрасывается.

(этов принципе, простой механизм состояний реализован над ключевыми событиями, которые могут генерировать (несколько) ключевых событий в качестве выходных данных.

Дополнительные примечания

  • Решение должно работать на скорости набора.
  • Потребители измененного ключевого потока событий, работающего под X в Linux (консоли, браузеры, редакторы и т. Д.).
  • На обработку влияют только события клавиатуры (без мыши и т. Д.)
  • Сопоставление может происходить на символах клавиш (немного проще) или кодах клавиш (немного сложнее).С последним мне просто нужно прочитать в отображении для перевода из кода в keysym.
  • Если возможно, я бы предпочел решение, которое работает как с клавиатурами USB, так и с виртуальной машиной (можетбыть проблемой, если работать на уровне драйвера, другие уровни должны быть в порядке).
  • Я довольно открыт в отношении языка реализации.

Возможные решения и вопросы

Итак, основной вопрос - как это реализовать.

Я реализовал решение в оконном менеджере, используя пассивные захваты (XGrabKey) и XSendEvent.К сожалению, пассивные захваты не работают в этом случае, так как они не захватывают правильно B^ во втором шаблоне выше.Причина в том, что преобразованный захват заканчивается на A^ и не продолжается до B^.Новый захват конвертируется в захват B, если он еще удерживается, но только через ~ 1 сек.В противном случае в заявку отправляется простой B^.Это можно проверить с помощью xev.

. Я мог бы преобразовать свою реализацию для использования активного захвата (XGrabKeyboard), но я не уверен насчет влияния на другие приложения, если оконный менеджер имеет активныйхвататься за клавиатуру все время.Документация X относится к активным захватам как навязчивым и предназначенным для краткосрочного использования.Если у кого-то есть опыт работы с этим и нет серьезных недостатков при длительном активном захвате, я бы посчитал это решением.

Я готов взглянуть на другие уровни обработки ключевых событий, кроме оконных менеджеров (которые работают как X-клиенты).Драйверы клавиатуры или сопоставления возможны, пока я могу решить вышеупомянутую проблему с ними.Это также подразумевает, что решение не должно быть отдельным приложением.Я в порядке, чтобы драйвер или модуль ядра сделали это для меня.Имейте в виду, что я никогда не занимался программированием ядра или драйвера, поэтому буду признателен за хорошие ресурсы.

Спасибо за любые указатели!

1 Ответ

3 голосов
/ 21 октября 2010

Используйте XInput2, чтобы заставить устройство (клавиатуру) плавать, затем следите за событиями KeyPress и KeyRelease на устройстве, используя XTest для генерации события KeyPress & KeyRelease.

...