Làm thế nào để biết bàn phím nào đã được sử dụng để nhấn phím?


15

Tôi thường xuyên làm việc trên các trạm ghép nối có cài đặt nhiều bàn phím. Tôi có thể sử dụng setxkbmapvới -device <ID>thiết lập bố trí cho một bàn phím cụ thể (sử dụng một ID từxinput ), nhưng thường thì không rõ ràng mà bàn phím tôi đang ở. Sẽ tốt hơn để tránh qua lại khi thử cả hai bàn phím, vì vậy tôi muốn viết một công cụ nhanh để có được thông tin này setxkbmap. Tôi mong đợi một trường hợp sử dụng điển hình như sau:

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

Giao diện nào cung cấp thông tin này trên Linux? Lý tưởng nhất là nó hoạt động mà không có X, nhưng đó không phải là một yêu cầu (dường như không có nhiều công cụ hỗ trợ việc này mà không có X).


Những phát hiện cho đến nay:

  • Linux phải biết bàn phím nào tôi đang gõ để hỗ trợ các bố cục khác nhau cho nhiều bàn phím cùng một lúc.
  • xinput→ list.c → list_xi2XIQueryDevicecung cấp ID thiết bị có thể sử dụng bởi setxkbmap.
  • showkeyxevkhông in ID bàn phím.
  • xinput list-props $IDhiển thị nơi các sự kiện bàn phím được gửi . Tuy nhiên, sử dụng mã từ một câu trả lời khác , có vẻ như thiết bị này không in bất cứ thứ gì để nhận dạng bàn phím.
  • Một giải pháp gần như có thể là chạy xinput --test <ID> &cho mỗi ID bàn phím và xem cái nào trả về cái gì trước. Vấn đề với đó là tìm ra "bàn phím" nào thực sự là bàn phím:

    $ 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
Có lẽ bạn đang tìm MPX.
Ignacio Vazquez-Abrams

@ IgnacioVazquez-Abrams Không phải là một giải pháp phức tạp hơn sao?
l0b0

Điều đó phụ thuộc vào vấn đề là gì.
Ignacio Vazquez-Abrams

"Dường như thiết bị này không in bất cứ thứ gì để nhận dạng bàn phím": ý bạn là gì? Nếu bạn less -f /dev/input/eventXvà nhấn một phím trên bàn phím tương ứng, bạn sẽ thấy "rác" hiển thị, do đó, phím nhấn của bạn thực sự được hướng vào một tệp dev chứ không phải các tệp khác.
L. Levrel

Bạn đã thử điều này chưa (tham khảo trong một câu trả lời khác cho câu hỏi khác mà bạn trích dẫn)?
L. Levrel

Câu trả lời:


4

Vô hiệu hóa thiết bị

Đây là một ý tưởng hướng tới việc xác định bàn phím nào. Bạn có thể sử dụng lệnh xinput để bật và tắt thiết bị.

Thí dụ

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

Đầu ra ở trên hiển thị các thiết bị khác nhau mà tôi có trên máy tính xách tay Thinkpad của mình. Tôi chỉ có 1 bàn phím kèm theo, cái này:

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

Bây giờ hãy xem các thuộc tính có sẵn thông qua thiết bị này:

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

Từ những điều trên bạn có thể thấy rằng nó được kích hoạt, vì vậy hãy vô hiệu hóa nó:

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

Để kích hoạt nó:

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

Ý tưởng?

Bạn có thể cho phép vô hiệu hóa một trong những bàn phím bằng lệnh này để xác định bạn đang dùng bàn phím nào.

Người giới thiệu


Đó không phải là nhiều công việc hơn? Cách tiếp cận của tôi liên quan đến tối thiểu một lệnh, nhiều nhất là ba. Cách tiếp cận này luôn bao gồm ba lệnh - vô hiệu hóa, kích hoạt, sau đó thiết lập bố cục (cộng với có thể là một công tắc bàn phím).
l0b0

@ l0b0 - vâng tôi cũng không thích thú với cách tiếp cận này. Tôi đang tiếp tục xem xét nhưng đã đặt phương pháp này ở đây là "1 cách". Không phải là lý tưởng mặc dù, tôi đồng ý.
slm

