¿Cómo asignar permanentemente un diseño de teclado diferente a un teclado USB?

16

A menudo conecto un teclado USB a mi computadora portátil (además del monitor externo y el mouse, que prácticamente convierten mi computadora portátil en una computadora de escritorio) y prefiero usar una distribución de teclado diferente.

Tengo que cambiar manualmente la distribución actual del teclado cada vez que conecto este teclado USB.

Y me gustaría utilizar una forma automatizada para esto, si es posible.

La respuesta de Radu a la pregunta aquí da algunas pistas, pero parece que necesitaré un script de inicio para esta tarea, ya que la identificación del dispositivo para mi teclado USB cambia cada vez que se inicia la computadora.

Este script de inicio probablemente incluirá primero el comando xinput -list | grep "USB Keyboard", y otro comando para tomar el primer número de identificación del teclado USB que se muestra y luego usarlo en el comando final para configurar mi diseño elegido para ese teclado USB de la siguiente manera:

setxkbmap -device <NUMBER> -layout <LAYOUT>

Sadi
fuente
1
@Sadi ¿Te refieres a voltear los Rutgers y las banderas de los Estados Unidos después del asesinato del Dr. Martin Luther King? Paul Robeson: The Great Forerunner por Freedomways en la página 182
invitado271314
@ guest271314 Muchas gracias! Pero me pregunto cómo es que terminaste aquí para comentar esta pregunta: history.stackexchange.com/questions/48704/… ;-) Esta también es otra forma inteligente de protesta, pero no creo que esto pueda eventualmente evolucionar hacia historia de oídas que recuerdo.
Sadi
@Sadi Su pregunta se eliminó en Política.
invitado271314

Respuestas:

15

Después de un poco de investigación, he encontrado una solución, aunque todavía estoy abierto a otras respuestas (probablemente mejores).

He aquí un script de inicio (que se puede añadir a aplicaciones de inicio ) que establecerá el introducida maually usbkbd_layout variable al usbkbd dispositivo de Identificación encontrado s en el -lista 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

Este script es bastante útil (y más estable) para escenarios en los que el usuario comienza a usar la computadora portátil en una configuración de escritorio (con teclado, mouse y monitor externos, etc.), y también se puede ejecutar manualmente cada vez que se conecta el teclado USB externo ...

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

LA MEJOR SOLUCIÓN (casi perfecta): encontrada gracias a MinimusHeximus y los respectivos contribuyentes al hilo que mencionó en su comentario a continuación:

¡Ahora solo puedo conectar mi teclado USB y aplicar automáticamente su diseño de teclado diferente (TR-F) mientras sigo manteniendo el diseño de teclado predeterminado (TR-Q) en mi computadora portátil!

Aquí están los archivos y sus contenidos que lo hacen posible:

/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. Por supuesto, los cuatro archivos en su carpeta "bin" deben tener los permisos necesarios (legibles y ejecutables) que pueden implementarse, por ejemplo, con un comando de Terminal como chmod - 755 /home/sadi/.bin/usb-keyboard-*
  2. A veces, después de enchufar el teclado USB, todavía usa la misma distribución de teclado (predeterminada) y cambia a la distribución especificada en el segundo intento (¿tal vez requiera un poco más de tiempo de reposo en alguna parte?)
  3. El diseño específico del teclado USB no es efectivo en la pantalla de inicio de sesión (cuando cierra sesión).
  4. Si usa una partición separada para / home , podría ser una mejor idea colocar los cuatro scripts en algún lugar de la partición raíz, por ejemplo / usr / local / bin y modificar el contenido de todos los archivos respectivos en consecuencia, ya que a veces puede buscar udev esos archivos antes de que se monte su partición / home y causen problemas.

PARA ADAPTAR ESTA CONFIGURACIÓN A DIFERENTES REQUISITOS:

  1. Teclado USB de proveedores de productos y los identificadores deben ser cambiados de acuerdo con el resultado del comando lsusb(por ejemplo, mi lsusbsalida tiene esto para mi teclado USB: Bus 001 Device 006: ID 09da:0260 A4 Tech Co., Ltd)
  2. PROPIETARIO y todos los nombres de directorio de usuarios deben cambiarse de "sadi" a otro nombre
  3. El usbkbd_id puede requerir un pequeño ajuste para tomar la identificación correcta del dispositivo (por ejemplo, la salida de los comandos xinput -list | grep "USB Keyboard"me da dos líneas; ↳ USB Keyboard id=14 [slave keyboard (3)]y ↳ USB Keyboard id=16 [slave keyboard (3)]; que luego se filtran awkusando "=" como delimitador de campo y capturando la segunda parte; luego cortando solo la primeros dos dígitos, y luego usando solo el valor en la primera línea)
  4. El valor de usbkbd_layout puede ser cualquier otra opción válida
