summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/windows')
-rw-r--r--src/plugins/platforms/windows/CMakeLists.txt5
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp61
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp12
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp1
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp7
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h7
-rw-r--r--src/plugins/platforms/windows/qwindowsmimeregistry.cpp18
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp653
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.h115
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.cpp13
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.h3
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h1
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.h1
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp11
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp3
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp133
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h6
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.cpp8
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.h11
23 files changed, 202 insertions, 881 deletions
diff --git a/src/plugins/platforms/windows/CMakeLists.txt b/src/plugins/platforms/windows/CMakeLists.txt
index 4b92317978..bbb8c46cf6 100644
--- a/src/plugins/platforms/windows/CMakeLists.txt
+++ b/src/plugins/platforms/windows/CMakeLists.txt
@@ -8,7 +8,7 @@
qt_internal_add_plugin(QWindowsIntegrationPlugin
OUTPUT_NAME qwindows
PLUGIN_TYPE platforms
- DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES windows
+ DEFAULT_IF "windows" IN_LIST QT_QPA_PLATFORMS
SOURCES
main.cpp
qtwindowsglobal.h
@@ -28,7 +28,6 @@ qt_internal_add_plugin(QWindowsIntegrationPlugin
qwindowskeymapper.cpp qwindowskeymapper.h
qwindowsmenu.cpp qwindowsmenu.h
qwindowsmimeregistry.cpp qwindowsmimeregistry.h
- qwindowsmousehandler.cpp qwindowsmousehandler.h
qwindowsnativeinterface.cpp qwindowsnativeinterface.h
qwindowsole.cpp qwindowsole.h
qwindowsopengltester.cpp qwindowsopengltester.h
@@ -132,6 +131,8 @@ qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION QT_FEATURE_tablete
qwindowstabletsupport.cpp qwindowstabletsupport.h
INCLUDE_DIRECTORIES
${QtBase_SOURCE_DIR}/src/3rdparty/wintab
+ ATTRIBUTION_FILE_DIR_PATHS
+ ../../../3rdparty/wintab
)
qt_internal_extend_target(QWindowsIntegrationPlugin CONDITION QT_FEATURE_sessionmanager
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index de65a2171d..11a9290a2e 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -7,7 +7,6 @@
#include "qwindowswindow.h"
#include "qwindowskeymapper.h"
#include "qwindowsnativeinterface.h"
-#include "qwindowsmousehandler.h"
#include "qwindowspointerhandler.h"
#include "qtwindowsglobal.h"
#include "qwindowsmenu.h"
@@ -141,7 +140,6 @@ struct QWindowsContextPrivate {
HDC m_displayContext = nullptr;
int m_defaultDPI = 96;
QWindowsKeyMapper m_keyMapper;
- QWindowsMouseHandler m_mouseHandler;
QWindowsPointerHandler m_pointerHandler;
QWindowsMimeRegistry m_mimeConverter;
QWindowsScreenManager m_screenManager;
@@ -162,7 +160,7 @@ bool QWindowsContextPrivate::m_v2DpiAware = false;
QWindowsContextPrivate::QWindowsContextPrivate()
: m_oleInitializeResult(OleInitialize(nullptr))
{
- if (m_pointerHandler.touchDevice() || m_mouseHandler.touchDevice())
+ if (m_pointerHandler.touchDevice())
m_systemInfo |= QWindowsContext::SI_SupportsTouch;
m_displayContext = GetDC(nullptr);
m_defaultDPI = GetDeviceCaps(m_displayContext, LOGPIXELSY);
@@ -201,6 +199,8 @@ QWindowsContext::~QWindowsContext()
if (d->m_powerDummyWindow)
DestroyWindow(d->m_powerDummyWindow);
+ d->m_screenManager.destroyWindow();
+
unregisterWindowClasses();
if (d->m_oleInitializeResult == S_OK || d->m_oleInitializeResult == S_FALSE) {
#ifdef QT_USE_FACTORY_CACHE_REGISTRATION
@@ -224,8 +224,7 @@ bool QWindowsContext::initTouch(unsigned integrationOptions)
{
if (d->m_systemInfo & QWindowsContext::SI_SupportsTouch)
return true;
- const bool usePointerHandler = (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) != 0;
- auto touchDevice = usePointerHandler ? d->m_pointerHandler.touchDevice() : d->m_mouseHandler.touchDevice();
+ auto touchDevice = d->m_pointerHandler.touchDevice();
if (touchDevice.isNull()) {
const bool mouseEmulation =
(integrationOptions & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch) == 0;
@@ -234,7 +233,6 @@ bool QWindowsContext::initTouch(unsigned integrationOptions)
if (touchDevice.isNull())
return false;
d->m_pointerHandler.setTouchDevice(touchDevice);
- d->m_mouseHandler.setTouchDevice(touchDevice);
QWindowSystemInterface::registerInputDevice(touchDevice.data());
d->m_systemInfo |= QWindowsContext::SI_SupportsTouch;
@@ -274,15 +272,6 @@ bool QWindowsContext::disposeTablet()
#endif
}
-bool QWindowsContext::initPointer(unsigned integrationOptions)
-{
- if (integrationOptions & QWindowsIntegration::DontUseWMPointer)
- return false;
-
- d->m_systemInfo |= QWindowsContext::SI_SupportsPointer;
- return true;
-}
-
extern "C" LRESULT QT_WIN_CALLBACK qWindowsPowerWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message != WM_POWERBROADCAST || wParam != PBT_POWERSETTINGCHANGE)
@@ -728,16 +717,12 @@ QWindow *QWindowsContext::findWindow(HWND hwnd) const
QWindow *QWindowsContext::windowUnderMouse() const
{
- return (d->m_systemInfo & QWindowsContext::SI_SupportsPointer) ?
- d->m_pointerHandler.windowUnderMouse() : d->m_mouseHandler.windowUnderMouse();
+ return d->m_pointerHandler.windowUnderMouse();
}
void QWindowsContext::clearWindowUnderMouse()
{
- if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer)
- d->m_pointerHandler.clearWindowUnderMouse();
- else
- d->m_mouseHandler.clearWindowUnderMouse();
+ d->m_pointerHandler.clearWindowUnderMouse();
}
/*!
@@ -1050,8 +1035,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
switch (et) {
case QtWindows::GestureEvent:
- if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
- return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateGestureEvent(platformWindow->window(), hwnd, et, msg, result);
+ // TODO???
break;
case QtWindows::InputMethodOpenCandidateWindowEvent:
case QtWindows::InputMethodCloseCandidateWindowEvent:
@@ -1191,16 +1175,11 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::NonClientMouseEvent:
if (!platformWindow->frameStrutEventsEnabled())
break;
- if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
- return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
- else
- return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
+ return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
case QtWindows::NonClientPointerEvent:
if (!platformWindow->frameStrutEventsEnabled())
break;
- if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
- return sessionManagerInteractionBlocked() || d->m_pointerHandler.translatePointerEvent(platformWindow->window(), hwnd, et, msg, result);
- break;
+ return sessionManagerInteractionBlocked() || d->m_pointerHandler.translatePointerEvent(platformWindow->window(), hwnd, et, msg, result);
case QtWindows::EnterSizeMoveEvent:
platformWindow->setFlag(QWindowsWindow::ResizeMoveActive);
if (!IsZoomed(hwnd))
@@ -1214,8 +1193,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
platformWindow->updateRestoreGeometry();
return true;
case QtWindows::ScrollEvent:
- if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
- return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateScrollEvent(platformWindow->window(), hwnd, msg, result);
+ // TODO???
break;
case QtWindows::MouseWheelEvent:
case QtWindows::MouseEvent:
@@ -1226,20 +1204,14 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
window = window->parent();
if (!window)
return false;
- if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer)
- return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(window, hwnd, et, msg, result);
- else
- return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result);
+ return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(window, hwnd, et, msg, result);
}
break;
case QtWindows::TouchEvent:
- if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
- return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result);
+ // TODO???
break;
case QtWindows::PointerEvent:
- if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer)
- return sessionManagerInteractionBlocked() || d->m_pointerHandler.translatePointerEvent(platformWindow->window(), hwnd, et, msg, result);
- break;
+ return sessionManagerInteractionBlocked() || d->m_pointerHandler.translatePointerEvent(platformWindow->window(), hwnd, et, msg, result);
case QtWindows::FocusInEvent: // see QWindowsWindow::requestActivateWindow().
case QtWindows::FocusOutEvent:
handleFocusEvent(et, platformWindow);
@@ -1443,7 +1415,7 @@ void QWindowsContext::handleExitSizeMove(QWindow *window)
// 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 currentButtons = QWindowsPointerHandler::queryMouseButtons();
const Qt::MouseButtons appButtons = QGuiApplication::mouseButtons();
if (currentButtons == appButtons)
return;
@@ -1459,10 +1431,7 @@ void QWindowsContext::handleExitSizeMove(QWindow *window)
currentButtons, button, type, keyboardModifiers);
}
}
- if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer)
- d->m_pointerHandler.clearEvents();
- else
- d->m_mouseHandler.clearEvents();
+ d->m_pointerHandler.clearEvents();
}
bool QWindowsContext::asyncExpose() const
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index 0539a22afc..4e9be1af96 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -53,8 +53,7 @@ public:
enum SystemInfoFlags
{
SI_RTL_Extensions = 0x1,
- SI_SupportsTouch = 0x2,
- SI_SupportsPointer = 0x4,
+ SI_SupportsTouch = 0x2
};
// Verbose flag set by environment variable QT_QPA_VERBOSE
@@ -67,7 +66,6 @@ public:
bool initTouch(unsigned integrationOptions); // For calls from QWindowsIntegration::QWindowsIntegration() only.
void registerTouchWindows();
bool initTablet();
- bool initPointer(unsigned integrationOptions);
bool disposeTablet();
bool initPowerNotificationHandler();
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index c6f55c3509..b872ef2ad6 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -11,7 +11,7 @@
#include "qwindowsintegration.h"
#include "qwindowsdropdataobject.h"
#include "qwindowswindow.h"
-#include "qwindowsmousehandler.h"
+#include "qwindowspointerhandler.h"
#include "qwindowscursor.h"
#include "qwindowskeymapper.h"
@@ -341,7 +341,7 @@ QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
// In some rare cases, when a mouse button is released but the mouse is static,
// grfKeyState will not be updated with these released buttons until the mouse
// is moved. So we use the async key state given by queryMouseButtons() instead.
- Qt::MouseButtons buttons = QWindowsMouseHandler::queryMouseButtons();
+ Qt::MouseButtons buttons = QWindowsPointerHandler::queryMouseButtons();
SCODE result = S_OK;
if (fEscapePressed || QWindowsDrag::isCanceled()) {
@@ -366,7 +366,7 @@ QWindowsOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
const QPoint localPos = m_windowUnderMouse->handle()->mapFromGlobal(globalPos);
QWindowSystemInterface::handleMouseEvent(m_windowUnderMouse.data(),
QPointF(localPos), QPointF(globalPos),
- QWindowsMouseHandler::queryMouseButtons(),
+ QWindowsPointerHandler::queryMouseButtons(),
Qt::LeftButton, QEvent::MouseButtonRelease);
}
m_currentButtons = Qt::NoButton;
@@ -460,7 +460,7 @@ void QWindowsOleDropTarget::handleDrag(QWindow *window, DWORD grfKeyState,
const Qt::DropActions actions = translateToQDragDropActions(*pdwEffect);
lastModifiers = toQtKeyboardModifiers(grfKeyState);
- lastButtons = QWindowsMouseHandler::queryMouseButtons();
+ lastButtons = QWindowsPointerHandler::queryMouseButtons();
const QPlatformDragQtResponse response =
QWindowSystemInterface::handleDrag(window, windowsDrag->dropData(),
@@ -530,7 +530,7 @@ QWindowsOleDropTarget::DragLeave()
const auto *keyMapper = QWindowsContext::instance()->keyMapper();
lastModifiers = keyMapper->queryKeyboardModifiers();
- lastButtons = QWindowsMouseHandler::queryMouseButtons();
+ lastButtons = QWindowsPointerHandler::queryMouseButtons();
QWindowSystemInterface::handleDrag(m_window, nullptr, QPoint(), Qt::IgnoreAction,
Qt::NoButton, Qt::NoModifier);
@@ -559,7 +559,7 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState,
QWindowsDrag *windowsDrag = QWindowsDrag::instance();
lastModifiers = toQtKeyboardModifiers(grfKeyState);
- lastButtons = QWindowsMouseHandler::queryMouseButtons();
+ lastButtons = QWindowsPointerHandler::queryMouseButtons();
const QPlatformDropQtResponse response =
QWindowSystemInterface::handleDrop(m_window, windowsDrag->dropData(),
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
index 0281025b5b..4b524c7a2c 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
@@ -5,7 +5,6 @@
#include "qwindowscontext.h"
#include "qwindowswindow.h"
#include "qwindowsintegration.h"
-#include "qwindowsmousehandler.h"
#include <QtCore/qdebug.h>
#include <QtCore/qobject.h>
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index aa6be266da..487e1d47b6 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -173,8 +173,6 @@ static inline unsigned parseOptions(const QStringList &paramList,
options |= QWindowsIntegration::AlwaysUseNativeMenus;
} else if (param == u"menus=none") {
options |= QWindowsIntegration::NoNativeMenus;
- } else if (param == u"nowmpointer") {
- options |= QWindowsIntegration::DontUseWMPointer;
} else if (param == u"reverse") {
options |= QWindowsIntegration::RtlEnabled;
} else if (param == u"darkmode=0") {
@@ -209,10 +207,7 @@ void QWindowsIntegrationPrivate::parseOptions(QWindowsIntegration *q, const QStr
if (tabletAbsoluteRange >= 0)
QWindowsContext::setTabletAbsoluteRange(tabletAbsoluteRange);
- if (m_context.initPointer(m_options))
- QCoreApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents);
- else
- m_context.initTablet();
+ QCoreApplication::setAttribute(Qt::AA_CompressHighFrequencyEvents);
QWindowSystemInterfacePrivate::TabletEvent::setPlatformSynthesizesMouse(false);
if (!dpiAwarenessSet) { // Set only once in case of repeated instantiations of QGuiApplication.
diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h
index c271207741..932a69a6b7 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.h
+++ b/src/plugins/platforms/windows/qwindowsintegration.h
@@ -42,10 +42,9 @@ public:
DontUseColorFonts = QWindowsFontDatabase::DontUseColorFonts,
AlwaysUseNativeMenus = 0x100,
NoNativeMenus = 0x200,
- DontUseWMPointer = 0x400,
- DetectAltGrModifier = 0x800,
- RtlEnabled = 0x1000,
- FontDatabaseGDI = 0x2000
+ DetectAltGrModifier = 0x400,
+ RtlEnabled = 0x0800,
+ FontDatabaseGDI = 0x1000
};
explicit QWindowsIntegration(const QStringList &paramList);
diff --git a/src/plugins/platforms/windows/qwindowsmimeregistry.cpp b/src/plugins/platforms/windows/qwindowsmimeregistry.cpp
index 8d147e8fa0..71faf4fe3b 100644
--- a/src/plugins/platforms/windows/qwindowsmimeregistry.cpp
+++ b/src/plugins/platforms/windows/qwindowsmimeregistry.cpp
@@ -923,16 +923,8 @@ QVariant QWindowsMimeImage::convertToMime(const QString &mimeType, IDataObject *
const bool canGetDibV5 = canGetData(CF_DIBV5, pDataObj);
const bool hasOrigDibV5 = canGetDibV5 ? hasOriginalDIBV5(pDataObj) : false;
qCDebug(lcQpaMime) << "canGetDibV5:" << canGetDibV5 << "hasOrigDibV5:" << hasOrigDibV5;
- if (hasOrigDibV5) {
- qCDebug(lcQpaMime) << "Decoding DIBV5";
- QImage img;
- QByteArray data = getData(CF_DIBV5, pDataObj);
- QBuffer buffer(&data);
- if (readDib(buffer, img))
- return img;
- }
- //PNG, MS Office place this (undocumented)
- if (canGetData(CF_PNG, pDataObj)) {
+ // PNG, MS Office place this (undocumented)
+ if (!hasOrigDibV5 && canGetData(CF_PNG, pDataObj)) {
qCDebug(lcQpaMime) << "Decoding PNG";
QImage img;
QByteArray data = getData(CF_PNG, pDataObj);
@@ -940,11 +932,11 @@ QVariant QWindowsMimeImage::convertToMime(const QString &mimeType, IDataObject *
return img;
}
}
- //Fallback to DIB
- if (canGetData(CF_DIB, pDataObj)) {
+
+ if (canGetDibV5 || canGetData(CF_DIB, pDataObj)) {
qCDebug(lcQpaMime) << "Decoding DIB";
QImage img;
- QByteArray data = getData(CF_DIBV5, pDataObj);
+ QByteArray data = getData(canGetDibV5 ? CF_DIBV5 : CF_DIB, pDataObj);
QBuffer buffer(&data);
if (readDib(buffer, img))
return img;
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
deleted file mode 100644
index 9af9fba408..0000000000
--- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
+++ /dev/null
@@ -1,653 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-
-#include "qwindowsmousehandler.h"
-#include "qwindowskeymapper.h"
-#include "qwindowscontext.h"
-#include "qwindowswindow.h"
-#include "qwindowsintegration.h"
-#include "qwindowsscreen.h"
-
-#include <qpa/qwindowsysteminterface.h>
-#include <QtGui/qguiapplication.h>
-#include <QtGui/qscreen.h>
-#include <QtGui/qpointingdevice.h>
-#include <QtGui/qwindow.h>
-#include <QtGui/qcursor.h>
-
-#include <QtCore/qdebug.h>
-
-#include <memory>
-
-#include <windowsx.h>
-
-QT_BEGIN_NAMESPACE
-
-static inline void compressMouseMove(MSG *msg)
-{
- // Compress mouse move events
- if (msg->message == WM_MOUSEMOVE) {
- MSG mouseMsg;
- while (PeekMessage(&mouseMsg, msg->hwnd, WM_MOUSEFIRST,
- WM_MOUSELAST, PM_NOREMOVE)) {
- if (mouseMsg.message == WM_MOUSEMOVE) {
-#define PEEKMESSAGE_IS_BROKEN 1
-#ifdef PEEKMESSAGE_IS_BROKEN
- // Since the Windows PeekMessage() function doesn't
- // correctly return the wParam for WM_MOUSEMOVE events
- // if there is a key release event in the queue
- // _before_ the mouse event, we have to also consider
- // key release events (kls 2003-05-13):
- MSG keyMsg;
- bool done = false;
- while (PeekMessage(&keyMsg, nullptr, WM_KEYFIRST, WM_KEYLAST,
- PM_NOREMOVE)) {
- if (keyMsg.time < mouseMsg.time) {
- if ((keyMsg.lParam & 0xC0000000) == 0x40000000) {
- PeekMessage(&keyMsg, nullptr, keyMsg.message,
- keyMsg.message, PM_REMOVE);
- } else {
- done = true;
- break;
- }
- } else {
- break; // no key event before the WM_MOUSEMOVE event
- }
- }
- if (done)
- break;
-#else
- // Actually the following 'if' should work instead of
- // the above key event checking, but apparently
- // PeekMessage() is broken :-(
- if (mouseMsg.wParam != msg.wParam)
- break; // leave the message in the queue because
- // the key state has changed
-#endif
- // Update the passed in MSG structure with the
- // most recent one.
- msg->lParam = mouseMsg.lParam;
- msg->wParam = mouseMsg.wParam;
- // Extract the x,y coordinates from the lParam as we do in the WndProc
- msg->pt.x = GET_X_LPARAM(mouseMsg.lParam);
- msg->pt.y = GET_Y_LPARAM(mouseMsg.lParam);
- clientToScreen(msg->hwnd, &(msg->pt));
- // Remove the mouse move message
- PeekMessage(&mouseMsg, msg->hwnd, WM_MOUSEMOVE,
- WM_MOUSEMOVE, PM_REMOVE);
- } else {
- break; // there was no more WM_MOUSEMOVE event
- }
- }
- }
-}
-
-/*!
- \class QWindowsMouseHandler
- \brief Windows mouse handler
-
- Dispatches mouse and touch events. Separate for code cleanliness.
-
- \internal
-*/
-
-QWindowsMouseHandler::QWindowsMouseHandler() = default;
-
-const QPointingDevice *QWindowsMouseHandler::primaryMouse()
-{
- static QPointer<const QPointingDevice> result;
- if (!result)
- result = QPointingDevice::primaryPointingDevice();
- return result;
-}
-
-void QWindowsMouseHandler::clearEvents()
-{
- m_lastEventType = QEvent::None;
- m_lastEventButton = Qt::NoButton;
-}
-
-Qt::MouseButtons QWindowsMouseHandler::queryMouseButtons()
-{
- Qt::MouseButtons result;
- const bool mouseSwapped = GetSystemMetrics(SM_SWAPBUTTON);
- if (GetAsyncKeyState(VK_LBUTTON) < 0)
- result |= mouseSwapped ? Qt::RightButton: Qt::LeftButton;
- if (GetAsyncKeyState(VK_RBUTTON) < 0)
- result |= mouseSwapped ? Qt::LeftButton : Qt::RightButton;
- if (GetAsyncKeyState(VK_MBUTTON) < 0)
- result |= Qt::MiddleButton;
- if (GetAsyncKeyState(VK_XBUTTON1) < 0)
- result |= Qt::XButton1;
- if (GetAsyncKeyState(VK_XBUTTON2) < 0)
- result |= Qt::XButton2;
- return result;
-}
-
-Q_CONSTINIT static QPoint lastMouseMovePos;
-
-namespace {
-struct MouseEvent {
- QEvent::Type type;
- Qt::MouseButton button;
-};
-
-#ifndef QT_NO_DEBUG_STREAM
-QDebug operator<<(QDebug d, const MouseEvent &e)
-{
- QDebugStateSaver saver(d);
- d.nospace();
- d << "MouseEvent(" << e.type << ", " << e.button << ')';
- return d;
-}
-#endif // QT_NO_DEBUG_STREAM
-} // namespace
-
-static inline Qt::MouseButton extraButton(WPARAM wParam) // for WM_XBUTTON...
-{
- return GET_XBUTTON_WPARAM(wParam) == XBUTTON1 ? Qt::BackButton : Qt::ForwardButton;
-}
-
-static inline MouseEvent eventFromMsg(const MSG &msg)
-{
- switch (msg.message) {
- case WM_MOUSEMOVE:
- return {QEvent::MouseMove, Qt::NoButton};
- case WM_LBUTTONDOWN:
- return {QEvent::MouseButtonPress, Qt::LeftButton};
- case WM_LBUTTONUP:
- return {QEvent::MouseButtonRelease, Qt::LeftButton};
- case WM_LBUTTONDBLCLK: // Qt QPA does not handle double clicks, send as press
- return {QEvent::MouseButtonPress, Qt::LeftButton};
- case WM_MBUTTONDOWN:
- return {QEvent::MouseButtonPress, Qt::MiddleButton};
- case WM_MBUTTONUP:
- return {QEvent::MouseButtonRelease, Qt::MiddleButton};
- case WM_MBUTTONDBLCLK:
- return {QEvent::MouseButtonPress, Qt::MiddleButton};
- case WM_RBUTTONDOWN:
- return {QEvent::MouseButtonPress, Qt::RightButton};
- case WM_RBUTTONUP:
- return {QEvent::MouseButtonRelease, Qt::RightButton};
- case WM_RBUTTONDBLCLK:
- return {QEvent::MouseButtonPress, Qt::RightButton};
- case WM_XBUTTONDOWN:
- return {QEvent::MouseButtonPress, extraButton(msg.wParam)};
- case WM_XBUTTONUP:
- return {QEvent::MouseButtonRelease, extraButton(msg.wParam)};
- case WM_XBUTTONDBLCLK:
- return {QEvent::MouseButtonPress, extraButton(msg.wParam)};
- case WM_NCMOUSEMOVE:
- return {QEvent::NonClientAreaMouseMove, Qt::NoButton};
- case WM_NCLBUTTONDOWN:
- return {QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton};
- case WM_NCLBUTTONUP:
- return {QEvent::NonClientAreaMouseButtonRelease, Qt::LeftButton};
- case WM_NCLBUTTONDBLCLK:
- return {QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton};
- case WM_NCMBUTTONDOWN:
- return {QEvent::NonClientAreaMouseButtonPress, Qt::MiddleButton};
- case WM_NCMBUTTONUP:
- return {QEvent::NonClientAreaMouseButtonRelease, Qt::MiddleButton};
- case WM_NCMBUTTONDBLCLK:
- return {QEvent::NonClientAreaMouseButtonPress, Qt::MiddleButton};
- case WM_NCRBUTTONDOWN:
- return {QEvent::NonClientAreaMouseButtonPress, Qt::RightButton};
- case WM_NCRBUTTONUP:
- return {QEvent::NonClientAreaMouseButtonRelease, Qt::RightButton};
- case WM_NCRBUTTONDBLCLK:
- return {QEvent::NonClientAreaMouseButtonPress, Qt::RightButton};
- default: // WM_MOUSELEAVE
- break;
- }
- return {QEvent::None, Qt::NoButton};
-}
-
-bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
- QtWindows::WindowsEventType et,
- MSG msg, LRESULT *result)
-{
- enum : quint64 { signatureMask = 0xffffff00, miWpSignature = 0xff515700 };
-
- if (et == QtWindows::MouseWheelEvent)
- return translateMouseWheelEvent(window, hwnd, msg, result);
-
- QPoint winEventPosition(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
- if ((et & QtWindows::NonClientEventFlag) == 0 && QWindowsBaseWindow::isRtlLayout(hwnd)) {
- RECT clientArea;
- GetClientRect(hwnd, &clientArea);
- winEventPosition.setX(clientArea.right - winEventPosition.x());
- }
-
- QPoint clientPosition;
- QPoint globalPosition;
- if (et & QtWindows::NonClientEventFlag) {
- globalPosition = winEventPosition;
- clientPosition = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPosition);
- } else {
- globalPosition = QWindowsGeometryHint::mapToGlobal(hwnd, winEventPosition);
- auto targetHwnd = hwnd;
- if (auto *pw = window->handle())
- targetHwnd = HWND(pw->winId());
- clientPosition = targetHwnd == hwnd
- ? winEventPosition
- : QWindowsGeometryHint::mapFromGlobal(targetHwnd, globalPosition);
- }
-
- // Windows sends a mouse move with no buttons pressed to signal "Enter"
- // when a window is shown over the cursor. Discard the event and only use
- // it for generating QEvent::Enter to be consistent with other platforms -
- // X11 and macOS.
- bool discardEvent = false;
- if (msg.message == WM_MOUSEMOVE) {
- const bool samePosition = globalPosition == lastMouseMovePos;
- lastMouseMovePos = globalPosition;
- if (msg.wParam == 0 && (m_windowUnderMouse.isNull() || samePosition))
- discardEvent = true;
- }
-
- Qt::MouseEventSource source = Qt::MouseEventNotSynthesized;
-
- const QPointingDevice *device = primaryMouse();
-
- // Check for events synthesized from touch. Lower byte is touch index, 0 means pen.
- static const bool passSynthesizedMouseEvents =
- !(QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch);
- // Check for events synthesized from touch. Lower 7 bits are touch/pen index, bit 8 indicates touch.
- // However, when tablet support is active, extraInfo is a packet serial number. This is not a problem
- // since we do not want to ignore mouse events coming from a tablet.
- // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms703320.aspx
- const auto extraInfo = quint64(GetMessageExtraInfo());
- if ((extraInfo & signatureMask) == miWpSignature) {
- if (extraInfo & 0x80) { // Bit 7 indicates touch event, else tablet pen.
- source = Qt::MouseEventSynthesizedBySystem;
- if (!m_touchDevice.isNull())
- device = m_touchDevice.data();
- if (!passSynthesizedMouseEvents)
- return false;
- }
- }
-
- const auto *keyMapper = QWindowsContext::instance()->keyMapper();
- const Qt::KeyboardModifiers keyModifiers = keyMapper->queryKeyboardModifiers();
- const MouseEvent mouseEvent = eventFromMsg(msg);
- Qt::MouseButtons buttons;
-
- if (mouseEvent.type >= QEvent::NonClientAreaMouseMove && mouseEvent.type <= QEvent::NonClientAreaMouseButtonDblClick)
- buttons = queryMouseButtons();
- else
- buttons = keyStateToMouseButtons(msg.wParam);
-
- // When the left/right mouse buttons are pressed over the window title bar
- // WM_NCLBUTTONDOWN/WM_NCRBUTTONDOWN messages are received. But no UP
- // messages are received on release, only WM_NCMOUSEMOVE/WM_MOUSEMOVE.
- // We detect it and generate the missing release events here. (QTBUG-75678)
- // The last event vars are cleared on QWindowsContext::handleExitSizeMove()
- // to avoid generating duplicated release events.
- if (m_lastEventType == QEvent::NonClientAreaMouseButtonPress
- && (mouseEvent.type == QEvent::NonClientAreaMouseMove || mouseEvent.type == QEvent::MouseMove)
- && (m_lastEventButton & buttons) == 0) {
- auto releaseType = mouseEvent.type == QEvent::NonClientAreaMouseMove ?
- QEvent::NonClientAreaMouseButtonRelease : QEvent::MouseButtonRelease;
- QWindowSystemInterface::handleMouseEvent(window, msg.time, device, clientPosition, globalPosition, buttons, m_lastEventButton,
- releaseType, keyModifiers, source);
- }
- m_lastEventType = mouseEvent.type;
- m_lastEventButton = mouseEvent.button;
-
- if (mouseEvent.type >= QEvent::NonClientAreaMouseMove && mouseEvent.type <= QEvent::NonClientAreaMouseButtonDblClick) {
- QWindowSystemInterface::handleMouseEvent(window, msg.time, device, clientPosition,
- globalPosition, buttons,
- mouseEvent.button, mouseEvent.type,
- keyModifiers, source);
- return false; // Allow further event processing (dragging of windows).
- }
-
- *result = 0;
- if (msg.message == WM_MOUSELEAVE) {
- qCDebug(lcQpaEvents) << mouseEvent << "for" << window << "previous window under mouse="
- << m_windowUnderMouse << "tracked window=" << m_trackedWindow;
-
- // When moving out of a window, WM_MOUSEMOVE within the moved-to window is received first,
- // so if m_trackedWindow is not the window here, it means the cursor has left the
- // application.
- if (window == m_trackedWindow) {
- QWindow *leaveTarget = m_windowUnderMouse ? m_windowUnderMouse : m_trackedWindow;
- qCDebug(lcQpaEvents) << "Generating leave event for " << leaveTarget;
- QWindowSystemInterface::handleLeaveEvent(leaveTarget);
- m_trackedWindow = nullptr;
- m_windowUnderMouse = nullptr;
- }
- return true;
- }
-
- auto *platformWindow = static_cast<QWindowsWindow *>(window->handle());
-
- // If the window was recently resized via mouse double-click on the frame or title bar,
- // we don't get WM_LBUTTONDOWN or WM_LBUTTONDBLCLK for the second click,
- // but we will get at least one WM_MOUSEMOVE with left button down and the WM_LBUTTONUP,
- // which will result undesired mouse press and release events.
- // To avoid those, we ignore any events with left button down if we didn't
- // get the original WM_LBUTTONDOWN/WM_LBUTTONDBLCLK.
- if (msg.message == WM_LBUTTONDOWN || msg.message == WM_LBUTTONDBLCLK) {
- m_leftButtonDown = true;
- } else {
- const bool actualLeftDown = buttons & Qt::LeftButton;
- if (!m_leftButtonDown && actualLeftDown) {
- // Autocapture the mouse for current window to and ignore further events until release.
- // Capture is necessary so we don't get WM_MOUSELEAVEs to confuse matters.
- // This autocapture is released normally when button is released.
- if (!platformWindow->hasMouseCapture()) {
- platformWindow->applyCursor();
- platformWindow->setMouseGrabEnabled(true);
- platformWindow->setFlag(QWindowsWindow::AutoMouseCapture);
- qCDebug(lcQpaEvents) << "Automatic mouse capture for missing buttondown event" << window;
- }
- m_previousCaptureWindow = window;
- return true;
- }
- if (m_leftButtonDown && !actualLeftDown)
- m_leftButtonDown = false;
- }
-
- // In this context, neither an invisible nor a transparent window (transparent regarding mouse
- // events, "click-through") can be considered as the window under mouse.
- QWindow *currentWindowUnderMouse = platformWindow->hasMouseCapture() ?
- QWindowsScreen::windowAt(globalPosition, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT) : window;
- while (currentWindowUnderMouse && currentWindowUnderMouse->flags() & Qt::WindowTransparentForInput)
- currentWindowUnderMouse = currentWindowUnderMouse->parent();
- // QTBUG-44332: When Qt is running at low integrity level and
- // a Qt Window is parented on a Window of a higher integrity process
- // using QWindow::fromWinId() (for example, Qt running in a browser plugin)
- // ChildWindowFromPointEx() may not find the Qt window (failing with ERROR_ACCESS_DENIED)
- if (!currentWindowUnderMouse) {
- const QRect clientRect(QPoint(0, 0), window->size());
- if (clientRect.contains(winEventPosition))
- currentWindowUnderMouse = window;
- }
-
- compressMouseMove(&msg);
- // Qt expects the platform plugin to capture the mouse on
- // any button press until release.
- if (!platformWindow->hasMouseCapture()
- && (mouseEvent.type == QEvent::MouseButtonPress || mouseEvent.type == QEvent::MouseButtonDblClick)) {
- platformWindow->setMouseGrabEnabled(true);
- platformWindow->setFlag(QWindowsWindow::AutoMouseCapture);
- qCDebug(lcQpaEvents) << "Automatic mouse capture " << window;
- // Implement "Click to focus" for native child windows (unless it is a native widget window).
- if (!window->isTopLevel() && !window->inherits("QWidgetWindow") && QGuiApplication::focusWindow() != window)
- window->requestActivate();
- } else if (platformWindow->hasMouseCapture()
- && platformWindow->testFlag(QWindowsWindow::AutoMouseCapture)
- && mouseEvent.type == QEvent::MouseButtonRelease
- && !buttons) {
- platformWindow->setMouseGrabEnabled(false);
- qCDebug(lcQpaEvents) << "Releasing automatic mouse capture " << window;
- }
-
- const bool hasCapture = platformWindow->hasMouseCapture();
- const bool currentNotCapturing = hasCapture && currentWindowUnderMouse != window;
- // Enter new window: track to generate leave event.
- // If there is an active capture, only track if the current window is capturing,
- // so we don't get extra leave when cursor leaves the application.
- if (window != m_trackedWindow && !currentNotCapturing) {
- TRACKMOUSEEVENT tme;
- tme.cbSize = sizeof(TRACKMOUSEEVENT);
- tme.dwFlags = TME_LEAVE;
- tme.hwndTrack = hwnd;
- tme.dwHoverTime = HOVER_DEFAULT; //
- if (!TrackMouseEvent(&tme))
- qWarning("TrackMouseEvent failed.");
- m_trackedWindow = window;
- }
-
- // No enter or leave events are sent as long as there is an autocapturing window.
- if (!hasCapture || !platformWindow->testFlag(QWindowsWindow::AutoMouseCapture)) {
- // Leave is needed if:
- // 1) There is no capture and we move from a window to another window.
- // Note: Leaving the application entirely is handled in WM_MOUSELEAVE case.
- // 2) There is capture and we move out of the capturing window.
- // 3) There is a new capture and we were over another window.
- if ((m_windowUnderMouse && m_windowUnderMouse != currentWindowUnderMouse
- && (!hasCapture || window == m_windowUnderMouse))
- || (hasCapture && m_previousCaptureWindow != window && m_windowUnderMouse
- && m_windowUnderMouse != window)) {
- qCDebug(lcQpaEvents) << "Synthetic leave for " << m_windowUnderMouse;
- QWindowSystemInterface::handleLeaveEvent(m_windowUnderMouse);
- if (currentNotCapturing) {
- // Clear tracking if capturing and current window is not the capturing window
- // to avoid leave when mouse actually leaves the application.
- m_trackedWindow = nullptr;
- // We are not officially in any window, but we need to set some cursor to clear
- // whatever cursor the left window had, so apply the cursor of the capture window.
- platformWindow->applyCursor();
- }
- }
- // Enter is needed if:
- // 1) There is no capture and we move to a new window.
- // 2) There is capture and we move into the capturing window.
- // 3) The capture just ended and we are over non-capturing window.
- if ((currentWindowUnderMouse && m_windowUnderMouse != currentWindowUnderMouse
- && (!hasCapture || currentWindowUnderMouse == window))
- || (m_previousCaptureWindow && window != m_previousCaptureWindow && currentWindowUnderMouse
- && currentWindowUnderMouse != m_previousCaptureWindow)) {
- QPoint localPosition;
- qCDebug(lcQpaEvents) << "Entering " << currentWindowUnderMouse;
- if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(currentWindowUnderMouse)) {
- localPosition = wumPlatformWindow->mapFromGlobal(globalPosition);
- wumPlatformWindow->applyCursor();
- }
- QWindowSystemInterface::handleEnterEvent(currentWindowUnderMouse, localPosition, globalPosition);
- }
- // We need to track m_windowUnderMouse separately from m_trackedWindow, as
- // Windows mouse tracking will not trigger WM_MOUSELEAVE for leaving window when
- // mouse capture is set.
- m_windowUnderMouse = currentWindowUnderMouse;
- }
-
- if (!discardEvent && mouseEvent.type != QEvent::None) {
- QWindowSystemInterface::handleMouseEvent(window, msg.time, device, clientPosition, globalPosition, buttons,
- mouseEvent.button, mouseEvent.type,
- keyModifiers, source);
- }
- m_previousCaptureWindow = hasCapture ? window : nullptr;
- // QTBUG-48117, force synchronous handling for the extra buttons so that WM_APPCOMMAND
- // is sent for unhandled WM_XBUTTONDOWN.
- return (msg.message != WM_XBUTTONUP && msg.message != WM_XBUTTONDOWN && msg.message != WM_XBUTTONDBLCLK)
- || QWindowSystemInterface::flushWindowSystemEvents();
-}
-
-static bool isValidWheelReceiver(QWindow *candidate)
-{
- if (candidate) {
- const QWindow *toplevel = QWindowsWindow::topLevelOf(candidate);
- if (toplevel->handle() && toplevel->handle()->isForeignWindow())
- return true;
- if (const QWindowsWindow *ww = QWindowsWindow::windowsWindowOf(toplevel))
- return !ww->testFlag(QWindowsWindow::BlockedByModal);
- }
-
- return false;
-}
-
-static void redirectWheelEvent(QWindow *window, unsigned long timestamp, 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.
-
- 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) {
- const QPoint point = (orientation == Qt::Vertical) ? QPoint(0, delta) : QPoint(delta, 0);
- QWindowSystemInterface::handleWheelEvent(receiver,
- timestamp,
- QWindowsGeometryHint::mapFromGlobal(receiver, globalPos),
- globalPos, QPoint(), point, mods);
- }
-}
-
-bool QWindowsMouseHandler::translateMouseWheelEvent(QWindow *window, HWND,
- MSG msg, LRESULT *)
-{
- const Qt::KeyboardModifiers mods = keyStateToModifiers(int(msg.wParam));
-
- int delta;
- if (msg.message == WM_MOUSEWHEEL || msg.message == WM_MOUSEHWHEEL)
- delta = GET_WHEEL_DELTA_WPARAM(msg.wParam);
- else
- delta = int(msg.wParam);
-
- Qt::Orientation orientation = (msg.message == WM_MOUSEHWHEEL
- || (mods & Qt::AltModifier)) ?
- Qt::Horizontal : Qt::Vertical;
-
- // according to the MSDN documentation on WM_MOUSEHWHEEL:
- // a positive value indicates that the wheel was rotated to the right;
- // a negative value indicates that the wheel was rotated to the left.
- // Qt defines this value as the exact opposite, so we have to flip the value!
- if (msg.message == WM_MOUSEHWHEEL)
- delta = -delta;
-
- const QPoint globalPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
- redirectWheelEvent(window, msg.time, globalPos, delta, orientation, mods);
-
- return true;
-}
-
-bool QWindowsMouseHandler::translateScrollEvent(QWindow *window, HWND,
- MSG msg, LRESULT *)
-{
- // This is a workaround against some touchpads that send WM_HSCROLL instead of WM_MOUSEHWHEEL.
- // We could also handle vertical scroll here but there's no reason to, there's no bug for vertical
- // (broken vertical scroll would have been noticed long time ago), so lets keep the change small
- // and minimize the chance for regressions.
-
- int delta = 0;
- switch (LOWORD(msg.wParam)) {
- case SB_LINELEFT:
- delta = 120;
- break;
- case SB_LINERIGHT:
- delta = -120;
- break;
- case SB_PAGELEFT:
- delta = 240;
- break;
- case SB_PAGERIGHT:
- delta = -240;
- break;
- default:
- return false;
- }
-
- redirectWheelEvent(window, msg.time, QCursor::pos(), delta, Qt::Horizontal, Qt::NoModifier);
-
- return true;
-}
-
-// from bool QApplicationPrivate::translateTouchEvent()
-bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND,
- QtWindows::WindowsEventType,
- MSG msg, LRESULT *)
-{
- using QTouchPoint = QWindowSystemInterface::TouchPoint;
- using QTouchPointList = QList<QWindowSystemInterface::TouchPoint>;
-
- if (!QWindowsContext::instance()->initTouch()) {
- qWarning("Unable to initialize touch handling.");
- return true;
- }
-
- const QScreen *screen = window->screen();
- if (!screen)
- screen = QGuiApplication::primaryScreen();
- if (!screen)
- return true;
- const QRect screenGeometry = screen->geometry();
-
- const int winTouchPointCount = int(msg.wParam);
- const auto winTouchInputs = std::make_unique<TOUCHINPUT[]>(winTouchPointCount);
-
- QTouchPointList touchPoints;
- touchPoints.reserve(winTouchPointCount);
- QEventPoint::States allStates;
-
- GetTouchInputInfo(reinterpret_cast<HTOUCHINPUT>(msg.lParam),
- UINT(msg.wParam), winTouchInputs.get(), sizeof(TOUCHINPUT));
- for (int i = 0; i < winTouchPointCount; ++i) {
- const TOUCHINPUT &winTouchInput = winTouchInputs[i];
- int id = m_touchInputIDToTouchPointID.value(winTouchInput.dwID, -1);
- if (id == -1) {
- id = m_touchInputIDToTouchPointID.size();
- m_touchInputIDToTouchPointID.insert(winTouchInput.dwID, id);
- }
- QTouchPoint touchPoint;
- touchPoint.pressure = 1.0;
- touchPoint.id = id;
- if (m_lastTouchPositions.contains(id))
- touchPoint.normalPosition = m_lastTouchPositions.value(id);
-
- const QPointF screenPos = QPointF(winTouchInput.x, winTouchInput.y) / qreal(100.);
- if (winTouchInput.dwMask & TOUCHINPUTMASKF_CONTACTAREA)
- touchPoint.area.setSize(QSizeF(winTouchInput.cxContact, winTouchInput.cyContact) / qreal(100.));
- touchPoint.area.moveCenter(screenPos);
- QPointF normalPosition = QPointF(screenPos.x() / screenGeometry.width(),
- screenPos.y() / screenGeometry.height());
- const bool stationaryTouchPoint = (normalPosition == touchPoint.normalPosition);
- touchPoint.normalPosition = normalPosition;
-
- if (winTouchInput.dwFlags & TOUCHEVENTF_DOWN) {
- touchPoint.state = QEventPoint::State::Pressed;
- m_lastTouchPositions.insert(id, touchPoint.normalPosition);
- } else if (winTouchInput.dwFlags & TOUCHEVENTF_UP) {
- touchPoint.state = QEventPoint::State::Released;
- m_lastTouchPositions.remove(id);
- } else {
- touchPoint.state = (stationaryTouchPoint
- ? QEventPoint::State::Stationary
- : QEventPoint::State::Updated);
- m_lastTouchPositions.insert(id, touchPoint.normalPosition);
- }
-
- allStates |= touchPoint.state;
-
- touchPoints.append(touchPoint);
- }
-
- CloseTouchInputHandle(reinterpret_cast<HTOUCHINPUT>(msg.lParam));
-
- // all touch points released, forget the ids we've seen, they may not be reused
- if (allStates == QEventPoint::State::Released)
- m_touchInputIDToTouchPointID.clear();
-
- const auto *keyMapper = QWindowsContext::instance()->keyMapper();
- QWindowSystemInterface::handleTouchEvent(window,
- msg.time,
- m_touchDevice.data(),
- touchPoints,
- keyMapper->queryKeyboardModifiers());
- return true;
-}
-
-bool QWindowsMouseHandler::translateGestureEvent(QWindow *window, HWND hwnd,
- QtWindows::WindowsEventType,
- MSG msg, LRESULT *)
-{
- Q_UNUSED(window);
- Q_UNUSED(hwnd);
- Q_UNUSED(msg);
- return false;
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.h b/src/plugins/platforms/windows/qwindowsmousehandler.h
deleted file mode 100644
index 7fde349f58..0000000000
--- a/src/plugins/platforms/windows/qwindowsmousehandler.h
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-
-#ifndef QWINDOWSMOUSEHANDLER_H
-#define QWINDOWSMOUSEHANDLER_H
-
-#include "qtwindowsglobal.h"
-#include <QtCore/qt_windows.h>
-
-#include <QtCore/qpointer.h>
-#include <QtCore/qhash.h>
-#include <QtCore/qsharedpointer.h>
-#include <QtGui/qevent.h>
-
-QT_BEGIN_NAMESPACE
-
-class QWindow;
-class QPointingDevice;
-
-class QWindowsMouseHandler
-{
- Q_DISABLE_COPY_MOVE(QWindowsMouseHandler)
-public:
- using QPointingDevicePtr = QSharedPointer<QPointingDevice>;
-
- QWindowsMouseHandler();
-
- const QPointingDevicePtr &touchDevice() const { return m_touchDevice; }
- void setTouchDevice(const QPointingDevicePtr &d) { m_touchDevice = d; }
-
- bool translateMouseEvent(QWindow *widget, HWND hwnd,
- QtWindows::WindowsEventType t, MSG msg,
- LRESULT *result);
- bool translateTouchEvent(QWindow *widget, HWND hwnd,
- QtWindows::WindowsEventType t, MSG msg,
- LRESULT *result);
- bool translateGestureEvent(QWindow *window, HWND hwnd,
- QtWindows::WindowsEventType,
- MSG msg, LRESULT *);
- bool translateScrollEvent(QWindow *window, HWND hwnd,
- MSG msg, LRESULT *result);
-
- static inline Qt::MouseButtons keyStateToMouseButtons(WPARAM);
- static inline Qt::KeyboardModifiers keyStateToModifiers(int);
- static inline int mouseButtonsToKeyState(Qt::MouseButtons);
-
- static Qt::MouseButtons queryMouseButtons();
- QWindow *windowUnderMouse() const { return m_windowUnderMouse.data(); }
- void clearWindowUnderMouse() { m_windowUnderMouse = nullptr; }
- void clearEvents();
-
- static const QPointingDevice *primaryMouse();
-
-private:
- inline bool translateMouseWheelEvent(QWindow *window, HWND hwnd,
- MSG msg, LRESULT *result);
-
- QPointer<QWindow> m_windowUnderMouse;
- QPointer<QWindow> m_trackedWindow;
- QHash<DWORD, int> m_touchInputIDToTouchPointID;
- QHash<int, QPointF> m_lastTouchPositions;
- QPointingDevicePtr m_touchDevice;
- bool m_leftButtonDown = false;
- QWindow *m_previousCaptureWindow = nullptr;
- QEvent::Type m_lastEventType = QEvent::None;
- Qt::MouseButton m_lastEventButton = Qt::NoButton;
-};
-
-Qt::MouseButtons QWindowsMouseHandler::keyStateToMouseButtons(WPARAM wParam)
-{
- Qt::MouseButtons mb(Qt::NoButton);
- if (wParam & MK_LBUTTON)
- mb |= Qt::LeftButton;
- if (wParam & MK_MBUTTON)
- mb |= Qt::MiddleButton;
- if (wParam & MK_RBUTTON)
- mb |= Qt::RightButton;
- if (wParam & MK_XBUTTON1)
- mb |= Qt::XButton1;
- if (wParam & MK_XBUTTON2)
- mb |= Qt::XButton2;
- return mb;
-}
-
-Qt::KeyboardModifiers QWindowsMouseHandler::keyStateToModifiers(int wParam)
-{
- Qt::KeyboardModifiers mods(Qt::NoModifier);
- if (wParam & MK_CONTROL)
- mods |= Qt::ControlModifier;
- if (wParam & MK_SHIFT)
- mods |= Qt::ShiftModifier;
- if (GetKeyState(VK_MENU) < 0)
- mods |= Qt::AltModifier;
- return mods;
-}
-
-int QWindowsMouseHandler::mouseButtonsToKeyState(Qt::MouseButtons mb)
-{
- int result = 0;
- if (mb & Qt::LeftButton)
- result |= MK_LBUTTON;
- if (mb & Qt::MiddleButton)
- result |= MK_MBUTTON;
- if (mb & Qt::RightButton)
- result |= MK_RBUTTON;
- if (mb & Qt::XButton1)
- result |= MK_XBUTTON1;
- if (mb & Qt::XButton2)
- result |= MK_XBUTTON2;
- return result;
-}
-
-QT_END_NAMESPACE
-
-#endif // QWINDOWSMOUSEHANDLER_H
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp
index 6a790bcc1b..38d1cdd738 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.cpp
+++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp
@@ -65,7 +65,9 @@ private:
QDirect3D9Handle::QDirect3D9Handle()
{
+#ifndef QT_NO_OPENGL
m_direct3D9 = Direct3DCreate9(D3D_SDK_VERSION);
+#endif
}
QDirect3D9Handle::~QDirect3D9Handle()
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
index 71c7217671..7995716444 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
@@ -4,7 +4,6 @@
#include <QtCore/qt_windows.h>
#include "qwindowspointerhandler.h"
-#include "qwindowsmousehandler.h"
#if QT_CONFIG(tabletevent)
# include "qwindowstabletsupport.h"
#endif
@@ -39,6 +38,14 @@ enum {
qint64 QWindowsPointerHandler::m_nextInputDeviceId = 1;
+const QPointingDevice *primaryMouse()
+{
+ static QPointer<const QPointingDevice> result;
+ if (!result)
+ result = QPointingDevice::primaryPointingDevice();
+ return result;
+}
+
QWindowsPointerHandler::~QWindowsPointerHandler()
{
}
@@ -215,7 +222,7 @@ static Qt::MouseButtons mouseButtonsFromKeyState(WPARAM keyState)
return result;
}
-static Qt::MouseButtons queryMouseButtons()
+Qt::MouseButtons QWindowsPointerHandler::queryMouseButtons()
{
Qt::MouseButtons result = Qt::NoButton;
const bool mouseSwapped = GetSystemMetrics(SM_SWAPBUTTON);
@@ -785,7 +792,7 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
}
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized;
- const QPointingDevice *device = QWindowsMouseHandler::primaryMouse();
+ const QPointingDevice *device = primaryMouse();
// Following the logic of the old mouse handler, only events synthesized
// for touch screen are marked as such. On some systems, using the bit 7 of
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.h b/src/plugins/platforms/windows/qwindowspointerhandler.h
index b64a8c146a..1827dd9df0 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.h
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.h
@@ -38,12 +38,15 @@ public:
void clearWindowUnderMouse() { m_windowUnderPointer = nullptr; }
void clearEvents();
+ static Qt::MouseButtons queryMouseButtons();
+
private:
bool translateTouchEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vTouchInfo, unsigned int count);
bool translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vPenInfo);
bool translateMouseWheelEvent(QWindow *window, QWindow *currentWindowUnderPointer, MSG msg, QPoint globalPos, Qt::KeyboardModifiers keyModifiers);
void handleCaptureRelease(QWindow *window, QWindow *currentWindowUnderPointer, HWND hwnd, QEvent::Type eventType, Qt::MouseButtons mouseButtons);
void handleEnterLeave(QWindow *window, QWindow *currentWindowUnderPointer, QPoint globalPos);
+
#if QT_CONFIG(tabletevent)
QPointingDevicePtr findTabletDevice(QPointingDevice::PointerType pointerType) const;
#endif
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index a50f9fd4b0..1f22fb4f60 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -698,11 +698,15 @@ void QWindowsScreenManager::initialize()
handleScreenChanges();
}
-QWindowsScreenManager::~QWindowsScreenManager()
+void QWindowsScreenManager::destroyWindow()
{
+ qCDebug(lcQpaScreen) << "Destroying display change observer" << m_displayChangeObserver;
DestroyWindow(m_displayChangeObserver);
+ m_displayChangeObserver = nullptr;
}
+QWindowsScreenManager::~QWindowsScreenManager() = default;
+
bool QWindowsScreenManager::isSingleScreen()
{
return QWindowsContext::instance()->screenManager().screens().size() < 2;
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index 0467ab2a0c..ea6a29efe3 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -105,6 +105,7 @@ public:
QWindowsScreenManager();
void initialize();
+ void destroyWindow();
~QWindowsScreenManager();
void clearScreens();
diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h
index 96ae6197b4..a89fb1e5bd 100644
--- a/src/plugins/platforms/windows/qwindowstheme.h
+++ b/src/plugins/platforms/windows/qwindowstheme.h
@@ -33,7 +33,6 @@ public:
Qt::ColorScheme colorScheme() const override;
void requestColorScheme(Qt::ColorScheme scheme) override;
- Qt::ColorScheme requestedColorScheme() const { return s_colorSchemeOverride; }
static void handleSettingsChanged();
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index ee0b88ba54..4b7ce0a979 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -855,12 +855,6 @@ static inline bool shouldApplyDarkFrame(const QWindow *w)
if (!QWindowsIntegration::instance()->darkModeHandling().testFlag(QWindowsApplication::DarkModeWindowFrames))
return false;
- // the application explicitly overrides the color scheme
- if (const auto requestedColorScheme = QWindowsTheme::instance()->requestedColorScheme();
- requestedColorScheme != Qt::ColorScheme::Unknown) {
- return requestedColorScheme == Qt::ColorScheme::Dark;
- }
-
// if the application supports a dark border, and the palette is dark (window background color
// is darker than the text), then turn dark-border support on, otherwise use a light border.
auto *dWindow = QWindowPrivate::get(const_cast<QWindow*>(w));
@@ -2488,6 +2482,11 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
GetWindowPlacement(m_data.hwnd, &windowPlacement);
const RECT geometry = RECTfromQRect(m_data.restoreGeometry);
windowPlacement.rcNormalPosition = geometry;
+ // Even if the window is hidden, windowPlacement's showCmd is not SW_HIDE, so change it
+ // manually to avoid unhiding a hidden window with the subsequent call to
+ // SetWindowPlacement().
+ if (!isVisible())
+ windowPlacement.showCmd = SW_HIDE;
SetWindowPlacement(m_data.hwnd, &windowPlacement);
}
// QTBUG-17548: We send expose events when receiving WM_Paint, but for
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 024711e7f3..b3cddc11d8 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -347,6 +347,8 @@ public:
int savedDpi() const { return m_savedDpi; }
qreal dpiRelativeScale(const UINT dpi) const;
+ bool isFrameless() const { return m_data.flags.testFlag(Qt::FramelessWindowHint); }
+
private:
inline void show_sys() const;
inline QWindowsWindowData setWindowFlags_sys(Qt::WindowFlags wt, unsigned flags = 0) const;
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
index 1abb412ccd..5892493281 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
@@ -127,6 +127,9 @@ void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event
return;
switch (event->type()) {
+ case QAccessible::Announcement:
+ QWindowsUiaMainProvider::raiseNotification(static_cast<QAccessibleAnnouncementEvent *>(event));
+ break;
case QAccessible::Focus:
QWindowsUiaMainProvider::notifyFocusChange(event);
break;
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
index 95ddbcced6..0f2e2d8a5c 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
@@ -23,6 +23,7 @@
#include "qwindowsuiaprovidercache.h"
#include <QtCore/qloggingcategory.h>
+#include <QtGui/private/qaccessiblebridgeutils_p.h>
#include <QtGui/qaccessible.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qwindow.h>
@@ -204,6 +205,24 @@ void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event)
}
}
+void QWindowsUiaMainProvider::raiseNotification(QAccessibleAnnouncementEvent *event)
+{
+ if (QAccessibleInterface *accessible = event->accessibleInterface()) {
+ if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
+ BSTR message = bStrFromQString(event->message());
+ QAccessible::AnnouncementPoliteness prio = event->politeness();
+ NotificationProcessing processing = (prio == QAccessible::AnnouncementPoliteness::Assertive)
+ ? NotificationProcessing_ImportantAll
+ : NotificationProcessing_All;
+ BSTR activityId = bStrFromQString(QString::fromLatin1(""));
+ UiaRaiseNotificationEvent(provider, NotificationKind_Other, processing, message, activityId);
+
+ ::SysFreeString(message);
+ ::SysFreeString(activityId);
+ }
+ }
+}
+
HRESULT STDMETHODCALLTYPE QWindowsUiaMainProvider::QueryInterface(REFIID iid, LPVOID *iface)
{
HRESULT result = QComObject::QueryInterface(iid, iface);
@@ -370,6 +389,93 @@ void QWindowsUiaMainProvider::fillVariantArrayForRelation(QAccessibleInterface*
pRetVal->parray = elements;
}
+void QWindowsUiaMainProvider::setAriaProperties(QAccessibleInterface *accessible, VARIANT *pRetVal)
+{
+ Q_ASSERT(accessible);
+
+ QAccessibleAttributesInterface *attributesIface = accessible->attributesInterface();
+ if (!attributesIface)
+ return;
+
+ QString ariaString;
+ const QList<QAccessible::Attribute> attrKeys = attributesIface->attributeKeys();
+ for (qsizetype i = 0; i < attrKeys.size(); ++i) {
+ if (i != 0)
+ ariaString += QStringLiteral(";");
+ const QAccessible::Attribute key = attrKeys.at(i);
+ const QVariant value = attributesIface->attributeValue(key);
+ // see "Core Accessibility API Mappings" spec: https://www.w3.org/TR/core-aam-1.2/
+ switch (key) {
+ case QAccessible::Attribute::Custom:
+ {
+ // forward custom attributes as-is
+ Q_ASSERT((value.canConvert<QHash<QString, QString>>()));
+ const QHash<QString, QString> attrMap = value.value<QHash<QString, QString>>();
+ for (auto [name, val] : attrMap.asKeyValueRange()) {
+ if (name != *attrMap.keyBegin())
+ ariaString += QStringLiteral(";");
+ ariaString += name + QStringLiteral("=") + val;
+ }
+ break;
+ }
+ case QAccessible::Attribute::Level:
+ Q_ASSERT(value.canConvert<int>());
+ ariaString += QStringLiteral("level=") + QString::number(value.toInt());
+ break;
+ default:
+ break;
+ }
+ }
+
+ setVariantString(ariaString, pRetVal);
+}
+
+void QWindowsUiaMainProvider::setStyle(QAccessibleInterface *accessible, VARIANT *pRetVal)
+{
+ Q_ASSERT(accessible);
+
+ QAccessibleAttributesInterface *attributesIface = accessible->attributesInterface();
+ if (!attributesIface)
+ return;
+
+ // currently, only heading styles are implemented here
+ if (accessible->role() != QAccessible::Role::Heading)
+ return;
+
+ const QVariant levelVariant = attributesIface->attributeValue(QAccessible::Attribute::Level);
+ if (!levelVariant.isValid())
+ return;
+
+ Q_ASSERT(levelVariant.canConvert<int>());
+ // UIA only has styles for heading levels 1-9
+ const int level = levelVariant.toInt();
+ if (level < 1 || level > 9)
+ return;
+
+ const int styleId = styleIdForHeadingLevel(level);
+ setVariantI4(styleId, pRetVal);
+}
+
+int QWindowsUiaMainProvider::styleIdForHeadingLevel(int headingLevel)
+{
+ // only heading levels 1-9 have a corresponding UIA style ID
+ Q_ASSERT(headingLevel > 0 && headingLevel <= 9);
+
+ static constexpr int styles[] = {
+ StyleId_Heading1,
+ StyleId_Heading2,
+ StyleId_Heading3,
+ StyleId_Heading4,
+ StyleId_Heading5,
+ StyleId_Heading6,
+ StyleId_Heading7,
+ StyleId_Heading8,
+ StyleId_Heading9,
+ };
+
+ return styles[headingLevel - 1];
+}
+
HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pRetVal)
{
qCDebug(lcQpaUiAutomation) << __FUNCTION__ << idProp;
@@ -393,9 +499,12 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR
// Accelerator key.
setVariantString(accessible->text(QAccessible::Accelerator), pRetVal);
break;
+ case UIA_AriaPropertiesPropertyId:
+ setAriaProperties(accessible, pRetVal);
+ break;
case UIA_AutomationIdPropertyId:
// Automation ID, which can be used by tools to select a specific control in the UI.
- setVariantString(automationIdForAccessible(accessible), pRetVal);
+ setVariantString(QAccessibleBridgeUtils::accessibleId(accessible), pRetVal);
break;
case UIA_ClassNamePropertyId:
// Class name.
@@ -493,31 +602,15 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR
setVariantString(name, pRetVal);
break;
}
+ case UIA_StyleIdAttributeId:
+ setStyle(accessible, pRetVal);
+ break;
default:
break;
}
return S_OK;
}
-// Generates an ID based on the name of the controls and their parents.
-QString QWindowsUiaMainProvider::automationIdForAccessible(const QAccessibleInterface *accessible)
-{
- QString result;
- if (accessible) {
- QObject *obj = accessible->object();
- while (obj) {
- QString name = obj->objectName();
- if (name.isEmpty())
- return result;
- if (!result.isEmpty())
- result.prepend(u'.');
- result.prepend(name);
- obj = obj->parent();
- }
- }
- return result;
-}
-
HRESULT QWindowsUiaMainProvider::get_HostRawElementProvider(IRawElementProviderSimple **pRetVal)
{
qCDebug(lcQpaUiAutomation) << __FUNCTION__ << this;
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
index 99db0ed318..8ea343e425 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
@@ -34,6 +34,7 @@ public:
static void notifyNameChange(QAccessibleEvent *event);
static void notifySelectionChange(QAccessibleEvent *event);
static void notifyTextChange(QAccessibleEvent *event);
+ static void raiseNotification(QAccessibleAnnouncementEvent *event);
// IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface) override;
@@ -58,8 +59,11 @@ public:
HRESULT STDMETHODCALLTYPE GetFocus(IRawElementProviderFragment **pRetVal) override;
private:
- QString automationIdForAccessible(const QAccessibleInterface *accessible);
static void fillVariantArrayForRelation(QAccessibleInterface *accessible, QAccessible::Relation relation, VARIANT *pRetVal);
+ static void setAriaProperties(QAccessibleInterface *accessible, VARIANT *pRetVal);
+ static void setStyle(QAccessibleInterface *accessible, VARIANT *pRetVal);
+ /** Returns the UIA style ID for a heading level from 1 to 9. */
+ static int styleIdForHeadingLevel(int headingLevel);
static QMutex m_mutex;
};
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.cpp
index 1593a07202..6954a881d0 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.cpp
@@ -69,6 +69,14 @@ HRESULT WINAPI UiaRaiseAutomationEvent(IRawElementProviderSimple *pProvider, EVE
return func.invoke(pProvider, id);
}
+HRESULT WINAPI UiaRaiseNotificationEvent(
+ IRawElementProviderSimple *pProvider, NotificationKind notificationKind,
+ NotificationProcessing notificationProcessing, BSTR displayString, BSTR activityId)
+{
+ static auto func = winapi_func("uiautomationcore", FN(UiaRaiseNotificationEvent));
+ return func.invoke(pProvider, notificationKind, notificationProcessing, displayString, activityId);
+}
+
#endif // defined(__MINGW32__) || defined(__MINGW64__)
#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.h
index a192b9b0fb..4eb37bafa0 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.h
@@ -14,8 +14,19 @@
#define UIA_SelectionPattern2Id 10034
#define UIA_IsReadOnlyAttributeId 40015
#define UIA_StrikethroughStyleAttributeId 40026
+#define UIA_StyleIdAttributeId 40034
#define UIA_CaretPositionAttributeId 40038
+#define StyleId_Heading1 70001
+#define StyleId_Heading2 70002
+#define StyleId_Heading3 70003
+#define StyleId_Heading4 70004
+#define StyleId_Heading5 70005
+#define StyleId_Heading6 70006
+#define StyleId_Heading7 70007
+#define StyleId_Heading8 70008
+#define StyleId_Heading9 70009
+
enum CaretPosition {
CaretPosition_Unknown = 0,
CaretPosition_EndOfLine = 1,