如何更改键盘布局(X11 API 解决方案)

发布于 2024-09-09 06:48:27 字数 48 浏览 5 评论 0原文

我想通过编程改变Linux中的键盘布局, X11的什么API函数可以实现这个功能?

I want to change keyboard layout in Linux by programming,
What X11's API function does this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

糖果控 2024-09-16 06:48:27

我找到了一个很好的解决方案。
这是由 Jay Bromley 编写的 C++ 类,我可以将其添加到我的应用程序中并使用它。

源代码

使用非常简单:

#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

您可以阅读源代码并发现其他一些有用的功能。
要编译独立版本,您需要取消注释“XKeyboard.cpp”中存在的“int main”函数(或编写您自己的 main.cpp)并使用如下内容:

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

I found one good solution.
It's a c++ class wrriten by Jay Bromley, that I can add to my app and using it.

source code

It's 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 source code and found some another useful functions.
for compiling standalone version you need to un-comments "int main" function present in "XKeyboard.cpp" (or write your own main.cpp) and use somethings like this:

g++ *.cpp -o getxkblayout -L/usr/lib -lX11
短暂陪伴 2024-09-16 06:48:27

我不确定 X11 库函数是什么,但 setxkbmap 是我用来实现它的 bash 命令。也许沿着这些线搜索会找到你想要的东西(或者在紧要关头你可以只执行 bash 命令)。

示例

setxkbmap dvorak
setxkbmap us

编辑:
经过一系列 setxkbmap 没有发现任何有用的信息后,我建议只调用:

system(“setxkbmap us”);

I'm not sure what the X11 library function is but setxkbmap is the bash command I use to achieve it. Maybe searching along these lines will find what you want (or at a pinch you could just execute the bash command).

Example

setxkbmap dvorak
setxkbmap us

EDIT:
After a strace of setxkbmap didn't turn up anything useful I suggest just calling:

system(“setxkbmap us”);
以可爱出名 2024-09-16 06:48:27

纯 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 标志进行编译

这将为英语(美国)qwerty 布局打印类似于 pc+us+inet(evdev) 的内容, pc+ru+us:2+inet(evdev) 用于俄语 йцукен 布局,pc+us(dvorak)+us:2+inet(evdev) 用于英语 dvorak布局。

A pure X11 API solution should look something like this:

#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);
}

Compile with -lX11 flag

This will print something like pc+us+inet(evdev) for English (USA) qwerty layout, pc+ru+us:2+inet(evdev) for Russian йцукен layout, pc+us(dvorak)+us:2+inet(evdev) for English dvorak layout.

怂人 2024-09-16 06:48:27

昨天我试图将 Google 的 xsecurelock 自动布局切换器设置为 EN。我尝试为 X11 api 找到一些现有的解决方案,但是...

所以我决定在 S. Razi 的帮助下编写自己的解决方案。
这是代码:(使用 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;
        }
    } 
}
}

在这里,您可以将 char* temp = "English" 更改为布局组的名称(例如:"Russian"),这个简单的代码将切换您当前的布局:)

Yesterday I was trying to make auto layuout switcher to EN for Google's xsecurelock. I tryed to find some existing solutions for X11 api, but...

So I decided to write my own with some help from 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 name of the group of your layout (exmp: "Russian"), and this simple code will switch your current layout :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文