xcb: simplify handling of keymap updates

The old code was somewhat too scattered.

Change-Id: Ib0445c66653f757ccac28778f34f4bcb5df49a70
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
Gatis Paeglis 2018-02-08 13:01:25 +01:00
parent 1a341d8333
commit 669070c404
3 changed files with 41 additions and 43 deletions

View File

@ -1132,7 +1132,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
m_keyboard->updateXKBStateFromCore(((xcb_key_release_event_t *)event)->state);
HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent);
case XCB_MAPPING_NOTIFY:
m_keyboard->handleMappingNotifyEvent(reinterpret_cast<xcb_mapping_notify_event_t *>(event));
m_keyboard->updateKeymap(reinterpret_cast<xcb_mapping_notify_event_t *>(event));
break;
case XCB_SELECTION_REQUEST:
{
@ -1220,7 +1220,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
handled = true;
break;
case XCB_XKB_MAP_NOTIFY:
m_keyboard->handleMappingNotifyEvent(&xkb_event->map_notify);
m_keyboard->updateKeymap();
handled = true;
break;
case XCB_XKB_NEW_KEYBOARD_NOTIFY: {

View File

@ -476,7 +476,7 @@ static QByteArray symbolsGroupString(const xcb_keysym_t *symbols, int count)
return groupString;
}
struct xkb_keymap *QXcbKeyboard::keymapFromCore()
struct xkb_keymap *QXcbKeyboard::keymapFromCore(const KeysymModifierMap &keysymMods)
{
/* Construct an XKB keymap string from information queried from
* the X server */
@ -602,7 +602,6 @@ struct xkb_keymap *QXcbKeyboard::keymapFromCore()
if (xkeymap.isEmpty())
return nullptr;
KeysymModifierMap keysymMods(keysymsToModifiers());
static const char *const builtinModifiers[] =
{ "Shift", "Lock", "Control", "Mod1", "Mod2", "Mod3", "Mod4", "Mod5" };
@ -719,8 +718,22 @@ struct xkb_keymap *QXcbKeyboard::keymapFromCore()
XKB_KEYMAP_COMPILE_NO_FLAGS);
}
void QXcbKeyboard::updateKeymap(xcb_mapping_notify_event_t *event)
{
if (connection()->hasXKB() || event->request == XCB_MAPPING_POINTER)
return;
xcb_refresh_keyboard_mapping(m_key_symbols, event);
updateKeymap();
}
void QXcbKeyboard::updateKeymap()
{
KeysymModifierMap keysymMods;
if (!connection()->hasXKB())
keysymMods = keysymsToModifiers();
updateModifiers(keysymMods);
m_config = true;
if (!m_xkbContext) {
@ -743,7 +756,7 @@ void QXcbKeyboard::updateKeymap()
m_xkbState.reset(xkb_x11_state_new_from_device(m_xkbKeymap.get(), xcb_connection(), core_device_id));
} else {
#endif
m_xkbKeymap.reset(keymapFromCore());
m_xkbKeymap.reset(keymapFromCore(keysymMods));
if (m_xkbKeymap)
m_xkbState.reset(xkb_state_new(m_xkbKeymap.get()));
#if QT_CONFIG(xkb)
@ -1152,8 +1165,6 @@ QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection)
#if QT_CONFIG(xkb)
core_device_id = 0;
if (connection->hasXKB()) {
updateVModMapping();
updateVModToRModMapping();
core_device_id = xkb_x11_get_core_keyboard_device_id(xcb_connection());
if (core_device_id == -1) {
qWarning("Qt: couldn't get core keyboard device info");
@ -1162,7 +1173,6 @@ QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection)
} else {
#endif
m_key_symbols = xcb_key_symbols_alloc(xcb_connection());
updateModifiers();
#if QT_CONFIG(xkb)
}
#endif
@ -1171,7 +1181,7 @@ QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection)
QXcbKeyboard::~QXcbKeyboard()
{
if (!connection()->hasXKB())
if (m_key_symbols)
xcb_key_symbols_free(m_key_symbols);
}
@ -1297,8 +1307,6 @@ void QXcbKeyboard::updateVModToRModMapping()
else if (vmod_masks.hyper == bit)
rmod_masks.hyper = modmap;
}
resolveMaskConflicts();
#endif
}
@ -1309,21 +1317,24 @@ static inline void applyModifier(uint *mask, int modifierBit)
*mask |= 1 << modifierBit;
}
void QXcbKeyboard::updateModifiers()
void QXcbKeyboard::updateModifiers(const KeysymModifierMap &keysymMods)
{
memset(&rmod_masks, 0, sizeof(rmod_masks));
// Compute X modifier bits for Qt modifiers
KeysymModifierMap keysymMods(keysymsToModifiers());
applyModifier(&rmod_masks.alt, keysymMods.value(XKB_KEY_Alt_L, -1));
applyModifier(&rmod_masks.alt, keysymMods.value(XKB_KEY_Alt_R, -1));
applyModifier(&rmod_masks.meta, keysymMods.value(XKB_KEY_Meta_L, -1));
applyModifier(&rmod_masks.meta, keysymMods.value(XKB_KEY_Meta_R, -1));
applyModifier(&rmod_masks.altgr, keysymMods.value(XKB_KEY_Mode_switch, -1));
applyModifier(&rmod_masks.super, keysymMods.value(XKB_KEY_Super_L, -1));
applyModifier(&rmod_masks.super, keysymMods.value(XKB_KEY_Super_R, -1));
applyModifier(&rmod_masks.hyper, keysymMods.value(XKB_KEY_Hyper_L, -1));
applyModifier(&rmod_masks.hyper, keysymMods.value(XKB_KEY_Hyper_R, -1));
if (connection()->hasXKB()) {
updateVModMapping();
updateVModToRModMapping();
} else {
memset(&rmod_masks, 0, sizeof(rmod_masks));
// Compute X modifier bits for Qt modifiers
applyModifier(&rmod_masks.alt, keysymMods.value(XKB_KEY_Alt_L, -1));
applyModifier(&rmod_masks.alt, keysymMods.value(XKB_KEY_Alt_R, -1));
applyModifier(&rmod_masks.meta, keysymMods.value(XKB_KEY_Meta_L, -1));
applyModifier(&rmod_masks.meta, keysymMods.value(XKB_KEY_Meta_R, -1));
applyModifier(&rmod_masks.altgr, keysymMods.value(XKB_KEY_Mode_switch, -1));
applyModifier(&rmod_masks.super, keysymMods.value(XKB_KEY_Super_L, -1));
applyModifier(&rmod_masks.super, keysymMods.value(XKB_KEY_Super_R, -1));
applyModifier(&rmod_masks.hyper, keysymMods.value(XKB_KEY_Hyper_L, -1));
applyModifier(&rmod_masks.hyper, keysymMods.value(XKB_KEY_Hyper_R, -1));
}
resolveMaskConflicts();
}
@ -1650,17 +1661,4 @@ void QXcbKeyboard::handleKeyReleaseEvent(const xcb_key_release_event_t *e)
handleKeyEvent(e->event, QEvent::KeyRelease, e->detail, e->state, e->time, fromSendEvent(e));
}
void QXcbKeyboard::handleMappingNotifyEvent(const void *event)
{
updateKeymap();
if (connection()->hasXKB()) {
updateVModMapping();
updateVModToRModMapping();
} else {
void *ev = const_cast<void *>(event);
xcb_refresh_keyboard_mapping(m_key_symbols, static_cast<xcb_mapping_notify_event_t *>(ev));
updateModifiers();
}
}
QT_END_NAMESPACE

