summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSebastien Braun2010-10-05 14:09:40 +0200
committerSebastien Braun2010-10-05 18:15:49 +0200
commit7fb94c8d48d70c47bb6c292cb5b58bc76b3ee376 (patch)
treee12b2aca85a7038c60c6e1f4247b8a52584c8067 /src
parentFix forgotten NOT on test for Xkb presence (diff)
downloadpvs-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.
Diffstat (limited to 'src')
-rw-r--r--src/input/x11FakeKeyboardHandler.cpp77
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;