Jak ponownie przypisać klawisze w systemie Linux tylko dla określonej klawiatury

18

Niedawno kupiłem klawiaturę Unicomp, która jest dostarczana z zamienionymi klawiszami right-alt i klawiszami Windows. Klawiatura identyfikuje się w następujący sposób na lsusb:

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

Czy istnieje sposób, aby jądro (tj. Nie oparte na xmodmap) zamieniało klawisze right-alt i Windows, aby każda aplikacja widziała je w zamienionych miejscach, nawet jeśli otrzymają surowe dane z klawiatury (zamiana rzeczy za pomocą xmodmap tego nie zrobi) ? Czy istnieje sposób, aby mieć to tylko dla tej jednej klawiatury?

FUZxxl
źródło
Podejrzewam, że możesz to zrobić za pomocą udev, dopasowując numer seryjny klawiatury, a następnie wywołując skrypt, który dokonuje mapowania. Prawdopodobnie potrzebujesz podobnego skryptu, aby zostać wywołanym przy odłączaniu, aby urządzenie mogło go przywrócić.
dżem
1
@jam Czy to zmieni mapowanie wszystkich dołączonych klawiatur? Nie mogę sobie wyobrazić, że Linux jest tak nieelastyczny, że może zarządzać tylko jedną tabelą mapowania dla wszystkich dołączonych klawiatur (USB).
FUZxxl
@jam Naprawdę byś mi pomógł, gdybyś mógł opisać, w jaki sposób dokonać faktycznej zamiany. Nie udało mi się znaleźć na tym nic przydatnego, tylko rzeczy xmodmap (których nie chcę używać).
FUZxxl
Jeśli nie chcesz korzystać z Xmodmap, to, o co pytasz, wydaje się zbyt szczegółowe dla mojej wiedzy, aby ci pomóc. Zaproponowana przeze mnie metoda użyłaby xmodmap do zamiany kodów klawiszy dla tych klawiszy dla wszystkich urządzeń, na czas podłączania określonej klawiatury, a następnie odłożenia jej z powrotem. Czy spodziewasz się, że będziesz używać wielu klawiatur jednocześnie?
jam
@jam Gdybym użył Xmodmap, programy X nadal widziałyby nieprawidłowe kody klawiszy, ponieważ serwer X również wysyła nieprzetłumaczone kody kluczy do klienta. Dotyczy to na przykład gier wideo. W jądrze powinno znajdować się rozwiązanie, które nie komplikuje mojego życia dzięki aplikacjom odczytującym kody skanowania.
FUZxxl,

Odpowiedzi:

27

Tak, jest to możliwe przy użyciu XKB. W przeciwieństwie do xmodmap, XKB może mapować klucze dla poszczególnych urządzeń.

Uwaga: Upewnij się, że masz xkbcomp> 1.2.0

Najpierw wypisz swoje urządzenia za pomocą:

xinput list

Otrzymasz coś takiego:

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

Zidentyfikuj ciąg urządzenia i edytuj poniższy skrypt powłoki, zmieniając linię sed na taką, która pasuje do nazwy twojego urządzenia. Następnie zmień klucze, które musisz ponownie przypisać.

Przykład: Załaduj xevi naciśnij klawisz, który chcesz ponownie przypisać. Załóżmy, że dowiadujesz się, że jest to kod 84. Wyszukaj 84 w https://gist.github.com/zoqaeski/3880640 . Jest tam kluczowa nazwa <KP5>. Następnie wyszukaj klucz, który chcesz zastąpić (w tym samym linku, dalej poniżej ) i skopiuj to, co jest w nawiasach. Powtórz proces dla wszystkich wymaganych kluczy.

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

Następnie zdobądź go (możesz dodać go do swojego .xinitrc). Wszystko gotowe! Teraz naciśnięcie klawiszy powinno wygenerować pożądane wyjście, tylko dla określonego urządzenia.

