Jak na stałe przypisać inny układ klawiatury do klawiatury USB?

16

Często podłączam klawiaturę USB do laptopa (oprócz zewnętrznego monitora i myszy, które praktycznie konwertują mojego laptopa na komputer stacjonarny) i wolę wtedy używać innego układu klawiatury.

Muszę ręcznie zmieniać bieżący układ klawiatury za każdym razem, gdy podłączam tę klawiaturę USB.

I chciałbym użyć do tego zautomatyzowanego sposobu, jeśli to możliwe.

Odpowiedź Radu na pytanie tutaj daje pewne wskazówki, ale wydaje się, że będę potrzebować skryptu uruchamiania do tego zadania, ponieważ identyfikator urządzenia dla mojej klawiatury USB zmienia się przy każdym uruchomieniu komputera.

Ten skrypt startowy prawdopodobnie najpierw będzie zawierał polecenie xinput -list | grep "USB Keyboard", a następnie inne polecenie, aby pobrać pierwszy wyświetlany numer identyfikacyjny klawiatury USB, a następnie użyć go w ostatnim poleceniu, aby ustawić mój wybrany układ dla tej klawiatury USB, jak poniżej:

setxkbmap -device <NUMBER> -layout <LAYOUT>

Sadi
źródło
1
@Sadi Czy masz na myśli odwrócenie flag Rutgers i USA do góry nogami po zabójstwie dr Martina Luthera Kinga? Paul Robeson: The Great Forerunner by Freedomways na stronie 182
guest271314
@ guest271314 Wielkie dzięki! Ale zastanawiam się, jak to się stało, że skomentowałeś to pytanie: history.stackexchange.com/questions/48704/... ;-) Jest to również kolejna sprytna forma protestu, ale nie sądzę, że może to ostatecznie przekształcić się w historia słyszenia, którą pamiętam.
Sadi
@Sadi Twoje pytanie zostało usunięte z Politics.
guest271314,

Odpowiedzi:

15

Po krótkich badaniach znalazłem rozwiązanie, chociaż wciąż jestem otwarty na inne (prawdopodobnie lepsze) odpowiedzi.

Oto skrypt startowy (który można dodać do aplikacji startowych ), który ustawi wprowadzoną ręcznie zmienną usbkbd_layout na identyfikatory urządzeń usbkbd znajdujące się na liście xinput :

#!/bin/bash
usbkbd=`xinput -list | grep -c "USB Keyboard"`
if [[ "$usbkbd" -gt 0 ]]
then
    usbkbd_ids=`xinput -list | grep "USB Keyboard" | awk -F'=' '{print $2}' | cut -c 1-2`
    usbkbd_layout="tr(f)"
    for ID in $usbkbd_ids
    do
      setxkbmap -device "${ID}" -layout "${usbkbd_layout}"
    done
fi
exit 0

Ten skrypt jest bardzo przydatny (i bardziej stabilny) w scenariuszach, w których użytkownik zaczyna korzystać z laptopa na komputerze stacjonarnym (z zewnętrzną klawiaturą, myszą i monitorem itp.), A także może być uruchamiany ręcznie za każdym razem, gdy podłączana jest zewnętrzna klawiatura USB ...

================================================== ========================

LEPSZE (prawie idealne) ROZWIĄZANIE - znalezione dzięki MinimusHeximus i odpowiednim autorom wątku, o którym wspominał w komentarzu poniżej:

Teraz mogę po prostu podłączyć klawiaturę USB i automatycznie zastosować inny układ klawiatury (TR-F) przy jednoczesnym zachowaniu domyślnego układu klawiatury (TR-Q) na moim laptopie!

Oto pliki i ich zawartość, które umożliwiają:

/etc/udev/rules.d/00-usb-keyboard.rules

ATTRS{idVendor}=="09da", ATTRS{idProduct}=="0260", OWNER="sadi"
ACTION=="add", RUN+="/home/sadi/.bin/usb-keyboard-in_udev"
ACTION=="remove", RUN+="/home/sadi/.bin/usb-keyboard-out_udev"

/home/sadi/.bin/usb-keyboard-in_udev

#!/bin/bash
/home/sadi/.bin/usb-keyboard-in &

/home/sadi/.bin/usb-keyboard-in

#!/bin/bash
sleep 1
DISPLAY=":0.0"
HOME=/home/sadi/
XAUTHORITY=$HOME/.Xauthority
export DISPLAY XAUTHORITY HOME
usbkbd_id=`xinput -list | grep "USB Keyboard" | awk -F'=' '{print $2}' | cut -c 1-2 | head -1`
usbkbd_layout="tr(f)"
if [ "${usbkbd_id}" ]; then
    gsettings set org.gnome.settings-daemon.plugins.keyboard active false
    sleep 2
    setxkbmap -device "${usbkbd_id}" -layout "${usbkbd_layout}"
