Tag: Teclado USB

Defina layouts de teclado separados para seu laptops com um teclado USB externo

Imagine este cenário: você tem um laptop com um teclado layout US que usa diariamente em sua mesa de escritório em casa. Vários dias por semana, você trabalha no escritório da empresa, que tem uma configuração agradável com duas telas extras, um mouse e um teclado. Tudo parece bem até você começar a digitar e ver caracteres estranhos aparecendo — com “z” em vez de “y”. Você percebe que o teclado da sua mesa tem um layout DE! “Sem problema”, você pensa, “vou apenas instalar um novo layout de teclado e alterná-lo quando estiver no escritório.” Simples o suficiente, até você desconectar seu laptop para uma reunião: troca de layout necessária. De volta à sua mesa: outra troca. Dez minutos depois, você está em outra sala com um teclado USB diferente — desta vez com layout US. E justamente quando você configurou tudo corretamente enquanto conectado, você precisa digitar no teclado do laptop!

Este cenário pode se tornar frustrante com o tempo. No entanto, você pode evitar essas dores de cabeça aproveitando a flexibilidade do Linux para automatizar o processo, eliminando a necessidade de gerenciá-lo manualmente.

Veja como configurei meu sistema para corresponder automaticamente o layout do teclado a qualquer teclado que esteja em uso. Minha configuração atual é:

  • Dell Latitude 5530 (layout US-int)
  • Teclado USB: Roccat Vulcan Pro TKL (layout DE)
  • Linux Mint 22.11 Cinnamon, Kernel 6.8.0-53-generic”

TL;DR

Vá para o meu github, copie todos os arquivos e execute o script de instalação. Ele fará tudo para você:
https://github.com/felipeheuer/usb_kb_layout

Script de detecção de teclado e alteração de layout

Identifique o nome do seu teclado USB.

$ xinput -list | grep "keyboard"
⎣ Virtual core keyboard                   	id=3	[master keyboard (2)]
    ↳ Virtual core XTEST keyboard             	id=5	[slave  keyboard (3)]
...
    ↳ ROCCAT ROCCAT Vulcan Pro TKL Consumer Control	id=12	[slave  keyboard (3)]
    ↳ ROCCAT ROCCAT Vulcan Pro TKL            	id=13	[slave  keyboard (3)]
    ↳ ROCCAT ROCCAT Vulcan Pro TKL            	id=14	[slave  keyboard (3)]
    ↳ ROCCAT ROCCAT Vulcan Pro TKL System Control	id=15	[slave  keyboard (3)]

Anote o nome do seu teclado (ignore as entradas com ‘Control’ no nome).

Certifique-se de que todos os arquivos e pastas que você criar aqui sejam de propriedade do root e tenham as permissões de execução adequadas.

Crie um novo script em /opt/usb_kb_layout/usb_kb_layout.sh com o seguinte conteúdo. Lembre-se de atualizar os valores kb_model_usb, kb_layout_usb e user_name.

#!/bin/bash

# this script sets a new layout for the selected keyboard
# <https://github.com/felipeheuer/usb_kb_layout>

# !!! update the following lines with your keyboard and user information
kb_model_usb="ROCCAT Vulcan Pro TKL"
kb_layout_usb="-layout de -variant legacy"
user_name="username"
# !!! no need to update bellow this line

log_enable=1
log_file=/var/log/usb_kb_layout.log
script_file=$(basename "${BASH_SOURCE[0]}")
update_laptop_kb=1

function log() {
    if [ $log_enable -eq 1 ]; then
        echo "$(date) $1" >> "$log_file"
    fi
}

function get_kb_id() {
    xinput -list | grep "keyboard" | grep "${1}"| grep -v "Control" | sed -n "s/.*id=\\([0-9]*\\).*/\\1/p" | sort -nr
}

# ------ script start ------
for pid in $(pidof -x "${script_file}"); do
    if [ $pid != $$ ]; then
        # stop the script if it's already running
        exit 1
    fi
done

log "Start"
kb_model="Virtual core keyboard"
kb_layout="-layout us -variant intl"

DISPLAY=":0.0"
HOME=/home/$user_name
XAUTHORITY=$HOME/.Xauthority
export DISPLAY XAUTHORITY HOME

sleep 1s

