summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb/qxcbkeyboard.cpp
diff options
context:
space:
mode:
authorGatis Paeglis <gatis.paeglis@qt.io>2018-01-04 13:36:45 +0100
committerGatis Paeglis <gatis.paeglis@qt.io>2018-02-22 21:37:50 +0000
commit1aec1a2d8df182a9e15906bcfede32a9841586ea (patch)
treec21db209699688f3555e64338b37442521fa226a /src/plugins/platforms/xcb/qxcbkeyboard.cpp
parentff169e8859457188f94aed86368876ba5bab2e90 (diff)
xcb: remove fragile and unnecessary missing-latin-keymap workaround
... which was trying to fix a rarely occurring situation where system settings from a desktop environment does not set any latin keymap on X. This is a DE bug and it has a simple workaround (details in the patch). Ubuntu has fixed this issue sometime between 12.10 -> 14.04. Gnome 3 always appends 'us' layout, even if you have only e.g. 'gr' listed in keyboard layouts (can be checked via setxkbmap -query). In KDE, the global system shorcuts seem to stop working as soon as latin keymap is not the first in the list, which means that KDE users won't be affected as they will likely always have a latin keymap present in the list. This patch removes parts of 2b666d9576210aa98700e219dba6b1bd4f93d793, the parts that in the commit message I was referring to by this quote: "lookupLatinKeysym() also handles the cases that did not work in Qt4 with XLookupString". Since finding a latin key is not working by XLookupString() in this rare case, then it would not work pretty much across the whole desktop. And users would be more interested at finding a solution that works across the desktop. We should not workaround this issue. Desktops that are doing it wrong should learn about this and not repeat the same mistakes on Wayland systems, where XKB keymap is assembled by compositor and passed to clients. Clients should work with the provided keymap as is. The missing-latin-keymap workaround is considered fragile for several reasons - it might not work with legacy or enterprise X server key codes and it relies on global _XKB_RULES_NAMES (there might be several connected keyboards). And theoretical limitation: client might be running in a restricted environment where we don't have access to keymaps on the file system. Change-Id: Ib445b2ea46174248cfa0e5da0eb642cd2a5cf2f6 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbkeyboard.cpp')
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp70
1 files changed, 24 insertions, 46 deletions
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index 2ed66394c9..20b5fe039a 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -1267,27 +1267,32 @@ static bool isLatin(xkb_keysym_t sym)
return ((sym >= 'a' && sym <= 'z') || (sym >= 'A' && sym <= 'Z'));
}
-void QXcbKeyboard::checkForLatinLayout()
+void QXcbKeyboard::checkForLatinLayout() const
{
- m_hasLatinLayout = false;
const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts(xkb_keymap);
const xcb_keycode_t minKeycode = connection()->setup()->min_keycode;
const xcb_keycode_t maxKeycode = connection()->setup()->max_keycode;
- struct xkb_state *kb_state = xkb_state_new(xkb_keymap);
+
+ ScopedXKBState state(xkb_state_new(xkb_keymap));
for (xkb_layout_index_t layout = 0; layout < layoutCount; ++layout) {
- xkb_state_update_mask(kb_state, 0, 0, 0, 0, 0, layout);
+ xkb_state_update_mask(state.get(), 0, 0, 0, 0, 0, layout);
for (xcb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
- xkb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, code);
+ xkb_keysym_t sym = xkb_state_key_get_one_sym(state.get(), code);
// if layout can produce any of these latin letters (chosen
// arbitrarily) then it must be a latin key based layout
- if (sym == XK_q || sym == XK_a || sym == XK_e) {
- m_hasLatinLayout = true;
- xkb_state_unref(kb_state);
+ if (sym == XK_q || sym == XK_a || sym == XK_e)
return;
- }
}
}
- xkb_state_unref(kb_state);
+ // This means that lookupLatinKeysym() will not find anything and latin
+ // key shortcuts might not work. This is a bug in the affected desktop
+ // environment. Usually can be solved via system settings by adding e.g. 'us'
+ // layout to the list of seleced layouts, or by using command line, "setxkbmap
+ // -layout rus,en". The position of latin key based layout in the list of the
+ // selected layouts is irrelevant. Properly functioning desktop environments
+ // handle this behind the scenes, even if no latin key based layout has been
+ // explicitly listed in the selected layouts.
+ qCWarning(lcQpaKeyboard, "no keyboard layouts with latin keys present");
}
xkb_keysym_t QXcbKeyboard::lookupLatinKeysym(xkb_keycode_t keycode) const
@@ -1310,39 +1315,13 @@ xkb_keysym_t QXcbKeyboard::lookupLatinKeysym(xkb_keycode_t keycode) const
break;
}
}
- // If user layouts don't contain any layout that results in a latin key, we query a
- // key from "US" layout, this allows for latin-key-based shorcuts to work even when
- // users have only one (non-latin) layout set.
- // But don't do this if using keymap obtained through the core protocol, as the key
- // codes may not match up with those expected by the XKB keymap.
- 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);
- if (sym == XKB_KEY_NoSymbol && !m_hasLatinLayout && !m_keymap_is_core) {
- if (!latin_keymap) {
- const struct xkb_rule_names names = { xkb_names.rules, xkb_names.model, "us", 0, 0 };
- latin_keymap = xkb_keymap_new_from_names(xkb_context, &names, (xkb_keymap_compile_flags)0);
- static bool printFailure = true;
- if (!latin_keymap && printFailure) {
- // print message about failure to compile US keymap only once,
- // no need to do this on every key press.
- printFailure = false;
- printKeymapError("Qt: Failed to compile US keymap, shortcut handling with "
- "non-Latin keyboard layouts may not be fully functional!");
- }
- }
- if (latin_keymap) {
- struct xkb_state *latin_state = xkb_state_new(latin_keymap);
- if (latin_state) {
- xkb_state_update_mask(latin_state, 0, latchedMods, lockedMods, 0, 0, 0);
- sym = xkb_state_key_get_one_sym(latin_state, keycode);
- xkb_state_unref(latin_state);
- } else {
- qWarning("QXcbKeyboard: failed to create a state for US keymap!");
- }
- }
- }
+
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);
+
// Check for uniqueness, consider the following setup:
// setxkbmap -layout us,ru,us -variant dvorak,, -option 'grp:ctrl_alt_toggle' (set 'ru' as active).
// In this setup, the user would expect to trigger a ctrl+q shortcut by pressing ctrl+<physical x key>,
@@ -1353,18 +1332,18 @@ 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;
- struct xkb_state *kb_state = xkb_state_new(xkb_keymap);
+ ScopedXKBState state(xkb_state_new(xkb_keymap));
for (xkb_layout_index_t prevLayout = 0; prevLayout < layout; ++prevLayout) {
- xkb_state_update_mask(kb_state, 0, latchedMods, lockedMods, 0, 0, prevLayout);
+ xkb_state_update_mask(state.get(), 0, latchedMods, lockedMods, 0, 0, prevLayout);
for (xcb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
- xkb_keysym_t prevSym = xkb_state_key_get_one_sym(kb_state, code);
+ xkb_keysym_t prevSym = xkb_state_key_get_one_sym(state.get(), code);
if (prevSym == sym) {
sym = XKB_KEY_NoSymbol;
break;
}
}
}
- xkb_state_unref(kb_state);
+
return sym;
}
@@ -1563,7 +1542,6 @@ QXcbKeyboard::~QXcbKeyboard()
xkb_state_unref(xkb_state);
xkb_keymap_unref(xkb_keymap);
xkb_context_unref(xkb_context);
- xkb_keymap_unref(latin_keymap);
if (!connection()->hasXKB())
xcb_key_symbols_free(m_key_symbols);
clearXKBConfig();