fi

/home/sadi/.bin/usb-keyboard-out_udev

#!/bin/bash
/home/sadi/.bin/usb-keyboard-out &

/home/sadi/.bin/usb-keyboard-out

#!/bin/bash
sleep 1
DISPLAY=":0.0"
HOME=/home/sadi/
XAUTHORITY=$HOME/.Xauthority
export DISPLAY XAUTHORITY HOME
gsettings set org.gnome.settings-daemon.plugins.keyboard active true

Uwagi:

  1. Oczywiście wszystkie cztery pliki w folderze „bin” powinny mieć niezbędne uprawnienia (czytelne i wykonywalne), które mogą być zaimplementowane na przykład za pomocą polecenia Terminal, takiego jak chmod - 755 /home/sadi/.bin/usb-keyboard-*
  2. Czasami po podłączeniu klawiatury USB nadal używa tego samego (domyślnego) układu klawiatury i przełącza się na określony układ przy drugiej próbie (być może wymaga to trochę więcej czasu na sen?)
  3. Układ klawiatury USB nie działa na ekranie logowania (po wylogowaniu).
  4. Jeśli używasz osobnej partycji dla / home , lepszym pomysłem może być umieszczenie czterech skryptów gdzieś w partycji głównej, np. / Usr / local / bin i odpowiednio zmodyfikowanie zawartości wszystkich odpowiednich plików, ponieważ czasami udev może poszukać te pliki przed zamontowaniem partycji / home i powodują problemy.

ABY DOSTOSOWAĆ TE USTAWIENIE DO RÓŻNYCH WYMAGAŃ:

  1. Klawiatura USB i dostawcy produktów identyfikatory powinny zostać zmienione zgodnie z wyjściem polecenia lsusb(Na przykład, mój lsusbwyjściowy ma to dla mojego USB Keyboard: Bus 001 Device 006: ID 09da:0260 A4 Tech Co., Ltd)
  2. WŁAŚCICIEL i wszystkie nazwy katalogów użytkowników należy zmienić z „sadi” na inną nazwę
  3. Identyfikator usbkbd_id może wymagać niewielkiej regulacji, aby pobrać poprawny identyfikator urządzenia (na przykład dane wyjściowe poleceń xinput -list | grep "USB Keyboard"dają mi dwie linie; ↳ USB Keyboard id=14 [slave keyboard (3)]i ↳ USB Keyboard id=16 [slave keyboard (3)]; które są następnie filtrowane za awkpomocą „=” jako separatora pola i przechwytywania drugiej części; następnie wycinanie tylko pierwsze dwie cyfry, a następnie używając tylko wartości w pierwszym wierszu)
  4. Wartością usbkbd_layout może być dowolny inny prawidłowy wybór
Sadi
źródło
Byłoby wspaniale, gdyby inny podobny skrypt mógł się automatycznie uruchamiać za każdym razem, gdy podłączona jest klawiatura USB, zgodnie z pytaniem (jeszcze nie odpowiedziano) tutaj: askubuntu.com/questions/284224/...
Sadi
2
Może być pomocne, jeśli możesz opublikować inną odpowiedź z tego niechlujnego wątku: superuser.com/questions/249064/…
nano - scal mnie
1
@MinimusHeximus Thanks a milion !!! Po przejrzeniu wątku, który wskazałeś i zrobieniu prób i błędów, w końcu go uporządkowałem i dodam to nowe (prawie) idealne rozwiązanie do podłączania na gorąco powyżej!
Sadi,
1
Moja klawiatura z jakiegoś powodu ma dwa identyfikatory, więc zamiast używać IFmusiałem użyć FOR. Działa dla mnie teraz, dziękuję! gist.github.com/zvictor/193b567c14b5b6a679fe
zVictor
1
@Sadi Sam jestem zwykłym przeciętnym użytkownikiem. Zamieszczę tutaj moje rozwiązanie. Może uda ci się z tego zrezygnować.
kleinfreund
9

W sterowniku udev można określić opcje sterownika X11, nie są wymagane żadne niestandardowe skrypty. Jako przykład, oto zawartość mojego /etc/udev/rules.d/99-usb-kbd.rules

