summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows/qwindowscontext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/windows/qwindowscontext.cpp')
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp174
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())