diff options
author | Samuel Nevala <samuel.nevala@intopalo.com> | 2015-10-30 17:00:46 +0200 |
---|---|---|
committer | Samuel Nevala <samuel.nevala@intopalo.com> | 2015-11-04 12:42:19 +0000 |
commit | 96c9817575516f8c3c676830997b9a86adf766e2 (patch) | |
tree | 5f304d60c961ceb8a4b85c7f9b7712c6e2f42574 /src/plugins/platforms/winrt | |
parent | cf0843c5f58ab7723843d3e6e3c88236bbf2f4c9 (diff) |
winrt: Avoid blocking the XAML thread
Blocking the XAML thread can lead to a deadlock, so switch to the
non-blocking version of handleExtendendKeyEvent.
Task-Id: QTBUG-49051
Change-Id: I65a348af1f77b6afcd7d0fb9a80c70d60fc94c27
Reviewed-by: Andrew Knight <andrew.knight@intopalo.com>
Reviewed-by: Oliver Wolff <oliver.wolff@theqtcompany.com>
Diffstat (limited to 'src/plugins/platforms/winrt')
-rw-r--r-- | src/plugins/platforms/winrt/qwinrtscreen.cpp | 123 |
1 files changed, 89 insertions, 34 deletions
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index d1a69c43f7..8ba71d88e7 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -89,6 +89,27 @@ typedef ITypedEventHandler<StatusBar*, IInspectable*> StatusBarHandler; QT_BEGIN_NAMESPACE +struct KeyInfo { + KeyInfo() + : virtualKey(0) + { + } + + KeyInfo(const QString &text, quint32 virtualKey) + : text(text) + , virtualKey(virtualKey) + { + } + + KeyInfo(quint32 virtualKey) + : virtualKey(virtualKey) + { + } + + QString text; + quint32 virtualKey; +}; + static inline Qt::ScreenOrientations qtOrientationsFromNative(DisplayOrientations native) { Qt::ScreenOrientations orientations = Qt::PrimaryOrientation; @@ -435,10 +456,7 @@ public: Qt::ScreenOrientation nativeOrientation; Qt::ScreenOrientation orientation; QList<QWindow *> visibleWindows; -#ifndef Q_OS_WINPHONE - QHash<quint32, QPair<Qt::Key, QString>> activeKeys; -#endif - + QHash<Qt::Key, KeyInfo> activeKeys; QHash<CoreWindowCallbackRemover, EventRegistrationToken> windowTokens; QHash<DisplayCallbackRemover, EventRegistrationToken> displayTokens; #ifdef Q_OS_WINPHONE @@ -827,57 +845,94 @@ void QWinRTScreen::handleExpose() HRESULT QWinRTScreen::onKeyDown(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IKeyEventArgs *args) { + Q_D(QWinRTScreen); VirtualKey virtualKey; - args->get_VirtualKey(&virtualKey); + HRESULT hr = args->get_VirtualKey(&virtualKey); + Q_ASSERT_SUCCEEDED(hr); + CorePhysicalKeyStatus status; + hr = args->get_KeyStatus(&status); + Q_ASSERT_SUCCEEDED(hr); + Qt::Key key = qKeyFromVirtual(virtualKey); // Defer character key presses to onCharacterReceived - if (key == Qt::Key_unknown || (key >= Qt::Key_Space && key <= Qt::Key_ydiaeresis)) + if (key == Qt::Key_unknown || (key >= Qt::Key_Space && key <= Qt::Key_ydiaeresis)) { + d->activeKeys.insert(key, KeyInfo(virtualKey)); return S_OK; - QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyPress, key, keyboardModifiers()); + } + + QWindowSystemInterface::handleExtendedKeyEvent( + topWindow(), + QEvent::KeyPress, + key, + keyboardModifiers(), + !status.ScanCode ? -1 : status.ScanCode, + virtualKey, + 0, + QString(), + status.RepeatCount > 1, + !status.RepeatCount ? 1 : status.RepeatCount, + false); return S_OK; } HRESULT QWinRTScreen::onKeyUp(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IKeyEventArgs *args) { - Qt::KeyboardModifiers mods = keyboardModifiers(); -#ifndef Q_OS_WINPHONE Q_D(QWinRTScreen); - CorePhysicalKeyStatus status; // Look for a pressed character key - if (SUCCEEDED(args->get_KeyStatus(&status)) && d->activeKeys.contains(status.ScanCode)) { - QPair<Qt::Key, QString> keyStatus = d->activeKeys.take(status.ScanCode); - QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease, - keyStatus.first, mods, keyStatus.second); - return S_OK; - } -#endif // !Q_OS_WINPHONE VirtualKey virtualKey; - args->get_VirtualKey(&virtualKey); - QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease, - qKeyFromVirtual(virtualKey), mods); + HRESULT hr = args->get_VirtualKey(&virtualKey); + Q_ASSERT_SUCCEEDED(hr); + CorePhysicalKeyStatus status; + hr = args->get_KeyStatus(&status); + Q_ASSERT_SUCCEEDED(hr); + + Qt::Key key = qKeyFromVirtual(virtualKey); + const KeyInfo info = d->activeKeys.take(key); + QWindowSystemInterface::handleExtendedKeyEvent( + topWindow(), + QEvent::KeyRelease, + key, + keyboardModifiers(), + !status.ScanCode ? -1 : status.ScanCode, + virtualKey, + 0, + info.text, + status.RepeatCount > 1, + !status.RepeatCount ? 1 : status.RepeatCount, + false); return S_OK; } HRESULT QWinRTScreen::onCharacterReceived(ICoreWindow *, ICharacterReceivedEventArgs *args) { + Q_D(QWinRTScreen); quint32 keyCode; - args->get_KeyCode(&keyCode); + HRESULT hr = args->get_KeyCode(&keyCode); + Q_ASSERT_SUCCEEDED(hr); + CorePhysicalKeyStatus status; + hr = args->get_KeyStatus(&status); + Q_ASSERT_SUCCEEDED(hr); + // Don't generate character events for non-printables; the meta key stage is enough if (qIsNonPrintable(keyCode)) return S_OK; - Qt::KeyboardModifiers mods = keyboardModifiers(); - Qt::Key key = qKeyFromCode(keyCode, mods); - QString text = QChar(keyCode); - QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyPress, key, mods, text); -#ifndef Q_OS_WINPHONE - Q_D(QWinRTScreen); - CorePhysicalKeyStatus status; // Defer release to onKeyUp for physical keys - if (SUCCEEDED(args->get_KeyStatus(&status)) && !status.IsKeyReleased) { - d->activeKeys.insert(status.ScanCode, qMakePair(key, text)); - return S_OK; - } -#endif // !Q_OS_WINPHONE - QWindowSystemInterface::handleKeyEvent(topWindow(), QEvent::KeyRelease, key, mods, text); + const Qt::KeyboardModifiers modifiers = keyboardModifiers(); + const Qt::Key key = qKeyFromCode(keyCode, modifiers); + const QString text = QChar(keyCode); + const quint32 virtualKey = d->activeKeys.value(key).virtualKey; + QWindowSystemInterface::handleExtendedKeyEvent( + topWindow(), + QEvent::KeyPress, + key, + modifiers, + !status.ScanCode ? -1 : status.ScanCode, + virtualKey, + 0, + text, + status.RepeatCount > 1, + !status.RepeatCount ? 1 : status.RepeatCount, + false); + d->activeKeys.insert(key, KeyInfo(text, virtualKey)); return S_OK; } |