ACTION=="add", ATTRS{idVendor}=="04d9", ATTRS{idProduct}=="2323", ENV{XKBMODEL}="pc104", ENV{XKBLAYOUT}="us", ENV{XKBVARIANT}="euro", ENV{XKBOPTIONS}="compose:caps"

Ta reguła zapewnia, że ​​określona klawiatura USB korzysta z amerykańskiego układu w Xorg (wewnętrzna klawiatura mojego laptopa jest niemiecka, a to także mój podstawowy układ). Ważne punkty:

  1. Można dowiedzieć się, idVendori idProductz urządzeniem za pomocą lsusblubevtest
  2. Możesz użyć dowolnego układu z /usr/share/X11/xkb/symbols. Zwróć uwagę, aby określić zarówno poprawny układ, jak i prawidłowy wariant.
  3. Nazwa pliku musi zaczynać się cyfrą> 64, aby ustawienia mogły zastąpić ustawienia systemowe określone w /lib/udev/rules.d/64-xorg-xkb.rules
  4. Upewnij się, że zarządzanie układem Gnome / KDE nie nadpisuje twoich ustawień.
pavel
źródło
Odłącz i ponownie podłącz klawiaturę i poszukaj /var/log/Xorg.0.logmożliwych problemów. Możesz także użyć udevadm infodo sprawdzenia, czy ustawienia zostały zastosowane poprawnie.
pavel
Eureka! Smart rozwiązanie rozpoczął pracę dopiero po wszedłem tej komendy (raz na zawsze), aby zastąpić bieżące ustawienie gconf: gsettings set org.gnome.settings-daemon.plugins.keyboard active false. Jeśli również dodać taką notatkę, postaram się oznaczyć je jako na odpowiedź (zamiast tego niezdarny, długa i kręta droga ;-)
Sadi
To jest wyjątkowe. W systemie Ubuntu 14.04 możliwe modele / układy / opcje / itp. są wymienione w/usr/share/X11/xkb/rules/evdev.lst
Jon
2
Niestety to miłe i łatwe rozwiązanie przestało działać po aktualizacji do Ubuntu Gnome 17.04 :-(
Sadi
Próbowałem Linux Mint 18.2, który jest oparty na Ubuntu 16.04 LTS, z udev w wersji 229-4ubuntu19 , bez efektu :-( Wszelkie pomysły na temat tego dziwnego zachowania udev ???
Sadi
2

Właśnie ulepszyłem to rozwiązanie dla klawiatury bépo Typematrix (francuska wersja zoptymalizowanego doskonałego dvoraka) oraz w szerokim kontekście systemowym (zakłada, że ​​masz dostęp do roota do komputera). Do działania potrzebne są tylko 3 pliki. Możesz sprawdzić plik dziennika w przypadku, gdy nie dowiesz się, co się nie powiedzie.

/etc/udev/96-usb-keyboard.rules

ATTRS{idVendor}=="1e54", ATTRS{idProduct}=="2030", SUBSYSTEMS=="usb", ACTION=="add", RUN+="/etc/udev/bepo-typematrix-kbd.sh in"
ATTRS{idVendor}=="1e54", ATTRS{idProduct}=="2030", SUBSYSTEMS=="usb", ACTION=="remove", RUN+="/etc/udev/bepo-typematrix-kbd.sh out"

/etc/udev/bepo-typematrix-kbd.sh (absolutnie konieczne, aby użyć pośredniego skryptu tła)

#!/bin/bash

dir=$(dirname $0)
command=$(basename $0)
command=$dir/${command%\.sh}
arg=$1 # must be "in" or "out"
LOG=/var/log/bepo-typematrix-kbd.log

[ -x "$command" ] && $command $arg >$LOG 2>&1 &

/ etc / udev / bepo-typematrix-kbd

#!/bin/bash
# jp dot ayanides at free.fr

MODEL="tm2030USB-102" # keyboard model
DISPLAY=':0.0'
GSETTING=/usr/bin/gsettings
XSET=/usr/bin/xset
SETXKBMAP=/usr/bin/setxkbmap
XINPUT=/usr/bin/xinput

USER=$(/usr/bin/who | /usr/bin/awk -v DIS=':0' '{if ($2==DIS) print $1}')
eval HOME=~$USER
XAUTHORITY=$HOME/.Xauthority
export DISPLAY XAUTHORITY HOME

case $1 in
        'in')
                BEPO=$($XINPUT list --short | grep "TypeMatrix.com USB Keyboard" | grep keyboard | sed -e 's/^.*id=\([0-9]\+\).*/\1/g')
                if [ -n "$BEPO" ]; then
                        [ -x $GSETTING ] && $GSETTING set org.gnome.settings-daemon.plugins.keyboard active false
                        # apparently nothing to do with TDE (trinity KDE)
                        for ID in $BEPO; do # case of multiple bepo keyboard is taken into account
                                [ -x $SETXKBMAP ] && $SETXKBMAP -device $ID -model $MODEL -layout fr -variant bepo
                        done
                fi
                echo "bépo keyboard id(s) is (are) $BEPO"
                [ -x $XSET ] && $XSET -display $DISPLAY r rate 250 40
        ;;
        'out')
                # apparently nothing to do with TDE (trinity KDE)
                [ -x $GSETTING ] && $GSETTING set org.gnome.settings-daemon.plugins.keyboard active true
        ;;
        *)
                printf "wrong parameter: $1\n"
                exit 1
        ;;
