diff options
Diffstat (limited to 'src/plugins/platforms/windows/qwindowscontext.cpp')
-rw-r--r-- | src/plugins/platforms/windows/qwindowscontext.cpp | 174 |
1 files changed, 141 insertions, 33 deletions
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 1da39a0516..03bb1bee48 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -43,6 +43,7 @@ #include "qwindowswindow.h" #include "qwindowskeymapper.h" #include "qwindowsmousehandler.h" +#include "qwindowspointerhandler.h" #include "qtwindowsglobal.h" #include "qwindowsmenu.h" #include "qwindowsmime.h" @@ -52,7 +53,7 @@ #endif #include "qwindowstheme.h" #include <private/qguiapplication_p.h> -#ifndef QT_NO_ACCESSIBILITY +#if QT_CONFIG(accessibility) # include "uiautomation/qwindowsuiaaccessibility.h" #endif #if QT_CONFIG(sessionmanager) @@ -62,20 +63,20 @@ #include "qwindowsscreen.h" #include "qwindowstheme.h" -#include <QtGui/qtguiglobal.h> -#include <QtGui/QWindow> +#include <QtGui/qwindow.h> #include <qpa/qwindowsysteminterface.h> +#include <qpa/qwindowsysteminterface_p.h> #include <qpa/qplatformnativeinterface.h> -#include <QtGui/QGuiApplication> -#include <QtGui/QOpenGLContext> - -#include <QtCore/QSet> -#include <QtCore/QHash> -#include <QtCore/QStringList> -#include <QtCore/QDebug> -#include <QtCore/QOperatingSystemVersion> -#include <QtCore/QSysInfo> -#include <QtCore/QScopedArrayPointer> +#include <QtGui/qguiapplication.h> +#include <QtGui/qopenglcontext.h> + +#include <QtCore/qset.h> +#include <QtCore/qhash.h> +#include <QtCore/qstringlist.h> +#include <QtCore/qdebug.h> +#include <QtCore/qoperatingsystemversion.h> +#include <QtCore/qsysinfo.h> +#include <QtCore/qscopedpointer.h> #include <QtCore/private/qsystemlibrary_p.h> #include <QtEventDispatcherSupport/private/qwindowsguieventdispatcher_p.h> @@ -89,7 +90,6 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcQpaWindows, "qt.qpa.windows") -Q_LOGGING_CATEGORY(lcQpaBackingStore, "qt.qpa.backingstore") Q_LOGGING_CATEGORY(lcQpaEvents, "qt.qpa.events") Q_LOGGING_CATEGORY(lcQpaGl, "qt.qpa.gl") Q_LOGGING_CATEGORY(lcQpaMime, "qt.qpa.mime") @@ -194,6 +194,17 @@ void QWindowsUser32DLL::init() getDisplayAutoRotationPreferences = (GetDisplayAutoRotationPreferences)library.resolve("GetDisplayAutoRotationPreferences"); setDisplayAutoRotationPreferences = (SetDisplayAutoRotationPreferences)library.resolve("SetDisplayAutoRotationPreferences"); + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8) { + enableMouseInPointer = (EnableMouseInPointer)library.resolve("EnableMouseInPointer"); + getPointerType = (GetPointerType)library.resolve("GetPointerType"); + getPointerInfo = (GetPointerInfo)library.resolve("GetPointerInfo"); + getPointerDeviceRects = (GetPointerDeviceRects)library.resolve("GetPointerDeviceRects"); + getPointerTouchInfo = (GetPointerTouchInfo)library.resolve("GetPointerTouchInfo"); + getPointerFrameTouchInfo = (GetPointerFrameTouchInfo)library.resolve("GetPointerFrameTouchInfo"); + getPointerPenInfo = (GetPointerPenInfo)library.resolve("GetPointerPenInfo"); + skipPointerFrameMessages = (SkipPointerFrameMessages)library.resolve("SkipPointerFrameMessages"); + } + if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 14393)) { enableNonClientDpiScaling = (EnableNonClientDpiScaling)library.resolve("EnableNonClientDpiScaling"); @@ -202,6 +213,13 @@ void QWindowsUser32DLL::init() } } +bool QWindowsUser32DLL::supportsPointerApi() +{ + return enableMouseInPointer && getPointerType && getPointerInfo && getPointerDeviceRects + && getPointerTouchInfo && getPointerFrameTouchInfo && getPointerPenInfo + && skipPointerFrameMessages; +} + void QWindowsShcoreDLL::init() { if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8_1) @@ -239,6 +257,7 @@ struct QWindowsContextPrivate { int m_defaultDPI = 96; QWindowsKeyMapper m_keyMapper; QWindowsMouseHandler m_mouseHandler; + QWindowsPointerHandler m_pointerHandler; QWindowsMimeConverter m_mimeConverter; QWindowsScreenManager m_screenManager; QSharedPointer<QWindowCreationContext> m_creationContext; @@ -256,7 +275,7 @@ QWindowsContextPrivate::QWindowsContextPrivate() QWindowsContext::user32dll.init(); QWindowsContext::shcoredll.init(); - if (m_mouseHandler.touchDevice()) + if (m_pointerHandler.touchDevice() || m_mouseHandler.touchDevice()) m_systemInfo |= QWindowsContext::SI_SupportsTouch; m_displayContext = GetDC(0); m_defaultDPI = GetDeviceCaps(m_displayContext, LOGPIXELSY); @@ -281,10 +300,6 @@ QWindowsContext::QWindowsContext() : const QByteArray bv = qgetenv("QT_QPA_VERBOSE"); if (!bv.isEmpty()) QLoggingCategory::setFilterRules(QString::fromLocal8Bit(bv)); -#if QT_CONFIG(tabletevent) - d->m_tabletSupport.reset(QWindowsTabletSupport::create()); - qCDebug(lcQpaTablet) << "Tablet support: " << (d->m_tabletSupport.isNull() ? QStringLiteral("None") : d->m_tabletSupport->description()); -#endif } QWindowsContext::~QWindowsContext() @@ -310,12 +325,17 @@ bool QWindowsContext::initTouch(unsigned integrationOptions) if (d->m_systemInfo & QWindowsContext::SI_SupportsTouch) return true; - QTouchDevice *touchDevice = d->m_mouseHandler.ensureTouchDevice(); + QTouchDevice *touchDevice = (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) ? + d->m_pointerHandler.ensureTouchDevice() : d->m_mouseHandler.ensureTouchDevice(); if (!touchDevice) return false; - if (!(integrationOptions & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch)) - touchDevice->setCapabilities(touchDevice->capabilities() | QTouchDevice::MouseEmulation); + if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) { + QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false); + } else { + if (!(integrationOptions & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch)) + touchDevice->setCapabilities(touchDevice->capabilities() | QTouchDevice::MouseEmulation); + } QWindowSystemInterface::registerTouchDevice(touchDevice); @@ -330,6 +350,33 @@ bool QWindowsContext::initTouch(unsigned integrationOptions) return true; } +bool QWindowsContext::initTablet(unsigned integrationOptions) +{ + Q_UNUSED(integrationOptions); +#if QT_CONFIG(tabletevent) + d->m_tabletSupport.reset(QWindowsTabletSupport::create()); + return true; +#else + return false; +#endif +} + +bool QWindowsContext::initPointer(unsigned integrationOptions) +{ + if (integrationOptions & QWindowsIntegration::DontUseWMPointer) + return false; + + if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8) + return false; + + if (!QWindowsContext::user32dll.supportsPointerApi()) + return false; + + QWindowsContext::user32dll.enableMouseInPointer(TRUE); + d->m_systemInfo |= QWindowsContext::SI_SupportsPointer; + return true; +} + void QWindowsContext::setTabletAbsoluteRange(int a) { #if QT_CONFIG(tabletevent) @@ -340,6 +387,11 @@ void QWindowsContext::setTabletAbsoluteRange(int a) #endif } +void QWindowsContext::setDetectAltGrModifier(bool a) +{ + d->m_keyMapper.setDetectAltGrModifier(a); +} + int QWindowsContext::processDpiAwareness() { int result; @@ -548,7 +600,7 @@ void QWindowsContext::unregisterWindowClasses() { const HINSTANCE appInstance = static_cast<HINSTANCE>(GetModuleHandle(0)); - foreach (const QString &name, d->m_registeredWindowClassNames) { + for (const QString &name : qAsConst(d->m_registeredWindowClassNames)) { if (!UnregisterClass(reinterpret_cast<LPCWSTR>(name.utf16()), appInstance) && QWindowsContext::verbose) qErrnoWarning("UnregisterClass failed for '%s'", qPrintable(name)); } @@ -632,12 +684,16 @@ QWindow *QWindowsContext::findWindow(HWND hwnd) const QWindow *QWindowsContext::windowUnderMouse() const { - return d->m_mouseHandler.windowUnderMouse(); + return (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) ? + d->m_pointerHandler.windowUnderMouse() : d->m_mouseHandler.windowUnderMouse(); } void QWindowsContext::clearWindowUnderMouse() { - d->m_mouseHandler.clearWindowUnderMouse(); + if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) + d->m_pointerHandler.clearWindowUnderMouse(); + else + d->m_mouseHandler.clearWindowUnderMouse(); } /*! @@ -958,7 +1014,9 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, switch (et) { case QtWindows::GestureEvent: - return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateGestureEvent(platformWindow->window(), hwnd, et, msg, result); + if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer)) + return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateGestureEvent(platformWindow->window(), hwnd, et, msg, result); + break; case QtWindows::InputMethodOpenCandidateWindowEvent: case QtWindows::InputMethodCloseCandidateWindowEvent: // TODO: Release/regrab mouse if a popup has mouse grab. @@ -975,7 +1033,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, case QtWindows::UnknownEvent: return false; case QtWindows::AccessibleObjectFromWindowRequest: -#ifndef QT_NO_ACCESSIBILITY +#if QT_CONFIG(accessibility) return QWindowsUiaAccessibility::handleWmGetObject(hwnd, wParam, lParam, result); #else return false; @@ -1084,18 +1142,25 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, case QtWindows::ExposeEvent: return platformWindow->handleWmPaint(hwnd, message, wParam, lParam); case QtWindows::NonClientMouseEvent: - if (platformWindow->frameStrutEventsEnabled()) + if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled()) return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); break; + case QtWindows::NonClientPointerEvent: + if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled()) + return sessionManagerInteractionBlocked() || d->m_pointerHandler.translatePointerEvent(platformWindow->window(), hwnd, et, msg, result); + break; case QtWindows::EnterSizeMoveEvent: platformWindow->setFlag(QWindowsWindow::ResizeMoveActive); return true; case QtWindows::ExitSizeMoveEvent: platformWindow->clearFlag(QWindowsWindow::ResizeMoveActive); platformWindow->checkForScreenChanged(); + handleExitSizeMove(platformWindow->window()); return true; case QtWindows::ScrollEvent: - return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateScrollEvent(platformWindow->window(), hwnd, msg, result); + if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer)) + return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateScrollEvent(platformWindow->window(), hwnd, msg, result); + break; case QtWindows::MouseWheelEvent: case QtWindows::MouseEvent: case QtWindows::LeaveEvent: @@ -1105,10 +1170,20 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, window = window->parent(); if (!window) return false; - return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result); + if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer)) + return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result); + else + return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(window, hwnd, et, msg, result); } + break; case QtWindows::TouchEvent: - return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result); + if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer)) + return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result); + break; + case QtWindows::PointerEvent: + if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) + return sessionManagerInteractionBlocked() || d->m_pointerHandler.translatePointerEvent(platformWindow->window(), hwnd, et, msg, result); + break; case QtWindows::FocusInEvent: // see QWindowsWindow::requestActivateWindow(). case QtWindows::FocusOutEvent: handleFocusEvent(et, platformWindow); @@ -1151,6 +1226,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, } break; case QtWindows::MouseActivateWindowEvent: + case QtWindows::PointerActivateWindowEvent: if (platformWindow->window()->flags() & Qt::WindowDoesNotAcceptFocus) { *result = LRESULT(MA_NOACTIVATE); return true; @@ -1295,6 +1371,37 @@ bool QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg) } #endif +void QWindowsContext::handleExitSizeMove(QWindow *window) +{ + // Windows can be moved/resized by: + // 1) User moving a window by dragging the title bar: Causes a sequence + // of WM_NCLBUTTONDOWN, WM_NCMOUSEMOVE but no WM_NCLBUTTONUP, + // leaving the left mouse button 'pressed' + // 2) User choosing Resize/Move from System menu and using mouse/cursor keys: + // No mouse events are received + // 3) Programmatically via QSizeGrip calling QPlatformWindow::startSystemResize/Move(): + // Mouse is left in pressed state after press on size grip (inside window), + // no further mouse events are received + // For cases 1,3, intercept WM_EXITSIZEMOVE to sync the buttons. + const Qt::MouseButtons currentButtons = QWindowsMouseHandler::queryMouseButtons(); + const Qt::MouseButtons appButtons = QGuiApplication::mouseButtons(); + if (currentButtons == appButtons) + return; + const Qt::KeyboardModifiers keyboardModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); + const QPoint globalPos = QWindowsCursor::mousePosition(); + const QPlatformWindow *platWin = window->handle(); + const QPoint localPos = platWin->mapFromGlobal(globalPos); + const QEvent::Type type = platWin->geometry().contains(globalPos) + ? QEvent::MouseButtonRelease : QEvent::NonClientAreaMouseButtonRelease; + for (Qt::MouseButton button : {Qt::LeftButton, Qt::RightButton, Qt::MiddleButton}) { + if (appButtons.testFlag(button) && !currentButtons.testFlag(button)) { + QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, + currentButtons, button, type, + keyboardModifiers); + } + } +} + bool QWindowsContext::asyncExpose() const { return d->m_asyncExpose; @@ -1307,7 +1414,8 @@ void QWindowsContext::setAsyncExpose(bool value) QTouchDevice *QWindowsContext::touchDevice() const { - return d->m_mouseHandler.touchDevice(); + return (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) ? + d->m_pointerHandler.touchDevice() : d->m_mouseHandler.touchDevice(); } static DWORD readDwordRegistrySetting(const wchar_t *regKey, const wchar_t *subKey, DWORD defaultValue) @@ -1400,7 +1508,7 @@ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPAR marginsFromRects(ncCalcSizeFrame, rectFromNcCalcSize(message, wParam, lParam, 0)); if (margins.left() >= 0) { if (platformWindow) { - platformWindow->setFrameMargins(margins); + platformWindow->setFullFrameMargins(margins); } else { const QSharedPointer<QWindowCreationContext> ctx = QWindowsContext::instance()->windowCreationContext(); if (!ctx.isNull()) |