UPDATE - Fully working script located at the bottom of my answer for anyone who isn't interested in the process of getting there.
I've been trying to write a bash script that makes use of xbindkeys, xkb, and xinput set-button-map in order to automatically change the layouts of my Razer Tartarus keypad and Logitech G502 Proteus mouse based on the currently active window. I've chosen to accomplish this by having the script constantly running in the background in an infinite loop that checks to see if the active window is different from the last check. I've seen others suggest to have your .xbindkeysrc run a different script for each key/key-combination that checks the active window before deciding which command to send, but with a 13-button mouse and a 21-button keypad, the number of necessary scripts would quickly get out of hand, especially once I start adding combinations.
autoProfileSwitch:
#!/bin/bash
Last=""
proteus_id=$(
xinput list |
sed -n 's/.*G502.*id=\([0-9]*\).*pointer.*/\1/p'
)
[ "$proteus_id" ] || exit
tartarus_id=$(
xinput list |
sed -n 's/.*Tartarus.*id=\([0-9]*\).*keyboard.*/\1/p'
)
[ "$tartarus_id" ] || exit
tartarus_profile="default"
proteus_profile="1 2 3 4 5 6 7 8 9 10 11 12 13"
xbindkeys_profile=".xbindkeysrc"
while true; do
Class=`xprop -id \`xprop -root |nawk '/_NET_ACTIVE_WINDOW/ {print $5; exit;}'\` |nawk -F = '/WM_CLASS/ {N=split($2, A, ", "); gsub(/\"/,"",A[2]); print A[2]; exit;}'`
if [ "$Class" != "$Last" ]
then
case $Class in
"Dwarf_Fortress")
tartarus_profile="dwarfFortress"
proteus_profile="1 3 2 4 5 6 7 8 9 10 11 12 13"
xbindkeys_profile="dwarfFortress";;
"Firefox")
tartarus_profile="default"
proteus_profile="1 2 3 4 5 6 7 8 9 10 11 12 13"
xbindkeys_profile=".xbindkeysrc";;
"")
tartarus_profile="default"
proteus_profile="1 2 3 4 5 6 7 8 9 10 11 12 13"
xbindkeys_profile=".xbindkeysrc";;
*)
tartarus_profile="default"
proteus_profile="1 2 3 4 5 6 7 8 9 10 11 12 13"
xbindkeys_profile=".xbindkeysrc";;
esac
if pgrep -x "xbindkeys" > /dev/null
then
killall xbindkeys
fi
xbindkeys -f $HOME/xbindkeys\ profiles/$xbindkeys_profile
tartarusProfile -p $tartarus_profile
#setxkbmap -device $tartarus_id -print |
#sed 's/\(xkb_symbols.*\)"/\1+tartarus('$tartarus_profile')"/' |
#xkbcomp -I$HOME/xbindkeys\ profiles/xkb -i $tartarus_id -synch -$DISPLAY 2>/dev/null
for i in $proteus_id
do
xinput set-button-map $i $proteus_profile
done
Last="$Class"
fi
done
I tried moving the contents of my tartarusProfile script into the autoProfileSwitch script (the reason for the unused tartarus_id variable and the commented out lines directly under the call to tartarusProfile), but kept receiving a "sed couldn't flush stdout: Broken pipe" error for some reason. The code works fine when in its own script
tartarusProfile:
#!/bin/bash
# Set profile variable to argument (or default if none)
PROFILE="default"
while getopts p: option; do
case "$option" in
p) PROFILE=$OPTARG;;
esac
done
# Get xinput device id for Razer Tartarus
tartarus_id=$(
xinput list |
sed -n 's/.*Tartarus.*id=\([0-9]*\).*keyboard.*/\1/p'
)
[ "$tartarus_id" ] || exit
# Remap Razer Tartarus to selected profile
setxkbmap -device $tartarus_id -print |
sed 's/\(xkb_symbols.*\)"/\1+tartarus('$PROFILE')"/' |
xkbcomp -I$HOME/xbindkeys\ profiles/xkb -i $tartarus_id -synch - $DISPLAY 2>/dev/null
These scripts are mostly working as intended, but there are some strange things going on that I can't seem to isolate. For starters: the xkb calls only seem to happen if a terminal window is open and not minimized (or in one more instance which I'll describe later), even when I run the script with "autoProfileSwitch &"; xbindkeys and xinput are both called regardless of if a terminal window is open however.
Another issue is that the "Tab" key is occasionally bound to my right mouse button (in addition to the intended swapping of MMB and RMB) when switching to my Dwarf Fortress profiles despite there being nothing in the xbindkeys profile to cause it.
Finally: even though xbindkeys doesn't require the terminal window be open, something weird is happening when I go from Dwarf Fortress to another window when it's closed. Right now my default is to have my mouse's G7 button bound to the "f" key to allow quick fullscreen on videos, but when I switch from Dwarf Fortress to another window, the first click of G7 gives an "s" (nothing in xbindkeys that should be causing this), and the second click gives the expected "f". After G7 becomes my "f" key, xkb gets called and my tartarus then switches to its default as well. This tends to keep xkb from switching back to the Dwarf Fortress profile when appropriate, even when the terminal window is open.
Any help would be much appreciated, and I can provide more info if necessary.