Using XKeycodeToKeysym
(in C++) I can get the KeySym for a key-press event. From what I understand this already should respect the keyboard layout. However, when I switch a keyboard layout (between english and hebrew) I get the same KeySym. I suspect that the Xlib Keysym only honors keyboard layout defined in the X11 level? In my system the keyboard layouts are defined only in the desktop environment level (Mate). And if so, is there any way to get the correct character without using a toolkit like Qt / GTK? Must I handle each desktop environment separately?
[Edit]
I've tried the following (according to Andrey's suggestion), which doesn't work:
#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;
}