September 22, 2019

Adapting the Keyboard Layout to Plugged Devices

When my notebook is connected to the keyboard on my desk I want to change the keyboard layout in linux fedora. The layout on the notebook is us en-us and the layout of my desktop keyboard is de-de.

Udev

First research turned out that the udev subsystem is the right place to script this behaviour.

I am reading https://opensource.com/article/18/11/udev.

  1. run 'sudo udevadm monitor' and plug device in to find the system path of the device.
  2. run 'sudo udevadm info -a -p $path' to find all udev info about the device

X-org keyboard configuration

I realized that I can have chocolate and ice-cream by using (XKB) to define my keyboard layouts. Then I can set the us layout to the internal keyboard and the de layout to the external one. Great – let's go!

Fetch the keyboard id:

/usr/bin/xinput list --id-only "Cooler Master Technology Inc. MasterKeys Pro S white"

Set the Keyboards to us and de:

setxkbmap -device 3 -layout us
setxkbmap -device 21 -layout de

Here the order of calls matters, since a change to the master keyboard (device 3) seems to override the changes on the slave keyboard (device 21)

Inputplug

After some more research it appears to me that udev is not the right place to setup my keyboard config. It seems there is a higher level event interface called 'X11 Input extension'. Any X11 client program can listen to the events and act on them. Now I am following this route: https://unix.stackexchange.com/questions/523635/prevent-keyboard-layout-reset-when-usb-keyboard-is-plugged-in/523959#523959

The xinput monitor that was advised is not available in the package resources for fedora. Therefore I went and checked out the src from https://bitbucket.org/andrew_shadura/inputplug/src/default/ and build it myself in /usr/local/src and moved the bin to /usr/local/bin

Also the developer is porting Inputplug over to XCB which he details here: https://blog.shadura.me/2018/05/20/porting-inputplug-from-xlib-to-xcb/

#! /bin/sh

echo >&2 "$@"
event=$1 id=$2 type=$3 name=$4


case "$event $type $name" in
'XIDeviceEnabled XISlaveKeyboard Cooler Master Technology Inc. MasterKeys Pro S white')
	sleep 1
	setxkbmap -device "$id" -layout de -display :1
	echo "setting map of device $id"
esac