Sadi
fuente
Sería genial si otro script similar pudiera ejecutarse automáticamente cada vez que se enchufa un teclado USB, como se preguntó (aún no se ha respondido) aquí: askubuntu.com/questions/284224/…
Sadi
2
Puede ser útil si puede publicar otra respuesta de este hilo desordenado: superuser.com/questions/249064/…
nano - fusionarme
1
@MinimusHeximus ¡Un millón de gracias! Después de pasar por el hilo que ha señalado y hacer un poco de prueba y error, finalmente lo resolví y agregaré esta nueva (casi) perfecta solución de conexión en caliente arriba.
Sadi
1
Mi teclado por alguna razón tiene dos identificaciones, lo que en lugar de usar una IFque tenía que usar una FOR. Me funciona ahora, gracias! gist.github.com/zvictor/193b567c14b5b6a679fe
zVictor
1
@Sadi Soy un simple usuario promedio. Publicaré mi solución aquí. Tal vez puedas sacar algunas ideas de eso.
kleinfreund
9

Se pueden especificar las opciones del controlador X11 dentro de la regla udev, no se necesitan scripts personalizados. Como ejemplo, aquí están los contenidos de mi /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"

Esta regla garantiza que un teclado USB en particular use un diseño estadounidense en Xorg (el teclado interno de mi computadora portátil es alemán, y este también es mi diseño principal). Puntos importantes:

  1. Puede averiguar idVendory idProductde su dispositivo usando lsusboevtest
  2. Puede usar cualquier diseño de /usr/share/X11/xkb/symbols. Preste atención para especificar tanto un diseño válido como una variante válida.
  3. El nombre del archivo debe comenzar con un número> 64 para que la configuración sobrescriba la configuración de todo el sistema especificada en /lib/udev/rules.d/64-xorg-xkb.rules
  4. Asegúrese de que la gestión de diseño de Gnome / KDE no sobrescriba su configuración.