esac
JP Ayanidès
źródło
1

Po tym, jak dużo się bawiłem, właśnie na to teraz biegnę. Może napiszę pełny artykuł i opublikuję kod w repozytorium, jeśli byłoby to interesujące.


Skonfiguruj nowy zestaw reguł dla udev w ten sposób:

 sudo gedit /etc/udev/rules.d/80-external-keyboard.rules

Reguła ma wywoływać skrypt powłoki za każdym razem, gdy jakieś działanie zostanie uruchomione przez urządzenie z podaną kombinacją dostawcy i identyfikatora produktu.

ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="4042", RUN+="/home/phil/.bin/switch-kb-layout-wrapper.sh"

Po dodaniu nowego zestawu reguł uruchom ponownie usługę udev:

sudo service udev restart

Uwaga: nie byłem w stanie osiągnąć wiarygodnych wyników, podając bardziej szczegółowe reguły dopasowania w tym pliku. Co najważniejsze, dodanie ACTIONreguły dopasowania nie działało. O ile wiem, skrypt i tak został uruchomiony. Podczas dodawania ACTION=="add"skrypt nadal będzie wywoływany po usunięciu urządzenia. Bardzo dziwne i mylące.

Jednak akcja, która uruchomiła regułę udev, będzie dostępna dla wywoływanego skryptu, jak pokazano poniżej.


Następnie sam skrypt. Cóż, niezupełnie. Zwróć uwagę na wrapperprzyrostek w nazwie pliku. Oznacza to, że nie jest to rzeczywisty skrypt, ale opakowanie, które wywołuje skrypt i wykonuje go w tle, aby udev mógł zakończyć proces.

~/.bin/switch-kb-layout-wrapper.sh:

#!/bin/sh
/home/phil/.bin/switch-kb-layout.sh "${ACTION}" &

Zmienna ACTIONzawiera akcję udev uruchomioną przez urządzenie. Zwraca wartości takie jak add(urządzenie zostało podłączone) i remove(urządzenie zostało usunięte). Wykorzystamy je później.

~/.bin/switch-kb-layout.sh:

#!/bin/sh

sleep 1

# Some environment variables that need to be set in order to run `setxkbmap`
DISPLAY=":0.0"
HOME=/home/phil
XAUTHORITY=$HOME/.Xauthority
export DISPLAY XAUTHORITY HOME

udev_action=$1
log_file="$HOME/switch-kb-layout.log"

if [ "${udev_action}" != "add" ] && [ "${udev_action}" != "remove" ]; then
    echo "Other action. Aborting." >> $log_file
    exit 1
fi

internal_kb_layout="de"
internal_kb_variant=""

external_kb_layout="us"
external_kb_variant="altgr-intl"

kb_layout=""
kb_variant=""

if [ "${udev_action}" = "add" ]; then
    kb_layout=$external_kb_layout
    kb_variant=$external_kb_variant
elif [ "${udev_action}" = "remove" ]; then
    kb_layout=$internal_kb_layout
    kb_variant=$internal_kb_variant
fi

setxkbmap -layout "${kb_layout}"
echo "set layout:" "$kb_layout" >> $log_file
if [ ! -z "${kb_variant}" ]; then
    setxkbmap -variant "${kb_variant}"
    echo "set variant:" "$kb_variant" >> $log_file
fi

Zastąp moją nazwę użytkownika swoją nazwą podczas ustawiania HOMEzmiennej ( $(whoami)tutaj nie będzie działać, ponieważ nie będzie ona wywoływana przez użytkownika, ale przez root).

sed -i "s/phil/YOUR_USERNAME/g" ~/.bin/switch-kb-layout.sh

Do celów testowych dodałem kilka wierszy rejestrujących określone zdarzenia do pliku w moim katalogu domowym, aby sprawdzić, czy wszystko działa. Możesz je łatwo usunąć.


