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>



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

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.

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

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 

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

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


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.