pavel
fuente
Desenchufe y vuelva a enchufar su teclado y busque /var/log/Xorg.0.logposibles problemas. También puede usar udevadm infopara verificar que la configuración se aplique correctamente.
Pavel
Eureka! Su solución inteligente comenzó a trabajar sólo después de que entré en este comando (una vez por todas) para anular la configuración gconf actual: gsettings set org.gnome.settings-daemon.plugins.keyboard active false. Si también agrega una nota, trataré de marcar la suya como la respuesta (en lugar de ese camino torpe, largo y sinuoso ;-)
Sadi
Esto es excepcional En Ubuntu 14.04 los posibles modelos / diseños / opciones / etc. están listados en/usr/share/X11/xkb/rules/evdev.lst
Jon
2
Desafortunadamente, esta solución agradable y fácil dejó de funcionar para mí después de actualizar a Ubuntu Gnome 17.04 :-(
Sadi
Intenté Linux Mint 18.2, que se basa en Ubuntu 16.04 LTS, con udev versión 229-4ubuntu19 , sin efecto nuevamente :-( ¿ Alguna idea sobre este comportamiento extraño de udev ???
Sadi
2

Acabo de mejorar esta solución para un teclado bépo Typematrix (versión francesa de dvorak excelente optimizado) y en un contexto de sistema amplio (supone que tiene acceso de root a la máquina). Solo necesita 3 archivos para funcionar. Puede consultar un archivo de registro en caso de que no se dé cuenta de lo que está fallando.

/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 necesario para usar un script de fondo intermedio)

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

Después de jugar mucho, esto es lo que tengo corriendo por ahora. Tal vez escriba un artículo completo y publique el código dentro de un repositorio, si eso fuera de interés.


Configure un nuevo conjunto de reglas para udev así:

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

Se supone que la regla llama a un script de shell cada vez que un dispositivo activa alguna acción con la combinación dada de proveedor e ID de producto.

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

Después de agregar el nuevo conjunto de reglas, reinicie el servicio udev:

sudo service udev restart

Nota: No pude lograr resultados confiables al proporcionar reglas de coincidencia más específicas en ese archivo. Lo más significativo es que agregar una ACTIONregla coincidente no funcionó. Por lo que puedo decir, el script se activó de todos modos. Al agregar ACTION=="add", la secuencia de comandos aún se invocaría al quitar el dispositivo. Muy extraño y confuso.

Sin embargo, la acción que activó la regla udev estará disponible para el script llamado como se muestra a continuación.


A continuación, el guión en sí. Bueno, no del todo. Tenga wrapperen cuenta el sufijo en el nombre del archivo. Esto indica que este no es el script real sino un contenedor que llama al script y lo ejecuta en segundo plano para que udev pueda finalizar su proceso.

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

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

La variable ACTIONcontiene la acción udev que fue activada por el dispositivo. Produce valores como add(se conectó el dispositivo) y remove(se retiró el dispositivo). Los usaremos más adelante.

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

Reemplace mi nombre de usuario con el suyo al configurar la HOMEvariable ( $(whoami)no funcionará aquí, ya que no será invocado por su usuario sino por root).

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

Para fines de prueba, agregué algunas líneas que registran ciertos eventos en un archivo en mi directorio de inicio para ver si todo funciona. Puede guardarlos con seguridad.


Finalmente, estos scripts deben tener permisos de ejecución. También puede ser importante tener en cuenta que estos scripts serán llamados por el rootusuario, así que tenga cuidado con lo que hace allí.

chmod +x ~/.bin/switch-kb-layout-wrapper.sh ~/.bin/switch-kb-layout.sh 
Kleinfreund
fuente
1
Gracias, buen trabajo! Lo tengo funcionando también. Sin embargo, por qué veo 14 veces "Agregar acción" y 3 veces "Otra acción" cuando conecto mi comando externo es un misterio, que trataré de resolver más adelante. Pero descubrí que es mejor agregar también la ID del dispositivo al comando setxkbmap para que el teclado interno siga siendo utilizable, así como el teclado externo, como en mi último script de inicio automático. Lo intentaré durante un par de días, y volveré y veré si la tuya puede considerarse como LA respuesta, tal vez con una pequeña modificación aquí y allá ;-)
Sadi
También obteniendo las mismas líneas registradas varias veces. Buena captura en la identificación del dispositivo en el comando.
kleinfreund
@Sadi También creo que la línea gsettings set org.gnome.settings-daemon.plugins.keyboard active falseno funciona según lo previsto, ya que la secuencia de comandos se ejecuta root. En mis pruebas, la línea no tuvo efecto en esa configuración.
kleinfreund
Creo que en tal escenario, podría ser una buena idea ejecutar el comando gsettings set org.gnome.settings-daemon.plugins.keyboard active falsecomo usuario de una vez por todas, y luego usar este script sin los gsettings setcomandos ...
Sadi
Hasta ahora he visto que todavía no podemos hacer que esto funcione sin problemas; udev no implementa la distribución del teclado de vez en cuando, y debe desconectarse y conectarse nuevamente. Creo que volveré a mi script de inicio (actualizado) en la parte superior de mi respuesta nuevamente por un tiempo, lo que me sirve sin problemas, solo que tengo que ejecutarlo manualmente si conecto mi teclado externo después del inicio. Parece que udev es un poco defectuoso, como también se puede ver en tantas repeticiones de acción (está ejecutando el script de envoltura muchas veces y de manera extraña) ...
Sadi
1

Tuve un problema de permiso con el script ejecutado por udev. Resolví con sudo de la siguiente manera:

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

Establecer el mapa del teclado para cada dispositivo

    for ID in $IDLIST; do
            sudo -u max /usr/bin/setxkbmap -device $ID -layout "${kb_layout}" -display :0
    done
user835020
fuente
Creo que puede ser más útil si puedes escribirlo en su totalidad. Por ejemplo, ¿dónde has puesto las líneas de arriba?
Sadi
0

También puede definirlo en un archivo de configuración de Xorg.

Se presenta en esta respuesta de intercambio de pila: /superuser//a/946575/437492

Golar Ramblar
fuente
Eso sería genial, si pudiera hacer que funcione. Pero usando la última versión de LTS, Ubuntu 18.04, solo puedo ver el directorio /usr/share/X11/xorg.conf.d/ que contiene un archivo llamado 40-libinput.conf . Así que simplemente agregué una sección para el teclado externo en ese archivo. Utilizando el controlador libinput o evdev y un nombre de proveedor cada vez más corto, no pude obtener ningún resultado. ¿Algunas ideas?
Sadi
@Sadi: Si lees un poco sobre la configuración de Xorg, descubrirás que simplemente puedes agregar nuevos archivos /etc/X11/xorg.conf.d/(ese es el lugar para ir).
Golar Ramblar
Gracias. Seguramente leí bastante e intenté primero usar "/etc/X11/xorg.conf.d/30-keyboard.conf". Probaré suerte con la respuesta de intercambio de pila mencionada anteriormente. ;-)
Sadi