【发布时间】:2016-05-24 12:24:47
【问题描述】:
使用XKeycodeToKeysym(在 C++ 中)我可以获得按键事件的 KeySym。据我了解,这已经应该尊重键盘布局。但是,当我切换键盘布局(在英语和希伯来语之间)时,我得到了相同的 KeySym。我怀疑 Xlib Keysym 只支持 X11 级别中定义的键盘布局?在我的系统中,键盘布局仅在桌面环境级别(Mate)中定义。如果是这样,有没有办法在不使用 Qt / GTK 之类的工具包的情况下获得正确的字符?我必须分别处理每个桌面环境吗?
[编辑]
我尝试了以下方法(根据 Andrey 的建议),但不起作用:
#include <X11/XKBlib.h>
#include <cstring>
#include <cassert>
#include <iostream>
int main() {
Display *display = XOpenDisplay(nullptr);
Window root, window;
XSetWindowAttributes swa;
root = DefaultRootWindow( display );
XSelectInput( display, root, MappingNotify );
std::memset(&swa, 0, sizeof swa );
swa.event_mask = MappingNotify | KeyPressMask;
window = XCreateWindow( display, root, 50, 200, 1024, 768, 0, CopyFromParent, InputOutput, CopyFromParent,
CWEventMask, &swa );
XMapRaised( display, window );
int xkbEventCode=0, n0=0, n1=0, n2=0, n3=0;
bool isOk = XkbQueryExtension( display, &n0, &xkbEventCode, &n1, &n2, &n3 ) ==True;
assert( isOk );
isOk = XkbSelectEvents( display, XkbUseCoreKbd, XkbAllEventsMask, XkbAllEventsMask ) ==True;
assert( isOk );
while (true) {
XEvent event;
std::memset( &event, 0, sizeof event );
XNextEvent( display, &event );
if (event.type == xkbEventCode)
switch (reinterpret_cast<XkbEvent*>(&event)->any.xkb_type) {
case XkbNewKeyboardNotify:
case XkbMapNotify: {
std::cout << "Keyboard mapping has changed." << std::endl;
break;
}
default: break;
}
else
switch (event.type) {
case KeyPress: {
KeyCode keyCode = event.xkey.keycode;
int keySymsPerkeyCode=0;
KeySym *keySyms( XGetKeyboardMapping(display, keyCode, 1, &keySymsPerkeyCode)),
*keySym = keySyms;
while (keySymsPerkeyCode-- && *keySym != NoSymbol) {
std::cout << *keySym << std::endl;
++keySym;
}
XFree( keySyms );
break;
}
case MappingNotify: {
std::cout << "Keyboard mapping has changed." << std::endl;
break;
}
default: break;
}
}
return 0;
}
【问题讨论】:
标签: c++ linux internationalization x11 xlib