Как переназначить клавиши под Linux только для конкретной клавиатуры

18

Я недавно купил клавиатуру Unicomp, которая поставляется со сменными правыми и клавишами Windows. Клавиатура идентифицирует как это на lsusb:

Bus 003 Device 002: ID 17f6:0822 Unicomp, Inc 

Есть ли способ заставить ядро ​​(то есть не основанное на xmodmap) поменять местами правые клавиши и клавиши Windows, чтобы каждое приложение видело их в местах перестановки, даже если они получают необработанный ввод с клавиатуры (замена содержимого с помощью xmodmap этого не сделает) ? Есть ли способ сделать это только для этой клавиатуры?

FUZxxl
источник
Я подозреваю, что вы могли бы сделать это с помощью udev, сопоставив серийный номер клавиатуры, а затем вызвав скрипт, который выполняет переназначение. Вероятно, вам понадобится аналогичный скрипт, который будет вызываться при отключении устройства, чтобы вернуть его обратно.
варенье
1
@jam Это переназначит все подключенные клавиатуры? Я не могу представить, что Linux настолько негибок, что может управлять только одной таблицей сопоставления для всех подключенных (USB) клавиатур.
FUZxxl
@jam Кроме того, вы бы действительно помогли мне, если бы вы могли описать, как сделать настоящий обмен. Мне не удалось найти ничего полезного, только материал xmodmap (который я не хочу использовать).
FUZxxl
Если вы не хотите использовать xmodmap, то, что вы спрашиваете, кажется слишком конкретным, чтобы мои знания помогли вам извиниться. Метод, который я предложил, будет использовать xmodmap для замены кодов клавиш для этих клавиш на всех устройствах, на время, когда ваша конкретная клавиатура подключена, и затем вставит ее обратно. Ожидаете ли вы использовать несколько клавиатур одновременно?
джем
@jam Если бы я использовал Xmodmap, X-программы все равно видели бы неправильные коды клавиш, поскольку X-сервер также отправлял непереведенные коды клавиш клиенту. Это имеет значение, например, для видеоигр. Предполагается, что в ядре есть решение, которое не усложнит мою жизнь с приложениями, считывающими коды сканирования.
FUZxxl

Ответы:

27

Да, это возможно с помощью XKB. В отличие от xmodmap, XKB может переназначать ваши ключи для отдельных устройств.

Примечание: убедитесь, что у вас есть xkbcomp> 1.2.0

Сначала перечислите свои устройства с:

xinput list

Вы получите что-то вроде этого:

⎡ Virtual core pointer                      id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ Wacom Bamboo Pen Pen stylus               id=11   [slave  pointer  (2)]
⎜   ↳ Wacom Bamboo Pen Finger touch             id=12   [slave  pointer  (2)]
⎜   ↳ Logitech USB-PS/2 Optical Mouse           id=13   [slave  pointer  (2)]
⎜   ↳ Wacom Bamboo Pen Pen eraser               id=14   [slave  pointer  (2)]
⎜   ↳ Wacom Bamboo Pen Finger pad               id=15   [slave  pointer  (2)]
⎜   ↳ GASIA USB KB V11                          id=17   [slave  pointer  (2)]
⎣ Virtual core keyboard                     id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
    ↳ Power Button                              id=6    [slave  keyboard (3)]
    ↳ Power Button                              id=7    [slave  keyboard (3)]
    ↳ G19 Gaming Keyboard                       id=8    [slave  keyboard (3)]
    ↳ G19 Gaming Keyboard                       id=9    [slave  keyboard (3)]
    ↳ Logitech G19 Gaming Keyboard              id=10   [slave  keyboard (3)]
    ↳ GASIA USB KB V11                          id=16   [slave  keyboard (3)]

Определите строку вашего устройства и отредактируйте следующий скрипт оболочки, заменив строку sed на строку, соответствующую имени вашего устройства. Затем измените ключи, которые вам нужно переназначить.

Пример: загрузите xevи нажмите клавишу, которую вы хотите переназначить. Предположим, вы узнали, что это ключевой код 84. Найдите 84 в https://gist.github.com/zoqaeski/3880640 . Ключевое имя там есть <KP5>. Затем найдите ключ, которым вы хотите заменить его (в той же ссылке, ниже ) и скопируйте то, что находится внутри скобок. Повторите процесс для всех ключей, которые вы хотите.

remote_id=$(
    xinput list |
    sed -n 's/.*GASIA.*id=\([0-9]*\).*keyboard.*/\1/p'
)
[ "$remote_id" ] || exit

# remap the following keys, only for my custom vintage atari joystick connected
# through an old USB keyboard:
#
# keypad 5 -> keypad 6
# . -> keypad 2
# [ -> keypad 8
# left shift -> left control

mkdir -p /tmp/xkb/symbols
# This is a name for the file, it could be anything you
# want. For us, we'll name it "custom". This is important
# later.
#
# The KP_* come from /usr/include/X11/keysymdef.h
# Also note the name, "remote" is there in the stanza
# definition.
cat >/tmp/xkb/symbols/custom <<\EOF

