diff options
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbkeyboard.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbkeyboard.cpp | 69 |
1 files changed, 48 insertions, 21 deletions
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 14893d9acc..d1729ed168 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -575,7 +575,7 @@ static const Qt::KeyboardModifiers ModsTbl[] = { Qt::AltModifier | Qt::ShiftModifier, // 5 Qt::AltModifier | Qt::ControlModifier, // 6 Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier, // 7 - Qt::NoModifier // Fall-back to raw Key_* + Qt::NoModifier // Fall-back to raw Key_*, for non-latin1 kb layouts }; Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) const @@ -594,8 +594,9 @@ Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) const return ret; } -void QXcbKeyboard::readXKBConfig(struct xkb_rule_names *xkb_names) +void QXcbKeyboard::readXKBConfig() { + clearXKBConfig(); xcb_generic_error_t *error; xcb_get_property_cookie_t cookie; xcb_get_property_reply_t *config_reply; @@ -626,15 +627,30 @@ void QXcbKeyboard::readXKBConfig(struct xkb_rule_names *xkb_names) length -= len + 1; } while (p < end || i < 5); - xkb_names->rules = qstrdup(names[0]); - xkb_names->model = qstrdup(names[1]); - xkb_names->layout = qstrdup(names[2]); - xkb_names->variant = qstrdup(names[3]); - xkb_names->options = qstrdup(names[4]); + xkb_names.rules = qstrdup(names[0]); + xkb_names.model = qstrdup(names[1]); + xkb_names.layout = qstrdup(names[2]); + xkb_names.variant = qstrdup(names[3]); + xkb_names.options = qstrdup(names[4]); free(config_reply); } +void QXcbKeyboard::clearXKBConfig() +{ + if (xkb_names.rules) + delete[] xkb_names.rules; + if (xkb_names.model) + delete[] xkb_names.model; + if (xkb_names.layout) + delete[] xkb_names.layout; + if (xkb_names.variant) + delete[] xkb_names.variant; + if (xkb_names.options) + delete[] xkb_names.options; + memset(&xkb_names, 0, sizeof(xkb_names)); +} + void QXcbKeyboard::updateKeymap() { m_config = true; @@ -646,22 +662,13 @@ void QXcbKeyboard::updateKeymap() return; } } - - struct xkb_rule_names xkb_names = {0, 0, 0, 0, 0}; - - readXKBConfig(&xkb_names); + readXKBConfig(); // Compile a keymap from RMLVO (rules, models, layouts, variants and options) names if (xkb_keymap) xkb_keymap_unref(xkb_keymap); xkb_keymap = xkb_keymap_new_from_names(xkb_context, &xkb_names, (xkb_keymap_compile_flags)0); - delete[] xkb_names.rules; - delete[] xkb_names.model; - delete[] xkb_names.layout; - delete[] xkb_names.variant; - delete[] xkb_names.options; - if (!xkb_keymap) { qWarning("Qt: Failed to compile a keymap"); m_config = false; @@ -835,7 +842,7 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const xkb_mod_index_t controlMod = xkb_keymap_mod_get_index(xkb_keymap, "Control"); xkb_mod_mask_t depressed; - + struct xkb_keymap *fallback_keymap = 0; int qtKey = 0; //obtain a list of possible shortcuts for the given key event for (uint i = 1; i < sizeof(ModsTbl) / sizeof(*ModsTbl) ; ++i) { @@ -851,8 +858,23 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const depressed |= (1 << controlMod); // update a keyboard state from a set of explicit masks - xkb_state_update_mask(kb_state, depressed, latchedMods, lockedMods, - baseLayout, latchedLayout, lockedLayout); + if (i == 8) { + // Add a fall back key for layouts with non Latin-1 characters + if (baseQtKey > 255) { + struct xkb_rule_names names = { xkb_names.rules, xkb_names.model, "us", 0, 0 }; + fallback_keymap = xkb_keymap_new_from_names(xkb_context, &names, (xkb_keymap_compile_flags)0); + if (!fallback_keymap) + continue; + xkb_state_unref(kb_state); + kb_state = xkb_state_new(fallback_keymap); + if (!kb_state) + continue; + } else + continue; + } else { + xkb_state_update_mask(kb_state, depressed, latchedMods, lockedMods, + baseLayout, latchedLayout, lockedLayout); + } sym = xkb_state_key_get_one_sym(kb_state, event->nativeScanCode()); if (sym == XKB_KEY_NoSymbol) @@ -867,8 +889,11 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const result += (qtKey + mods); } } + if (kb_state) + xkb_state_unref(kb_state); + if (fallback_keymap) + xkb_keymap_unref(fallback_keymap); - xkb_state_unref(kb_state); return result; } @@ -938,6 +963,7 @@ QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection) , core_device_id(0) #endif { + memset(&xkb_names, 0, sizeof(xkb_names)); updateKeymap(); #ifndef QT_NO_XKB if (connection->hasXKB()) { @@ -979,6 +1005,7 @@ QXcbKeyboard::~QXcbKeyboard() #ifdef QT_NO_XKB xcb_key_symbols_free(m_key_symbols); #endif + clearXKBConfig(); } #ifndef QT_NO_XKB |