13

Whenever I plug in a USB keyboard, the layout of all keyboards is reset to some system default (a US layout which doesn't have modifiers and other keys the way I want them). I've observed this on many Debian and Ubuntu systems, including Ubuntu 16.04 and 18.04. This behavior has been around for a very long time.

I use X11 with no desktop environment (though some Gnome demons tend to get started). I set my keyboard layout with XKB (specifically … | xkbcomp - "$DISPLAY") when I log in.

When I insert a USB keyboard, I want it to have my layout, not the system layout. In fact, I wish the system would just keep using my current layout for both the already present keyboard(s) if any, and the newly inserted keyboard. If that's not possible, I'd settle for re-applying a layout that I chose.

Likewise the repeat rate on both keyboards is set to the login-time default instead of the rate I set with xset r.

How can I prevent a keyboard hotplug from resetting the keyboard layout and the repeat rate? Or failing that how can I at least make it reset to my chosen layout?

There's a fairly clumsy way which is with a udev rule. It's clumsy because it assumes that there's a single X server, and most problematically, it assumes that the user has root permission. I do not have root permissions, so any method that involves setting udev rules or editing Xorg.conf is inapplicable here.

  • 1
    Related: https://superuser.com/q/1290624/897702 –  Jun 07 '19 at 22:00
  • If all keyboard layouts (i.e. already plugged-in keyboards) get reset, I'd assume some of the Gnome stuff you (accidentally) started gets triggered by an existing udev rule. So to debug this, first I'd look at the existing udev rules on your system, and together with udevadm and putting udevd in debug mode (udev tracing is no fun) find out what exactly happens. Once you found that out, you can think of ways to disable it. – dirkt Jun 08 '19 at 07:58
  • 1
    The xinput and xinput2 X11 extensions let any client monitor when an input device is added or removed. There may be ready-made apps for that, but they're not great and what they do is trivial. Eg. inputplug -n -c /bin/echo. –  Jun 08 '19 at 09:01
  • If this is not your system and you don't have root access, this means some other person has root access and is admin for this system. Complain to this person and have him/her fix it. He/she might already know what is causing the layout reset... – dirkt Jun 09 '19 at 05:02
  • @dirkt I can reproduce the problem on my home machines where I'm root. I don't know what's causing it, but it's not some weird configuration on a specific machine. – Gilles 'SO- stop being evil' Jun 09 '19 at 08:21
  • If you can reproduce the problem on your home machine, you can also use your root permissions there to debug it, and investigate what's causing it (as I wrote in the other comment). You debug stuff by looking at what happens and narrowing it down until you find the culprit, not by guessing, or by adding workarounds which may fix the symptom, but not the cause. Yes, that takes effort, and you may need to learn about the parts of the system you are debugging. And nobody can do that except you. – dirkt Jun 09 '19 at 08:27
  • @dirkt Yes, I can reproduce this. But that doesn't mean I know what's going on. Narrowing down from where? I couldn't find anything in the system logs or in the X log that says “Hey, I saw you plug in a keyboard so I'm resetting all your keyboard settings.” The hint about udev debug mode you provided in a comment may help towards that, I haven't tried yet. – Gilles 'SO- stop being evil' Jun 09 '19 at 08:31
  • So please try. Yes, udev rule actions won't show up in any log, which is why udev rule debugging is no fun. But this is where all starts - the kernel produces an event that a new input USB device is available, and whatever goes wrong and loads new keyboard layouts for all devices happens in userspace and is eventually triggered by this event. – dirkt Jun 09 '19 at 08:35
  • @Gilles Notice that while I do use client-side xkb loading (with xkbcomp) just like you, I don't use inputplug, but my own program; I've just learned about and tested inputplug because of this Q, so I cannot vouch for it. YMMV. –  Jun 10 '19 at 08:54

2 Answers2

11

I set my keyboard layout with XKB (specifically … | xkbcomp - "$DISPLAY") when I log in.

How can I prevent a keyboard hotplug from resetting the keyboard layout and the repeat rate?

It's not that it resets it. If you already have a keyboard plugged in, and are adding a second one, the old keyboard will continue to use the same settings.

The problem is that the either the client-side way of loading an xkb configuration (with xkbcomp) or the server-side (with setxkbmap) will only apply the layout to the existing, actual devices, not to the "Core Keyboard" abstraction. When a device is unplugged, its settings are lost.

The solution is to monitor yourself when a keyboard is added, and call xkbcomp/setxkbmap and xset r rate with your preferred settings.

For that, you do not need any udev rule or any root privileges; any X11 client program can monitor changes to the input devices via the X11 Input extension and act on them.

A program which can be used from the shell for that and is readily installable with apt-get on Debian & similar distros is inputplug.

Example:

$ cat ./on-new-kbd
#! /bin/sh
keymap=/path/to/your/keymap

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

case "$event $type" in 'XIDeviceEnabled XISlaveKeyboard') xset r rate 200 50 xkbcomp -i "$id" "$keymap" "$DISPLAY" esac

