diff options
| author | Sebastien Braun | 2010-10-05 14:09:40 +0200 |
|---|---|---|
| committer | Sebastien Braun | 2010-10-05 18:15:49 +0200 |
| commit | 7fb94c8d48d70c47bb6c292cb5b58bc76b3ee376 (patch) | |
| tree | e12b2aca85a7038c60c6e1f4247b8a52584c8067 | |
| parent | Fix forgotten NOT on test for Xkb presence (diff) | |
| download | pvs-7fb94c8d48d70c47bb6c292cb5b58bc76b3ee376.tar.gz pvs-7fb94c8d48d70c47bb6c292cb5b58bc76b3ee376.tar.xz pvs-7fb94c8d48d70c47bb6c292cb5b58bc76b3ee376.zip | |
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.
| -rw-r--r-- | src/input/x11FakeKeyboardHandler.cpp | 77 |
1 files changed, 71 insertions, 6 deletions
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 <X11/keysym.h> #include <X11/keysymdef.h> #include <X11/extensions/XTest.h> +#include <X11/extensions/XInput2.h> #include <X11/XKBlib.h> #include <src/util/consoleLogger.h> #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<<ShiftMapIndex) & ~(1<<LockMapIndex); + if(isalpha(ks)) + { + // 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<<ShiftMapIndex) & ~(1<<LockMapIndex); + } + else + { + // Not an alpha character. We do need to respect Shift and Lock for those: + mods |= basic_modifiers[ks]; + } // now, tweak the modifiers tweak_sequence_type tweaks; |
