Skip to content

Instantly share code, notes, and snippets.

@luebking
Created January 12, 2025 15:07
Show Gist options
  • Select an option

  • Save luebking/053bd6fd8c5ba80252927e0859216fe8 to your computer and use it in GitHub Desktop.

Select an option

Save luebking/053bd6fd8c5ba80252927e0859216fe8 to your computer and use it in GitHub Desktop.
xkb layout switcher
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/XKBlib.h>
int main(int argc, char **argv) {
if (argc != 2) {
printf("Usage: %s list|<match>\nMatch is lazy, the first layout beginning with the token is chosen\n", argv[0]);
return False;
}
Display* dpy = XOpenDisplay(NULL);
XkbDescRec* kbdDescPtr = XkbAllocKeyboard();
if (!kbdDescPtr) {
printf("Failed to get keyboard description.\n");
return False;
}
kbdDescPtr->dpy = dpy;
int deviceId = XkbUseCoreKbd;
/* if (deviceId != XkbUseCoreKbd) {
kbdDescPtr->device_spec = deviceId;
} */
XkbGetControls(dpy, XkbAllControlsMask, kbdDescPtr);
XkbGetNames(dpy, XkbSymbolsNameMask|XkbGroupNamesMask, kbdDescPtr);
Atom* groupSource = kbdDescPtr->names->groups;
int groupCount = 0;
if (kbdDescPtr->ctrls) {
groupCount = kbdDescPtr->ctrls->num_groups;
} else {
while (groupCount < XkbNumKbdGroups && groupSource[groupCount]) {
++groupCount;
}
}
Atom* tmpGroupSource = kbdDescPtr->names->groups;
Atom curGroupAtom;
char* groupName;
int printList = (strncmp(argv[1], "list", 4) == 0);
for (int i = 0; i < groupCount; i++) {
if ((curGroupAtom = tmpGroupSource[i]) != None) {
groupName = XGetAtomName(dpy, curGroupAtom);
if (!groupName) {
continue;
}
if (printList) {
printf("%s\n", groupName);
} else if (strncmp(argv[1], groupName, strlen(argv[1])) == 0) {
printf ("Setting %s\n", groupName);
// printf ("%d\n", i);
XkbLockGroup(dpy, deviceId, i);
XFree(groupName);
XCloseDisplay(dpy);
return True;
}
XFree(groupName);
}
}
XCloseDisplay(dpy);
return printList;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment