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:
parent
dbe5306c2c
commit
b212fc80a7
@ -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:
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user