From 7fb94c8d48d70c47bb6c292cb5b58bc76b3ee376 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Tue, 5 Oct 2010 14:09:40 +0200 Subject: Fix Xkb handling on certain systems. On some systems XTEST events are delivered via a special input device that may be configured with a different keymap than the physical keyboard. This patch fixes the keycode lookup to take the XTEST device into account. --- src/input/x11FakeKeyboardHandler.cpp | 77 +++++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/input/x11FakeKeyboardHandler.cpp b/src/input/x11FakeKeyboardHandler.cpp index 95e83ab..82cc437 100644 --- a/src/input/x11FakeKeyboardHandler.cpp +++ b/src/input/x11FakeKeyboardHandler.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include "x11InputUtils.h" @@ -502,14 +503,64 @@ void initialize_basic_keycodes() } else { + // Try to find out what device XTest will send events on: + int xkbDeviceId = XkbUseCoreKbd; + Atom xtestDeviceProp = XInternAtom(dpy, "XTEST Device", false); + int ndevinfos; + XIDeviceInfo* devinfos = XIQueryDevice(dpy, XIAllDevices, &ndevinfos); + if(devinfos) + { + for(int i = 0; i < ndevinfos && xkbDeviceId == XkbUseCoreKbd; i++) + { + XIDeviceInfo* devinfo = devinfos + i; + qDebug("Found device of type %d with name %s", devinfo->use, devinfo->name); + + // We want it to be a keyboard. + if(devinfo->use != XIMasterKeyboard && devinfo->use != XISlaveKeyboard) + continue; + + int nprops; + Atom* props = XIListProperties(dpy, devinfo->deviceid, &nprops); + if(props) + { + for(int j = 0; j < nprops && xkbDeviceId == XkbUseCoreKbd; j++) + { + Atom prop = props[j]; + if(prop == xtestDeviceProp) + { + // The device is the XTest Keyboard: + xkbDeviceId = devinfo->deviceid; + } + } + XFree(props); + } + } + XIFreeDeviceInfo(devinfos); + } + + // Okay, we know which device to query. Now get its keymap: + XkbDescPtr keybDesc = XkbGetKeyboard(dpy, XkbAllComponentsMask, xkbDeviceId); + if(!keybDesc) + { + qWarning("Unable to retrieve keyboard description for device %d. Falling back to unreliable global mapping", xkbDeviceId); + } + for(int i = min_keycode; i <= max_keycode; i++) { for(int j = 0; j <= 0xff; j++) { KeySym ks = 0; unsigned int unconsumed; - if(!XkbLookupKeySym(dpy, i, j, &unconsumed, &ks) || ks == NoSymbol) - continue; + if(keybDesc) + { + if(!XkbTranslateKeyCode(keybDesc, i, j, &unconsumed, &ks) || ks == NoSymbol) + continue; + } + else + { + if(!XkbLookupKeySym(dpy, i, j, &unconsumed, &ks) || ks == NoSymbol) + continue; + } if(ks && (ks < 0x100)) { @@ -527,6 +578,12 @@ void initialize_basic_keycodes() } } } + + // Free the keyboard description: + if(keybDesc) + { + XkbFreeKeyboard(keybDesc, XkbAllComponentsMask, true); + } } // find out which keycodes cause the modifier state bits: @@ -750,10 +807,18 @@ void X11FakeKeyboardHandler::handle(InputEvent const& evt) xmodifier_type mods = translate_modifiers(evt.qt_modifiers()); // we may need to press additional modifiers to generate this keysym: - // but, since we do not differentiate upper and lower case, - // and instead let the sender handle those modifiers, - // we need to AND ShiftModifier and LockModifier out. - mods |= basic_modifiers[ks] & ~(1<