Como atribuir permanentemente um layout de teclado diferente a um teclado USB?

16

Costumo plugar um teclado USB no meu laptop (além do monitor e mouse externos, que virtualmente convertem meu laptop em um computador de mesa) e prefiro usar um layout de teclado diferente.

Eu tenho que alterar manualmente o layout do teclado atual cada vez que plugo este teclado USB.

E eu gostaria de usar uma maneira automatizada para isso, se possível.

A resposta de Radu à pergunta aqui fornece algumas pistas, mas parece que vou precisar de um script de inicialização para esta tarefa, pois o ID do dispositivo do meu teclado USB muda sempre que o computador é iniciado.

Esse script de inicialização provavelmente incluirá primeiro o comando xinput -list | grep "USB Keyboard"e outro comando para pegar o primeiro número de ID do teclado USB exibido e depois usá-lo no comando final para definir o layout escolhido para o teclado USB, conforme abaixo:

setxkbmap -device <NUMBER> -layout <LAYOUT>

Sadi
fonte
11
@Sadi Você está se referindo a virar as bandeiras dos Rutgers e dos EUA de cabeça para baixo após o assassinato do Dr. Martin Luther King? Paul Robeson: The Great Forerunner por Freedomways na página 182
guest271314
@ guest271314 Muito obrigado! Mas eu me pergunto por que você acabou aqui para comentar esta pergunta: history.stackexchange.com/questions/48704/… ;-) Essa também é outra forma inteligente de protesto, mas não acho que isso possa eventualmente evoluir para o história boatos que eu me lembro.
Sadi
@Sadi Sua pergunta foi excluída no Politics.
guest271314

Respostas:

15

Depois de um pouco de pesquisa, encontrei uma solução, embora ainda esteja aberto a outras respostas (provavelmente melhores).

Aqui está um script de inicialização (que pode ser adicionado a aplicativos de inicialização ) que irá definir o maually entrou usbkbd_layout variável para o usbkbd dispositivo id constatada s na -list 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

Esse script é bastante útil (e mais estável) para cenários em que o usuário começa a usar o laptop em uma configuração de área de trabalho (com teclado, mouse e monitor externos etc.) e também pode ser executado manualmente sempre que o teclado USB externo estiver conectado ...

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

A MELHOR (quase perfeita) SOLUÇÃO - encontrada graças ao MinimusHeximus e aos respectivos colaboradores do tópico que ele mencionou em seu comentário abaixo:

Agora posso apenas conectar meu teclado USB e aplicar automaticamente seu layout de teclado (TR-F) diferente, mantendo o layout de teclado padrão (TR-Q) no meu laptop!

Aqui estão os arquivos e seu conteúdo que tornam isso possível:

/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

Notas:

  1. Obviamente, todos os quatro arquivos na sua pasta. "Bin" devem ter as permissões necessárias (legíveis e executáveis) que talvez sejam implementadas, por exemplo, com um comando Terminal como chmod - 755 /home/sadi/.bin/usb-keyboard-*
  2. Às vezes, depois que o teclado USB é conectado, ele ainda usa o mesmo layout de teclado (padrão) e muda para o layout especificado na segunda tentativa (talvez exigindo um pouco mais de tempo de sono em algum lugar?)
  3. O layout específico do teclado USB não é eficaz na tela de login (quando você faz logout).
  4. Se você usar uma partição separada para / home , poderá ser uma idéia melhor colocar os quatro scripts em algum lugar da partição raiz, por exemplo, / usr / local / bin e modificar o conteúdo de todos os respectivos arquivos de acordo, pois às vezes o udev pode procurar esses arquivos antes de sua partição / home ser montada e causar problemas.

PARA ADAPTAR ESTA CONFIGURAÇÃO A DIFERENTES REQUISITOS:

  1. Teclado USB de fornecedores e produtos ids deve ser alterado de acordo com a saída do comando lsusb(Por exemplo, a minha lsusbsaída tem isso para o meu teclado USB: Bus 001 Device 006: ID 09da:0260 A4 Tech Co., Ltd)
  2. PROPRIETÁRIO e todos os nomes de diretório de usuário devem ser alterados de "sadi" para outro nome
  3. O usbkbd_id pode exigir um pequeno ajuste para obter a identificação correta do dispositivo (por exemplo, a saída dos comandos xinput -list | grep "USB Keyboard"me fornece duas linhas; ↳ USB Keyboard id=14 [slave keyboard (3)]e ↳ USB Keyboard id=16 [slave keyboard (3)]; que são filtradas awkusando "=" como delimitador de campo e capturando a segunda parte; depois cortando apenas o dois primeiros dígitos e, em seguida, usando apenas o valor na primeira linha)
  4. O valor para usbkbd_layout pode ser qualquer outra opção válida
