How do I turn off Caps Lock (the lock, not the key) by command line?
I don't know of any command line tool for that in Ubuntu. (For Num Lock, there is numlockx .) Here's a one-liner that you can copy-paste into a terminal window:
python -c 'from ctypes import *; X11 = cdll.LoadLibrary("libX11.so.6"); display = X11.XOpenDisplay(None); X11.XkbLockModifiers(display, c_uint(0x0100), c_uint(2), c_uint(0)); X11.XCloseDisplay(display)'
Here it is again in a more expanded form. We use the Python ctypes library to call C functions from the X library directly. The function XkbLockModifiers
changes the state of the keyboard locks, on the core keyboard (XkbUseCoreKbd
= 0x0100), affecting Caps Lock (2), setting it to 0 (off).
#!/usr/bin/env python
from ctypes import *
X11 = cdll.LoadLibrary("libX11.so.6")
display = X11.XOpenDisplay(None)
X11.XkbLockModifiers(display, c_uint(0x0100), c_uint(2), c_uint(0))
X11.XCloseDisplay(display)
If you have a stuck modifier, change 2 to the mask of the modifiers you want to turn off. The modifiers are 1=Shift, 2=Lock (Caps Lock), 4=Control, 8=Mod1, 16=Mod2, 32=Mod3, 64=Mod4, 128=Mod5. Run xmodmap -pm
to see what Mod1 through Mod5 correspond to. For example, to turn off all modifiers, call X11.XkbLockModifiers(display, c_uint(0x0100), c_uint(255), c_uint(0))
. To turn on Num Lock which is on Mod2 and at the same time turn off Caps Lock, call X11.XkbLockModifiers(display, c_uint(0x0100), c_uint(2 | 16), c_uint(16))
.
Here's a C version if you want to make a small binary instead of invoking Python. Compile with gcc -O -Wall -o caps_lock_off caps_lock_off.c -lX11
, with the packages build-essentials
and libx11-dev
installed.
#include <stdio.h>
#include <X11/X.h>
#include <X11/XKBlib.h>
int main()
{
Display *display = XOpenDisplay(NULL);
if (display == NULL) {
fprintf(stderr, "Couldn't open display\n");
return 2;
}
Bool sent = XkbLockModifiers(display, XkbUseCoreKbd, LockMask, 0);
if (!sent) {
fprintf(stderr, "Couldn't send LatchLockState\n");
return 1;
}
#ifdef REPORT_STATE
XkbStateRec xkb_state;
Status status = XkbGetState(display, XkbUseCoreKbd, &xkb_state);
if (status) {
fprintf(stderr, "XkbGetState returned %d\n", status);
return 1;
}
printf("state.group=%02x\n", xkb_state.group);
printf("state.locked_group=%02x\n", xkb_state.locked_group);
printf("state.base_group=%02x\n", xkb_state.base_group);
printf("state.latched_group=%02x\n", xkb_state.latched_group);
printf("state.mods=%02x\n", xkb_state.mods);
printf("state.base_mods=%02x\n", xkb_state.base_mods);
printf("state.latched_mods=%02x\n", xkb_state.latched_mods);
printf("state.locked_mods=%02x\n", xkb_state.locked_mods);
printf("state.compat_state=%02x\n", xkb_state.compat_state);
printf("state.grab_mods=%02x\n", xkb_state.grab_mods);
printf("state.compat_grab_mods=%02x\n", xkb_state.compat_grab_mods);
printf("state.lookup_mods=%02x\n", xkb_state.lookup_mods);
printf("state.compat_lookup_mods=%02x\n", xkb_state.compat_lookup_mods);
printf("state.ptr_buttons=%02x\n", xkb_state.ptr_buttons);
#endif
int err = XCloseDisplay(display);
if (err) {
fprintf(stderr, "XCloseDisplay returned %d\n", err);
return 1;
}
return 0;
}
Also possibly of interest is a way to temporarily ignore Caps Lock:
xkbset nullify lock
After this, Caps Lock will effectively be permanently off, until you reenable it with xkbset nullify -lock
.
Using Xorg automation
Xorg automation tools could be used for sending the required key events.
Note:
For first use, This solution needs you to tape the correct password to install new tool, if your CAPS is currently active:
- Use SHIFT key to type lowercase letters.
- Enable accessibility, overlay virtual keyboard.
- Re-plug an external keyboard. (Thanks to chris455)
- Open office writer, write password there, change the letter case, copy it, then paste it to password dialog.
If all previous options are not possible or don't work, Go with Gilles' answer / python script. It does not need to install any additional tool, it uses only
python
&libX11
shared lib which are pre-installed.
Using xdotool
-
Install it
sudo apt-get install xdotool
-
Send a CAPS down/up event
xdotool key Caps_Lock
Another tool is xte
-
Install it
sudo apt-get install xautomation
-
Send a CAPS lock down/up event
xte "key Caps_Lock"
References:
- Ubuntu Forums: Caps lock inverted
man xdotool
man xte
As for Gilles' Python version not working in newer Ubuntus, setting the correct return for the open display seems to do the trick:
#!/usr/bin/env python
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))
X11.XCloseDisplay(display)
(Code adapted from https://stackoverflow.com/questions/29638210/how-can-i-use-python-xlib-to-generate-a-single-keypress)