How to change keyboard layout (X11 API solution)

I want to change the keyboard layout on Linux by programming. What is the function of the X11 API?

+3
source share
4 answers

I found one good solution. This is a C ++ class written by Jay Bromley that I can add to my application and use it.

source

It is very easy to use:

#include "XKeyboard.h"

XKeyboard xkb;

std::string cGrpName=xkb.currentGroupName(); //return somethings like "USA"
std::string cGrpSymb=xkb.currentGroupSymbol(); //return somethings like "us"

xkb.setGroupByNum(0);//set keyboard layout to first layout in available ones

you can read the source code and find another useful feature. to compile the standalone version you need to disable the "int main" function present in "XKeyboard.cpp" (or write your own main.cpp file) and use things like this:

g++ *.cpp -o getxkblayout -L/usr/lib -lX11
+4
source

, X11, setxkbmap - bash, . , , ( bash).

setxkbmap dvorak
setxkbmap us

: , strace setxkbmap , :

system("setxkbmap us");
+2

X11 API :

#include <stdio.h>
#include <X11/XKBlib.h>

int main() {
    Display* _display;
    char* displayName = "";
    _display = XOpenDisplay(displayName);

    XkbDescRec* _kbdDescPtr = XkbAllocKeyboard();
    XkbGetNames(_display, XkbSymbolsNameMask, _kbdDescPtr);
    Atom symName = _kbdDescPtr -> names -> symbols;
    char* layoutString = XGetAtomName(_display, symName);

    XCloseDisplay(_display);
    printf("%s\n", layoutString);
}

-lX11

- pc+us+inet(evdev) () qwerty layout, pc+ru+us:2+inet(evdev) , pc+us(dvorak)+us:2+inet(evdev) dvorak.

+2

EN Google xsecurelock. X11 api, ...

So I decided to write my own with the help of S. Razi. Here is the code: (run with gcc -lX11)

#include <stdio.h>
#include <stdlib.h>
#include <X11/XKBlib.h>

int main(){

Display* _display;
char* displayName = "";
_display = XOpenDisplay(displayName);

int _deviceId = XkbUseCoreKbd;
int i = 0;
int _groupCount = 0;

XkbDescRec* kbdDescPtr = XkbAllocKeyboard();
if (kbdDescPtr == NULL) {
printf("%s\n", "Failed to get keyboard description."); 
return False;
}

kbdDescPtr->dpy = _display;
if (_deviceId != XkbUseCoreKbd) {
    kbdDescPtr->device_spec = _deviceId;
}

XkbGetControls(_display, XkbAllControlsMask, kbdDescPtr);
XkbGetNames(_display, XkbSymbolsNameMask, kbdDescPtr);
XkbGetNames(_display, XkbGroupNamesMask, kbdDescPtr);

         /* count groups */

Atom* groupSource = kbdDescPtr->names->groups;
if (kbdDescPtr->ctrls != NULL) {
    _groupCount = kbdDescPtr->ctrls->num_groups;
} else {
    _groupCount = 0;
    while (_groupCount < XkbNumKbdGroups &&
           groupSource[_groupCount] != 0) {
        _groupCount++;
    }
}

        /* get group names */
Atom* tmpGroupSource = kbdDescPtr->names->groups;
Atom curGroupAtom;
char* groupName;
for (i = 0; i < _groupCount; i++) {
    if ((curGroupAtom = tmpGroupSource[i]) != None) {
        char* groupNameC = XGetAtomName(_display, curGroupAtom);
            if (groupNameC == NULL) {
            continue;

        } else {
            groupName =  groupNameC;
            char *temp = "English";

            if (strncmp(temp, groupName, 7) == 0){
                printf ("%s\n", groupName);
                printf ("%d\n", i);
                XkbLockGroup(_display, _deviceId, i);
                XFree(groupNameC);
                XCloseDisplay(_display);
            }
            return 0;
        }
    } 
}
}

Here you can change char * temp = "English" to the name of the group of your layout (exmp: "Russian"), and this simple code will switch your current layout :)

0
source

Source: https://habr.com/ru/post/1754270/


All Articles