xkb_symbols "remote" {
    key <KP5>  { [ KP_Right, KP_6, U2192, U21D2 ]       };
    key <I129> { [ KP_Down, KP_2, U2193, U21D3 ]       };
    key <AD12> { [ KP_Up, KP_8, U2191, U21D1 ]  };
    key <LFSH> { [ Control_L ]        };
};
EOF

# (1) We list our current definition
# (2) Modify it to have a keyboard mapping using the name
#     we used above, in this case it's the "remote" definition
#     described in the file named "custom" which we specify in
#     this world as "custom(remote)".
# (3) Now we take that as input back into our definition of the
#     keyboard. This includes the file we just made, read in last,
#     so as to override any prior definitions.  Importantly we 
#     need to include the directory of the place we placed the file
#     to be considered when reading things in.
#
# Also notice that we aren't including exactly the 
# directory we specified above. In this case, it will be looking
# for a directory structure similar to /usr/share/X11/xkb
# 
# What we provided was a "symbols" file. That's why above we put
# the file into a "symbols" directory, which is not being included
# below.
setxkbmap -device $remote_id -print \
 | sed 's/\(xkb_symbols.*\)"/\1+custom(remote)"/' \
 | xkbcomp -I/tmp/xkb -i $remote_id -synch - $DISPLAY 2>/dev/null

Затем отправьте его (вы можете добавить его в свой .xinitrc). Все сделано! Теперь нажатие клавиш должно генерировать желаемый вывод только для указанного вами устройства.

Изменить : Недавно я заметил, что по какой-то причине новая конфигурация не применяется сразу. Сначала необходимо нажать клавишу на другой клавиатуре, а затем проверить настроенные клавиши на измененной клавиатуре. Я не знаю, почему это происходит, может быть, какой-то кеш.

Watcom
источник
Позвольте мне попробовать это в понедельник, когда я вернусь к компьютеру, где я использую эту клавиатуру.
FUZxxl
1
а) sed -n 's/.*G19 Gaming Keyboard.*id=\([0-9]*\).*keyboard.*/\1/p' в) Да, вам обязательно нужно сначала проверить его, заменив $remote_idего идентификатором. Обратите внимание, что там есть две ссылки $remote_id, вы изменили обе?
Watcom
1
Да, и при тестировании жестко запрограммированного $remote_idкода обязательно закомментируйте строку, [ "$remote_id" ] || exitесли вы еще этого не сделали, иначе она просто вылетит.
Watcom
1
@ stats-hb $9не сработает, ты имел ввиду 9?
Watcom
1
Это работает для меня lampjs.wordpress.com/2015/06/26/...
usil
6

Для всех, кто приезжает сюда из Google и хочет получить ответ, более соответствующий тому, на что изначально надеялся спрашивающий, мне известны два способа переназначения событий на evdevуровне, чтобы изменение относилось ко всем приложениям:

  1. udev предоставляет API для изменения записей аппаратной базы данных, которые управляют отображениями между кодами сканирования и кодами клавиш. Эта страница ArchiWiki , которая содержит инструкции, прямо говорит, что она будет работать как для X11, так и для ввода с консоли.

    Суть заключается в том, что вы создаете пользовательскую запись, в /etc/udev/hwdb.d/которой содержатся шаблон сопоставления устройств и некоторые определения повторного сопоставления кода скан-кода, а затем запускаетесь, systemd-hwdb updateчтобы перестроить базу данных и udevadm triggerприменить ее без перезагрузки.

  2. Учитывая, что Wayland не использует клавиатурную подсистему X11, а основные композиторы Wayland, такие как GNOME Shell и Weston, не реализуют пользовательские интерфейсы для настройки соответствующих аспектов libinput, кто-то написал демон с именем evdevremapkeys, который решает проблему аналогично драйверу пространства пользователя G15Daemon для Logitech. G15 игровые клавиатуры.

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

ssokolow
источник
Я прихожу сюда с DuckDuckGo, но все равно спасибо за ответ (:
sm4rk0
0

Для тех, кто не справился с опцией @Watcom, просто добавьте новый файл сопоставления, например:

xkb_symbols "remote" {
    key <KP5>  { [ KP_Right, KP_6, U2192, U21D2 ]       };
    key <I129> { [ KP_Down, KP_2, U2193, U21D3 ]       };
    key <AD12> { [ KP_Up, KP_8, U2191, U21D1 ]  };
    key <LFSH> { [ Control_L ]        };
};

в / usr / share / X11 / xkb / symbols / как root (ubuntu, может отличаться для вашего дистрибутива), назовите файл «custom». Запросите текущую строку макета с помощью setxkbmap -device <device id> -print | grep xkb_symbolsи добавьте +customк ней. Установите новый макет с переназначенными ключами и измененной строкой макета:

setxkbmap -device <device id> -layout "us+ru:2+us:3+inet(evdev)+capslock(grouplock)+custom"

Эффект не является постоянным и, к сожалению, сбрасывается при подключении другой клавиатуры, пока не понял, как это исправить. Вы можете добавить указанную выше команду к своему устройству .bashrc, поэтому при перезапуске ключи меняются местами.

eviltnan
источник