Sadi
fonte
Seria ótimo se outro script semelhante poderia funcionar automaticamente sempre que um teclado USB é conectado, tal como solicitado (ainda não respondeu) aqui: askubuntu.com/questions/284224/...
Sadi
2
Ele pode ser útil se você pode enviar outra resposta fora deste segmento confuso: superuser.com/questions/249064/...
user126106
11
@MinimusHeximus Thanks a million !!! Depois de analisar o tópico que você apontou e fazer algumas tentativas e erros, finalmente resolvi e adicionarei esta nova (quase) solução perfeita de hotplugging acima!
Sadi
11
Meu teclado, por algum motivo, tem dois IDs; portanto, em vez de usar um IF, tive que usar um FOR. Funciona para mim agora, obrigado! gist.github.com/zvictor/193b567c14b5b6a679fe
zVictor
11
@ Sadi Eu sou um mero usuário comum. Vou postar minha solução aqui. Talvez você possa tirar algumas idéias disso.
22417 kleinfreund
9

Pode-se especificar as opções do driver X11 dentro da regra do udev, nenhum script personalizado é necessário. Como exemplo, aqui está o conteúdo de minhas /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"

Essa regra garante que um teclado USB específico use o layout dos EUA no Xorg (o teclado interno do meu laptop é alemão e esse também é o meu layout principal). Pontos importantes:

  1. Você pode descobrir idVendore idProductdo seu dispositivo usando lsusbouevtest
  2. Você pode usar qualquer layout a partir de /usr/share/X11/xkb/symbols. Preste atenção para especificar um layout válido e uma variante válida.
  3. O nome do arquivo deve começar com um número> 64 para que as configurações substituam as configurações gerais do sistema especificadas em /lib/udev/rules.d/64-xorg-xkb.rules
  4. Certifique-se de que o gerenciamento de layout do Gnome / KDE não substitua suas configurações.
