(O script desenvolvido neste post pode ser encontrado aqui.)
Em um episódio anterior deste blog, vimos como usar o xmodmap para alterar o keymap do X. Também vimos que embora o xmodmap seja muito mais simples de usar do que o XKB, ele está semi-obsoleto e não lida muito bem com certos recursos mais modernos do XKB. Recentemente eu descobri mais um: o xmodmap não funciona direito com múltiplos teclados (e.g., um teclado builtin de notebook e um teclado externo). Especificamente:
Sendo assim, temos dois problemas a resolver: detectar quando um teclado é conectado (o que independe de usarmos xmodmap ou XKB), e atribuir um layout a ele (o que exige o XKB se quisermos usar um layout específico para cada teclado; se quisermos apenas propagar o layout corrente para o novo teclado, podemos usar o xmodmap).
A maneira mais palatável que eu encontrei de detectar o teclado* é monitorando o arquivo de log do X (/var/log/Xorg.n.log, onde n é o número do display). As linhas relevantes do arquivo têm a forma:
[ 10848.216] (II) XINPUT: Adding extended input device "GASIA GASIA USB KB Pro" (type: KEYBOARD)
Podemos fazer um script que monitora esse arquivo com o comando tail -f, filtra apenas os dados que nos interessam, e fica em um laço aguardando que novas linhas sejam escritas no arquivo:
#!/bin/bash [[ $DISPLAY == :* ]] || echo "$0: Oops, remote display?" >&2 display="${DISPLAY##*:}" display="${display%%.*}" logfile="/var/log/Xorg.$display.log" tail -n +1 -f "$logfile" | sed -une 's/.*XINPUT: Adding extended input device "\([^"]*\)" (type: \([^)]*\)).*/\2\t\1/p' | while IFS=$'\t' read type name; do echo "Dispositivo detectado: $name" # comandos... done
Salve esse script em algum local apropriado (e.g., ~/bin/xinput-monitor) e dê-lhe permissão de execução (chmod +x ~/bin/xinput-monitor). Você pode executá-lo como está para testar se os dispositivos estão sendo realmente detectados (experimente conectar um teclado externo com o script rodando).
A opção -n +1 faz com que o tail imprima o conteúdo do arquivo desde a primeira linha antes de começar a monitorá-lo; isso faz com que o script "detecte" mesmo os dispositivos que já estavam conectados antes de ele rodar. Se você não desejar esse comportamento, pode trocar o -n +1 por -n 0.
Se tudo o que você quer é rodar o xmodmap (ou qualquer outro comando) quando um dispositivo é conectado, basta colocar o comando no trecho indicado no while. Feito isso, basta pôr o script para rodar na inicialização de seu ambiente gráfico (colocando uma linha do tipo ~/bin/xinput-monitor & no seu ~/.xinitrc ou ~/.xsession, ou em algum arquivo de configuração do seu ambiente gráfico favorito).
Note que nem todos os dispositivos listados são teclados (nem mesmo todos os dispositivos com type: KEYBOARD são teclados); se você não quiser executar o xmodmap uma vez para cada um desses dispositivos (o que em tese é inofensivo, mas nunca se sabe), você pode usar um if ou case para ignorar os dispositivos que não lhe interessam. Por exemplo:
... while IFS=$'\t' read type name; do echo "Dispositivo detectado: $name" case "$name" in 'Power Button'|'Video Bus'|'Integrated Webcam'|*'Synaptics'*) # Não faz nada. ;; *) # Os comandos que desejamos executar quando um teclado é conectado. xmodmap ~/.xmodmaprc xset r rate 250 xkbset exp =m ;; esac done
Para atribuir um layout individual para cada teclado conectado, teremos que abandonar o bom[citation needed] e velho xmodmap e entrar no maravilhoso[dubious – discuss] mundo do XKB. Felizmente, usar um layout pronto com o XKB é bem simples: basta executar um comando como:
# Layout ABNT-2. setxkbmap -device device_id br abnt2 # Layout US internacional (com acentos). setxkbmap -device device_id us intl
A opção -device device_id indica qual teclado o comando deve afetar. Se ela não for especificada, o comando afeta todos os teclados.
O grande problema é determinar o device_id de cada teclado; ele pode variar dependendo dos dispositivos presentes e da ordem em que o X os encontra. Aparentemente o id não aparece no arquivo de log do X. A solução é usar o xinput (que vem no pacote xinput no Debian, Ubuntu e companhia), um comando que permite ver e modificar diversas configurações de dispositivos de entrada no X (tais como os dez mil parâmetros que controlam velocidade, aceleração, gestures e outras firulas de touchpads), entre outras coisas. O comando xinput list produz uma listagem dos dispositivos presentes e respectivos ids, com a seguinte cara:
# xinput list ⎡ Virtual core pointer \tid=2\t[master pointer (3)] ⎜ ↳ Virtual core XTEST pointer \tid=4\t[slave pointer (2)] ⎜ ↳ SynPS/2 Synaptics TouchPad \tid=13\t[slave pointer (2)] ⎜ ↳ GASIA GASIA USB KB Pro \tid=10\t[slave pointer (2)] ⎣ Virtual core keyboard \tid=3\t[master keyboard (2)] ↳ Virtual core XTEST keyboard \tid=5\t[slave keyboard (3)] ↳ Power Button \tid=6\t[slave keyboard (3)] ↳ Video Bus \tid=7\t[slave keyboard (3)] ↳ Power Button \tid=8\t[slave keyboard (3)] ↳ Integrated Webcam \tid=11\t[slave keyboard (3)] ↳ AT Translated Set 2 keyboard \tid=12\t[slave keyboard (3)] ↳ GASIA GASIA USB KB Pro \tid=9\t[slave keyboard (3)]
(Os \t representam TABs.)
Um problema visível nessa saída é que pode haver mais de um dispositivo com o mesmo nome (temos dois Power Button e dois GASIA GASIA USB KB Pro (sendo que um deles é um mouse (!))). Como chamar o setxkbmap sobre um não-teclado parece não ter efeito algum, podemos simplesmente tentar os dois ids e nos darmos por satisfeitos.
O primeiro passo é obter os ids a partir dos nomes. Para isso, podemos recorrer ao sed:
device_ids="$(xinput list | sed -n "s|.*↳ $name *\tid=\([^\t]*\)\t.*|\1|p")"
Com os ids à mão, basta executar o setxkbmap para cada id, usando os parâmetros apropriados dependendo do nome do dispositivo detectado (altere as cláusulas do case para "configurar" o script para os seus teclados e layouts):
for id in $device_ids; do case "$name" in 'AT Translated Set 2 keyboard') setxkbmap -device "$id" us intl ;; 'Some weird keyboard') setxkbmap -device "$id" is ;; *) setxkbmap -device "$id" br abnt2 ;; esac done
E era isso. Eis uma versão completa do script. Ficou faltando resolver o problema de portar um xmodmaprc personalizado (caso você tenha um) para o XKB, mas isso fica para um próximo post.
(Este foi o 100-ésimo post do blog, por sinal.)
____
* Outra maneira freqüentemente citada pelo povo da Internet é alterar as configurações do udev para rodar um script quando o teclado é conectado. Além de exigir direitos de root, o script vai ter que descobrir o nome que o X atribui ao teclado por vodu, vai rodar como root (a menos que você tome a precaução de fazer o script trocar para o usuário "dono" da sessão X, o que implica descobrir quem é o dono), e você vai ter que tomar precauções para o caso de haver mais de um display X rodando (por exemplo, se você estiver usando a função "trocar de usuário" de certos ambientes gráficos). Just say no.
Copyright © 2010-2024 Vítor De Araújo
O conteúdo deste blog, a menos que de outra forma especificado, pode ser utilizado segundo os termos da licença Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International.
Powered by Blognir.