Fix shortcut handling for level three and above shortcuts

Calling `xkb_state_update_mask` with correctly set `depressed_mods` allows xkb to
return keys on level three or above (and not the equivalent level one key).

To preserve level two shortcuts (return equivalent level one key)
`depressed_mods` gets only set, if the pressed key is on level three or above.

Example shortcuts which now will work:
  Shortcut  German Layout (de) [AltGr is a level three switch]
  Ctrl+@    Ctrl+AltGr+Q
  Shift+1   Shift+1  (as before)

  Shortcut  German Neo Layout (de neo) [1] [AltGr is a level five switch]
  Left      AltGr+S

[1] http://neo-layout.org

Task-number: QTBUG-53121
Change-Id: I637a01edc9f2f92a5d3e7a24f5051fb1d3ac2f7f
Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
bb10
Bernhard Scheirle 2016-06-18 14:30:15 +02:00 committed by Gatis Paeglis
parent 2714d94ff4
commit db1a6ac357
1 changed files with 13 additions and 2 deletions

View File

@ -973,10 +973,21 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
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_state_update_mask(kb_state, 0, latchedMods, lockedMods, 0, 0, lockedLayout);
xkb_state_update_mask(kb_state, depressedMods, latchedMods, lockedMods, 0, 0, lockedLayout);
quint32 keycode = event->nativeScanCode();
// handle shortcuts for level three and above
xkb_layout_index_t layoutIndex = xkb_state_key_get_layout(kb_state, keycode);
xkb_level_index_t levelIndex = 0;
if (layoutIndex != XKB_LAYOUT_INVALID) {
levelIndex = xkb_state_key_get_level(kb_state, keycode, layoutIndex);
if (levelIndex == XKB_LEVEL_INVALID)
levelIndex = 0;
}
if (levelIndex <= 1)
xkb_state_update_mask(kb_state, 0, latchedMods, lockedMods, 0, 0, lockedLayout);
xkb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, keycode);
if (sym == XKB_KEY_NoSymbol) {
xkb_state_unref(kb_state);