You are not logged in.
I've written a shell script that needs to know the xinput id of the keyboard being used. In the case of my Devuan box the id happens to be 9. However, in my OpenBSD box the id is 6.
I want to make the script portable and don't want to bother myself or other users with having to run xinput --list and then manually editing the keyboard id in the script. Is there a way to determine the id automatically? If the script has to wait for user to press a key so that script can find the id, that would be fine.
I've checked what xdotooland xev but neither one seems able to help. grepping output of xinput --list for "keyboard" won't work because there's more than one line with that word in it. Also, I don't want to assume that the system language is English.
Any ideas?
Last edited by GNUser (2019-09-14 17:46:15)
Offline
Maybe more creative grepping will do it. Hm... not so easy. I think I can do it, but I'd need to see what your xinput shows and which line you want.
Assuming I want the one that says "keyboard" but not "Virtual core" on the left side, and says "slave keyboard" on the right side, this works on two of my machines. (One is "Microsoft Wired Keyboard 600" and the other is "AT Translated set 2 keyboard" on a Thinkpad.)
keyboard_id=$(xinput --list | grep 'slave keyboard' | sed -e 's/\[.*//g' | grep -i keyboard | grep -v core | cut -d"=" -f2)
Offline
not quite. That way leaves white space at the end. Maybe add another sed that removes the white space. (not sure if it's a tab or several spaces.)
$ echo "$keyboard_id"
10
$echo "$keyboard_id"x
10 x
Offline
To avoid the language problem, I would go for using xinput --list --long, and the id of the "originating class" from the first line with type XIKeyClass. Perhaps something like the following:
xinput --list --long | grep -Fwm1 XIKeyClass | egrep -oE '[0-9]*'
which would allow almost any i18n of the sought line, merely expecting XIKeyClass to be present, and the id being the only number on the line.
That method should find at least one of the currently available keyboards; I think it'll pick "the last one" if you connect additional USB or Bluetooth keyboards. Or possibly it's "the last one used".
Online
Can you not just do
LANG=C xinput --list --long
Or similar?
This space intentionally left blank.
Offline
Wow, thanks guys!
ralph.ronnquist's suggestion works in Devuan, in Tiny Core Linux (which uses BusyBox instead of coreutils), and even in OpenBSD. I modified it slightly to something that does same thing but makes more sense to me:
xinput --list --long | grep XIKeyClass | head -n 1 | egrep -o '[0-9]+'
There's no way I would have figured this out on my own. Thanks again, ralph. You're a wizard!
The only thing I don't understand is why the entry of interest always happens to be the first match.
Offline
Perhaps it's merely incidental, or perhaps it's because it's the detail associated with the 'master keyboard' where something in the xinput code makes it a reliable feature. I did do a quick test with a couple of different hardware set ups, including a laptop with a USB keyboard, and it seemed to offer the right result for those.
It's also a guess that the label XIKeyClass is a code label without i18n, and that no i18n of that detail line will morph the id number, or add any other digits into the mix.
It works while it works
Eventually someone with direct insight into the source might pass by, to confirm or refute.
Online
The first line with XIKeyClass on my desktop is my mouse. On the laptop, it's Virtual Core Keyboard.
⎜ ↳ Logitech USB Receiver id=11 [slave pointer (2)]
Reporting 6 classes:
Class originated from: 11. Type: XIButtonClass
Buttons supported: 7
Button labels: "Button 0" "Button Unknown" "Button Unknown" "Button Wheel Up" "Button Wheel Do
wn" "Button Horiz Wheel Left" "Button Horiz Wheel Right"
Button state:
Class originated from: 11. Type: XIKeyClass
Offline
Few things kill a perfectly good theory as effectivly as does reality....
Online
Thank you both. I think we're getting warmer. Does this work on all your test systems?
LANG=C xinput --list | grep -i keyboard | egrep -iv 'virtual|video|button|bus' | egrep -o 'id=[0-9]+' | egrep -o '[0-9]+'
Last edited by GNUser (2019-09-14 11:19:02)
Offline
Doesn't work on my wife's Sony Vaio:
$ LANG=C xinput --list | grep -i keyboard | egrep -iv 'virtual|video|button|bus'
↳ Sony Vaio Keys id=7 [slave keyboard (3)]
↳ USB 2.0 Camera: USB 2.0 Camera id=10 [slave keyboard (3)]
↳ AT Translated Set 2 keyboard id=12 [slave keyboard (3)]
↳ Sony Vaio Jogdial id=14 [slave keyboard (3)]
This is tough.
Offline
That one gives me two numbers, 13 and 12, which corrspond to:
↳ Microsoft Wired Keyboard 600 id=13 [slave pointer (2)]
↳ Microsoft Wired Keyboard 600 id=12 [slave keyboard (3)]
Offline
Perhaps it's important that the id of the entry is different from the id of the origin class. E.g. in post#8 above, the origin class id, 11, is the same as the id of the entry it concerns, and it should therefore be ignored. This logic could be done as:
xinput list --id-only | \
xargs -n 1 -I+ sh -c "xinput list + | grep -wv + | grep XIKeyClass" | \
grep -oE "[0-9]+"
I.e., in words: for each of the available ids, check the details for the id, but ignoring lines containing the id, for a XIKeyClass line, and then reduce resulting lines to the number they contains. Ideally there should be only one resulting line, but if there are more... well.
Then you might want to check out https://unix.stackexchange.com/question … ress-a-key on how to "really" do this
Online
Yes, that works even on my wife's wonky hardware where multiple "slave keyboards" are listed.
eileen@vaio:~$ xinput list --id-only | xargs -n 1 -I+ sh -c "xinput list + | grep -wv + | grep XIKeyClass" | egrep -o '[0-9]+'
12
Wow, ralph.ronnquist. Very impressive. Thank you!
I understand the logic of the command, but don't understand how you figured out that it was the necessary logic. Will chew on it.
BTW, I had also found that nugget on stackexchange, but do not want to give users anything in addition to the shell script I've created. The script is here if you are curious:
https://github.com/bdantas/iksilo
Last edited by GNUser (2019-09-14 16:36:42)
Offline
That would not work on my devuan system:
chris@rigel:~/bin$ xinput --list
bash: xinput: command not found
So how can it be done without asking the user to install xinput?
Chris
Offline
Why would you need the xinput id if you don't have xinput installed?
Last edited by GNUser (2019-09-14 18:08:30)
Offline
I tinkered with ralph.ronnquist's solution in post #13 and figured out that this is what's actually going on when you decompress the logic:
$ master_id=$(LANG=C xinput list | grep -i 'master keyboard' | egrep -o 'id=[0-9]+' | egrep -o '[0-9]+')
$ keyboard_id=$(LANG=C xinput list $master_id | grep 'XIKeyClass' | egrep -o '[0-9]+')
This version is easier for my pea brain to grasp.
Last edited by GNUser (2019-09-15 00:47:35)
Offline
Just a quick followup: I found a way to detect keyboard input without needing the keyboard id at all!
$ LANG=C xinput --test-xi2 --root | awk '
/RawKeyPress/ { relevant=1 }
relevant==1 && /detail/ { print $2; relevant=0 }
'
The most obvious application of this is a keylogger (https://github.com/bdantas/keylogger), but the keylogger itself may just be a stepping stone to something more useful (e.g., https://github.com/bdantas/iksilo).
Last edited by GNUser (2019-10-07 18:29:00)
Offline