Blob Blame History Raw
From 76adb6c29f9284a3d7cceb8fb09c3bb7c4cd5e1b Mon Sep 17 00:00:00 2001
From: Albert Astals Cid <aacid@kde.org>
Date: Thu, 21 Apr 2016 01:39:27 +0200
Subject: [PATCH 036/352] xcb: Use the state of the key event to process it

Instead of the global state

Task-number: QTBUG-48795
Change-Id: Ic2c545718adb68df41730e5a3bf25adb374ffce3
Reviewed-by: Frederik Gladhorn <frederik.gladhorn@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
---
 src/plugins/platforms/xcb/qxcbkeyboard.cpp | 72 ++++++++++++++++++------------
 src/plugins/platforms/xcb/qxcbkeyboard.h   |  2 +
 2 files changed, 46 insertions(+), 28 deletions(-)

diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index 28de86b..e0fcc01 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -742,8 +742,7 @@ void QXcbKeyboard::updateKeymap()
     // update xkb state object
     xkb_state_unref(xkb_state);
     xkb_state = new_state;
-    if (!connection()->hasXKB())
-        updateXKBMods();
+    updateXKBMods();
 
     checkForLatinLayout();
 }
@@ -768,32 +767,37 @@ void QXcbKeyboard::updateXKBState(xcb_xkb_state_notify_event_t *state)
 }
 #endif
 
+void QXcbKeyboard::updateXKBStateFromState(struct xkb_state *kb_state, quint16 state)
+{
+    const quint32 modsDepressed = xkb_state_serialize_mods(kb_state, XKB_STATE_MODS_DEPRESSED);
+    const quint32 modsLatched = xkb_state_serialize_mods(kb_state, XKB_STATE_MODS_LATCHED);
+    const quint32 modsLocked = xkb_state_serialize_mods(kb_state, XKB_STATE_MODS_LOCKED);
+    const quint32 xkbMask = xkbModMask(state);
+
+    const quint32 latched = modsLatched & xkbMask;
+    const quint32 locked = modsLocked & xkbMask;
+    quint32 depressed = modsDepressed & xkbMask;
+    // set modifiers in depressed if they don't appear in any of the final masks
+    depressed |= ~(depressed | latched | locked) & xkbMask;
+
+    const xkb_state_component newState
+            = xkb_state_update_mask(kb_state,
+                            depressed,
+                            latched,
+                            locked,
+                            0,
+                            0,
+                            (state >> 13) & 3); // bits 13 and 14 report the state keyboard group
+
+    if ((newState & XKB_STATE_LAYOUT_EFFECTIVE) == XKB_STATE_LAYOUT_EFFECTIVE) {
+        //qWarning("TODO: Support KeyboardLayoutChange on QPA (QTBUG-27681)");
+    }
+}
+
 void QXcbKeyboard::updateXKBStateFromCore(quint16 state)
 {
     if (m_config && !connection()->hasXKB()) {
-        const quint32 modsDepressed = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_DEPRESSED);
-        const quint32 modsLatched = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED);
-        const quint32 modsLocked = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED);
-        const quint32 xkbMask = xkbModMask(state);
-
-        const quint32 latched = modsLatched & xkbMask;
-        const quint32 locked = modsLocked & xkbMask;
-        quint32 depressed = modsDepressed & xkbMask;
-        // set modifiers in depressed if they don't appear in any of the final masks
-        depressed |= ~(depressed | latched | locked) & xkbMask;
-
-        const xkb_state_component newState
-                = xkb_state_update_mask(xkb_state,
-                              depressed,
-                              latched,
-                              locked,
-                              0,
-                              0,
-                              (state >> 13) & 3); // bits 13 and 14 report the state keyboard group
-
-        if ((newState & XKB_STATE_LAYOUT_EFFECTIVE) == XKB_STATE_LAYOUT_EFFECTIVE) {
-            //qWarning("TODO: Support KeyboardLayoutChange on QPA (QTBUG-27681)");
-        }
+        updateXKBStateFromState(xkb_state, state);
     }
 }
 
@@ -1455,7 +1459,16 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
     if (type == QEvent::KeyPress)
         targetWindow->updateNetWmUserTime(time);
 
-    xcb_keysym_t sym = xkb_state_key_get_one_sym(xkb_state, code);
+    // Have a temporary keyboard state filled in from state
+    // 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);
+    if (!kb_state)
+        return;
+    updateXKBStateFromState(kb_state, state);
+
+    xcb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, code);
 
     QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext();
     QMetaMethod method;
@@ -1474,11 +1487,13 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
                       Q_ARG(uint, code),
                       Q_ARG(uint, state),
                       Q_ARG(bool, type == QEvent::KeyPress));
-        if (retval)
+        if (retval) {
+            xkb_state_unref(kb_state);
             return;
+        }
     }
 
-    QString string = lookupString(xkb_state, code);
+    QString string = lookupString(kb_state, code);
 
     // Ιf control modifier is set we should prefer latin character, this is
     // used for standard shortcuts in checks like "key == QKeySequence::Copy",
@@ -1547,6 +1562,7 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
             QWindowSystemInterface::handleExtendedKeyEvent(window, time, QEvent::KeyPress, qtcode, modifiers,
                                                            code, sym, state, string, isAutoRepeat);
     }
+    xkb_state_unref(kb_state);
 }
 
 QString QXcbKeyboard::lookupString(struct xkb_state *state, xcb_keycode_t code) const
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h
index 457a27a..dc27511 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.h
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.h
@@ -98,6 +98,8 @@ protected:
     void checkForLatinLayout();
 
 private:
+    void updateXKBStateFromState(struct xkb_state *kb_state, quint16 state);
+
     bool m_config;
     xcb_keycode_t m_autorepeat_code;
 
-- 
2.9.3