Подключиться к обработке событий в ключе Linux
Я хочу подключиться к обработке событий на клавиатуре Linux.
Нажатие кнопки CapsLock должно ввести какую-то командную строку.
Некоторые из команд, которые я хочу реализовать:
- d/x: удалить текущую позицию курсора до символа
x
. (вдохновленный vi)
- a: Перейти к началу строки, например pos1. (вдохновленный emacs).
- k: Удалить до конца строки. (вдохновленный emacs).
- ...
Команды должны работать в любом текстовом поле: браузер, почтовый клиент, терминал gnome,...
AFAIK низкоуровневый xmodmap не поможет мне здесь.
Возможно ли подобное?
Где мне нужно разместить крючок?
Текущей целевой платформой является Ubuntu >= 14.04
Справочная информация. Я хочу, чтобы мои пальцы указывали на F и J, и используйте компьютер, не глядя на клавиатуру. Работает для A-Z с нескольких лет, но клавиши, такие как Pos1/End, получить нелегко.
Пожалуйста, оставьте комментарий, если вы не понимаете часть этого вопроса. Спасибо.
Обновление
Этот вопрос касается только того, как подключиться к обработке ключевых событий. Другой материал (командная строка) - это другая тема. Как вы можете уловить, например, CapsLock x
?
Update2
Я вижу, что нет простого и прямого решения. Если у вас нет ответа, но вы знаете, где я могу найти дополнительную помощь (например, спросить в списке рассылки FOO), пожалуйста, скажите мне.
Update3
Поскольку некоторые люди не понимают, что я хочу, я пытаюсь объяснить это: если я использую emacs или bash, я чувствую, что контролирую, если компьютер: он похож на полет, при этом очень мало движений, я могу сказать, что компьютер делай то, что я хочу. Редактирование текста в текстовом поле webbrowser, LibreOffice или использовании thunderbird заставляет это чувство уйти. Движения курсора громоздки, ему не хочется летать. Я хочу контролировать рабочий стол, а не только одно приложение, и держать указательные пальцы на клавишах F и J.
Ответы
Ответ 1
UPDATE
Вместо того, чтобы сообщать X-серверу об игнорировании устройства, вы можете использовать EVIOCGRAB
ioctl, который я добавил в программу ниже.
Вам нужно сделать следующее:
1.Убедитесь, что модуль CONFIG_UINPUT скомпилирован и загружен. Я считаю, Ubuntu уже имеет его. Если вы не видите устройство /dev/uinput
, попробуйте запустить modprobe -v uinput
, чтобы загрузить модуль.
2. Запустите следующую программу с правами root и укажите путь к клавиатурному устройству, например:
./process /dev/input/by-id/usb-Microsoft_Wired_Keyboard_600-event-kbd
Следующая программа создает поддельное устройство ввода под названием uinput-sample
и пересылает все события с данного устройства ввода на него. Я адаптировал его из образца, приведенного в http://thiemonge.org/getting-started-with-uinput
Вы можете изменить его, чтобы делать то, что вы хотите сделать.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
#include <linux/uinput.h>
#define die(str, args...) do { \
perror(str); \
exit(EXIT_FAILURE); \
} while(0)
int
main(int argc, char* argv[])
{
int fdo, fdi;
struct uinput_user_dev uidev;
struct input_event ev;
int i;
if(argc != 2) die("error: specify input device");
fdo = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
if(fdo < 0) die("error: open");
fdi = open(argv[1], O_RDONLY);
if(fdi < 0) die("error: open");
if(ioctl(fdi, EVIOCGRAB, 1) < 0) die("error: ioctl");
if(ioctl(fdo, UI_SET_EVBIT, EV_SYN) < 0) die("error: ioctl");
if(ioctl(fdo, UI_SET_EVBIT, EV_KEY) < 0) die("error: ioctl");
if(ioctl(fdo, UI_SET_EVBIT, EV_MSC) < 0) die("error: ioctl");
for(i = 0; i < KEY_MAX; ++i)
if(ioctl(fdo, UI_SET_KEYBIT, i) < 0) die("error: ioctl");
memset(&uidev, 0, sizeof(uidev));
snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-sample");
uidev.id.bustype = BUS_USB;
uidev.id.vendor = 0x1;
uidev.id.product = 0x1;
uidev.id.version = 1;
if(write(fdo, &uidev, sizeof(uidev)) < 0) die("error: write");
if(ioctl(fdo, UI_DEV_CREATE) < 0) die("error: ioctl");
while(1)
{
if(read(fdi, &ev, sizeof(struct input_event)) < 0)
die("error: read");
ev.time.tv_sec = 0;
ev.time.tv_usec = 0;
if(write(fdo, &ev, sizeof(struct input_event)) < 0)
die("error: write");
}
if(ioctl(fdo, UI_DEV_DESTROY) < 0) die("error: ioctl");
close(fdi);
close(fdo);
return 0;
}
Ответ 2
Путь грубой силы - это сделать modyfy/rebuild xserver-xorg-input-evdev
и заменить /usr/lib/xorg/modules/input/evdev_drv.so
. Я бы начал с попытки изменить функцию EvdevQueueKbdEvent()
в xf86-input-evdev-2.9.0/src/evdev.c
. Не выглядит очень элегантным решением, но я думаю, вы получите гибкость в изменении очереди событий на клавиатуре.
Менее интрузивное решение может быть возможно с помощью XGRabKey()
(некоторые подробности здесь) и/или XGrabKeyboard()
.
Некоторая информация, которая может быть полезной здесь (относительно расширения XTest).
Ответ 3
Еще один способ взглянуть на ваш вопрос: вам нужен специализированный оконный менеджер. Подробнее читайте EWMH. Прочтите перед обзором X11.
Или рассмотрите некоторые существующие X window manager. Их много. Я подозреваю, что ratpoison или xmonad (или возможно sawfish и т.д.) можно настроить для удовлетворения ваших потребностей. (Но я не очень хорошо знаю эти WM).
Подумайте дважды, прежде чем внедрять свой оконный менеджер с нуля. Это может означать годы работы! AFAIU, WM может перенаправлять, фильтровать, захватывать или синтезировать события клавиатуры или мыши.
Конечно, с wayland все будет по-другому.
Ответ 4
Вот также проект python с использованием драйвера uinput:
http://hetgrotebos.org/wiki/uinput-mapper