จะทราบได้อย่างไรว่าคีย์บอร์ดตัวไหนที่ใช้กดปุ่ม?


16

ฉันมักจะทำงานกับสถานีจับคู่ที่มีการติดตั้งคีย์บอร์ดหลายตัว ฉันสามารถใช้setxkbmapกับ-device <ID>การตั้งค่ารูปแบบสำหรับแป้นพิมพ์ที่เฉพาะเจาะจง (ใช้รหัสจากxinput ) แต่มักจะเป็นไม่ชัดเจนซึ่งแป้นพิมพ์ฉันที่ มันจะเป็นการดีกว่าถ้าคุณหลีกเลี่ยงการไปมาระหว่างคีย์บอร์ดทั้งสองแป้นดังนั้นฉันอยากจะเขียนเครื่องมือด่วนเพื่อรับข้อมูลsetxkbmapนี้ ฉันคาดว่ากรณีการใช้งานทั่วไปดังต่อไปนี้:

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

อินเทอร์เฟซใดให้ข้อมูลนี้บน Linux เป็นการดีที่มันควรจะทำงานโดยไม่มี X แต่นั่นไม่ใช่ข้อกำหนด (ดูเหมือนจะไม่มีเครื่องมือมากมายที่สนับสนุนสิ่งนี้หากไม่มี X)


การค้นพบจนถึง:

  • Linux ต้องรู้ว่าฉันใช้แป้นพิมพ์ตัวใดเพื่อรองรับรูปแบบที่แตกต่างกันสำหรับแป้นพิมพ์หลายตัวพร้อมกัน
  • xinput→ list.c → list_xi2→ ให้รหัสอุปกรณ์ใช้งานได้โดยXIQueryDevicesetxkbmap
  • showkeyและxevไม่พิมพ์รหัสคีย์บอร์ด
  • xinput list-props $IDแสดงให้เห็นว่าเหตุการณ์ที่แป้นพิมพ์จะถูกส่ง อย่างไรก็ตามการใช้รหัสจากคำตอบอื่นดูเหมือนว่าอุปกรณ์นี้ไม่ได้พิมพ์อะไรเพื่อระบุแป้นพิมพ์
  • วิธีแก้ปัญหาหนึ่งที่เกือบจะเป็นไปได้ก็คือการเรียกใช้xinput --test <ID> &สำหรับแป้นพิมพ์แต่ละรหัสและดูว่าจะส่งคืนสิ่งใดก่อน ปัญหาที่จะหาที่ "คีย์บอร์ด" มีจริงคีย์บอร์ด:

    $ 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
บางทีคุณกำลังมองหา MPX
Ignacio Vazquez-Abrams

@ IgnacioVazquez-Abrams นั่นไม่ใช่คำตอบที่ซับซ้อนกว่านี้ใช่มั้ย
l0b0

ขึ้นอยู่กับว่าปัญหาคืออะไร
Ignacio Vazquez-Abrams

"ดูเหมือนว่าอุปกรณ์นี้ไม่ได้พิมพ์อะไรเพื่อระบุแป้นพิมพ์": คุณหมายถึงอะไร หากคุณless -f /dev/input/eventXและกดปุ่มบนแป้นพิมพ์ที่สอดคล้องกันคุณควรเห็น "ขยะ" ปรากฏขึ้นดังนั้นการกดแป้นพิมพ์ของคุณจะถูกนำไปสู่ไฟล์ dev หนึ่งไฟล์ไม่ใช่ไฟล์อื่น ๆ
L. Levrel

คุณได้ลองนี้ (อ้างอิงในคำตอบของคำถามอื่น ๆ ที่คุณกล่าวอ้างอื่น)?
L. Levrel

คำตอบ:


4

ปิดใช้งานอุปกรณ์

ต่อไปนี้เป็นแนวคิดหนึ่งในการระบุว่าแป้นพิมพ์ใดอยู่ คุณสามารถใช้คำสั่งxinputเพื่อเปิดใช้งานและปิดใช้งานอุปกรณ์

ตัวอย่าง

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

ผลลัพธ์ด้านบนแสดงอุปกรณ์ต่าง ๆ ที่ฉันมีในแล็ปท็อป Thinkpad ของฉัน ฉันมีเพียง 1 แป้นต่อพ่วงอันนี้:

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

ตอนนี้มาดูคุณสมบัติที่มีให้ผ่านอุปกรณ์นี้:

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

จากด้านบนคุณจะเห็นว่ามีการเปิดใช้งานดังนั้นให้ปิดการใช้งาน:

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

วิธีเปิดใช้งาน:

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

ความคิด?

คุณสามารถเปิดใช้งานการปิดการใช้งานคีย์บอร์ดอย่างใดอย่างหนึ่งโดยใช้คำสั่งนี้เพื่อกำหนดว่าคุณกำลังใช้

อ้างอิง


นั่นมันใช้งานไม่ได้อีกแล้วเหรอ? แนวทางของฉันเกี่ยวข้องกับคำสั่งอย่างน้อยหนึ่งคำสั่งไม่เกินสามคำสั่ง วิธีนี้มักจะเกี่ยวข้องกับสามคำสั่ง - ปิดใช้งานเปิดใช้งานจากนั้นตั้งค่าเค้าโครง (รวมถึงสวิตช์แป้นพิมพ์)
l0b0

