Commit d682f0f5 authored by Dmitry Kazakov's avatar Dmitry Kazakov
Browse files

[win] Fix unbalanced KeyPress/Release events when using non-latin layout on Windows

When the key is released with a different set of modifiers, we should
notify application about the release of the old key, not the new one.
E.g. for '2' vs '@' keys.

CCBUG:454256
parent d518783c
Pipeline #181020 failed with stage
in 36 minutes and 44 seconds
From 5034b2c0ca273a75d8dc819c2fb43aecd08fbc56 Mon Sep 17 00:00:00 2001
From: Dmitry Kazakov <dimula73@gmail.com>
Date: Wed, 25 May 2022 16:46:08 +0300
Subject: [PATCH] [win] Fix unbalanced KeyPress/Release events when using
non-latin layout
When the key is released with a different set of modifiers, we should
notify application about the release of the old key, not the new one.
E.g. for '2' vs '@' keys.
https://bugs.kde.org/show_bug.cgi?id=454256
---
.../platforms/windows/qwindowskeymapper.cpp | 25 ++++++++++++++-----
1 file changed, 19 insertions(+), 6 deletions(-)
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index 68074ad6..fc14dd7e 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -130,13 +130,14 @@ enum { scancodeBitmask = 0x1ff };
// Key recorder ------------------------------------------------------------------------[ start ] --
struct KeyRecord {
- KeyRecord(int c, int a, int s, const QString &t) : code(c), ascii(a), state(s), text(t) {}
+ KeyRecord(int c, int a, int s, const QString &t, int sc) : code(c), ascii(a), state(s), text(t), sentCode(sc) {}
KeyRecord() {}
int code;
int ascii;
int state;
QString text;
+ int sentCode;
};
// We need to record the pressed keys in order to decide, whether the key event is an autorepeat
@@ -145,7 +146,7 @@ static const int QT_MAX_KEY_RECORDINGS = 64; // User has LOTS of fingers...
struct KeyRecorder
{
inline KeyRecord *findKey(int code, bool remove);
- inline void storeKey(int code, int ascii, int state, const QString& text);
+ inline void storeKey(int code, int ascii, int state, const QString& text, int sentCode);
inline void clearKeys();
int nrecs = 0;
@@ -183,7 +184,7 @@ KeyRecord *KeyRecorder::findKey(int code, bool remove)
return result;
}
-void KeyRecorder::storeKey(int code, int ascii, int state, const QString& text)
+void KeyRecorder::storeKey(int code, int ascii, int state, const QString& text, int sentCode)
{
Q_ASSERT_X(nrecs != QT_MAX_KEY_RECORDINGS,
"Internal KeyRecorder",
@@ -193,7 +194,7 @@ void KeyRecorder::storeKey(int code, int ascii, int state, const QString& text)
qWarning("Qt: Internal keyboard buffer overflow");
return;
}
- records[nrecs++] = KeyRecord(code,ascii,state,text);
+ records[nrecs++] = KeyRecord(code,ascii,state,text,sentCode);
}
void KeyRecorder::clearKeys()
@@ -1162,6 +1163,13 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
// (Consumed by modal widget is one possibility) So, remove the record from the list
// This will stop the auto-repeat of the key, should a modifier change, for example
if (rec && rec->state != state) {
+
+ const QString text = rec->text;
+ const Qt::KeyboardModifiers modifiers(state);
+
+ QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyRelease, rec->sentCode,
+ modifiers, scancode, quint32(msg.wParam), nModifiers, text, false);
+
key_recorder.findKey(int(msg.wParam), true);
rec = nullptr;
}
@@ -1285,7 +1293,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
return false;
}
#endif // !QT_NO_SHORTCUT
- key_recorder.storeKey(int(msg.wParam), a, state, text);
+ key_recorder.storeKey(int(msg.wParam), a, state, text, code);
// QTBUG-71210
// VK_PACKET specifies multiple characters. The system only sends the first
@@ -1328,8 +1336,13 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
|| code == Qt::Key_Alt)) {
// Someone ate the key down event
} else {
- if (!code)
+ if (rec && rec->state != state) {
+ // if the state of modifiers has changed, make sure that
+ // the original key code is delivered
+ code = rec->sentCode;
+ } else if (!code) {
code = asciiToKeycode(rec->ascii ? char(rec->ascii) : char(msg.wParam), state);
+ }
// Map SHIFT + Tab to SHIFT + BackTab, QShortcutMap knows about this translation
if (code == Qt::Key_Tab && (state & Qt::ShiftModifier) == Qt::ShiftModifier)
--
2.23.0.windows.1
......@@ -181,6 +181,7 @@ if (WIN32)
COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/0001-Return-0-for-Window-if-there-is-no-widget.patch
COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/0001-QMenu-make-less-sensitive-to-mouse-jitter.patch
COMMAND ${PATCH_COMMAND} -p1 -d qtbase -i ${CMAKE_CURRENT_SOURCE_DIR}/0001-win-Fix-unbalanced-KeyPress-Release-events-when-usin.patch
)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment