Come dire quale tastiera è stata usata per premere un tasto?


16

Lavoro frequentemente su stazioni di associazione in cui sono installate più tastiere. Posso usare setxkbmapcon -device <ID>per impostare il layout di una tastiera specifica (usando un ID daxinput ), ma spesso non è ovvio in quale tastiera mi trovo. Sarebbe meglio evitare i tentativi di provare entrambe le tastiere, quindi mi piacerebbe scrivere uno strumento rapido per ottenere queste informazioni setxkbmap. Mi aspetterei un caso d'uso tipico come il seguente:

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

Quale interfaccia fornisce queste informazioni su Linux? Idealmente dovrebbe funzionare senza X, ma questo non è un requisito (non sembrano esserci molti strumenti che supportano questo senza X).


Risultati finora:

  • Linux deve sapere su quale tastiera sto digitando per supportare diversi layout contemporaneamente per più tastiere.
  • xinput→ list.c → list_xi2XIQueryDevicefornisce gli ID dispositivo utilizzabili da setxkbmap.
  • showkeye xevnon stampare gli ID tastiera.
  • xinput list-props $IDmostra dove vengono inviati gli eventi della tastiera . Tuttavia, usando il codice di un'altra risposta sembra che questo dispositivo non stia stampando nulla per identificare la tastiera.
  • Una soluzione quasi possibile è eseguire xinput --test <ID> &per ogni ID tastiera e vedere quale restituisce prima qualcosa. Il problema è quello di capire quali "tastiere" sono in realtà tastiere:

    $ 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)]
    

1
Forse stai cercando MPX.
Ignacio Vazquez-Abrams,

@ IgnacioVazquez-Abrams Non è una soluzione enormemente più complicata?
l0b0

Dipende da quale sia il problema.
Ignacio Vazquez-Abrams,

"sembra che questo dispositivo non stampi nulla per identificare la tastiera": cosa intendi? Se tu less -f /dev/input/eventXe premi un tasto sulla tastiera corrispondente, dovresti vedere "spazzatura" che appare, quindi i tuoi tasti premuti sono effettivamente diretti in un file dev e non negli altri.
L. Levrel,

Hai provato questo (indicato in un'altra risposta dell'altra domanda che hai citato)?
L. Levrel,

Risposte:


4

Disabilita il dispositivo

Ecco un'idea per identificare quale tastiera è quale. È possibile utilizzare il comando xinput per abilitare e disabilitare i dispositivi.

Esempio

$ 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)]

L'output sopra mostra i vari dispositivi che ho sul mio laptop Thinkpad. Ho solo 1 tastiera collegata, questa:

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

Ora dai un'occhiata alle proprietà disponibili tramite questo 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.

Da quanto sopra puoi vedere che è abilitato, quindi disabilitiamolo:

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

Per abilitarlo:

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

L'idea?

Puoi abilitare disabilitare una delle tastiere usando questo comando per determinare quale sei su.

Riferimenti


Non è ancora più lavoro? Il mio approccio prevede almeno un comando, al massimo tre. Questo approccio prevede sempre tre comandi: disabilitare, abilitare, quindi impostare il layout (più eventualmente un interruttore da tastiera).
l0b0

@ l0b0 - sì, non sono entusiasta neanche di questo approccio. Sto continuando a cercare ma ho inserito questo metodo come "1 via". Non è l'ideale però, sono d'accordo.
slm

@lobo - Questa risposta non otterrà la generosità quindi non preoccuparti, aveva i voti prima di iniziare la generosità. stackoverflow.com/help/bounty . Inoltre, qual è la tua rabbia nei miei confronti per cercare di aiutarti qui? Non ti ho dato una soluzione ideale, ma 1 modo per svolgere il tuo compito. L'ho fornito oltre 2 anni fa e questa Q è stata pubblicata qui con 0 alternative. Penso che devi chiederti se è forse il problema / la domanda / approccio. Ovviamente solo i miei $ 0,02 ma è già abbastanza.
slm

La mia cattiva x 2: non ho notato nulla di "creato dopo l'inizio della taglia", e apprezzo che tu abbia scritto una risposta molto ben formulata. Ma non posso votare una soluzione che è più complicata di quella originale e non capisco perché lo facciano gli altri.
l0b0,

1
@ l0b0 La mia ragione per l'upgrade: è un singolo comando che posso usare per confermare rapidamente e facilmente il mio sospetto su quale tastiera fosse, invece di dover leggere un intero script per assicurarmi che non cancelli il mio disco rigido, quindi salva e eseguilo. Oppure, nel caso della risposta più votata finora, compilare il codice C. Inoltre, idee creative come questa meritano voti.
Fabian Röling,

4

La domanda sembra un po 'contraddittoria poiché stai citando gli strumenti X ma chiedi una soluzione che "idealmente dovrebbe funzionare senza X".

A proposito della tua quarta scoperta: xinputti darà la corrispondenza

$ 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"

almeno con la seguente versione

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


Primo passo: rilevare il dispositivo degli eventi della tastiera in 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;
}

Mille grazie a questa pagina . Ho rimosso la maggior parte dei controlli di sicurezza dal codice che ho preso in prestito lì, per chiarezza, nel codice reale che probabilmente li desideri.

Si noti che vengono premuti i tasti premuti, quindi si potrebbe desiderare di chiedere gentilmente all'utente di premere un tasto modificatore (Maiusc, Controllo ...) anziché qualsiasi tasto.

Secondo passaggio: utilizzare xinput per ottenere l'ID X dal nome del dispositivo

Compilare la fonte C sopra e usare in questo modo:

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


C'è anche/dev/input/by-id
jill

Grazie per il consiglio. Ho citato strumenti X solo perché la maggior parte degli strumenti sembrano richiedere X. Io non so come lavorare con /dev/input/event*- ho cercato tailTing, ma senza alcun risultato.
1616

by-id fornisce i collegamenti simbolici che mappano il nome del dispositivo alla coda degli eventi, senza richiedere X.
jthill

@jthill Sulla macchina in cui mi trovo, questa directory ha solo collegamenti per il mouse.
L. Levrel,

Hunh. Ok, vivi e impara, la mia tastiera è elencata in modo carino.
jill,

1

Ulteriori ricerche hanno rivelato un'altra soluzione che utilizza Bash semplice e un normale account utente. 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.