Como remapear teclas no Linux apenas para um teclado específico

17

Recentemente, comprei um teclado Unicomp que vem com as teclas right-alt e Windows trocadas. O teclado se identifica assim em lsusb:

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

Existe uma maneira de fazer com que o kernel (ou seja, não baseado no xmodmap) troque as teclas right-alt e windows para que cada aplicativo as veja nos locais trocados, mesmo que recebam entrada bruta do teclado (trocar coisas com o xmodmap não fará isso) ? Existe uma maneira de ter isso apenas para este teclado?

FUZxxl
fonte
Eu suspeito que você poderia fazer isso com o udev combinando o número de série do teclado e depois chamando um script que faz o remapeamento. Você provavelmente precisaria de um script semelhante para ser chamado de desanexação para que o dispositivo o recoloque.
jam
11
@jam Isso remapearia todos os teclados conectados? Não consigo imaginar que o Linux seja tão inflexível que possa gerenciar apenas uma tabela de mapeamento para todos os teclados conectados (USB).
FUZxxl
@jam Além disso, você realmente me ajudaria se pudesse descrever como fazer a troca real. Eu não consegui encontrar nada útil sobre isso, apenas coisas xmodmap (que eu não quero usar).
FUZxxl
Se você não quiser usar o xmodmap, o que você está pedindo parece ser específico demais para o meu conhecimento, para ajudá-lo a se desculpar. O método que propus usaria o xmodmap para trocar os códigos de teclas por todas as chaves em todos os dispositivos, durante o tempo em que seu teclado específico estiver conectado e depois devolvê-lo. Você espera usar vários teclados simultaneamente?
jam
@jam Se eu usasse o Xmodmap, os programas X ainda veriam os códigos de chave errados, pois o servidor X também envia códigos de chave não traduzidos para o cliente. Isso é importante, por exemplo, para videogames. Supõe-se que haja uma solução no kernel que não torne minha vida mais complicada com aplicativos que leem códigos de verificação.
precisa saber é o seguinte

Respostas:

27

Sim, é possível usando o XKB. Diferentemente do xmodmap, o XKB pode remapear suas chaves para dispositivos individuais.

Nota: Verifique se você possui o xkbcomp> 1.2.0

Primeiro, liste seus dispositivos com:

xinput list

Você obterá algo como isto:

⎡ 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)]

Identifique a string do seu dispositivo e edite o seguinte script de shell, alterando a linha sed por uma que se encaixe no nome do seu dispositivo. Em seguida, altere as teclas necessárias para remapear.

Exemplo: Carregue xeve pressione a tecla que deseja remapear. Suponha que você descubra o código-chave 84. Pesquise 84 em https://gist.github.com/zoqaeski/3880640 . O nome da chave existe <KP5>. Em seguida, procure a chave pela qual você deseja que ela seja substituída (no mesmo link, mais abaixo ) e copie o que está dentro dos colchetes. Repita o processo para todas as chaves que você deseja.

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

Em seguida, faça a fonte (você pode adicioná-lo ao seu .xinitrc). Tudo feito! Agora, pressionar as teclas deve gerar a saída desejada, apenas para o dispositivo que você especificou.

Edit : Recentemente, notei que, por algum motivo, a nova configuração não é aplicada imediatamente. Você deve primeiro pressionar uma tecla no outro teclado e testar as teclas configuradas no teclado modificado. Não sei por que isso acontece, talvez algum tipo de cache.

Watcom
fonte
Deixe-me tentar na segunda-feira quando voltar ao computador em que uso este teclado.
FUZxxl
11
a) sed -n 's/.*G19 Gaming Keyboard.*id=\([0-9]*\).*keyboard.*/\1/p' c) Sim, você definitivamente deve testá-lo primeiro substituindo $remote_idpelo número de identificação. Observe que existem duas referências a $remote_idisso, você mudou as duas?
Watcom
11
Ah, e ao testar o código codificado $remote_id, certifique-se de comentar a linha, [ "$remote_id" ] || exitcaso ainda não a tenha, caso contrário ela será liberada.
Watcom
11
@ stats-hb $9não funcionará, você quis dizer 9?
Watcom
11
isso funciona para mim lampjs.wordpress.com/2015/06/26/…
usil
6

Para quem está vindo do Google e quer uma resposta mais alinhada com o que o questionador esperava originalmente, conheço duas maneiras de remapear eventos no evdevnível para que a alteração se aplique a todos os aplicativos:

  1. O udev fornece uma API para modificar as entradas do banco de dados de hardware que controlam os mapeamentos entre scancodes e keycodes. Esta página do ArchiWiki , que contém instruções, diz explicitamente que funcionará tanto para o X11 quanto para a entrada do console.

    A essência é que você cria uma entrada personalizada na /etc/udev/hwdb.d/qual consiste em um padrão de correspondência de dispositivo e algumas definições de remapeamento de scancode para keycode, depois executa systemd-hwdb updatepara reconstruir o banco de dados e udevadm triggeraplicá-lo sem reinicialização.

  2. Como o Wayland não usa o subsistema de teclado do X11 e os principais compositores do Wayland, como o GNOME Shell e o Weston, não implementam interfaces de usuário para configurar os aspectos relevantes da libinput, alguém escreveu um daemon chamado evdevremapkeys que resolve o problema de maneira semelhante ao driver de espaço de usuário G15Daemon da Logitech Teclados para jogos G15.

    (Ele engole os eventos que pretende remapear, para que mais ninguém escute no dispositivo possa vê-los, emite os eventos corrigidos por meio da uinputAPI para criar dispositivos de entrada no nível do kernel a partir do espaço do usuário.)

ssokolow
fonte
Estou vindo aqui do DuckDuckGo, mas obrigado pela resposta de qualquer maneira (:
sm4rk0
0

Para aqueles que não tiveram sucesso com a opção @Watcom, basta colocar seu novo arquivo de mapeamento, como:

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 ]        };
};

para / usr / share / X11 / xkb / symbols / como talvez root (ubuntu, pode ser diferente para o seu distrib), chame o arquivo de 'custom'. Peça sua string de layout atual setxkbmap -device <device id> -print | grep xkb_symbolse adicione- +customa. Defina um novo layout com chaves remapeadas e uma sequência de layout modificada:

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

O efeito não é permanente e, infelizmente, é redefinido quando outro teclado está conectado, ainda não se sabe como corrigi-lo. Você pode adicionar o comando acima ao seu .bashrc, para que as chaves sejam trocadas na reinicialização, se necessário.

eviltnan
fonte