View File

@ -64,9 +64,9 @@ public:
void handleKeyPressEvent(const xcb_key_press_event_t *event);
void handleKeyReleaseEvent(const xcb_key_release_event_t *event);
void handleMappingNotifyEvent(const void *event);
Qt::KeyboardModifiers translateModifiers(int s) const;
void updateKeymap(xcb_mapping_notify_event_t *event);
void updateKeymap();
QList<int> possibleKeys(const QKeyEvent *e) const;
@ -94,11 +94,11 @@ protected:
int keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers modifiers,
struct xkb_state *state, xcb_keycode_t code) const;
struct xkb_keymap *keymapFromCore();
typedef QMap<xcb_keysym_t, int> KeysymModifierMap;
struct xkb_keymap *keymapFromCore(const KeysymModifierMap &keysymMods);
// when XKEYBOARD not present on the X server
void updateModifiers();
typedef QMap<xcb_keysym_t, int> KeysymModifierMap;
void updateModifiers(const KeysymModifierMap &keysymMods);
KeysymModifierMap keysymsToModifiers();
// when XKEYBOARD is present on the X server
void updateVModMapping();
@ -122,7 +122,7 @@ private:
_mod_masks rmod_masks;
// when XKEYBOARD not present on the X server
xcb_key_symbols_t *m_key_symbols;
xcb_key_symbols_t *m_key_symbols = nullptr;
struct _xkb_mods {
xkb_mod_index_t shift;
xkb_mod_index_t lock;