@lobo - Câu trả lời này sẽ không nhận được tiền thưởng vì vậy đừng lo lắng về nó, nó đã có phiếu bầu trước khi bạn bắt đầu tiền thưởng. stackoverflow.com/help/bounty . Ngoài ra sự tức giận của bạn đối với tôi đang cố gắng giúp bạn ở đây là gì? Tôi đã cho bạn không phải là một giải pháp lý tưởng, nhưng 1 cách để hoàn thành nhiệm vụ của bạn. Tôi đã cung cấp điều này hơn 2 năm trước và Q này đã ngồi ở đây với 0 lựa chọn thay thế. Tôi nghĩ bạn cần phải tự hỏi mình nếu có lẽ câu hỏi / cách tiếp cận đó là vấn đề. Rõ ràng chỉ cần 0,02 đô la của tôi nhưng nó đã đủ.
slm

Xấu của tôi x 2: Tôi đã không nhận thấy một chút về "được tạo ra sau khi tiền thưởng bắt đầu" và tôi đánh giá cao rằng bạn đã viết một câu trả lời được xây dựng rất tốt. Nhưng tôi không thể đưa ra một giải pháp phức tạp hơn giải pháp ban đầu và tôi không hiểu tại sao những giải pháp khác lại làm như vậy.
l0b0

1
@ l0b0 Lý do của tôi để nâng cấp: Đó là một lệnh duy nhất mà tôi có thể sử dụng để nhanh chóng và dễ dàng xác nhận sự nghi ngờ của mình về bàn phím, thay vì cần phải đọc toàn bộ tập lệnh để đảm bảo rằng nó không xóa sạch ổ cứng của tôi, sau đó lưu và Thực hiện nó. Hoặc, trong trường hợp câu trả lời được bình chọn cao nhất cho đến nay, hãy biên dịch mã C. Ngoài ra, những ý tưởng sáng tạo như thế này xứng đáng được nâng cấp.
Fabian Röling

4

Câu hỏi nghe có vẻ hơi mâu thuẫn vì bạn đang trích dẫn các công cụ X nhưng yêu cầu một giải pháp "lý tưởng nhất nên hoạt động mà không cần X".

Về phát hiện thứ 4 của bạn : xinputsẽ cung cấp cho bạn sự tương ứng

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

ít nhất là với phiên bản sau

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


Bước đầu tiên: phát hiện thiết bị sự kiện bàn phím trong 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;
}

Rất cám ơn trang này . Tôi đã loại bỏ hầu hết các kiểm tra an toàn từ mã tôi đã mượn ở đó, để rõ ràng, trong mã thực sự bạn có thể muốn chúng.

Lưu ý rằng các lần nhấn phím được lặp lại, vì vậy bạn thực sự có thể muốn yêu cầu người dùng nhấn một phím bổ trợ (Shift, Control ...) thay vì bất kỳ phím nào .

Bước thứ hai: sử dụng xinput để lấy X ID từ tên thiết bị

Biên dịch nguồn C ở trên và sử dụng theo cách này:

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


Ngoài ra còn có/dev/input/by-id
jthill

Cảm ơn vì tiền hỗ trợ. Tôi đã chỉ trích dẫn các công cụ X vì hầu hết các công cụ dường như yêu cầu X. Tôi không biết cách làm việc với /dev/input/event*- Tôi đã thử tailting nhưng không có kết quả.
l0b0

by-id cung cấp tên thiết bị ánh xạ liên kết tượng trưng cho hàng đợi sự kiện, mà không yêu cầu X.
jthill

@jthill Trên máy tôi hiện đang bật, thư mục này chỉ có liên kết cho chuột.
L. Levrel

Hoài. Được rồi, sống và học hỏi, bàn phím của tôi được liệt kê khá đẹp.
jthill

0

Việc đào thêm đã tiết lộ một giải pháp khác sử dụng Bash đơn giản và một tài khoản người dùng bình thường. Kịch bản :

#!/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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.