$ chmod 755 ./on-new-kbd

$ inputplug -d -c ./on-new-kbd

<plug keyboard>

XIDeviceEnabled 13 XISlavePointer GASIA USB KB V11 XISlaveAdded 13 XIFloatingSlave GASIA USB KB V11 XISlaveAdded 14 XIFloatingSlave GASIA USB KB V11 XIDeviceEnabled 14 XISlaveKeyboard GASIA USB KB V11

Notice the -i option of xkbcomp -- you can use different settings for each keyboard. The protocol also allows to set the repeat rate on a per-device basis, but I don't know how to do that with xset.

Of course, your window manager / desktop environment may itself listen for those events and override your settings.

  • 1
    The OP said specifically the all keyboard layouts get reset when he plugs in a new keyboard. At least that's how I understood what he wrote. And the fact that all keyboard layouts get reset is the strange thing here. If the problem is indeed that only the new keyboard he plugs in gets the default layout and not the layout he already applied to the other keyboard, it's a completely different question. OP should edit his question and clarify. – dirkt Jun 11 '19 at 06:03
  • 1
    I don't care to do any second guessing (I didn't get any feedback, and that certainly doesn't happen on my machine), but an X11/XInput client can get a notification whenever a keyboard is added or removed, so my fix should just work even then (the -i id of xkbcomp can be omitted to apply the layout to all keyboards). –  Jun 11 '19 at 06:15
  • This reminds me of my old Nokia N810 where the silly DE will override my xkb settings with its crappy defaults whenever getting out of sleep, etc, and there's was no way to prevent it from doing that, and the only solution had been to modify its stock xkb layout under /usr/share/X11/.. –  Jun 11 '19 at 07:24
  • 2
    Love this solution over udev, a bit slower to react but that's good enough. I added the command to my ~/.xinitrc with full paths to inputplug and the script with the -d flag. – sberder Nov 13 '19 at 02:02
  • This solution is the shizniz! If you try to read the code of inputplug, I think it serves as proof of why this was so difficult to do before. It is quite incomprehensible - unless you you know a lot about X / xcb. – Ярослав Рахматуллин Dec 09 '20 at 23:32
2

I just ran into the same issue using a usb switch to share a keyboard between two systems. When I switch back into my Pop!_OS 20.04 LTS system, a Debian/Ubuntu derived system, I have settings disappear. I have been using gnome-tweak to set Caps Lock to act like a Ctrl.

This is the setting that kept acting up for me. I found this command line way to set it to what I want so I don't have to keep running gnome-tweak to fix the issue.

dconf write  /org/gnome/desktop/input-sources/xkb-options "['caps:ctrl_modifier']"

The man page for xkeyboard-config has a list of allowed values for xkb-options along with brief descriptions.

I don't know how to keep the issue from happening, but it is less annoying now that I can fix it from the command line.

AdminBee
  • 22,803
js9986
  • 21
  • If you have a more complex setup, you can see what you currently have set in the dconf database by "dconf read /org/gnome/desktop/input-sources/xkb-options" and use the results to construct your dconf write command line – js9986 Oct 13 '20 at 03:12