Capturing Keypresses from the Background
Asked Answered
N

1

5

I am trying to write a bash script that watches the keyboard for specific key presses, and runs commands when it detects them. I am currently able to do this using the input command, but only if the terminal running it is in the foreground. I need to make it work when the window is not in focus.

I have looked at using xinput test-xi2 --root to get each event, which seems to work pretty well, but I am not sure how to effectively convert that input to a key definition that is useful to me.

Here is my current program:

while true; do
    read -rsn1 input
    if [ "$input" = "a" ];
    then
        #Do Something
    fi
done

The above code works, but only in the foreground.

Any help would be greatly appreciated!

Nidifugous answered 14/6, 2019 at 16:22 Comment(1)
Do you mean you want to be able to capture the letter "a" no matter what application is in the foreground? Even a GUI application? I think that can't be done with a bash script running in the background. Do some research about keyloggers. It can be done with expect but only for a single shell process.Advertising
N
6

After doing a lot of messing around, I was able to get it to work by using xinput watching my keyboard. Anytime an event happened on the keyboard, it would throw a keyPressed message, and then a keyReleased message. I piped these into grep to get the message if it was a key released, and then piped this into a loop. Inside the loop, I narrow down the lines to just the one with the key information, and then remove the excess info with sed. This leaves me with the key code, which can be converted into the character, although I am just using the number. Here is my code:

xinput test-xi2 --root 3 | grep -A2 --line-buffered RawKeyRelease | while read -r line;
do
    if [[ $line == *"detail"* ]];
    then
        key=$( echo $line | sed "s/[^0-9]*//g")

    #Do something with the key

done

Hope this helps somebody!

Nidifugous answered 14/6, 2019 at 22:52 Comment(1)
All of the above can be replaced by: xinput test-xi2 --root 3 | gawk '/RawKeyRelease/ {getline; getline; print $2; fflush()}' | while read -r key; do echo "$key"; done which saves spawning sed on every matched line and also eliminates the if. If your AWK is mawk it will need the -W interactive option.Ladner

© 2022 - 2024 — McMap. All rights reserved.