Comment remapper des clés sous Linux pour un clavier spécifique uniquement

18

J'ai récemment acheté un clavier Unicomp qui vient avec les touches alt-right et Windows permutées. Le clavier identifie comme ceci sur lsusb:

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

Existe-t-il un moyen pour que le noyau (c'est-à-dire non basé sur xmodmap) permute les touches alt-droite et windows de sorte que chaque application les voit aux endroits échangés même si elles obtiennent une entrée de clavier brute (l'échange de trucs avec xmodmap ne fera pas cela) ? Existe-t-il un moyen de n'avoir cela que pour ce seul clavier?

FUZxxl
la source
Je soupçonne que vous pouvez le faire avec udev en faisant correspondre le numéro de série du clavier, puis en appelant un script qui effectue le remappage. Vous auriez probablement besoin d'un script similaire pour être appelé lors du détachement pour que l'appareil le remette.
jam
1
@jam Cela remapperait-il tous les claviers attachés? Je ne peux pas imaginer que Linux soit si rigide qu'il ne peut gérer qu'une seule table de mappage pour tous les claviers (USB) connectés.
FUZxxl
@jam De plus, vous m'aideriez vraiment si vous pouviez décrire comment effectuer le swapping. Je n'ai pas réussi à trouver quelque chose d'utile à ce sujet, seulement des trucs xmodmap (que je ne veux pas utiliser).
FUZxxl
Si vous ne voulez pas utiliser xmodmap, ce que vous demandez semble être trop spécifique à ma connaissance pour vous aider désolé. La méthode que j'ai proposée utiliserait xmodmap pour échanger les codes clés de ces touches pour tous les appareils, pour la durée de votre clavier spécifique, puis le remettre. Vous attendez-vous à utiliser simultanément plusieurs claviers?
jam
@jam Si j'utilisais Xmodmap, les programmes X verraient toujours les mauvais codes clés car le serveur X envoie également des codes clés non traduits au client. C'est important par exemple pour les jeux vidéo. Il est censé y avoir une solution dans le noyau qui ne me complique pas la vie avec des applications qui lisent les codes de scan.
FUZxxl

Réponses:

27

Oui, c'est possible en utilisant XKB. Contrairement à xmodmap, XKB peut remapper vos clés pour des appareils individuels.

Remarque: assurez-vous que vous avez xkbcomp> 1.2.0

Listez d'abord vos appareils avec:

xinput list

Vous obtiendrez quelque chose comme ceci:

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

Identifiez la chaîne de votre appareil et modifiez le script shell suivant, en changeant la ligne sed par celle qui correspond au nom de votre appareil. Modifiez ensuite les clés dont vous avez besoin remappées.

Exemple: Chargez xevet appuyez sur une touche que vous souhaitez remapper. Supposons que vous découvrez son code clé 84. Recherchez 84 dans https://gist.github.com/zoqaeski/3880640 . Le nom de la clé est là <KP5>. Recherchez ensuite la clé par laquelle vous souhaitez la remplacer (dans le même lien, plus loin ci-dessous ) et copiez ce qui est à l'intérieur des crochets. Répétez le processus pour toutes les clés souhaitées.

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

Puis sourcez-le (vous pouvez l'ajouter à votre .xinitrc). Terminé! Maintenant, appuyer sur les touches devrait générer la sortie souhaitée, uniquement pour le périphérique que vous avez spécifié.

Edit : Récemment, j'ai remarqué que, pour une raison quelconque, la nouvelle configuration n'est pas appliquée immédiatement. Vous devez d'abord appuyer sur une touche de votre autre clavier, puis tester les touches configurées sur votre clavier modifié. Je ne sais pas pourquoi cela se produit, peut-être une sorte de cache.

Watcom
la source
Permettez-moi d'essayer ce lundi lorsque je reviens à l'ordinateur où j'utilise ce clavier.
FUZxxl
1
a) sed -n 's/.*G19 Gaming Keyboard.*id=\([0-9]*\).*keyboard.*/\1/p' c) Oui, vous devez absolument le tester avant de le remplacer $remote_idpar le numéro d'identification. Notez qu'il y a deux références à $remote_idcela, avez-vous changé les deux?
Watcom
1
Oh, et lorsque vous testez le codé en dur $remote_id, assurez-vous de commenter la ligne [ "$remote_id" ] || exitsi vous ne l'avez pas déjà fait, sinon elle se renflouera.
Watcom
1
@ stats-hb $9ne fonctionnera pas, vous vouliez dire 9?
Watcom
1
cela fonctionne pour moi lampjs.wordpress.com/2015/06/26/…
usil
6

Pour tous ceux qui viennent ici de Google et veulent une réponse plus conforme à ce que le questionneur espérait à l'origine, je suis conscient de deux façons de remapper les événements au evdevniveau afin que le changement s'applique à toutes les applications:

  1. udev fournit une API pour modifier les entrées de la base de données matérielle qui contrôlent les mappages entre scancodes et keycodes. Cette page ArchiWiki , qui contient des instructions, dit explicitement que cela fonctionnera pour les entrées X11 et console.

    L'essentiel est que vous créez une entrée personnalisée dans /etc/udev/hwdb.d/laquelle se compose d'un modèle de correspondance de périphérique et de quelques définitions de remappage scancode-to-keycode, puis exécutez systemd-hwdb updatepour reconstruire la base de données et l' udevadm triggerappliquer sans redémarrage.

  2. Étant donné que Wayland n'utilise pas le sous-système de clavier de X11 et que les principaux compositeurs Wayland comme GNOME Shell et Weston n'implémentent pas d'interfaces utilisateur pour configurer les aspects pertinents de libinput, quelqu'un a écrit un démon nommé evdevremapkeys qui résout le problème de la même manière que le pilote d'espace utilisateur G15Daemon pour Logitech Claviers de jeu G15.

    (Il avale les événements qu'il a l'intention de remapper, donc rien d'autre qui écoute sur l'appareil ne peut les voir, puis émet les événements corrigés via l' uinputAPI pour créer des périphériques d'entrée au niveau du noyau à partir de l'espace utilisateur.)

ssokolow
la source
Je viens ici de DuckDuckGo, mais merci pour la réponse quand même (:
sm4rk0
0

Pour ceux qui n'ont pas réussi avec l'option @Watcom, mettez simplement votre nouveau fichier de mappage, smth comme:

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 / symboles / comme peut-être root (ubuntu, peut différer pour votre distribution), appelez le fichier 'custom'. Demandez votre chaîne de disposition actuelle avec setxkbmap -device <device id> -print | grep xkb_symbolset ajoutez +custom-la. Définissez une nouvelle disposition avec des clés remappées et une chaîne de disposition modifiée:

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

L'effet n'est pas permanent et se réinitialise malheureusement lorsqu'un autre clavier est connecté, n'a pas encore trouvé comment le réparer. Vous pouvez cependant ajouter la commande ci-dessus à votre .bashrc, afin que les clés soient échangées au redémarrage si nécessaire.

eviltnan
la source