usbkbd_id=$(get_kb_id "$kb_model_usb")
if [ "${usbkbd_id}" ]; then
    if [ $update_laptop_kb -eq 1 ]; then
        kb_laptop_id=$(get_kb_id "$kb_model")
        setxkbmap -verbose -device $kb_laptop_id $kb_layout
        log "${kb_model} updated with '${kb_layout}', id: $kb_laptop_id"
    fi

    for kb_id in $usbkbd_id; do
        if [ "${kb_id}" ]; then
            setxkbmap -verbose -device $kb_id $kb_layout_usb
            log "${kb_model_usb} updated with '${kb_layout_usb}', id: $kb_id"
        fi
    done
fi
log "Done"

exit 0

Embora o script funcione quando executado manualmente, você precisaria executá-lo cada vez que conectar seu teclado USB. Para automação completa, podemos usar o sistema udev para acionar o script automaticamente quando você conectar seu teclado. Usando os códigos de fornecedor e produto do dispositivo, podemos garantir que o script seja executado apenas quando seu teclado específico estiver conectado.

$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
...
Bus 003 Device 024: ID 1e7d:311a ROCCAT ROCCAT Vulcan Pro TKL

O código 1e7d:311a consiste em duas partes: o ID do fornecedor à esquerda e o ID do produto à direita.

Agora crie um novo arquivo de regra em /etc/udev/rules.d/99-usb-keyboard.rules

ATTRS{idVendor}=="1e7d", ATTRS{idProduct}=="311a", ACTION=="bind", OWNER="username", RUN+="/opt/usb_kb_layout/usb_kb_layout_wrapper.sh"

Atualize o arquivo de regra com os IDs de fornecedor e produto do seu dispositivo e seu nome de usuário (usando o mesmo nome de usuário do script anterior).

Observe que o parâmetro RUN não chama nosso script original diretamente, mas chama usb_kb_layout_wrapper. Este wrapper é necessário porque as regras udev exigem execução de script assíncrona. O wrapper chamará nosso script original com o parâmetro &. Crie este wrapper em /opt/usb_kb_layout/usb_kb_layout_wrapper.sh.

#!/bin/bash

# this is a wrapper script so udev can call the main script non-blocking
# <https://github.com/felipeheuer/usb_kb_layout>

/opt/usb_kb_layout/usb_kb_layout.sh &

Agora, toda vez que você conectar seu teclado USB, o script de atualização de layout será executado automaticamente.

Para automação completa, você também vai querer que o script seja executado quando você fizer login no sistema. Isso pode ser feito adicionando um script chamado start_usb_kb_layout.sh a /etc/profile.d/.

#!/bin/bash

# this is a startup script so your keyboard gets updated on boot
# <https://github.com/felipeheuer/usb_kb_layout>

if [ -f /opt/usb_kb_layout/usb_kb_layout_wrapper.sh ]; then
  . /opt/usb_kb_layout/usb_kb_layout_wrapper.sh
fi

Seus teclados agora devem estar funcionando com seus respectivos layouts, eliminando a necessidade de alternar manualmente as configurações de idioma do teclado do sistema.

Se você tiver algum problema, verifique o arquivo de log usado pelo script principal.

$ cat /var/log/usb_kb_layout.log
Fri Mar  7 08:15:26 CET 2025 Start
Fri Mar  7 08:15:27 CET 2025 Virtual core keyboard updated with '-layout us -variant intl', id: 3
Fri Mar  7 08:1

Esse post foi inspirado por uma pesquisa feita em diversos locais:

  1. https://askubuntu.com/questions/1414404/how-to-change-keyboard-layout-when-usb-keyboard-connected
  2. https://askubuntu.com/questions/337411/how-to-permanently-assign-a-different-keyboard-layout-to-a-usb-keyboard
  3. https://askubuntu.com/questions/337351/two-keyboards-two-language-layouts
  4. https://askubuntu.com/questions/337411/how-to-permanently-assign-a-different-keyboard-layout-to-a-usb-keyboard?noredirect=1&lq=1
  5. https://unix.stackexchange.com/questions/99085/save-setxkbmap-settings
  6. https://forum.endeavouros.com/t/unable-to-permanently-set-setxkbmap/34612/4
  7. https://gist.github.com/mierzejk/c71d9c110a74844a41906337d22caff6#file-setting-xinput-properties-of-pointing-devices-having-indistinct-names-md
  8. https://unix.stackexchange.com/questions/612686/udev-not-running-xinput-command-inside-script