Wreszcie skrypty te muszą mieć uprawnienia do wykonywania. Warto również pamiętać, że skrypty te będą wywoływane przez rootużytkownika, więc uważaj, co tam robisz.

chmod +x ~/.bin/switch-kb-layout-wrapper.sh ~/.bin/switch-kb-layout.sh 
kleinfreund
źródło
1
Dzięki, świetna robota! Mam to również działające. Jednak dlaczego 14 razy widzę „Dodaj akcję” i 3 razy „Inna akcja”, kiedy podłączę moją zewnętrzną komendę, jest zagadką, którą spróbuję rozwiązać później. Odkryłem jednak, że lepiej jest również dodać identyfikator urządzenia do polecenia setxkbmap, aby klawiatura wewnętrzna była nadal użyteczna, podobnie jak klawiatura zewnętrzna, jak w moim ostatnim skrypcie autostartup. Spróbuję tego przez kilka dni i wrócę i zobaczę, czy twoje można uznać za odpowiedź, być może z małą modyfikacją tu i tam ;-)
Sadi
Również uzyskiwanie tych samych zalogowanych linii wiele razy. Dobry chwyt identyfikatora urządzenia w poleceniu.
kleinfreund
@Sadi Również myślę, że linia gsettings set org.gnome.settings-daemon.plugins.keyboard active falsenie działa zgodnie z przeznaczeniem, ponieważ skrypt jest uruchamiany przez root. W moich testach linia nie miała wpływu na to ustawienie.
kleinfreund
Myślę, że w takim scenariuszu dobrym pomysłem może być wykonanie polecenia gsettings set org.gnome.settings-daemon.plugins.keyboard active falsejako użytkownik raz na zawsze, a następnie użycie tego skryptu bez gsettings setpoleceń ...
Sadi
Do tej pory widziałem, że nadal nie możemy sprawnie działać; od czasu do czasu układ klawiatury nie jest wdrażany przez udev, a ty musisz się podłączyć i podłączyć ponownie. Myślę, że jeszcze przez jakiś czas wrócę do (zaktualizowanego) skryptu startowego u góry mojej odpowiedzi, co służy mi bardziej płynnie - tylko muszę go uruchomić ręcznie, jeśli podłączę zewnętrzną klawiaturę po uruchomieniu. Wygląda na to, że udev jest trochę błędny, co widać również w wielu powtórzeniach akcji (uruchamia skrypt otoki wiele razy i w dziwny sposób) ...
Sadi
1

Miałem problem z uprawnieniami do skryptu wykonanego przez udev. Rozwiązałem sudo w następujący sposób:

# Estract id of MX3 keyboard devices that present themself as "123 COM Smart Control"
    IDLIST=$(sudo -u max /usr/bin/xinput -list | grep "123 COM Smart Control" | grep keyboard | sed -e 's/^.*id=\([0-9]\+\).*/\1/g')

Ustaw mapę klawiatury dla każdego urządzenia

    for ID in $IDLIST; do
            sudo -u max /usr/bin/setxkbmap -device $ID -layout "${kb_layout}" -display :0
    done
użytkownik835020
źródło
Myślę, że to może być bardziej przydatne, jeśli możesz napisać to w całości. Na przykład, gdzie umieściłeś powyższe linie?
Sadi
0

Możesz go również zdefiniować w pliku konfiguracyjnym Xorg.

Jest on ułożony w tej odpowiedzi wymiany stosu: /superuser//a/946575/437492

Golar Ramblar
źródło
Byłoby wspaniale, gdybym mógł uruchomić. Ale używając najnowszej wersji LTS, Ubuntu 18.04, widzę tylko katalog /usr/share/X11/xorg.conf.d/, który zawiera plik o nazwie 40-libinput.conf . W tym pliku po prostu dodałem sekcję klawiatury zewnętrznej. Używając sterownika libinput lub evdev oraz dłuższej i krótszej nazwy dostawcy, nie mogłem uzyskać żadnego wyniku. Jakieś pomysły?
Sadi
@Sadi: Jeśli przeczytasz trochę o konfiguracji Xorg, zorientujesz się, że możesz po prostu dodać nowe pliki /etc/X11/xorg.conf.d/(to jest miejsce, do którego należy się udać).
Golar Ramblar
Dzięki. Z pewnością sporo przeczytałem i najpierw spróbowałem użyć „/etc/X11/xorg.conf.d/30-keyboard.conf”. Spróbuję szczęścia pod wspomnianą wyżej odpowiedzią wymiany stosów. ;-)
Sadi