I wrote this script to change the usb keyboard layout automatically on plug-in
import pyudev
from subprocess import call
monitor = pyudev.Monitor.from_netlink(pyudev.Context())
monitor.filter_by('usb')
def kbd_event(action, device):
if action == 'add':
call(["setxkbmap", "carpalx"])
observer = pyudev.MonitorObserver(monitor, kbd_event)
observer.start()
setxkbmap carpalx
works if I type it in bash, but it doesn't change the layout in the above code. So I did this in bash:
setxkbmap carpalx
xmodmap -pke > carpalx2
changed the above call line to call(["xmodmap", "./carpalx2"])
and now the script works. I have the following problems:
call(["xmodmap", "./carpalx2"])
is run for every usb device I plug in. How can I further filter the events so the layout changes only when I insert a keyboard?With my current code, the keyboard layout changes every time I plug in my mouse :)
You can filter keyboards by checking for the ID_INPUT_KEYBOARD
property:
if action == 'add' and device['ID_INPUT_KEYBOARD'] == '1':
print('a keyboard was added')
Concerning the difference between calling setxkbmap
directly and using the script, I'd guess that the X server needs time to initialize the keyboard, too. UDev invokes the callback as soon as the keyboard has finished udev processing, but this can easily before the X11 server configures and initializes the new keyboard.
Check the X.org logs, and any error message that setxkbmap
might print.