Edycja : Ostatnio zauważyłem, że z jakiegoś powodu nowa konfiguracja nie jest stosowana natychmiast. Najpierw musisz nacisnąć klawisz na drugiej klawiaturze, a następnie przetestować skonfigurowane klawisze na zmodyfikowanej klawiaturze. Nie wiem, dlaczego tak się dzieje, może jakiś bufor.

Watcom
źródło
Pozwól mi spróbować w poniedziałek, kiedy wrócę do komputera, na którym używam tej klawiatury.
FUZxxl,
1
a) sed -n 's/.*G19 Gaming Keyboard.*id=\([0-9]*\).*keyboard.*/\1/p' c) Tak, zdecydowanie powinieneś najpierw przetestować, zastępując $remote_idgo numerem identyfikacyjnym. Uwaga: są tam dwa odniesienia $remote_id, czy zmieniłeś oba?
Watcom,
1
Aha, a podczas testowania zakodowanego na stałe $remote_id, upewnij się, że skomentowałeś linię, [ "$remote_id" ] || exitjeśli jeszcze tego nie zrobiłeś, po prostu wyskoczy.
Watcom,
1
@ stats-hb $9nie będzie działać, miałeś na myśli 9?
Watcom,
1
to działa dla mnie lampjs.wordpress.com/2015/06/26/…
usil
6

Dla każdego, kto przychodzi tutaj z Google i chce odpowiedzi bardziej zgodnej z tym, czego pierwotnie oczekiwał pytający, znam dwa sposoby ponownego mapowania zdarzeń na evdevpoziomie, aby zmiana dotyczyła wszystkich aplikacji:

  1. udev zapewnia interfejs API do modyfikowania wpisów w bazie danych sprzętu, które kontrolują odwzorowania między scancodes i kodami klawiszy. Ta strona ArchiWiki , która zawiera instrukcje, wyraźnie mówi, że będzie działać zarówno dla X11, jak i konsoli.

    Istotą jest utworzenie niestandardowego wpisu, w /etc/udev/hwdb.d/którego skład wchodzą wzorzec dopasowania urządzenia i niektóre definicje odwzorowania kodu scancode-na-keycode, a następnie uruchomić, systemd-hwdb updateaby odbudować bazę danych i udevadm triggerzastosować ją bez ponownego uruchamiania.

  2. Biorąc pod uwagę, że Wayland nie używa podsystemu klawiatury X11, a główne komponenty Wayland, takie jak GNOME Shell i Weston, nie implementują interfejsów użytkownika w celu skonfigurowania odpowiednich aspektów libinput, ktoś napisał demona o nazwie evdevremapkeys, który rozwiązuje problem podobnie do sterownika przestrzeni użytkownika G15Daemon dla Logitech Klawiatury do gier G15.

    (Przełyka zdarzenia, które zamierza ponownie odwzorować, więc nic innego nasłuchującego na urządzeniu ich nie widzi, a następnie emituje poprawione zdarzenia za pośrednictwem uinputinterfejsu API do tworzenia urządzeń wejściowych na poziomie jądra z przestrzeni użytkownika).

ssokolow
źródło
Idę tutaj z DuckDuckGo, ale i tak dziękuję za odpowiedź (:
sm4rk0
0

Dla tych, którym się nie udało z opcją @Watcom, po prostu włóż nowy plik mapowania, coś w stylu:

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

do / usr / share / X11 / xkb / symbols / jak może root (ubuntu, może różnić się w zależności od dystrybucji), nazwij plik „niestandardowy”. Zapytaj o bieżący ciąg układu za pomocą setxkbmap -device <device id> -print | grep xkb_symbolsi dodaj +customdo niego. Ustaw nowy układ za pomocą mapowanych klawiszy i zmodyfikowanego ciągu układu:

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

Efekt nie jest trwały i niestety resetuje się, gdy podłączona jest inna klawiatura, jeszcze nie wymyśliłem, jak to naprawić. Możesz dodać powyższe polecenie do swojego .bashrc, więc klucze są zamieniane przy ponownym uruchomieniu, jeśli to konieczne.

eviltnan
źródło