diff options
Diffstat (limited to 'src/plugins/platforms/windows')
13 files changed, 135 insertions, 38 deletions
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/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index 593ff3cef1..e427ee162a 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -56,6 +56,7 @@ #include <QtGui/QRasterWindow> #include <QtGui/QGuiApplication> #include <qpa/qwindowsysteminterface_p.h> +#include <QtGui/private/qdnd_p.h> #include <QtGui/private/qguiapplication_p.h> #include <QtGui/private/qhighdpiscaling_p.h> diff --git a/src/plugins/platforms/windows/qwindowsdrag.h b/src/plugins/platforms/windows/qwindowsdrag.h index 2b4ca2dce1..d934679488 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.h +++ b/src/plugins/platforms/windows/qwindowsdrag.h @@ -44,6 +44,7 @@ #include "qwindowsinternalmimedata.h" #include <qpa/qplatformdrag.h> +#include <QtGui/qdrag.h> #include <QtGui/QPixmap> struct IDropTargetHelper; diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index b9dd2c557e..2dbca6047c 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -530,6 +530,14 @@ bool QWindowsInputContext::endComposition(HWND hwnd) if (m_compositionContext.focusObject.isNull()) return false; + // QTBUG-58300: Ignore WM_IME_ENDCOMPOSITION when CTRL is pressed to prevent + // for example the text being cleared when pressing CTRL+A + if (m_locale.language() == QLocale::Korean + && QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier)) { + reset(); + return true; + } + m_endCompositionRecursionGuard = true; imeNotifyCancelComposition(m_compositionContext.hwnd); diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 287b65cd5d..0a9e8b9d91 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -552,7 +552,7 @@ QPlatformDrag *QWindowsIntegration::drag() const { return &d->m_drag; } -# endif // !QT_NO_DRAGANDDROP +# endif // QT_CONFIG(draganddrop) #endif // !QT_NO_CLIPBOARD QPlatformInputContext * QWindowsIntegration::inputContext() const diff --git a/src/plugins/platforms/windows/qwindowsinternalmimedata.h b/src/plugins/platforms/windows/qwindowsinternalmimedata.h index a7df1ee6e0..a44f5b509c 100644 --- a/src/plugins/platforms/windows/qwindowsinternalmimedata.h +++ b/src/plugins/platforms/windows/qwindowsinternalmimedata.h @@ -42,7 +42,7 @@ #include <QtCore/qt_windows.h> -#include <QtGui/private/qdnd_p.h> // QInternalMime +#include <QtGui/private/qinternalmimedata_p.h> #include <QtCore/QVariant> QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index af62936a18..950d8ecd36 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -102,6 +102,7 @@ QWindowsKeyMapper::QWindowsKeyMapper() QGuiApplication *app = static_cast<QGuiApplication *>(QGuiApplication::instance()); QObject::connect(app, &QGuiApplication::applicationStateChanged, app, clearKeyRecorderOnApplicationInActive); + changeKeyboard(); } QWindowsKeyMapper::~QWindowsKeyMapper() @@ -317,9 +318,9 @@ static const uint KeyTbl[] = { // Keyboard mapping table Qt::Key_9, // 105 0x69 VK_NUMPAD9 | Numeric keypad 9 key Qt::Key_Asterisk, // 106 0x6A VK_MULTIPLY | Multiply key Qt::Key_Plus, // 107 0x6B VK_ADD | Add key - Qt::Key_Comma, // 108 0x6C VK_SEPARATOR | Separator key + Qt::Key_unknown, // 108 0x6C VK_SEPARATOR | Separator key (locale-dependent) Qt::Key_Minus, // 109 0x6D VK_SUBTRACT | Subtract key - Qt::Key_Period, // 110 0x6E VK_DECIMAL | Decimal key + Qt::Key_unknown, // 110 0x6E VK_DECIMAL | Decimal key (locale-dependent) Qt::Key_Slash, // 111 0x6F VK_DIVIDE | Divide key Qt::Key_F1, // 112 0x70 VK_F1 | F1 key Qt::Key_F2, // 113 0x71 VK_F2 | F2 key @@ -810,7 +811,7 @@ bool QWindowsKeyMapper::translateKeyEvent(QWindow *widget, HWND hwnd, // Reset layout map when system keyboard layout is changed if (msg.message == WM_INPUTLANGCHANGE) { - deleteLayouts(); + changeKeyboard(); return true; } @@ -830,7 +831,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) @@ -854,15 +855,19 @@ bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, con sendExtendedPressRelease(receiver, qtKey, Qt::KeyboardModifier(state), 0, 0, 0); // QTBUG-43343: Make sure to return false if Qt does not handle the key, otherwise, // the keys are not passed to the active media player. +# if QT_CONFIG(shortcut) const QKeySequence sequence(Qt::Modifier(state) + qtKey); return QGuiApplicationPrivate::instance()->shortcutMap.hasShortcutForKeySequence(sequence); +# else + return false; +# endif #else Q_UNREACHABLE(); return false; #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 +1061,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 +1273,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); diff --git a/src/plugins/platforms/windows/qwindowsmenu.cpp b/src/plugins/platforms/windows/qwindowsmenu.cpp index b89e1b66a3..71802b9017 100644 --- a/src/plugins/platforms/windows/qwindowsmenu.cpp +++ b/src/plugins/platforms/windows/qwindowsmenu.cpp @@ -390,6 +390,7 @@ void QWindowsMenuItem::setChecked(bool isChecked) menuItemSetChangeState(parentMenuHandle(), m_id, FALSE, m_checked, MF_CHECKED, MF_UNCHECKED); } +#if QT_CONFIG(shortcut) void QWindowsMenuItem::setShortcut(const QKeySequence &shortcut) { qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << shortcut << ')' << this; @@ -399,6 +400,7 @@ void QWindowsMenuItem::setShortcut(const QKeySequence &shortcut) if (m_parentMenu != nullptr) updateText(); } +#endif void QWindowsMenuItem::setEnabled(bool enabled) { @@ -441,10 +443,12 @@ UINT QWindowsMenuItem::state() const QString QWindowsMenuItem::nativeText() const { QString result = m_text; +#if QT_CONFIG(shortcut) if (!m_shortcut.isEmpty()) { result += QLatin1Char('\t'); result += m_shortcut.toString(QKeySequence::NativeText); } +#endif return result; } @@ -894,8 +898,10 @@ void QWindowsMenuItem::formatDebug(QDebug &d) const d << ", subMenu=" << static_cast<const void *>(m_subMenu); d << ", tag=" << showbase << hex << tag() << noshowbase << dec << ", id=" << m_id; +#if QT_CONFIG(shortcut) if (!m_shortcut.isEmpty()) d << ", shortcut=" << m_shortcut; +#endif if (m_visible) d << " [visible]"; if (m_enabled) diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index 34e6041687..0439797a7d 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -40,7 +40,7 @@ #include "qwindowsmime.h" #include "qwindowscontext.h" -#include <QtGui/private/qdnd_p.h> +#include <QtGui/private/qinternalmimedata_p.h> #include <QtCore/QByteArrayMatcher> #include <QtCore/QTextCodec> #include <QtCore/QMap> @@ -1255,7 +1255,7 @@ bool QBuiltInMimes::convertFromMime(const FORMATETC &formatetc, const QMimeData } else { #if QT_CONFIG(draganddrop) data = QInternalMimeData::renderDataHelper(outFormats.value(getCf(formatetc)), mimeData); -#endif //QT_NO_DRAGANDDROP +#endif // QT_CONFIG(draganddrop) } return setData(data, pmedium); } @@ -1363,7 +1363,7 @@ bool QLastResortMimes::canConvertFromMime(const FORMATETC &formatetc, const QMim Q_UNUSED(formatetc); return formatetc.tymed & TYMED_HGLOBAL && formats.contains(formatetc.cfFormat); -#endif //QT_NO_DRAGANDDROP +#endif // QT_CONFIG(draganddrop) } bool QLastResortMimes::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const @@ -1376,7 +1376,7 @@ bool QLastResortMimes::convertFromMime(const FORMATETC &formatetc, const QMimeDa Q_UNUSED(formatetc); Q_UNUSED(pmedium); return false; -#endif //QT_NO_DRAGANDDROP +#endif // QT_CONFIG(draganddrop) } QVector<FORMATETC> QLastResortMimes::formatsForMime(const QString &mimeType, const QMimeData * /*mimeData*/) const @@ -1484,7 +1484,7 @@ QString QLastResortMimes::mimeForFormat(const FORMATETC &formatetc) const format = clipFormat; } } -#endif //QT_NO_DRAGANDDROP +#endif // QT_CONFIG(draganddrop) } return format; @@ -1559,7 +1559,7 @@ QVector<FORMATETC> QWindowsMimeConverter::allFormatsForMime(const QMimeData *mim { ensureInitialized(); QVector<FORMATETC> formatics; -#ifdef QT_NO_DRAGANDDROP +#if !QT_CONFIG(draganddrop) Q_UNUSED(mimeData); #else formatics.reserve(20); @@ -1568,7 +1568,7 @@ QVector<FORMATETC> QWindowsMimeConverter::allFormatsForMime(const QMimeData *mim for (int i = m_mimes.size() - 1; i >= 0; --i) formatics += m_mimes.at(i)->formatsForMime(formats.at(f), mimeData); } -#endif //QT_NO_DRAGANDDROP +#endif // QT_CONFIG(draganddrop) return formatics; } diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 814291c54a..17851618b4 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -395,10 +395,24 @@ static bool isValidWheelReceiver(QWindow *candidate) static void redirectWheelEvent(QWindow *window, const QPoint &globalPos, int delta, Qt::Orientation orientation, Qt::KeyboardModifiers mods) { + // Redirect wheel event to one of the following, in order of preference: + // 1) The window under mouse + // 2) The window receiving the event // If a window is blocked by modality, it can't get the event. - if (isValidWheelReceiver(window)) { - QWindowSystemInterface::handleWheelEvent(window, - QWindowsGeometryHint::mapFromGlobal(window, globalPos), + + QWindow *receiver = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE); + while (receiver && receiver->flags().testFlag(Qt::WindowTransparentForInput)) + receiver = receiver->parent(); + bool handleEvent = true; + if (!isValidWheelReceiver(receiver)) { + receiver = window; + if (!isValidWheelReceiver(receiver)) + handleEvent = false; + } + + if (handleEvent) { + QWindowSystemInterface::handleWheelEvent(receiver, + QWindowsGeometryHint::mapFromGlobal(receiver, globalPos), globalPos, delta, orientation, mods); } } diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index f1762146ec..a2883e2601 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1144,11 +1144,11 @@ void QWindowsWindow::initialize() const Qt::WindowState state = w->windowState(); if (state != Qt::WindowMaximized && state != Qt::WindowFullScreen && creationContext->requestedGeometryIn != creationContext->obtainedGeometry) { - QWindowSystemInterface::handleGeometryChange(w, creationContext->obtainedGeometry); + QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(w, creationContext->obtainedGeometry); } QPlatformScreen *obtainedScreen = screenForGeometry(creationContext->obtainedGeometry); if (obtainedScreen && screen() != obtainedScreen) - QWindowSystemInterface::handleWindowScreenChanged(w, obtainedScreen->screen()); + QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(w, obtainedScreen->screen()); } } @@ -1248,7 +1248,7 @@ void QWindowsWindow::setDropSiteEnabled(bool dropEnabled) RevokeDragDrop(m_data.hwnd); m_dropTarget = 0; } -#endif // !QT_NO_CLIPBOARD && !QT_NO_DRAGANDDROP +#endif // QT_CONFIG(clipboard) && QT_CONFIG(draganddrop) } // Returns topmost QWindowsWindow ancestor even if there are embedded windows in the chain. |