summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGatis Paeglis <gatis.paeglis@qt.io>2018-01-04 18:50:59 +0100
committerGatis Paeglis <gatis.paeglis@qt.io>2018-02-24 12:15:08 +0000
commitd5abf545971da717014d316127045fc19edbcd65 (patch)
tree6bb3f2d97c9665f9e11e338940feae53d6f460ba
parent9280a04afebef9ee992e75c469e29c0c443b66c6 (diff)
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 <shawn.rutledge@qt.io>
-rw-r--r--config_help.txt2
-rw-r--r--src/3rdparty/xkbcommon.pri2
-rw-r--r--src/gui/configure.json23
-rw-r--r--src/gui/configure.pri15
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp224
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.h21
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 <dir> ... With -qt-xkbcommon-x11, set default XKB config
- root <dir> [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",
@@ -1580,12 +1565,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",
"message": "XCB support on macOS is minimal and untested. Some features will
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<xkb_keymap_compile_flags>(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<QByteArray> 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<xkb_keymap_compile_flags> (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<xXIModifierInfo *>(modInfo);
xXIGroupInfo *group = static_cast<xXIGroupInfo *>(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<int> 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<int>();
}
// 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<int> 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<struct xkb_state, XKBStateDeleter>;
+ using ScopedXKBKeymap = std::unique_ptr<struct xkb_keymap, XKBKeymapDeleter>;
+ using ScopedXKBContext = std::unique_ptr<struct xkb_context, XKBContextDeleter>;
+
+ ScopedXKBState m_xkbState;
+ ScopedXKBKeymap m_xkbKeymap;
+ ScopedXKBContext m_xkbContext;
};
QT_END_NAMESPACE