diff options
-rw-r--r-- | src/corelib/tools/qbytearray.cpp | 49 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_winrt.cpp | 4 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowscontext.cpp | 74 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowscontext.h | 3 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowskeymapper.cpp | 23 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowskeymapper.h | 2 |
6 files changed, 113 insertions, 42 deletions
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 7b0e691127..d9cd20ffbf 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -238,7 +238,8 @@ qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t heade Returns a duplicate string. Allocates space for a copy of \a src, copies it, and returns a - pointer to the copy. If \a src is 0, it immediately returns 0. + pointer to the copy. If \a src is nullptr, it immediately returns + nullptr. Ownership is passed to the caller, so the returned string must be deleted using \c delete[]. @@ -247,7 +248,7 @@ qCalculateGrowingBlockSize(size_t elementCount, size_t elementSize, size_t heade char *qstrdup(const char *src) { if (!src) - return 0; + return nullptr; char *dst = new char[strlen(src) + 1]; return qstrcpy(dst, src); } @@ -255,26 +256,28 @@ char *qstrdup(const char *src) /*! \relates QByteArray Copies all the characters up to and including the '\\0' from \a - src into \a dst and returns a pointer to \a dst. If \a src is 0, - it immediately returns 0. + src into \a dst and returns a pointer to \a dst. If \a src is + nullptr, it immediately returns nullptr. This function assumes that \a dst is large enough to hold the contents of \a src. + \note If \a dst and \a src overlap, the behavior is undefined. + \sa qstrncpy() */ char *qstrcpy(char *dst, const char *src) { if (!src) - return 0; + return nullptr; #ifdef Q_CC_MSVC const int len = int(strlen(src)); // This is actually not secure!!! It will be fixed // properly in a later release! if (len >= 0 && strcpy_s(dst, len+1, src) == 0) return dst; - return 0; + return nullptr; #else return strcpy(dst, src); #endif @@ -287,11 +290,13 @@ char *qstrcpy(char *dst, const char *src) Copies at most \a len bytes from \a src (stopping at \a len or the terminating '\\0' whichever comes first) into \a dst and returns a pointer to \a dst. Guarantees that \a dst is '\\0'-terminated. If - \a src or \a dst is 0, returns 0 immediately. + \a src or \a dst is nullptr, returns nullptr immediately. This function assumes that \a dst is at least \a len characters long. + \note If \a dst and \a src overlap, the behavior is undefined. + \note When compiling with Visual C++ compiler version 14.00 (Visual C++ 2005) or later, internally the function strncpy_s will be used. @@ -302,7 +307,7 @@ char *qstrcpy(char *dst, const char *src) char *qstrncpy(char *dst, const char *src, uint len) { if (!src || !dst) - return 0; + return nullptr; if (len > 0) { #ifdef Q_CC_MSVC strncpy_s(dst, len, src, len - 1); @@ -320,7 +325,7 @@ char *qstrncpy(char *dst, const char *src, uint len) A safe \c strlen() function. Returns the number of characters that precede the terminating '\\0', - or 0 if \a str is 0. + or 0 if \a str is nullptr. \sa qstrnlen() */ @@ -332,7 +337,7 @@ char *qstrncpy(char *dst, const char *src, uint len) A safe \c strnlen() function. Returns the number of characters that precede the terminating '\\0', but - at most \a maxlen. If \a str is 0, returns 0. + at most \a maxlen. If \a str is nullptr, returns 0. \sa qstrlen() */ @@ -346,10 +351,10 @@ char *qstrncpy(char *dst, const char *src, uint len) is less than \a str2, 0 if \a str1 is equal to \a str2 or a positive value if \a str1 is greater than \a str2. - Special case 1: Returns 0 if \a str1 and \a str2 are both 0. + Special case 1: Returns 0 if \a str1 and \a str2 are both nullptr. - Special case 2: Returns an arbitrary non-zero value if \a str1 is 0 - or \a str2 is 0 (but not both). + Special case 2: Returns an arbitrary non-zero value if \a str1 is + nullptr or \a str2 is nullptr (but not both). \sa qstrncmp(), qstricmp(), qstrnicmp(), {8-bit Character Comparisons} */ @@ -371,10 +376,10 @@ int qstrcmp(const char *str1, const char *str2) str1 is equal to \a str2 or a positive value if \a str1 is greater than \a str2. - Special case 1: Returns 0 if \a str1 and \a str2 are both 0. + Special case 1: Returns 0 if \a str1 and \a str2 are both nullptr. - Special case 2: Returns a random non-zero value if \a str1 is 0 - or \a str2 is 0 (but not both). + Special case 2: Returns a random non-zero value if \a str1 is nullptr + or \a str2 is nullptr (but not both). \sa qstrcmp(), qstricmp(), qstrnicmp(), {8-bit Character Comparisons} */ @@ -390,10 +395,10 @@ int qstrcmp(const char *str1, const char *str2) str1 is equal to \a str2 or a positive value if \a str1 is greater than \a str2. - Special case 1: Returns 0 if \a str1 and \a str2 are both 0. + Special case 1: Returns 0 if \a str1 and \a str2 are both nullptr. - Special case 2: Returns a random non-zero value if \a str1 is 0 - or \a str2 is 0 (but not both). + Special case 2: Returns a random non-zero value if \a str1 is nullptr + or \a str2 is nullptr (but not both). \sa qstrcmp(), qstrncmp(), qstrnicmp(), {8-bit Character Comparisons} */ @@ -424,10 +429,10 @@ int qstricmp(const char *str1, const char *str2) is equal to \a str2 or a positive value if \a str1 is greater than \a str2. - Special case 1: Returns 0 if \a str1 and \a str2 are both 0. + Special case 1: Returns 0 if \a str1 and \a str2 are both nullptr. - Special case 2: Returns a random non-zero value if \a str1 is 0 - or \a str2 is 0 (but not both). + Special case 2: Returns a random non-zero value if \a str1 is nullptr + or \a str2 is nullptr (but not both). \sa qstrcmp(), qstrncmp(), qstricmp(), {8-bit Character Comparisons} */ diff --git a/src/network/ssl/qsslsocket_winrt.cpp b/src/network/ssl/qsslsocket_winrt.cpp index 53a8a8b61b..e72edcbc52 100644 --- a/src/network/ssl/qsslsocket_winrt.cpp +++ b/src/network/ssl/qsslsocket_winrt.cpp @@ -647,6 +647,10 @@ HRESULT QSslSocketBackendPrivate::onSslUpgrade(IAsyncAction *action, AsyncStatus connectionEncrypted = true; emit q->encrypted(); + // The write buffer may already have data written to it, so we need to call transmit. + // This has to be done in 'q's thread, and not in the current thread (the XAML thread). + QMetaObject::invokeMethod(q, [this](){ transmit(); }); + if (pendingClose) { pendingClose = false; q->disconnectFromHost(); diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 072012064f..98a4b261fd 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -246,14 +246,12 @@ struct QWindowsContextPrivate { QScopedPointer<QWindowsTabletSupport> m_tabletSupport; #endif const HRESULT m_oleInitializeResult; - const QByteArray m_eventType; QWindow *m_lastActiveWindow = nullptr; bool m_asyncExpose = false; }; QWindowsContextPrivate::QWindowsContextPrivate() : m_oleInitializeResult(OleInitialize(NULL)) - , m_eventType(QByteArrayLiteral("windows_generic_MSG")) { QWindowsContext::user32dll.init(); QWindowsContext::shcoredll.init(); @@ -866,6 +864,33 @@ static bool shouldHaveNonClientDpiScaling(const QWindow *window) ; } +static inline bool isInputMessage(UINT m) +{ + switch (m) { + case WM_IME_STARTCOMPOSITION: + case WM_IME_ENDCOMPOSITION: + case WM_IME_COMPOSITION: + case WM_TOUCH: + case WM_MOUSEHOVER: + case WM_MOUSELEAVE: + case WM_NCHITTEST: + case WM_NCMOUSEHOVER: + case WM_NCMOUSELEAVE: + case WM_SIZING: + case WM_MOVING: + case WM_SYSCOMMAND: + case WM_COMMAND: + case WM_DWMNCRENDERINGCHANGED: + case WM_PAINT: + return true; + default: + break; + } + return (m >= WM_MOUSEFIRST && m <= WM_MOUSELAST) + || (m >= WM_NCMOUSEMOVE && m <= WM_NCXBUTTONDBLCLK) + || (m >= WM_KEYFIRST && m <= WM_KEYLAST); +} + /*! \brief Main windows procedure registered for windows. @@ -901,21 +926,14 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, QWindowsWindow *platformWindow = findPlatformWindow(hwnd); *platformWindowPtr = platformWindow; - // Run the native event filters. - long filterResult = 0; - QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance(); - if (dispatcher && dispatcher->filterNativeEvent(d->m_eventType, &msg, &filterResult)) { - *result = LRESULT(filterResult); + // Run the native event filters. QTBUG-67095: Exclude input messages which are sent + // by QEventDispatcherWin32::processEvents() + if (!isInputMessage(msg.message) && filterNativeEvent(&msg, result)) + return true; + + if (platformWindow && filterNativeEvent(platformWindow->window(), &msg, result)) return true; - } - if (platformWindow) { - filterResult = 0; - if (QWindowSystemInterface::handleNativeEvent(platformWindow->window(), d->m_eventType, &msg, &filterResult)) { - *result = LRESULT(filterResult); - return true; - } - } if (et & QtWindows::InputMethodEventFlag) { QWindowsInputContext *windowsInputContext = ::windowsInputContext(); // Disable IME assuming this is a special implementation hooking into keyboard input. @@ -1393,4 +1411,30 @@ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPAR return result; } + +static inline QByteArray nativeEventType() { return QByteArrayLiteral("windows_generic_MSG"); } + +// Send to QAbstractEventDispatcher +bool QWindowsContext::filterNativeEvent(MSG *msg, LRESULT *result) +{ + QAbstractEventDispatcher *dispatcher = QAbstractEventDispatcher::instance(); + long filterResult = 0; + if (dispatcher && dispatcher->filterNativeEvent(nativeEventType(), msg, &filterResult)) { + *result = LRESULT(filterResult); + return true; + } + return false; +} + +// Send to QWindowSystemInterface +bool QWindowsContext::filterNativeEvent(QWindow *window, MSG *msg, LRESULT *result) +{ + long filterResult = 0; + if (QWindowSystemInterface::handleNativeEvent(window, nativeEventType(), &msg, &filterResult)) { + *result = LRESULT(filterResult); + return true; + } + return false; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index f2ec307be2..0a7f20ca83 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -212,6 +212,9 @@ public: QTouchDevice *touchDevice() const; + static bool filterNativeEvent(MSG *msg, LRESULT *result); + static bool filterNativeEvent(QWindow *window, MSG *msg, LRESULT *result); + private: void handleFocusEvent(QtWindows::WindowsEventType et, QWindowsWindow *w); #ifndef QT_NO_CONTEXTMENU diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index af62936a18..2e44626112 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -830,7 +830,7 @@ bool QWindowsKeyMapper::translateKeyEvent(QWindow *widget, HWND hwnd, if (PeekMessage(&peekedMsg, hwnd, 0, 0, PM_NOREMOVE) && peekedMsg.message == WM_DEADCHAR) return true; - return translateKeyEventInternal(widget, msg, false); + return translateKeyEventInternal(widget, msg, false, result); } bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, const MSG &msg) @@ -862,7 +862,7 @@ bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, con #endif } -bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &msg, bool /* grab */) +bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &msg, bool /* grab */, LRESULT *lResult) { const UINT msgType = msg.message; @@ -1056,6 +1056,10 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms QChar uch; if (PeekMessage(&wm_char, 0, charType, charType, PM_REMOVE)) { + if (QWindowsContext::filterNativeEvent(&wm_char, lResult)) + return true; + if (receiver && QWindowsContext::filterNativeEvent(receiver, &wm_char, lResult)) + return true; // Found a ?_CHAR uch = QChar(ushort(wm_char.wParam)); if (uch.isHighSurrogate()) { @@ -1264,8 +1268,19 @@ QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const for (size_t i = 1; i < NumMods; ++i) { Qt::KeyboardModifiers neededMods = ModsTbl[i]; quint32 key = kbItem.qtKey[i]; - if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) - result << int(key + (keyMods & ~neededMods)); + if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) { + const Qt::KeyboardModifiers missingMods = keyMods & ~neededMods; + const int matchedKey = int(key) + missingMods; + const QList<int>::iterator it = + std::find_if(result.begin(), result.end(), + [key] (int k) { return (k & ~Qt::KeyboardModifierMask) == key; }); + // QTBUG-67200: Use the match with the least modifiers (prefer + // Shift+9 over Alt + Shift + 9) resulting in more missing modifiers. + if (it == result.end()) + result << matchedKey; + else if (missingMods > (*it & Qt::KeyboardModifierMask)) + *it = matchedKey; + } } return result; diff --git a/src/plugins/platforms/windows/qwindowskeymapper.h b/src/plugins/platforms/windows/qwindowskeymapper.h index 2657644780..c6b46b0c30 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.h +++ b/src/plugins/platforms/windows/qwindowskeymapper.h @@ -90,7 +90,7 @@ public: QList<int> possibleKeys(const QKeyEvent *e) const; private: - bool translateKeyEventInternal(QWindow *receiver, const MSG &msg, bool grab); + bool translateKeyEventInternal(QWindow *receiver, const MSG &msg, bool grab, LRESULT *lResult); bool translateMultimediaKeyEventInternal(QWindow *receiver, const MSG &msg); void updateKeyMap(const MSG &msg); |