Como saber qual teclado foi usado para pressionar uma tecla?

15

Freqüentemente trabalho em estações de emparelhamento onde há vários teclados instalados. Posso usar setxkbmap com -device <ID> para definir o layout de um teclado específico (usando um ID de xinput ), mas muitas vezes não é óbvio em qual teclado eu estou. Seria melhor evitar o andamento dos dois teclados, por isso gostaria de escrever uma ferramenta rápida para obter essas informações para setxkbmap . Eu esperaria um caso de uso típico como o seguinte:

$ setxkbmap -device "$(get-keyboard-id)" -layout gb
Press Enter to detect keyboard ID

Qual interface fornece essa informação no Linux? O ideal é que funcione sem o X, mas isso não é um requisito (não parece haver muitas ferramentas que suportam isso sem o X).

Resultados até agora:

  • O Linux deve saber em qual teclado estou digitando para suportar diferentes layouts para vários teclados simultaneamente.
  • xinput → list.c → list_xi2XIQueryDevice fornece IDs de dispositivos utilizáveis por setxkbmap .
  • showkey e xev não imprimem IDs de teclado.
  • xinput list-props $ID mostra onde os eventos do teclado são enviados . No entanto, usando o código de outra resposta , parece que este dispositivo não imprime nada para identificar o teclado.
  • Uma solução quase possível é executar xinput --test <ID> & para cada ID de teclado e ver qual deles retorna primeiro. O problema é descobrir quais "teclados" são realmente teclados:

    $ xinput | grep keyboard
    ⎣ Virtual core keyboard                         id=3    [master keyboard (2)]
        ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
        ↳ Power Button                              id=6    [slave  keyboard (3)]
        ↳ Video Bus                                 id=7    [slave  keyboard (3)]
        ↳ Power Button                              id=8    [slave  keyboard (3)]
        ↳ Sleep Button                              id=9    [slave  keyboard (3)]
        ↳ WebCam SC-13HDL10931N                     id=10   [slave  keyboard (3)]
        ↳ AT Translated Set 2 keyboard              id=11   [slave  keyboard (3)]
    
por l0b0 05.09.2013 / 15:57

3 respostas

0

Mais escavações revelaram outra outra solução usando Bash simples e uma conta de usuário normal. Script :

#!/usr/bin/env bash

set -o errexit -o nounset -o noclobber -o pipefail

# Remove leftover files and processes on exit
trap 'rm --recursive -- "$dir"; kill -- -$$' EXIT
dir="$(mktemp --directory)"
cd "$dir"

# Log key presses to file
xinput --list --id-only | while read id
do
    # Only check devices linked to an event source
    if xinput --list-props "$id" | grep --quiet --extended-regexp '^\s+Device Node.*/dev/input/event'
    then
        xinput test "$id" > "$id" &
    fi
done

# Check for key presses
while sleep 0.1
do
    for file in *
    do
        if [[ -s "$file" ]]
        then
            echo "$file"
            exit
        fi
    done
done
    
por 15.09.2016 / 23:53
3

Desativar dispositivo

Aqui está uma idéia para identificar qual teclado é qual. Você pode usar o comando xinput para ativar e desativar dispositivos.

Exemplo

$ xinput list
⎡ Virtual core pointer                      id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ SynPS/2 Synaptics TouchPad                id=12   [slave  pointer  (2)]
⎜   ↳ TPPS/2 IBM TrackPoint                     id=13   [slave  pointer  (2)]
⎜   ↳ Logitech USB Receiver                     id=9    [slave  pointer  (2)]
⎜   ↳ Logitech USB Receiver                     id=10   [slave  pointer  (2)]
⎣ Virtual core keyboard                     id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
    ↳ Power Button                              id=6    [slave  keyboard (3)]
    ↳ Video Bus                                 id=7    [slave  keyboard (3)]
    ↳ Sleep Button                              id=8    [slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard              id=11   [slave  keyboard (3)]
    ↳ ThinkPad Extra Buttons                    id=14   [slave  keyboard (3)]

A saída acima mostra os vários dispositivos que eu tenho no meu laptop Thinkpad. Eu só tenho 1 teclado conectado, este aqui:

    ↳ AT Translated Set 2 keyboard              id=11   [slave  keyboard (3)]

Agora, dê uma olhada nas propriedades disponíveis por meio deste dispositivo:

$ xinput list-props "AT Translated Set 2 keyboard"
Device 'AT Translated Set 2 keyboard':
    Device Enabled (124):   1
    Coordinate Transformation Matrix (126): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.

Do acima, você pode ver que está ativado, então vamos desativá-lo:

$ xinput set-prop "AT Translated Set 2 keyboard" "Device Enabled" 0

Para ativá-lo:

$ xinput set-prop "AT Translated Set 2 keyboard" "Device Enabled" 1

A ideia?

Você pode ativar desativar um dos teclados usando este comando para determinar em qual deles você está.

Referências

por 06.09.2013 / 05:30
3

A questão parece um pouco contraditória, já que você está citando ferramentas X, mas pede uma solução que "idealmente funcione sem X".

Sobre o seu achado em 4 th : xinput lhe dará a correspondência

$ xinput list-props 11
Device 'AT Translated Set 2 keyboard':
    Device Enabled (145):   1
    Coordinate Transformation Matrix (147): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000
    Device Product ID (266):    1, 1
    Device Node (267):  "/dev/input/event0"

pelo menos com a seguinte versão

$ xinput --version
xinput version 1.6.1
XI version on server: 2.3

Primeiro passo: detectando o dispositivo de evento do teclado em C

#include <stdio.h>
//#include <unistd.h>
#include <fcntl.h>
#include <linux/input.h>

// typical use : sudo ./a.out /dev/input/event*
int main (int argc, char *argv[])
{
  struct input_event ev[64];
  int fd[argc],rd,idev,value, size = sizeof (struct input_event);
  char name[256] = "Unknown";

  if(argc==1) return -1;

  int ndev=1;
  while(ndev<argc && (fd[ndev] = open (argv[ndev], O_RDONLY|O_NONBLOCK)) != -1){
    ndev++;
  }
  fprintf (stderr,"Found %i devices.\n", ndev);
  if(ndev==1) return -1;

  while (1){
    for(idev=1; idev<argc; idev++){
      if( (rd=read (fd[idev], ev, size * 64)) >= size){
      value = ev[0].value;
      if (value != ' ' && ev[1].value == 1 && ev[1].type == 1){
        ioctl (fd[idev], EVIOCGNAME (sizeof (name)), name);
        printf ("%s\n", name);
        return idev;
      }
      }
    }
//    sleep(1);
  }
  return -1;
}

Muito obrigado a esta página . Eu tirei a maioria das verificações de segurança do código que pedi emprestado, para maior clareza, no código real, você provavelmente as quer.

Note que os pressionamentos de tecla são ecoados, então você pode, de fato, pedir gentilmente ao usuário para apertar uma tecla modificadora (Shift, Control ...) ao invés de qualquer tecla .

Segundo passo: use xinput para obter o ID X do nome do dispositivo

Compile a fonte C acima e use desta maneira:

xinput list --id-only "keyboard:$(sudo ./a.out /dev/input/event*)"

    
por 10.05.2016 / 17:42