xkbcommon: make shortcuts persistent across layouts
It can happen the same key has different Latin symbols on different layouts: for example, "`" symbol on English layout, no symbol ("^" dead key) on German and ";" symbol on Czech and Hebrew layouts. This creates a problem as these keys will produce different shortcuts depending on what layout is currently active. This patch makes keys generate the same shortcuts corresponding to the first Latin layout configured in the system, independently of layout actually active. For example, when having settings like: setxkbmap -model pc105 -layout "us,de" -option "grp:alt_shift_toggle" After Alt+Shift, the layout changes to de from us. But Ctrl+"^" still generates Ctrl+` shortcut which is from the first(or default) layout. [ChangeLog][QtGui][QXkbCommon] make keys produce the same shortcuts independently of current layout Fixes: QTBUG-108761 Change-Id: Id204a1609ca731f9c56ed3d32847ca18b94be4a0 Reviewed-by: Liang Qi <liang.qi@qt.io> Reviewed-by: Andrey Butirsky <butirsky@gmail.com>
This commit is contained in:
parent
d53607225a
commit
5e76a9569e
@ -488,11 +488,9 @@ 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.
|
||||
if (!QXkbCommon::isLatin1(keysym)) {
|
||||
xkb_keysym_t latinKeysym = QXkbCommon::lookupLatinKeysym(state, code);
|
||||
if (latinKeysym != XKB_KEY_NoSymbol)
|
||||
keysym = latinKeysym;
|
||||
}
|
||||
xkb_keysym_t latinKeysym = QXkbCommon::lookupLatinKeysym(state, code);
|
||||
if (latinKeysym != XKB_KEY_NoSymbol)
|
||||
keysym = latinKeysym;
|
||||
}
|
||||
|
||||
return keysymToQtKey_internal(keysym, modifiers, state, code, superAsMeta, hyperAsMeta);
|
||||
@ -732,12 +730,9 @@ xkb_keysym_t QXkbCommon::lookupLatinKeysym(xkb_state *state, xkb_keycode_t keyco
|
||||
xkb_keysym_t sym = XKB_KEY_NoSymbol;
|
||||
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,34 +743,6 @@ 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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user