pavel
fonte
Desconecte e reconecte o teclado e procure /var/log/Xorg.0.logpossíveis problemas. Você também pode usar udevadm infopara verificar se as configurações foram aplicadas corretamente.
Pavel
Eureka! Sua solução inteligente começou a trabalhar somente depois entrei este comando (uma vez por todas) para substituir a configuração gconf atual: gsettings set org.gnome.settings-daemon.plugins.keyboard active false. Se você também adicionar essa nota, eu vou tentar marcar o seu como a resposta (em vez de que desajeitado, estrada longa e sinuosa ;-)
Sadi
Isto é excepcional. No Ubuntu 14.04, os possíveis modelos / layouts / opções / etc. estão listados em/usr/share/X11/xkb/rules/evdev.lst
Jon
2
Infelizmente, este agradável e fácil solução parou de trabalhar para mim após a atualização para o Ubuntu Gnome 17,04 :-(
Sadi
Tentei o Linux Mint 18.2, que é baseado no Ubuntu 16.04 LTS, com a versão 229-4ubuntu19 do udev , sem efeito novamente :-( Alguma idéia sobre esse comportamento estranho do udev ???
Sadi
2

Acabei de melhorar esta solução para um teclado bépo Typematrix (versão francesa do excelente dvorak otimizado) e em um amplo contexto do sistema (supõe-se que você tenha acesso root à máquina). Ele precisa de apenas 3 arquivos para funcionar. Você pode consultar um arquivo de log em caso de falha para descobrir o que está falhando.

/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 (absolutamente necessário para usar um script de segundo plano intermediário)

#!/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
fonte
1

Depois de mexer bastante, é para isso que eu tenho agora. Talvez eu escreva um artigo completo e publique o código em um repositório, se isso for interessante.


Configure um novo conjunto de regras para o udev assim:

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

A regra deve chamar um script de shell sempre que alguma ação é acionada por um dispositivo com a combinação fornecida de fornecedor e ID do produto.

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

Após adicionar o novo conjunto de regras, reinicie o serviço udev:

sudo service udev restart

Nota: Não consegui obter resultados confiáveis ​​fornecendo regras de correspondência mais específicas nesse arquivo. Mais significativamente, a adição de uma ACTIONregra de correspondência não funcionou. Até onde eu sei, o script foi acionado de qualquer maneira. Ao adicionar ACTION=="add", o script ainda seria chamado ao remover o dispositivo. Muito estranho e confuso.

No entanto, a ação que acionou a regra do udev estará disponível para o script chamado, como mostrado abaixo.


Em seguida, o próprio script. Bem, não exatamente. Anote o wrappersufixo no nome do arquivo. Isso indica que esse não é o script real, mas um wrapper que chama o script e o executa em segundo plano para que o udev possa concluir seu processo.

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

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

A variável ACTIONcontém a ação do udev que foi acionada pelo dispositivo. Ele gera valores como add(o dispositivo foi conectado) e remove(o dispositivo foi removido). Nós os usaremos mais tarde.

~/.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

Substitua meu nome de usuário pelo seu ao definir a HOMEvariável ( $(whoami)não funcionará aqui, pois isso não será chamado pelo usuário, mas por root).

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

Para fins de teste, adicionei algumas linhas que registram determinados eventos em um arquivo no meu diretório pessoal para ver se tudo funciona. Você pode removê-los com segurança.


Finalmente, esses scripts precisam ter permissões de execução. Também pode ser importante observar que esses scripts serão chamados pelo rootusuário, portanto, tenha cuidado com o que você faz lá.

chmod +x ~/.bin/switch-kb-layout-wrapper.sh ~/.bin/switch-kb-layout.sh 
Kleinfreund
fonte
11
Obrigado, ótimo trabalho! Eu tenho que trabalhar também. No entanto, por que vejo 14 vezes "Adicionar ação" e 3 vezes "Outra ação" quando plugo meu comando externo é um mistério, que tentarei resolver mais tarde. Mas descobri que é melhor adicionar também o ID do dispositivo ao comando setxkbmap para que o teclado interno ainda seja utilizável e o teclado externo, como no meu último script de inicialização automática. Vou tentar dar um presente para um par de dias, e voltar e ver se o seu pode ser considerado como a resposta, talvez com uma pequena modificação aqui e ali ;-)
Sadi
Também obtendo as mesmas linhas registradas várias vezes. Boa captura do ID do dispositivo no comando.
22417 kleinfreund
@ Sadi Também acho que a linha gsettings set org.gnome.settings-daemon.plugins.keyboard active falsenão funciona como pretendido, pois o script é executado root. Nos meus testes, a linha não teve efeito sobre essa configuração.
Kleinfreund
Eu acho que no cenário tal, pode ser uma boa idéia para executar o comando gsettings set org.gnome.settings-daemon.plugins.keyboard active falsecomo usuário de uma vez por todas, e, em seguida, usar esse script sem os gsettings setcomandos ...
Sadi
Até agora, vi que ainda não conseguimos fazer isso funcionar sem problemas; de tempos em tempos, o layout do teclado não está sendo implementado pelo udev, e você deve desconectá-lo e conectá-lo novamente. Acho que voltarei ao meu script de inicialização (atualizado) na parte superior da minha resposta novamente por algum tempo, o que me serve mais tranqüilamente - só preciso executá-lo manualmente se conectar o teclado externo após a inicialização. Parece udev é um pouco buggy como também pode ser visto em tantas repetições de ação (que está a executar o script wrapper muitas vezes, e de forma estranha) ...
Sadi
1

Eu tive algum problema de permissão com o script executado pelo udev. Eu resolvi com o sudo da seguinte maneira:

# 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')

Defina o mapa do teclado para cada dispositivo

    for ID in $IDLIST; do
            sudo -u max /usr/bin/setxkbmap -device $ID -layout "${kb_layout}" -display :0
    done
user835020
fonte
Eu acho que pode ser mais útil se você puder escrever na íntegra. Por exemplo, onde você colocou as linhas acima?
Sadi
0

Você também pode defini-lo em um arquivo de configuração do Xorg.

É apresentado nesta resposta de stackexchange: /superuser//a/946575/437492

Golar Ramblar
fonte
Seria ótimo se eu conseguisse fazer funcionar. Mas, usando a versão mais recente do LTS, Ubuntu 18.04, só consigo ver o diretório /usr/share/X11/xorg.conf.d/ , que contém um arquivo chamado 40-libinput.conf . Então, simplesmente adicionei uma seção para o teclado externo nesse arquivo. Usando o libinput do driver ou evdev e um nome de fornecedor mais longo e mais curto, não obtive nenhum resultado. Alguma ideia?
Sadi
@Sadi: Se você ler um pouco sobre a configuração do Xorg, descobrirá que pode simplesmente adicionar novos arquivos /etc/X11/xorg.conf.d/(esse é o lugar para você).
Golar Ramblar
Obrigado. Eu certamente li bastante e tentei primeiro usar o "/etc/X11/xorg.conf.d/30-keyboard.conf". Vou tentar a minha sorte com a resposta stackexchange mencionada acima. ;-)
Sadi