summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/platform/unix/qxkbcommon.cpp39
1 files changed, 36 insertions, 3 deletions
diff --git a/src/gui/platform/unix/qxkbcommon.cpp b/src/gui/platform/unix/qxkbcommon.cpp
index 162ba90efe..2fa2ae8911 100644
--- a/src/gui/platform/unix/qxkbcommon.cpp
+++ b/src/gui/platform/unix/qxkbcommon.cpp
@@ -488,9 +488,11 @@ int QXkbCommon::keysymToQtKey(xkb_keysym_t keysym, Qt::KeyboardModifiers modifie
// With standard shortcuts we should prefer a latin character, this is
// for checks like "some qkeyevent == QKeySequence::Copy" to work even
// when using for example 'russian' keyboard layout.
- xkb_keysym_t latinKeysym = QXkbCommon::lookupLatinKeysym(state, code);
- if (latinKeysym != XKB_KEY_NoSymbol)
- keysym = latinKeysym;
+ if (!QXkbCommon::isLatin1(keysym)) {
+ xkb_keysym_t latinKeysym = QXkbCommon::lookupLatinKeysym(state, code);
+ if (latinKeysym != XKB_KEY_NoSymbol)
+ keysym = latinKeysym;
+ }
}
return keysymToQtKey_internal(keysym, modifiers, state, code, superAsMeta, hyperAsMeta);
@@ -735,9 +737,12 @@ xkb_keysym_t QXkbCommon::lookupLatinKeysym(xkb_state *state, xkb_keycode_t keyco
return sym;
xkb_keymap *keymap = xkb_state_get_keymap(state);
const xkb_layout_index_t layoutCount = xkb_keymap_num_layouts_for_key(keymap, keycode);
+ const xkb_layout_index_t currentLayout = xkb_state_key_get_layout(state, 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 = nullptr;
xkb_level_index_t level = xkb_state_key_get_level(state, keycode, layout);
if (xkb_keymap_key_get_syms_by_level(keymap, keycode, layout, level, &syms) != 1)
@@ -748,6 +753,34 @@ xkb_keysym_t QXkbCommon::lookupLatinKeysym(xkb_state *state, xkb_keycode_t keyco
}
}
+ if (sym == XKB_KEY_NoSymbol)
+ return sym;
+
+ xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(state, XKB_STATE_MODS_LATCHED);
+ xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(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>,
+ // because "US dvorak" is higher up in the layout settings list. This check verifies that an obtained
+ // 'sym' can not be acquired by any other layout higher up in the user's layout list. If it can be acquired
+ // then the obtained key is not unique. This prevents ctrl+<physical q key> from generating a ctrl+q
+ // shortcut in the above described setup. We don't want ctrl+<physical x key> and ctrl+<physical q key> to
+ // generate the same shortcut event in this case.
+ const xkb_keycode_t minKeycode = xkb_keymap_min_keycode(keymap);
+ const xkb_keycode_t maxKeycode = xkb_keymap_max_keycode(keymap);
+ ScopedXKBState queryState(xkb_state_new(keymap));
+ for (xkb_layout_index_t prevLayout = 0; prevLayout < layout; ++prevLayout) {
+ xkb_state_update_mask(queryState.get(), 0, latchedMods, lockedMods, 0, 0, prevLayout);
+ for (xkb_keycode_t code = minKeycode; code < maxKeycode; ++code) {
+ xkb_keysym_t prevSym = xkb_state_key_get_one_sym(queryState.get(), code);
+ if (prevSym == sym) {
+ sym = XKB_KEY_NoSymbol;
+ break;
+ }
+ }
+ }
+
return sym;
}