diff options
Diffstat (limited to 'src/plugins/platforms/windows/qwindowskeymapper.cpp')
-rw-r--r-- | src/plugins/platforms/windows/qwindowskeymapper.cpp | 145 |
1 files changed, 111 insertions, 34 deletions
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index 950d8ecd36..1209b6c4b4 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -43,13 +43,14 @@ #include "qwindowswindow.h" #include "qwindowsinputcontext.h" -#include <QtGui/QGuiApplication> -#include <QtGui/QWindow> +#include <QtGui/qguiapplication.h> +#include <QtGui/qwindow.h> #include <qpa/qwindowsysteminterface.h> #include <private/qguiapplication_p.h> #include <private/qhighdpiscaling_p.h> -#include <QtGui/QKeyEvent> +#include <QtGui/qevent.h> #include <QtEventDispatcherSupport/private/qwindowsguieventdispatcher_p.h> +#include <QtCore/private/qdebug_p.h> #if defined(WM_APPCOMMAND) # ifndef FAPPCOMMAND_MOUSE @@ -105,9 +106,7 @@ QWindowsKeyMapper::QWindowsKeyMapper() changeKeyboard(); } -QWindowsKeyMapper::~QWindowsKeyMapper() -{ -} +QWindowsKeyMapper::~QWindowsKeyMapper()= default; #ifndef LANG_PASHTO #define LANG_PASHTO 0x63 @@ -544,6 +543,59 @@ static const Qt::KeyboardModifiers ModsTbl[] = { static const size_t NumMods = sizeof ModsTbl / sizeof *ModsTbl; Q_STATIC_ASSERT((NumMods == KeyboardLayoutItem::NumQtKeys)); +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d, const KeyboardLayoutItem &k) +{ + QDebugStateSaver saver(d); + d.nospace(); + d << "KeyboardLayoutItem("; + if (k.exists) { + for (size_t i = 0; i < NumMods; ++i) { + if (const quint32 qtKey = k.qtKey[i]) { + d << '[' << i << ' '; + QtDebugUtils::formatQFlags(d, ModsTbl[i]); + d << ' ' << hex << showbase << qtKey << dec << noshowbase << ' '; + QtDebugUtils::formatQEnum(d, Qt::Key(qtKey)); + if (qtKey >= 32 && qtKey < 128) + d << " '" << char(qtKey) << '\''; + if (k.deadkeys & (1<<i)) + d << " deadkey"; + d << "] "; + } + } + } + d << ')'; + return d; +} + +// Helpers to format a list of int as Qt key sequence +class formatKeys +{ +public: + explicit formatKeys(const QList<int> &keys) : m_keys(keys) {} + +private: + friend QDebug operator<<(QDebug d, const formatKeys &keys); + const QList<int> &m_keys; +}; + +QDebug operator<<(QDebug d, const formatKeys &k) +{ + QDebugStateSaver saver(d); + d.nospace(); + d << '('; + for (int i =0, size = k.m_keys.size(); i < size; ++i) { + if (i) + d << ", "; + d << QKeySequence(k.m_keys.at(i)); + } + d << ')'; + return d; +} +#else // !QT_NO_DEBUG_STREAM +static int formatKeys(const QList<int> &) { return 0; } +#endif // QT_NO_DEBUG_STREAM + /** Remap return or action key to select key for windows mobile. */ @@ -599,8 +651,8 @@ static inline int asciiToKeycode(char a, int state) void QWindowsKeyMapper::deleteLayouts() { - for (size_t i = 0; i < NumKeyboardLayoutItems; ++i) - keyLayout[i].exists = false; + for (KeyboardLayoutItem &k : keyLayout) + k.exists = false; } void QWindowsKeyMapper::changeKeyboard() @@ -620,6 +672,7 @@ void QWindowsKeyMapper::changeKeyboard() bidi = true; keyboardInputDirection = bidi ? Qt::RightToLeft : Qt::LeftToRight; + m_seenAltGr = false; } // Helper function that is used when obtaining the list of characters that can be produced by one key and @@ -722,21 +775,8 @@ void QWindowsKeyMapper::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 ::ToAscii(VK_SPACE, 0, emptyBuffer, reinterpret_cast<LPWORD>(&buffer), 0); ::ToAscii(vk_key, scancode, kbdBuffer, reinterpret_cast<LPWORD>(&buffer), 0); } - if (QWindowsContext::verbose > 1 && lcQpaEvents().isDebugEnabled()) { - QString message; - QDebug debug(&message); - debug <<__FUNCTION__ << " for virtual key = 0x" << hex << vk_key << dec<< '\n'; - for (size_t i = 0; i < NumMods; ++i) { - const quint32 qtKey = keyLayout[vk_key].qtKey[i]; - debug << " [" << i << "] (" << qtKey << ',' - << hex << showbase << qtKey << noshowbase << dec - << ",'" << char(qtKey ? qtKey : 0x03) << "')"; - if (keyLayout[vk_key].deadkeys & (1<<i)) - debug << " deadkey"; - debug << '\n'; - } - qCDebug(lcQpaEvents) << message; - } + qCDebug(lcQpaEvents) << __FUNCTION__ << "for virtual key=" + << hex << showbase << vk_key << dec << noshowbase << keyLayout[vk_key]; } static inline QString messageKeyText(const MSG &msg) @@ -867,8 +907,34 @@ bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, con #endif } -bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &msg, bool /* grab */, LRESULT *lResult) +// QTBUG-69317: Check for AltGr found on some keyboards +// which is a sequence of left Ctrl (SYSKEY) + right Menu (Alt). +static bool isAltGr(MSG *msg) { + enum : LONG_PTR { RightFlag = 0x1000000 }; + if (msg->wParam != VK_CONTROL || (msg->lParam & RightFlag) != 0 + || (msg->message != WM_KEYDOWN && msg->message != WM_SYSKEYUP)) { + return false; + } + const UINT expectedMessage = msg->message == WM_SYSKEYUP + ? WM_KEYUP : msg->message; + MSG peekedMsg; + if (PeekMessage(&peekedMsg, msg->hwnd, 0, 0, PM_NOREMOVE) == FALSE + || peekedMsg.message != expectedMessage || peekedMsg.wParam != VK_MENU + || (peekedMsg.lParam & RightFlag) == 0) { + return false; + } + *msg = peekedMsg; + PeekMessage(&peekedMsg, msg->hwnd, 0, 0, PM_REMOVE); + return true; +} + +bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg, + bool /* grab */, LRESULT *lResult) +{ + const bool altGr = m_detectAltGrModifier && isAltGr(&msg); + if (altGr) + m_seenAltGr = true; const UINT msgType = msg.message; const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask; @@ -897,10 +963,12 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms // Get the modifier states (may be altered later, depending on key code) int state = 0; state |= (nModifiers & ShiftAny ? int(Qt::ShiftModifier) : 0); - state |= (nModifiers & ControlAny ? int(Qt::ControlModifier) : 0); - state |= (nModifiers & AltAny ? int(Qt::AltModifier) : 0); + state |= (nModifiers & AltLeft ? int(Qt::AltModifier) : 0); + if ((nModifiers & AltRight) != 0) + state |= m_seenAltGr ? Qt::GroupSwitchModifier : Qt::AltModifier; + if ((nModifiers & ControlAny) != 0 && (state & Qt::GroupSwitchModifier) == 0) + state |= Qt::ControlModifier; state |= (nModifiers & MetaAny ? int(Qt::MetaModifier) : 0); - // A multi-character key or a Input method character // not found by our look-ahead if (msgType == WM_CHAR || msgType == WM_IME_CHAR) { @@ -971,8 +1039,17 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms modifiersIndex |= (nModifiers & ControlAny ? 0x2 : 0); modifiersIndex |= (nModifiers & AltAny ? 0x4 : 0); + // Note: For the resulting key, AltGr is equivalent to Alt + Ctrl (as + // opposed to Linux); hence no entry in KeyboardLayoutItem is required int code = keyLayout[vk_key].qtKey[modifiersIndex]; + // If the bit 24 of lParm is set you received a enter, + // otherwise a Return. (This is the extended key bit) + if ((code == Qt::Key_Return) && (msg.lParam & 0x1000000)) + code = Qt::Key_Enter; + else if (altGr) + code = Qt::Key_AltGr; + // Invert state logic: // If the key actually pressed is a modifier key, then we remove its modifier key from the // state, since a modifier-key can't have itself as a modifier @@ -982,11 +1059,8 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms state = state ^ Qt::ShiftModifier; else if (code == Qt::Key_Alt) state = state ^ Qt::AltModifier; - - // If the bit 24 of lParm is set you received a enter, - // otherwise a Return. (This is the extended key bit) - if ((code == Qt::Key_Return) && (msg.lParam & 0x1000000)) - code = Qt::Key_Enter; + else if (code == Qt::Key_AltGr) + state = state ^ Qt::GroupSwitchModifier; // All cursor keys without extended bit if (!(msg.lParam & 0x1000000)) { @@ -1070,7 +1144,8 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms if (uch.isHighSurrogate()) { m_lastHighSurrogate = uch; return true; - } else if (uch.isLowSurrogate() && !m_lastHighSurrogate.isNull()) { + } + if (uch.isLowSurrogate() && !m_lastHighSurrogate.isNull()) { if (QObject *focusObject = QGuiApplication::focusObject()) { const QChar chars[2] = {m_lastHighSurrogate, uch}; QInputMethodEvent event; @@ -1287,7 +1362,9 @@ QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const *it = matchedKey; } } - + qCDebug(lcQpaEvents) << __FUNCTION__ << e << "nativeVirtualKey=" + << showbase << hex << e->nativeVirtualKey() << dec << noshowbase + << e->modifiers() << kbItem << "\n returns" << formatKeys(result); return result; } |