@ l0b0 - ใช่ฉันไม่ได้ตื่นเต้นกับวิธีนี้เช่นกัน ฉันดูต่อไป แต่วางวิธีนี้ที่นี่เป็น "1 วิธี" ไม่เหมาะอย่างยิ่งแม้ว่าฉันเห็นด้วย
slm

@lobo - คำตอบนี้จะไม่ได้รับรางวัลดังนั้นไม่ต้องกังวลกับมันมีคะแนนเสียงก่อนที่คุณจะเริ่มรางวัล stackoverflow.com/help/bounty ความโกรธของคุณที่มีต่อฉันคืออะไรพยายามช่วยคุณที่นี่ ฉันไม่ได้ให้วิธีแก้ปัญหาในอุดมคติแก่คุณ แต่เป็นวิธีหนึ่งในการทำงานให้สำเร็จ ฉันให้สิ่งนี้มากกว่า 2 ปีที่ผ่านมาและคำถามนี้มีที่นี่ w / 0 ทางเลือก ฉันคิดว่าคุณต้องถามตัวเองว่าอาจเป็นคำถาม / แนวทางที่เป็นปัญหาหรือไม่ เห็นได้ชัดว่าแค่ $ 0.02 ของฉัน แต่ก็เพียงพอแล้ว
slm

x 2 ที่ไม่ดีของฉัน: ฉันไม่ได้สังเกตเลยว่า "สร้างขึ้นหลังจากที่เงินรางวัลเริ่มขึ้น" และฉันขอขอบคุณที่คุณเขียนคำตอบที่มีสูตรดีมาก แต่ฉันไม่สามารถแก้ปัญหาที่ซับซ้อนกว่าเดิมได้และฉันไม่เข้าใจว่าทำไมคนอื่นถึงทำ
l0b0

1
@ l0b0 เหตุผลของฉันสำหรับ upvoting: มันเป็นคำสั่งเดียวที่ฉันสามารถใช้เพื่อยืนยันข้อสงสัยของฉันได้อย่างรวดเร็วและง่ายดายว่าเป็นคีย์บอร์ดแบบไหนแทนที่จะต้องอ่านสคริปต์ทั้งหมดเพื่อให้แน่ใจว่าไม่ได้เช็ดฮาร์ดไดรฟ์ของฉันจากนั้นบันทึกและ รันมัน หรือในกรณีของคำตอบที่ได้คะแนนสูงสุดให้รวบรวมรหัส C นอกจากนี้ความคิดสร้างสรรค์เช่นนี้สมควรได้รับ upvotes
Fabian Röling

4

คำถามฟังดูขัดแย้งเล็กน้อยเนื่องจากคุณอ้างถึงเครื่องมือ X แต่ขอวิธีแก้ปัญหาที่ "ควรจะทำงานได้โดยไม่ต้อง X"

เกี่ยวกับ 4 ของคุณวันที่ค้นพบ: xinputจะช่วยให้คุณติดต่อ

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

อย่างน้อยกับรุ่นต่อไปนี้

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


ขั้นตอนแรก: ตรวจจับอุปกรณ์เหตุการณ์แป้นพิมพ์ใน 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;
}

ขอบคุณมากที่ หน้านี้ ฉันได้ตรวจสอบความปลอดภัยส่วนใหญ่จากรหัสที่ฉันยืมมาเพื่อความชัดเจนในรหัสจริงที่คุณอาจต้องการพวกเขา

โปรดทราบว่าการกดปุ่มจะถูกสะท้อนดังนั้นคุณอาจต้องการให้ผู้ใช้กดปุ่มตัวปรับเปลี่ยน (Shift, Control ... ) แทน ปุ่มใดก็ได้

ขั้นตอนที่สอง: ใช้ xinput เพื่อรับ X ID จากชื่ออุปกรณ์

รวบรวมแหล่ง C ข้างต้นและใช้วิธีนี้:

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


นอกจากนี้ยังมี/dev/input/by-id
jthill

ขอบคุณสำหรับทิป. ฉันอ้างถึงเครื่องมือ X เพียงอย่างเดียวเนื่องจากเครื่องมือส่วนใหญ่ดูเหมือนจะต้องการ X ฉันไม่ทราบวิธีการทำงานกับ/dev/input/event*- ฉันพยายามแต่งtailแต่ก็ไม่มีประโยชน์
l0b0

by-id ให้ชื่ออุปกรณ์การแมป
symlink

@jthill บนเครื่องที่ฉันเปิดอยู่ในขณะนี้ dir นี้มีลิงก์สำหรับเมาส์เท่านั้น
L. Levrel

Hunh ตกลงใช้ชีวิตและเรียนรู้แป้นพิมพ์ของฉันมีรายชื่อทั้งหมดสวย
jthill

1

การขุดเพิ่มเติมเปิดเผยวิธีการอื่นโดยใช้ Bash ธรรมดาและบัญชีผู้ใช้ปกติ สคริปต์ :

#!/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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.