From d5abf545971da717014d316127045fc19edbcd65 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Thu, 4 Jan 2018 18:50:59 +0100 Subject: xcb: re-factor QXcbKeyboard::updateKeymap() to remove various fallbacks 3edcd9420e3ad661cad89420e18dbb70e7ad450b added more robust support for keyboard input on XKeyboard-less X servers. The various fallbacks that we had did not work that well in practice. We can remove them now. The xkb_keymap_new_from_names() function relies on reading XKB config files from a file system. Since we don't use this function anymore, we can also simplify xkb context creation (see XKB_CONTEXT_NO_DEFAULT_INCLUDES), as we don't care about DFLT_XKB_CONFIG_ROOT (which we previously set via -xkb-config-root for the bundled libxkbcommon). This patch also changes the code to use smart pointers for managing the global xkb context, keymap and state. [ChangeLog][X11] The -xkb-config-root command line switch has been removed as it it no longer needed when configuring with -qt-xkbcommon-x11. Change-Id: I80eecf83adae90af5cd20df434c1fba0358a12fd Reviewed-by: Shawn Rutledge --- config_help.txt | 2 - src/3rdparty/xkbcommon.pri | 2 +- src/gui/configure.json | 23 +-- src/gui/configure.pri | 15 -- src/plugins/platforms/xcb/qxcbkeyboard.cpp | 224 ++++++++--------------------- src/plugins/platforms/xcb/qxcbkeyboard.h | 21 +-- 6 files changed, 71 insertions(+), 216 deletions(-) diff --git a/config_help.txt b/config_help.txt index f61601ec7a..3e2c0c61b0 100644 --- a/config_help.txt +++ b/config_help.txt @@ -298,8 +298,6 @@ Gui, printing, widget options: -xinput2 ........... Enable XInput2 support [auto] -xkbcommon-x11 ..... Select xkbcommon used in combination with xcb [system/qt/no] - -xkb-config-root ... With -qt-xkbcommon-x11, set default XKB config - root [detect] -xkbcommon-evdev ... Enable X-less xkbcommon in combination with libinput [auto] diff --git a/src/3rdparty/xkbcommon.pri b/src/3rdparty/xkbcommon.pri index af71b232d5..1d953d8372 100644 --- a/src/3rdparty/xkbcommon.pri +++ b/src/3rdparty/xkbcommon.pri @@ -6,7 +6,7 @@ INCLUDEPATH += $$PWD/xkbcommon \ include($$shadowed($$PWD/../gui/qtgui-config.pri)) -DEFINES += DFLT_XKB_CONFIG_ROOT='\\"$$QMAKE_XKB_CONFIG_ROOT\\"' +DEFINES += DFLT_XKB_CONFIG_ROOT='\\"/usr/share/X11/xkb\\"' # unused, but needs to be set to something ### RMLVO names can be overwritten with environmental variables (see libxkbcommon documentation) DEFINES += DEFAULT_XKB_RULES='\\"evdev\\"' diff --git a/src/gui/configure.json b/src/gui/configure.json index 27e913877f..220662ea8e 100644 --- a/src/gui/configure.json +++ b/src/gui/configure.json @@ -46,7 +46,6 @@ "xcb-xlib": "boolean", "xinput2": "boolean", "xkb": "boolean", - "xkb-config-root": "string", "xkbcommon": { "type": "enum", "values": [ "no", "qt", "system" ] }, "xkbcommon-evdev": "boolean", "xkbcommon-x11": { "type": "enum", "name": "xkbcommon", "values": [ "no", "qt", "system" ] } @@ -624,8 +623,7 @@ }, "testTypeAliases": { - "files": [ "directX" ], - "getPkgConfigVariable": [ "xkbConfigRoot" ] + "files": [ "directX" ] }, "tests": { @@ -888,13 +886,6 @@ "value": "/usr", "log": "value" }, - "xkbconfigroot": { - "label": "XKB config root", - "type": "xkbConfigRoot", - "pkg-config-args": "xkeyboard-config", - "pkg-config-variable": "xkb_base", - "log": "value" - }, "xlib": { "label": "XLib", "type": "compile", @@ -1355,12 +1346,6 @@ "condition": "libs.xkbcommon_x11", "output": [ "privateFeature" ] }, - "xkb-config-root": { - "label": "XKB config root", - "emitIf": "features.xcb", - "condition": "features.xcb && !features.xkbcommon-system && tests.xkbconfigroot", - "output": [ { "type": "varAssign", "name": "QMAKE_XKB_CONFIG_ROOT", "value": "tests.xkbconfigroot.value"} ] - }, "xlib": { "label": "XLib", "autoDetect": "!config.darwin || features.xcb", @@ -1579,12 +1564,6 @@ ], "report": [ - { - "type": "warning", - "condition": "features.xcb && !features.xkbcommon-system && !features.xkb-config-root", - "message": "Could not find XKB config root, use -xkb-config-root to set a path to -XKB configuration data. This is required for keyboard input support." - }, { "type": "note", "condition": "features.xcb && config.darwin", diff --git a/src/gui/configure.pri b/src/gui/configure.pri index aaffa835dc..fcd2d1f73e 100644 --- a/src/gui/configure.pri +++ b/src/gui/configure.pri @@ -42,21 +42,6 @@ defineTest(qtConfTest_directX) { return(false) } -defineTest(qtConfTest_xkbConfigRoot) { - qtConfTest_getPkgConfigVariable($${1}): return(true) - - for (dir, $$list("/usr/share/X11/xkb", "/usr/local/share/X11/xkb")) { - exists($$dir) { - $${1}.value = $$dir - export($${1}.value) - $${1}.cache += value - export($${1}.cache) - return(true) - } - } - return(false) -} - defineTest(qtConfTest_qpaDefaultPlatform) { name = !isEmpty(config.input.qpa_default_platform): name = $$config.input.qpa_default_platform diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 9b107b6633..23d47de58c 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -701,75 +701,6 @@ Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) const return ret; } -void QXcbKeyboard::readXKBConfig() -{ - clearXKBConfig(); - - xcb_connection_t *c = xcb_connection(); - xcb_window_t rootWindow = connection()->rootWindow(); - - auto config_reply = Q_XCB_REPLY(xcb_get_property, c, 0, rootWindow, - atom(QXcbAtom::_XKB_RULES_NAMES), XCB_ATOM_STRING, 0, 1024); - if (!config_reply) { - qWarning("Qt: Couldn't interpret the _XKB_RULES_NAMES property"); - return; - } - char *xkb_config = (char *)xcb_get_property_value(config_reply.get()); - int length = xcb_get_property_value_length(config_reply.get()); - - // on old X servers xkb_config can be 0 even if config_reply indicates a succesfull read - if (!xkb_config || length == 0) - return; - // ### TODO some X servers don't set _XKB_RULES_NAMES at all, in these cases it is filled - // with gibberish, we would need to do some kind of sanity check - - char *names[5] = { 0, 0, 0, 0, 0 }; - char *p = xkb_config, *end = p + length; - int i = 0; - // The result from xcb_get_property_value() is not necessarily \0-terminated, - // we need to make sure that too many or missing '\0' symbols are handled safely. - do { - uint len = qstrnlen(p, length); - names[i++] = p; - p += len + 1; - 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]); -} - -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::printKeymapError(const char *error) const -{ - qWarning() << error; - if (xkb_context) { - qWarning("Current XKB configuration data search paths are: "); - for (unsigned int i = 0; i < xkb_context_num_include_paths(xkb_context); ++i) - qWarning() << xkb_context_include_path_get(xkb_context, i); - } - qWarning("Use QT_XKB_CONFIG_ROOT environmental variable to provide an additional search path, " - "add ':' as separator to provide several search paths and/or make sure that XKB configuration data " - "directory contains recent enough contents, to update please see http://cgit.freedesktop.org/xkeyboard-config/ ."); -} - /* Look at a pair of unshifted and shifted key symbols. * If the 'unshifted' symbol is uppercase and there is no shifted symbol, * return the matching lowercase symbol; otherwise return 0. @@ -1051,91 +982,55 @@ struct xkb_keymap *QXcbKeyboard::keymapFromCore() keymap += "};\n"; // xkb_keymap - return xkb_keymap_new_from_buffer(xkb_context, + return xkb_keymap_new_from_buffer(m_xkbContext.get(), keymap.constData(), keymap.size(), XKB_KEYMAP_FORMAT_TEXT_V1, - static_cast(0)); + XKB_KEYMAP_COMPILE_NO_FLAGS); } void QXcbKeyboard::updateKeymap() { m_config = true; - m_keymap_is_core = false; - // set xkb context object - if (!xkb_context) { - if (qEnvironmentVariableIsSet("QT_XKB_CONFIG_ROOT")) { - xkb_context = xkb_context_new((xkb_context_flags)XKB_CONTEXT_NO_DEFAULT_INCLUDES); - const QList xkbRootList = QByteArray(qgetenv("QT_XKB_CONFIG_ROOT")).split(':'); - for (const QByteArray &xkbRoot : xkbRootList) - xkb_context_include_path_append(xkb_context, xkbRoot.constData()); - } else { - xkb_context = xkb_context_new((xkb_context_flags)0); - } - if (!xkb_context) { - printKeymapError("Qt: Failed to create XKB context!"); + + if (!m_xkbContext) { + m_xkbContext.reset(xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES)); + if (!m_xkbContext) { + qCWarning(lcQpaKeyboard, "failed to create XKB context"); m_config = false; return; } - // log only critical errors, we do our own error logging from printKeymapError() - xkb_context_set_log_level(xkb_context, (xkb_log_level)XKB_LOG_LEVEL_CRITICAL); + xkb_log_level logLevel = lcQpaKeyboard().isDebugEnabled() ? + XKB_LOG_LEVEL_DEBUG : XKB_LOG_LEVEL_CRITICAL; + xkb_context_set_log_level(m_xkbContext.get(), logLevel); } - // update xkb keymap object - xkb_keymap_unref(xkb_keymap); - xkb_keymap = 0; - struct xkb_state *new_state = 0; #if QT_CONFIG(xkb) if (connection()->hasXKB()) { - xkb_keymap = xkb_x11_keymap_new_from_device(xkb_context, xcb_connection(), core_device_id, (xkb_keymap_compile_flags)0); - if (xkb_keymap) { - // Create a new keyboard state object for a keymap - new_state = xkb_x11_state_new_from_device(xkb_keymap, xcb_connection(), core_device_id); - } + m_xkbKeymap.reset(xkb_x11_keymap_new_from_device(m_xkbContext.get(), xcb_connection(), + core_device_id, XKB_KEYMAP_COMPILE_NO_FLAGS)); + if (m_xkbKeymap) + m_xkbState.reset(xkb_x11_state_new_from_device(m_xkbKeymap.get(), xcb_connection(), core_device_id)); + } else { +#endif + m_xkbKeymap.reset(keymapFromCore()); + if (m_xkbKeymap) + m_xkbState.reset(xkb_state_new(m_xkbKeymap.get())); +#if QT_CONFIG(xkb) } #endif - if (!xkb_keymap) { - // Read xkb RMLVO (rules, models, layouts, variants and options) names - readXKBConfig(); - - bool rmlvo_is_incomplete = !xkb_names.rules || !(*xkb_names.rules) - || !xkb_names.model || !(*xkb_names.model) - || !xkb_names.layout || !(*xkb_names.layout); - if (rmlvo_is_incomplete) { - // Try to build xkb map from core mapping information - xkb_keymap = keymapFromCore(); - m_keymap_is_core = xkb_keymap != 0; - } - - if (!xkb_keymap) { - // Compile a keymap from RMLVO - xkb_keymap = xkb_keymap_new_from_names(xkb_context, &xkb_names, - static_cast (0)); - } - if (!xkb_keymap) { - // last fallback is to used hard-coded keymap name, see DEFAULT_XKB_* in xkbcommon.pri - qWarning() << "Qt: Could not determine keyboard configuration data" - " from X server, will use hard-coded keymap configuration."; - clearXKBConfig(); - xkb_keymap = xkb_keymap_new_from_names(xkb_context, &xkb_names, (xkb_keymap_compile_flags)0); - } - if (xkb_keymap) { - new_state = xkb_state_new(xkb_keymap); - } else { - printKeymapError("Qt: Failed to compile a keymap!"); - m_config = false; - return; - } + if (!m_xkbKeymap) { + qCWarning(lcQpaKeyboard, "failed to compile a keymap"); + m_config = false; + return; } - if (!new_state) { - qWarning("Qt: Failed to create xkb state!"); + if (!m_xkbState) { + qCWarning(lcQpaKeyboard, "failed to create XKB state"); m_config = false; return; } - // update xkb state object - xkb_state_unref(xkb_state); - xkb_state = new_state; + updateXKBMods(); checkForLatinLayout(); @@ -1146,7 +1041,7 @@ void QXcbKeyboard::updateXKBState(xcb_xkb_state_notify_event_t *state) { if (m_config && connection()->hasXKB()) { const xkb_state_component newState - = xkb_state_update_mask(xkb_state, + = xkb_state_update_mask(m_xkbState.get(), state->baseMods, state->latchedMods, state->lockedMods, @@ -1191,7 +1086,7 @@ void QXcbKeyboard::updateXKBStateFromState(struct xkb_state *kb_state, quint16 s void QXcbKeyboard::updateXKBStateFromCore(quint16 state) { if (m_config && !connection()->hasXKB()) { - updateXKBStateFromState(xkb_state, state); + updateXKBStateFromState(m_xkbState.get(), state); } } @@ -1201,7 +1096,7 @@ void QXcbKeyboard::updateXKBStateFromXI(void *modInfo, void *groupInfo) if (m_config && !connection()->hasXKB()) { xXIModifierInfo *mods = static_cast(modInfo); xXIGroupInfo *group = static_cast(groupInfo); - const xkb_state_component newState = xkb_state_update_mask(xkb_state, + const xkb_state_component newState = xkb_state_update_mask(m_xkbState.get(), mods->base_mods, mods->latched_mods, mods->locked_mods, @@ -1242,14 +1137,14 @@ quint32 QXcbKeyboard::xkbModMask(quint16 state) void QXcbKeyboard::updateXKBMods() { - xkb_mods.shift = xkb_keymap_mod_get_index(xkb_keymap, XKB_MOD_NAME_SHIFT); - xkb_mods.lock = xkb_keymap_mod_get_index(xkb_keymap, XKB_MOD_NAME_CAPS); - xkb_mods.control = xkb_keymap_mod_get_index(xkb_keymap, XKB_MOD_NAME_CTRL); - xkb_mods.mod1 = xkb_keymap_mod_get_index(xkb_keymap, "Mod1"); - xkb_mods.mod2 = xkb_keymap_mod_get_index(xkb_keymap, "Mod2"); - xkb_mods.mod3 = xkb_keymap_mod_get_index(xkb_keymap, "Mod3"); - xkb_mods.mod4 = xkb_keymap_mod_get_index(xkb_keymap, "Mod4"); - xkb_mods.mod5 = xkb_keymap_mod_get_index(xkb_keymap, "Mod5"); + xkb_mods.shift = xkb_keymap_mod_get_index(m_xkbKeymap.get(), XKB_MOD_NAME_SHIFT); + xkb_mods.lock = xkb_keymap_mod_get_index(m_xkbKeymap.get(), XKB_MOD_NAME_CAPS); + xkb_mods.control = xkb_keymap_mod_get_index(m_xkbKeymap.get(), XKB_MOD_NAME_CTRL); + xkb_mods.mod1 = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Mod1"); + xkb_mods.mod2 = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Mod2"); + xkb_mods.mod3 = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Mod3"); + xkb_mods.mod4 = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Mod4"); + xkb_mods.mod5 = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Mod5"); } static bool isLatin(xkb_keysym_t sym) @@ -1259,11 +1154,11 @@ static bool isLatin(xkb_keysym_t sym) void QXcbKeyboard::checkForLatinLayout() const { - const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts(xkb_keymap); + const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts(m_xkbKeymap.get()); const xcb_keycode_t minKeycode = connection()->setup()->min_keycode; const xcb_keycode_t maxKeycode = connection()->setup()->max_keycode; - ScopedXKBState state(xkb_state_new(xkb_keymap)); + ScopedXKBState state(xkb_state_new(m_xkbKeymap.get())); for (xkb_layout_index_t layout = 0; layout < layoutCount; ++layout) { xkb_state_update_mask(state.get(), 0, 0, 0, 0, 0, layout); for (xcb_keycode_t code = minKeycode; code < maxKeycode; ++code) { @@ -1289,16 +1184,16 @@ xkb_keysym_t QXcbKeyboard::lookupLatinKeysym(xkb_keycode_t keycode) const { xkb_layout_index_t layout; xkb_keysym_t sym = XKB_KEY_NoSymbol; - const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts_for_key(xkb_keymap, keycode); - const xkb_layout_index_t currentLayout = xkb_state_key_get_layout(xkb_state, keycode); + const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts_for_key(m_xkbKeymap.get(), keycode); + const xkb_layout_index_t currentLayout = xkb_state_key_get_layout(m_xkbState.get(), keycode); // Look at user layouts in the order in which they are defined in system // settings to find a latin keysym. for (layout = 0; layout < layoutCount; ++layout) { if (layout == currentLayout) continue; const xkb_keysym_t *syms; - xkb_level_index_t level = xkb_state_key_get_level(xkb_state, keycode, layout); - if (xkb_keymap_key_get_syms_by_level(xkb_keymap, keycode, layout, level, &syms) != 1) + xkb_level_index_t level = xkb_state_key_get_level(m_xkbState.get(), keycode, layout); + if (xkb_keymap_key_get_syms_by_level(m_xkbKeymap.get(), keycode, layout, level, &syms) != 1) continue; if (isLatin(syms[0])) { sym = syms[0]; @@ -1309,8 +1204,8 @@ xkb_keysym_t QXcbKeyboard::lookupLatinKeysym(xkb_keycode_t keycode) const if (sym == XKB_KEY_NoSymbol) return sym; - xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED); - xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED); + xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_LATCHED); + xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_LOCKED); // Check for uniqueness, consider the following setup: // setxkbmap -layout us,ru,us -variant dvorak,, -option 'grp:ctrl_alt_toggle' (set 'ru' as active). @@ -1322,7 +1217,7 @@ xkb_keysym_t QXcbKeyboard::lookupLatinKeysym(xkb_keycode_t keycode) const // generate the same shortcut event in this case. const xcb_keycode_t minKeycode = connection()->setup()->min_keycode; const xcb_keycode_t maxKeycode = connection()->setup()->max_keycode; - ScopedXKBState state(xkb_state_new(xkb_keymap)); + ScopedXKBState state(xkb_state_new(m_xkbKeymap.get())); for (xkb_layout_index_t prevLayout = 0; prevLayout < layout; ++prevLayout) { xkb_state_update_mask(state.get(), 0, latchedMods, lockedMods, 0, 0, prevLayout); for (xcb_keycode_t code = minKeycode; code < maxKeycode; ++code) { @@ -1343,16 +1238,16 @@ QList QXcbKeyboard::possibleKeys(const QKeyEvent *event) const Qt::KeyboardModifiers notNeeded = Qt::KeypadModifier | Qt::GroupSwitchModifier; Qt::KeyboardModifiers modifiers = event->modifiers() &= ~notNeeded; // create a fresh kb state and test against the relevant modifier combinations - struct xkb_state *kb_state = xkb_state_new(xkb_keymap); + struct xkb_state *kb_state = xkb_state_new(m_xkbKeymap.get()); if (!kb_state) { qWarning("QXcbKeyboard: failed to compile xkb keymap!"); return QList(); } // get kb state from the master xkb_state and update the temporary kb_state - xkb_layout_index_t lockedLayout = xkb_state_serialize_layout(xkb_state, XKB_STATE_LAYOUT_LOCKED); - xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED); - xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED); - xkb_mod_mask_t depressedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_DEPRESSED); + xkb_layout_index_t lockedLayout = xkb_state_serialize_layout(m_xkbState.get(), XKB_STATE_LAYOUT_LOCKED); + xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_LATCHED); + xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_LOCKED); + xkb_mod_mask_t depressedMods = xkb_state_serialize_mods(m_xkbState.get(), XKB_STATE_MODS_DEPRESSED); xkb_state_update_mask(kb_state, depressedMods, latchedMods, lockedMods, 0, 0, lockedLayout); quint32 keycode = event->nativeScanCode(); @@ -1378,10 +1273,10 @@ QList QXcbKeyboard::possibleKeys(const QKeyEvent *event) const if (baseQtKey) result += (baseQtKey + modifiers); - xkb_mod_index_t shiftMod = xkb_keymap_mod_get_index(xkb_keymap, "Shift"); - xkb_mod_index_t altMod = xkb_keymap_mod_get_index(xkb_keymap, "Alt"); - xkb_mod_index_t controlMod = xkb_keymap_mod_get_index(xkb_keymap, "Control"); - xkb_mod_index_t metaMod = xkb_keymap_mod_get_index(xkb_keymap, "Meta"); + xkb_mod_index_t shiftMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Shift"); + xkb_mod_index_t altMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Alt"); + xkb_mod_index_t controlMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Control"); + xkb_mod_index_t metaMod = xkb_keymap_mod_get_index(m_xkbKeymap.get(), "Meta"); Q_ASSERT(shiftMod < 32); Q_ASSERT(altMod < 32); @@ -1506,7 +1401,6 @@ int QXcbKeyboard::keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers &modi QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection) : QXcbObject(connection) { - memset(&xkb_names, 0, sizeof(xkb_names)); #if QT_CONFIG(xkb) core_device_id = 0; if (connection->hasXKB()) { @@ -1529,12 +1423,8 @@ QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection) QXcbKeyboard::~QXcbKeyboard() { - xkb_state_unref(xkb_state); - xkb_keymap_unref(xkb_keymap); - xkb_context_unref(xkb_context); if (!connection()->hasXKB()) xcb_key_symbols_free(m_key_symbols); - clearXKBConfig(); } void QXcbKeyboard::updateVModMapping() @@ -1880,7 +1770,7 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, // this way we allow for synthetic events to have different state // from the current state i.e. you can have Alt+Ctrl pressed // and receive a synthetic key event that has neither Alt nor Ctrl pressed - struct xkb_state *kb_state = xkb_state_new(xkb_keymap); + struct xkb_state *kb_state = xkb_state_new(m_xkbKeymap.get()); if (!kb_state) return; updateXKBStateFromState(kb_state, state); diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h index 8ea16f099b..2e2e26367d 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.h +++ b/src/plugins/platforms/xcb/qxcbkeyboard.h @@ -90,10 +90,7 @@ protected: QString lookupString(struct xkb_state *state, xcb_keycode_t code) const; int keysymToQtKey(xcb_keysym_t keysym) const; int keysymToQtKey(xcb_keysym_t keysym, Qt::KeyboardModifiers &modifiers, const QString &text) const; - void printKeymapError(const char *error) const; - void readXKBConfig(); - void clearXKBConfig(); struct xkb_keymap *keymapFromCore(); // when XKEYBOARD not present on the X server @@ -111,14 +108,8 @@ private: void updateXKBStateFromState(struct xkb_state *kb_state, quint16 state); bool m_config = false; - bool m_keymap_is_core = false; xcb_keycode_t m_autorepeat_code = 0; - struct xkb_context *xkb_context = nullptr; - struct xkb_keymap *xkb_keymap = nullptr; - struct xkb_state *xkb_state = nullptr; - struct xkb_rule_names xkb_names; - struct _mod_masks { uint alt; uint altgr; @@ -151,7 +142,19 @@ private: struct XKBStateDeleter { void operator()(struct xkb_state *state) const { return xkb_state_unref(state); } }; + struct XKBKeymapDeleter { + void operator()(struct xkb_keymap *keymap) const { return xkb_keymap_unref(keymap); } + }; + struct XKBContextDeleter { + void operator()(struct xkb_context *context) const { return xkb_context_unref(context); } + }; using ScopedXKBState = std::unique_ptr; + using ScopedXKBKeymap = std::unique_ptr; + using ScopedXKBContext = std::unique_ptr; + + ScopedXKBState m_xkbState; + ScopedXKBKeymap m_xkbKeymap; + ScopedXKBContext m_xkbContext; }; QT_END_NAMESPACE -- cgit v1.2.3