Resolve modifier mask conflicts on X11

On X11 key codes and modifiers can have many-to-many relationship, i.e.
a key can activate several modifiers, and a modifier may be activated
by several keys. This patch handles these cases, the logic is borrowed from Qt4.

Task-number: QTBUG-31572
Change-Id: Ide4eb890ec723c68afafe0576d8285440a47d7b0
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
Gatis Paeglis 2013-07-01 14:08:32 +02:00 committed by The Qt Project
parent dbe5306c2c
commit b212fc80a7
2 changed files with 37 additions and 1 deletions

View File

@ -1035,6 +1035,10 @@ void QXcbKeyboard::updateVModMapping()
vmod_masks.meta = bit;
else if (qstrcmp(vmod_name, "AltGr") == 0)
vmod_masks.altgr = bit;
else if (qstrcmp(vmod_name, "Super") == 0)
vmod_masks.super = bit;
else if (qstrcmp(vmod_name, "Hyper") == 0)
vmod_masks.hyper = bit;
}
free(name_reply);
@ -1096,9 +1100,14 @@ void QXcbKeyboard::updateVModToRModMapping()
rmod_masks.meta = modmap;
else if (vmod_masks.altgr == bit)
rmod_masks.altgr = modmap;
else if (vmod_masks.super == bit)
rmod_masks.super = modmap;
else if (vmod_masks.hyper == bit)
rmod_masks.hyper = modmap;
}
free(map_reply);
resolveMaskConflicts();
}
#else
void QXcbKeyboard::updateModifiers()
@ -1123,7 +1132,8 @@ void QXcbKeyboard::updateModifiers()
// for Alt and Meta L and R are the same
static const xcb_keysym_t symbols[] = {
XK_Alt_L, XK_Meta_L, XK_Mode_switch
XK_Alt_L, XK_Meta_L, XK_Mode_switch, XK_Super_L, XK_Super_R,
XK_Hyper_L, XK_Hyper_R
};
static const size_t numSymbols = sizeof symbols / sizeof *symbols;
@ -1149,6 +1159,10 @@ void QXcbKeyboard::updateModifiers()
rmod_masks.meta = mask;
if (sym == XK_Mode_switch)
rmod_masks.altgr = mask;
if ((sym == XK_Super_L) || (sym == XK_Super_R))
rmod_masks.super = mask;
if ((sym == XK_Hyper_L) || (sym == XK_Hyper_R))
rmod_masks.hyper = mask;
}
}
}
@ -1157,9 +1171,28 @@ void QXcbKeyboard::updateModifiers()
for (size_t i = 0; i < numSymbols; ++i)
free(modKeyCodes[i]);
free(modMapReply);
resolveMaskConflicts();
}
#endif
void QXcbKeyboard::resolveMaskConflicts()
{
// if we don't have a meta key (or it's hidden behind alt), use super or hyper to generate
// Qt::Key_Meta and Qt::MetaModifier, since most newer XFree86/Xorg installations map the Windows
// key to Super
if (rmod_masks.alt == rmod_masks.meta)
rmod_masks.meta = 0;
if (rmod_masks.meta == 0) {
// no meta keys... s/meta/super,
rmod_masks.meta = rmod_masks.super;
if (rmod_masks.meta == 0) {
// no super keys either? guess we'll use hyper then
rmod_masks.meta = rmod_masks.hyper;
}
}
}
class KeyChecker
{
public:

View File

@ -84,6 +84,7 @@ public:
protected:
void handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycode_t code, quint16 state, xcb_timestamp_t time);
void resolveMaskConflicts();
QString keysymToUnicode(xcb_keysym_t sym) const;
@ -111,6 +112,8 @@ private:
uint alt;
uint altgr;
uint meta;
uint super;
uint hyper;
};
_mod_masks rmod_masks;