Bagaimana cara mengetahui keyboard mana yang digunakan untuk menekan tombol?

16

Saya sering bekerja pada stasiun pasangan di mana ada beberapa keyboard yang diinstal. Saya dapat menggunakan setxkbmapdengan -device <ID>untuk mengatur tata letak keyboard tertentu (menggunakan ID darixinput ), tetapi seringkali tidak jelas keyboard mana yang saya gunakan . Akan lebih baik untuk menghindari bolak-balik mencoba kedua keyboard, jadi saya ingin menulis alat cepat untuk mendapatkan informasi ini setxkbmap. Saya mengharapkan kasus penggunaan tipikal seperti berikut ini:

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

Antarmuka mana yang menyediakan informasi ini di Linux? Idealnya itu harus bekerja tanpa X, tapi itu bukan keharusan (sepertinya tidak ada banyak alat yang mendukung ini tanpa X).


Temuan sejauh ini:

  • Linux harus tahu keyboard mana yang saya ketikkan untuk mendukung tata letak yang berbeda untuk beberapa keyboard secara bersamaan.
  • xinput→ list.c → list_xi2XIQueryDevicememberikan ID perangkat yang dapat digunakan oleh setxkbmap.
  • showkeydan xevjangan cetak ID keyboard.
  • xinput list-props $IDmenunjukkan tempat acara keyboard dikirim . Namun, menggunakan kode dari jawaban lain sepertinya perangkat ini tidak mencetak apa pun untuk mengidentifikasi keyboard.
  • Salah satu solusi yang hampir mungkin adalah berjalan xinput --test <ID> &untuk setiap ID keyboard dan melihat mana yang mengembalikan sesuatu terlebih dahulu. Masalah dengan itu adalah mencari tahu "keyboard" mana yang sebenarnya adalah keyboard:

    $ 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)]
    
l0b0
sumber
1
Mungkin Anda sedang mencari MPX.
Ignacio Vazquez-Abrams
@ IgnacioVazquez-Abrams Bukankah itu solusi yang jauh lebih rumit?
l0b0
Itu tergantung pada apa masalahnya.
Ignacio Vazquez-Abrams
"Sepertinya perangkat ini tidak mencetak apa pun untuk mengidentifikasi keyboard": apa maksudmu? Jika Anda less -f /dev/input/eventXdan menekan tombol pada keyboard yang sesuai, Anda akan melihat "sampah" muncul, sehingga penekanan tombol Anda memang diarahkan ke satu file dev dan bukan yang lain.
L. Levrel
Sudahkah Anda mencoba ini (dirujuk dalam jawaban lain dari pertanyaan lain yang Anda kutip)?
L. Levrel

Jawaban:

4

Nonaktifkan perangkat

Berikut ini satu ide untuk mengidentifikasi keyboard mana. Anda dapat menggunakan perintah xinput untuk mengaktifkan dan menonaktifkan perangkat.

Contoh

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

Output di atas menunjukkan berbagai perangkat yang saya miliki di laptop Thinkpad saya. Saya hanya memiliki 1 keyboard yang terpasang, yang ini:

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

Sekarang lihat properti yang tersedia melalui perangkat ini:

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

Dari hal di atas, Anda dapat melihat bahwa itu diaktifkan, jadi mari kita nonaktifkan:

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

Untuk mengaktifkannya:

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

Ide?

Anda dapat mengaktifkan menonaktifkan salah satu keyboard menggunakan perintah ini untuk menentukan yang sedang Anda gunakan.

Referensi

slm
sumber
Bukankah itu lebih banyak pekerjaan? Pendekatan saya melibatkan minimal satu perintah, paling banyak tiga. Pendekatan ini selalu melibatkan tiga perintah - nonaktifkan, aktifkan, lalu atur tata letak (plus kemungkinan sakelar keyboard).
10b0
@ l0b0 - ya saya tidak senang dengan pendekatan ini juga. Saya terus mencari tetapi menempatkan metode ini di sini sebagai "1 arah". Tapi bukan yang ideal, saya setuju.
slm
@lobo - Jawaban ini tidak akan mendapatkan hadiah jadi jangan khawatir tentang itu, ia memiliki suara sebelum Anda memulai hadiah. stackoverflow.com/help/bounty . Juga apa kemarahan Anda terhadap saya yang mencoba membantu Anda di sini? Saya memberi Anda bukan solusi yang ideal, tetapi 1 cara untuk menyelesaikan tugas Anda. Saya memberikan ini lebih dari 2+ tahun yang lalu dan Q ini telah duduk di sini w / 0 alternatif. Saya pikir Anda perlu bertanya pada diri sendiri apakah mungkin pertanyaan / pendekatan itulah masalahnya. Jelas hanya $ 0,02 saya tetapi sudah cukup.
slm
Buruk saya x 2: Saya tidak memperhatikan sedikit tentang "dibuat setelah karunia dimulai", dan saya menghargai bahwa Anda menulis jawaban yang dirumuskan dengan sangat baik. Tapi saya tidak bisa memilih solusi yang lebih rumit daripada yang asli, dan saya tidak mengerti mengapa orang lain melakukannya.
l0b0
1
@ l0b0 Alasan saya upvoting: Ini adalah perintah tunggal yang dapat saya gunakan untuk dengan cepat dan mudah mengkonfirmasi kecurigaan saya tentang keyboard itu, daripada perlu membaca seluruh skrip untuk memastikan tidak menghapus hard drive saya, kemudian simpan dan jalankan itu. Atau, dalam hal jawaban dengan suara tertinggi sejauh ini, kompilasi kode C. Juga, ide-ide kreatif seperti ini patut mendapat dukungan.
Fabian Röling
4

Pertanyaannya terdengar agak kontradiktif karena Anda mengutip alat X tetapi meminta solusi yang "idealnya bekerja tanpa X".

Tentang temuan keempat Anda : xinputakan memberi Anda korespondensi

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

setidaknya dengan versi berikut

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


Langkah pertama: mendeteksi perangkat acara keyboard di 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;
}

Terima kasih banyak untuk halaman ini . Saya telah menghapus sebagian besar pemeriksaan keamanan dari kode yang saya pinjam di sana, untuk kejelasan, dalam kode nyata Anda mungkin menginginkannya.

Perhatikan bahwa penekanan tombol digema, jadi Anda mungkin ingin meminta pengguna untuk menekan tombol pengubah (Shift, Control ...) daripada tombol apa pun .

Langkah kedua: gunakan xinput untuk mendapatkan X ID dari nama perangkat

Kompilasi sumber C di atas dan gunakan cara ini:

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

L. Levrel
sumber
Ada juga/dev/input/by-id
jthill
Terima kasih atas tipnya. Saya telah mengutip alat X hanya karena sebagian besar alat tampaknya memerlukan X. Saya tidak tahu bagaimana bekerja dengan /dev/input/event*- saya mencoba tailtetapi tidak berhasil.
l0b0
by-id memberikan nama perangkat pemetaan symlinks ke antrian acara, tanpa memerlukan X.
jthill
@ jthill Pada mesin yang saya pakai sekarang, dir ini hanya memiliki tautan untuk mouse.
L. Levrel
Hunh. Oke, hidup dan pelajari, keyboard milikku sudah terdaftar dengan cantik.
jthill
1

Lebih banyak penggalian mengungkapkan solusi lain menggunakan Bash biasa dan akun pengguna normal. Skrip :

#!/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
l0b0
sumber