Turning off the X server's CapsLock modifier

May 15, 2024

In the process of upgraded my office desktop to Fedora 40, I wound up needing to turn off the X server's CapsLock modifier. For people with a normal keyboard setup, this is simple; to turn off the CapsLock modifier, you tap the CapsLock key. However, I turn CapsLock into another Ctrl key (and then I make heavy use of tapping CapsLock to start dmenu (also)), which leaves the regular CapsLock functionality unavailable to me under normal circumstances. Since I don't have a CapsLock key, you might wonder how the CapsLock modifier got turned on in the first place.

The answer is that sometimes I have a CapsLock key after all. I turn CapsLock into Ctrl with setxkbmap settings, and apparently some Fedora packages clears these keyboard mapping settings when they're updated. Since upgrading to a new Fedora release updates all of these packages, my 'Ctrl' key resets to CapsLock during the process and I don't necessarily notice immediately. Because I expect my input settings to get cleared, I have a script to re-establish them, which I run when I notice my special Ctrl key handling isn't working. What happened this time around was that I noticed that my keyboard settings had been cleared when CapsLock didn't work as Ctrl, then reflexively invoked the script. Of course at this point I had tapped CapsLock, which turned on the CapsLock modifier, and then when the script reset CapsLock to be Ctrl, I no longer had a key that I could use to turn CapsLock off.

(Actually dealing with this situation was made more complicated by how I could now only type upper case letters in shells, browser windows, and so on. Fortunately I had a phone to do Internet searches on, and I could switch to another Linux virtual console, which had CapsLock off, and access the X server with 'export DISPLAY=:0' so I could run commands that talked to it.)

There are two solutions I wound up with, the narrow one and the general one. The narrow solution is to use xdotool to artificially send a CapsLock key down/up event with this:

xdotool key Caps_Lock

This will toggle the state of the CapsLock modifier in the X server, which will turn CapsLock off if it's currently on, as it was for me. This key down/up event works even if you have the CapsLock key remapped at the time, as I did, and you can run it from another virtual console with 'DISPLAY=:0 xdotool key Caps_Lock' (although you may need to vary the :0 bit). Or you can put it in a script called 'RESET-CAPSLOCK' so you can type its name with CapsLock active.

(Possibly I should give my 'reset-input' script an all-caps alias. It's also accessible from a window manager menu, but modifiers can make those inaccessible too.)

However, I'd like something to clear the CapsLock modifier that I can put in my 're-establish my keyboard settings' script, and since this xdotool trick only toggles the setting it's not suitable. Fortunately you can clear modifier states from an X client; unfortunately, as far as I know there's no canned 'capslockx' program the way there is a numlockx (which people have and use for good reasons). Fortunately, the same AskUbuntu question and answer that I got the xdotool invocation from also had a working Python program (you want the one from this answer by diegogs. For assorted reasons, I'm putting my current version of that Python program here:

from ctypes import *

class Display(Structure):
  """ opaque struct """

X11 = cdll.LoadLibrary("libX11.so.6")
X11.XOpenDisplay.restype = POINTER(Display)

display = X11.XOpenDisplay(c_int(0))
X11.XkbLockModifiers(display, c_uint(0x0100), c_uint(2), c_uint(0))

(There is also a C version in the question and answers, but you obviously have to compile it.)

In theory there is probably some way to reset the setxkbmap settings state so that CapsLock is a CapsLock key again (after all, package updates do it), which would have let me directly turn off CapsLock. In practice I couldn't find out how to do this in my flailing Internet searches so I went with the answer I could find. In retrospect I could might also have been able to reset settings by unplugging and replugging my USB keyboard or plugging in a second keyboard, and we do have random USB keyboards sitting around in the office.

Comments on this page:

By franklin at 2024-05-16 02:07:50:

I turn CapsLock into Ctrl with setxkbmap settings, and apparently some Fedora packages clears these keyboard mapping settings when they're updated.

That used to happen to me on Debian. The fix was to put my settings in /etc/default/keyboard instead: XKBOPTION="ctrl:swapcaps". It appears to be a cross-distro thing, so maybe something like that will work for you—I guess with "nocaps" instead of "swapcaps".

(The options are listed in /usr/share/X11/xkb/rules/base.lst in my system, and there's all kinds of fun stuff in there—from "Shift cancels Caps Lock" to "Right Win chooses 5th level and acts as a one-time lock if pressed with another 5th level chooser".)

By Ian Z aka nobrowser at 2024-05-16 13:11:01:

I turn Capslock into a Menu key, since at least two of my favorite keyboards have no physical Menu key. Not that I need it often, but I need Capslock even less; and for these very rare situations, I also turn on the option "both Shift keys together turn on Capslock".

xdotool is essential indeed. I dread the encroachment of Wayland where nothing like it exists, to my knowledge.

I could never understand that "5th level" stuff, though. Franklin, do you know what it does? Maybe it's only useful for typing Asian scripts?

By franklin at 2024-05-16 19:12:59:

I could never understand that "5th level" stuff, though. Franklin, do you know what it does?

Nope. Your guess is as good as mine.

The Wikipedia page for AltGr says "Shift" accesses a second level, "AltGr" a third, and both together a fourth. A web search reveals an Ubuntu thread about a fifth and sixth level, but I don't know whether that's a standard thing or just something for crazy keyboard hackers.

I see a "ydotool" in APT: "ydotool works differently from xdotool. xdotool sends X events directly to X server, while ydotool uses the uinput framework of Linux kernel to emulate an input device." So, I think that could work on Wayland. Remapping via /etc/default/keyboard should work there too; it does work at text-based Linux consoles.

Written on 15 May 2024.
« The X Window System and the curse of NumLock
Thoughts on (not) automating the setup of our first cloud server »

Page tools: View Source, View Normal, Add Comment.
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Wed May 15 23:05:12 2024
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.