summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2019-06-06 15:35:06 +0200
committerAlexandru Croitor <alexandru.croitor@qt.io>2019-06-06 19:00:41 +0200
commit2a302a73613d68475e667f69b8e36ce07853c813 (patch)
tree06de55baaed993b51af517dba8f230fab749882c /src/plugins/platforms/windows
parent5505d25be972948db1621e1511b89b4144aa8bfc (diff)
parentdea7110b29c5c68a5b09454c968324042ed1b607 (diff)
Merge remote-tracking branch 'origin/dev' into wip/qt6
Diffstat (limited to 'src/plugins/platforms/windows')
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsclipboard.h6
-rw-r--r--src/plugins/platforms/windows/qwindowscombase.h2
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp47
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h10
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.h6
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.h12
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp7
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h5
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.h6
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp55
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.h12
-rw-r--r--src/plugins/platforms/windows/qwindowsopenglcontext.h8
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.cpp50
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.h7
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp12
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.h2
-rw-r--r--src/plugins/platforms/windows/qwindowssessionmanager.h2
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.cpp72
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.h4
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.h4
-rw-r--r--src/plugins/platforms/windows/qwindowsthreadpoolrunner.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsvulkaninstance.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsvulkaninstance.h2
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp347
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h80
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp27
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h2
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiawindowprovider.cpp168
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiawindowprovider.h73
-rw-r--r--src/plugins/platforms/windows/uiautomation/uiautomation.pri2
52 files changed, 863 insertions, 221 deletions
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.h b/src/plugins/platforms/windows/qwindowsbackingstore.h
index 088ab3b257..b96c8f0e61 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.h
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.h
@@ -52,7 +52,7 @@ class QWindowsNativeImage;
class QWindowsBackingStore : public QPlatformBackingStore
{
- Q_DISABLE_COPY(QWindowsBackingStore)
+ Q_DISABLE_COPY_MOVE(QWindowsBackingStore)
public:
QWindowsBackingStore(QWindow *window);
~QWindowsBackingStore() override;
diff --git a/src/plugins/platforms/windows/qwindowsclipboard.h b/src/plugins/platforms/windows/qwindowsclipboard.h
index 469d638b89..24a6bc908d 100644
--- a/src/plugins/platforms/windows/qwindowsclipboard.h
+++ b/src/plugins/platforms/windows/qwindowsclipboard.h
@@ -58,7 +58,7 @@ protected:
class QWindowsClipboard : public QPlatformClipboard
{
- Q_DISABLE_COPY(QWindowsClipboard)
+ Q_DISABLE_COPY_MOVE(QWindowsClipboard)
public:
QWindowsClipboard();
~QWindowsClipboard() override;
@@ -87,8 +87,8 @@ private:
QWindowsClipboardRetrievalMimeData m_retrievalData;
QWindowsOleDataObject *m_data = nullptr;
- HWND m_clipboardViewer = 0;
- HWND m_nextClipboardViewer = 0;
+ HWND m_clipboardViewer = nullptr;
+ HWND m_nextClipboardViewer = nullptr;
bool m_formatListenerRegistered = false;
};
diff --git a/src/plugins/platforms/windows/qwindowscombase.h b/src/plugins/platforms/windows/qwindowscombase.h
index 6b25d665dc..45cba9c68b 100644
--- a/src/plugins/platforms/windows/qwindowscombase.h
+++ b/src/plugins/platforms/windows/qwindowscombase.h
@@ -80,7 +80,7 @@ bool qWindowsComQueryUnknownInterfaceMulti(Derived *d, REFIID id, LPVOID *iface)
// Helper base class to provide IUnknown methods for COM classes (single inheritance)
template <class ComInterface> class QWindowsComBase : public ComInterface
{
- Q_DISABLE_COPY(QWindowsComBase)
+ Q_DISABLE_COPY_MOVE(QWindowsComBase)
public:
explicit QWindowsComBase(ULONG initialRefCount = 1) : m_ref(initialRefCount) {}
virtual ~QWindowsComBase() = default;
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 9ab9c2708b..9be6d4ced7 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -210,6 +210,7 @@ void QWindowsUser32DLL::init()
if (QOperatingSystemVersion::current()
>= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 14393)) {
+ adjustWindowRectExForDpi = (AdjustWindowRectExForDpi)library.resolve("AdjustWindowRectExForDpi");
enableNonClientDpiScaling = (EnableNonClientDpiScaling)library.resolve("EnableNonClientDpiScaling");
getWindowDpiAwarenessContext = (GetWindowDpiAwarenessContext)library.resolve("GetWindowDpiAwarenessContext");
getAwarenessFromDpiAwarenessContext = (GetAwarenessFromDpiAwarenessContext)library.resolve("GetAwarenessFromDpiAwarenessContext");
@@ -712,7 +713,7 @@ static inline bool findPlatformWindowHelper(const POINT &screenPoint, unsigned c
HWND *hwnd, QWindowsWindow **result)
{
POINT point = screenPoint;
- ScreenToClient(*hwnd, &point);
+ screenToClient(*hwnd, &point);
// Returns parent if inside & none matched.
const HWND child = ChildWindowFromPointEx(*hwnd, point, cwexFlags);
if (!child || child == *hwnd)
@@ -977,7 +978,7 @@ static inline bool resizeOnDpiChanged(const QWindow *w)
return result;
}
-static bool shouldHaveNonClientDpiScaling(const QWindow *window)
+bool QWindowsContext::shouldHaveNonClientDpiScaling(const QWindow *window)
{
return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10
&& window->isTopLevel()
@@ -1042,7 +1043,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
// For non-client-area messages, these are screen coordinates (as expected
// in the MSG structure), otherwise they are client coordinates.
if (!(et & QtWindows::NonClientEventFlag)) {
- ClientToScreen(msg.hwnd, &msg.pt);
+ clientToScreen(msg.hwnd, &msg.pt);
}
} else {
GetCursorPos(&msg.pt);
@@ -1133,13 +1134,11 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::QuerySizeHints:
d->m_creationContext->applyToMinMaxInfo(reinterpret_cast<MINMAXINFO *>(lParam));
return true;
- case QtWindows::ResizeEvent: {
- const QSize size(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) - d->m_creationContext->menuHeight);
- d->m_creationContext->obtainedGeometry.setSize(size);
- }
+ case QtWindows::ResizeEvent:
+ d->m_creationContext->obtainedSize = QSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
return true;
case QtWindows::MoveEvent:
- d->m_creationContext->obtainedGeometry.moveTo(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ d->m_creationContext->obtainedPos = QPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
return true;
case QtWindows::NonClientCreate:
if (shouldHaveNonClientDpiScaling(d->m_creationContext->window))
@@ -1321,15 +1320,24 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
#endif
} break;
case QtWindows::DpiChangedEvent: {
- if (!resizeOnDpiChanged(platformWindow->window()))
- return false;
- platformWindow->setFlag(QWindowsWindow::WithinDpiChanged);
- const RECT *prcNewWindow = reinterpret_cast<RECT *>(lParam);
- SetWindowPos(hwnd, nullptr, prcNewWindow->left, prcNewWindow->top,
- prcNewWindow->right - prcNewWindow->left,
- prcNewWindow->bottom - prcNewWindow->top, SWP_NOZORDER | SWP_NOACTIVATE);
- platformWindow->clearFlag(QWindowsWindow::WithinDpiChanged);
- return true;
+ // Try to apply the suggested size first and then notify ScreenChanged
+ // so that the resize event sent from QGuiApplication incorporates it
+ // WM_DPICHANGED is sent with a size that avoids resize loops (by
+ // snapping back to the previous screen, see QTBUG-65580).
+ const bool doResize = resizeOnDpiChanged(platformWindow->window());
+ if (doResize) {
+ platformWindow->setFlag(QWindowsWindow::WithinDpiChanged);
+ platformWindow->updateFullFrameMargins();
+ const auto prcNewWindow = reinterpret_cast<RECT *>(lParam);
+ qCDebug(lcQpaWindows) << __FUNCTION__ << "WM_DPICHANGED"
+ << platformWindow->window() << *prcNewWindow;
+ SetWindowPos(hwnd, nullptr, prcNewWindow->left, prcNewWindow->top,
+ prcNewWindow->right - prcNewWindow->left,
+ prcNewWindow->bottom - prcNewWindow->top, SWP_NOZORDER | SWP_NOACTIVATE);
+ platformWindow->clearFlag(QWindowsWindow::WithinDpiChanged);
+ }
+ platformWindow->checkForScreenChanged(QWindowsWindow::FromDpiChange);
+ return doResize;
}
#if QT_CONFIG(sessionmanager)
case QtWindows::QueryEndSessionApplicationEvent: {
@@ -1478,6 +1486,10 @@ void QWindowsContext::handleExitSizeMove(QWindow *window)
keyboardModifiers);
}
}
+ if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer)
+ d->m_pointerHandler.clearEvents();
+ else
+ d->m_mouseHandler.clearEvents();
}
bool QWindowsContext::asyncExpose() const
@@ -1587,6 +1599,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) {
+ qCDebug(lcQpaWindows) << __FUNCTION__ << "WM_NCCALCSIZE for" << hwnd << margins;
platformWindow->setFullFrameMargins(margins);
} else {
const QSharedPointer<QWindowCreationContext> ctx = QWindowsContext::instance()->windowCreationContext();
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index fd6c72668c..d94ae3f73b 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -102,6 +102,7 @@ struct QWindowsUser32DLL
typedef BOOL (WINAPI *RemoveClipboardFormatListener)(HWND);
typedef BOOL (WINAPI *GetDisplayAutoRotationPreferences)(DWORD *);
typedef BOOL (WINAPI *SetDisplayAutoRotationPreferences)(DWORD);
+ typedef BOOL (WINAPI *AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
typedef BOOL (WINAPI *EnableNonClientDpiScaling)(HWND);
typedef int (WINAPI *GetWindowDpiAwarenessContext)(HWND);
typedef int (WINAPI *GetAwarenessFromDpiAwarenessContext)(int);
@@ -131,6 +132,7 @@ struct QWindowsUser32DLL
GetDisplayAutoRotationPreferences getDisplayAutoRotationPreferences = nullptr;
SetDisplayAutoRotationPreferences setDisplayAutoRotationPreferences = nullptr;
+ AdjustWindowRectExForDpi adjustWindowRectExForDpi = nullptr;
EnableNonClientDpiScaling enableNonClientDpiScaling = nullptr;
GetWindowDpiAwarenessContext getWindowDpiAwarenessContext = nullptr;
GetAwarenessFromDpiAwarenessContext getAwarenessFromDpiAwarenessContext = nullptr;
@@ -153,7 +155,7 @@ struct QWindowsShcoreDLL {
class QWindowsContext
{
- Q_DISABLE_COPY(QWindowsContext)
+ Q_DISABLE_COPY_MOVE(QWindowsContext)
public:
enum SystemInfoFlags
@@ -178,11 +180,11 @@ public:
QString registerWindowClass(const QWindow *w);
QString registerWindowClass(QString cname, WNDPROC proc,
- unsigned style = 0, HBRUSH brush = 0,
+ unsigned style = 0, HBRUSH brush = nullptr,
bool icon = false);
HWND createDummyWindow(const QString &classNameIn,
const wchar_t *windowName,
- WNDPROC wndProc = 0, DWORD style = WS_OVERLAPPED);
+ WNDPROC wndProc = nullptr, DWORD style = WS_OVERLAPPED);
HDC displayContext() const;
int screenDepth() const;
@@ -201,6 +203,8 @@ public:
QWindowsWindow *findPlatformWindowAt(HWND parent, const QPoint &screenPoint,
unsigned cwex_flags) const;
+ static bool shouldHaveNonClientDpiScaling(const QWindow *window);
+
QWindow *windowUnderMouse() const;
void clearWindowUnderMouse();
diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h
index 2e57c80def..d5c189b5ca 100644
--- a/src/plugins/platforms/windows/qwindowscursor.h
+++ b/src/plugins/platforms/windows/qwindowscursor.h
@@ -68,7 +68,7 @@ inline uint qHash(const QWindowsPixmapCursorCacheKey &k, uint seed) noexcept
class CursorHandle
{
- Q_DISABLE_COPY(CursorHandle)
+ Q_DISABLE_COPY_MOVE(CursorHandle)
public:
explicit CursorHandle(HCURSOR hcursor = nullptr) : m_hcursor(hcursor) {}
~CursorHandle()
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index e0bd38c951..e55b8fd7b8 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -507,7 +507,7 @@ class QWindowsNativeFileDialogBase;
class QWindowsNativeFileDialogEventHandler : public QWindowsComBase<IFileDialogEvents>
{
- Q_DISABLE_COPY(QWindowsNativeFileDialogEventHandler)
+ Q_DISABLE_COPY_MOVE(QWindowsNativeFileDialogEventHandler)
public:
static IFileDialogEvents *create(QWindowsNativeFileDialogBase *nativeFileDialog);
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.h b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
index 6099ea9ac6..f0a7ef5e90 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.h
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.h
@@ -64,7 +64,7 @@ namespace QWindowsDialogs
template <class BaseClass>
class QWindowsDialogHelperBase : public BaseClass
{
- Q_DISABLE_COPY(QWindowsDialogHelperBase)
+ Q_DISABLE_COPY_MOVE(QWindowsDialogHelperBase)
public:
typedef QSharedPointer<QWindowsNativeDialogBase> QWindowsNativeDialogBasePtr;
~QWindowsDialogHelperBase() { cleanupThread(); }
@@ -75,7 +75,7 @@ public:
QWindow *parent) override;
void hide() override;
- virtual bool supportsNonModalDialog(const QWindow * /* parent */ = 0) const { return true; }
+ virtual bool supportsNonModalDialog(const QWindow * /* parent */ = nullptr) const { return true; }
protected:
QWindowsDialogHelperBase() = default;
@@ -91,7 +91,7 @@ private:
void cleanupThread();
QWindowsNativeDialogBasePtr m_nativeDialog;
- HWND m_ownerWindow = 0;
+ HWND m_ownerWindow = nullptr;
int m_timerId = 0;
QThread *m_thread = nullptr;
};
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h
index 8a1e1ddae8..d96e266159 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.h
+++ b/src/plugins/platforms/windows/qwindowseglcontext.h
@@ -109,7 +109,7 @@ private:
class QWindowsEGLStaticContext : public QWindowsStaticOpenGLContext
{
- Q_DISABLE_COPY(QWindowsEGLStaticContext)
+ Q_DISABLE_COPY_MOVE(QWindowsEGLStaticContext)
public:
static QWindowsEGLStaticContext *create(QWindowsOpenGLTester::Renderers preferredType);
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index d534ce87cd..66dd32d05e 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -916,7 +916,7 @@ void QWindowsOpenGLContextFormat::apply(QSurfaceFormat *format) const
class QOpenGLTemporaryContext
{
- Q_DISABLE_COPY(QOpenGLTemporaryContext)
+ Q_DISABLE_COPY_MOVE(QOpenGLTemporaryContext)
public:
QOpenGLTemporaryContext();
~QOpenGLTemporaryContext();
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h
index 199f8112e3..1abe2eb390 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.h
+++ b/src/plugins/platforms/windows/qwindowsglcontext.h
@@ -75,9 +75,9 @@ struct QOpenGLContextData
QOpenGLContextData(HGLRC r, HWND h, HDC d) : renderingContext(r), hwnd(h), hdc(d) {}
QOpenGLContextData() {}
- HGLRC renderingContext = 0;
- HWND hwnd = 0;
- HDC hdc = 0;
+ HGLRC renderingContext = nullptr;
+ HWND hwnd = nullptr;
+ HDC hdc = nullptr;
};
class QOpenGLStaticContext;
@@ -89,7 +89,7 @@ struct QWindowsOpenGLContextFormat
QSurfaceFormat::OpenGLContextProfile profile = QSurfaceFormat::NoProfile;
int version = 0; //! majorVersion<<8 + minorVersion
- QSurfaceFormat::FormatOptions options = 0;
+ QSurfaceFormat::FormatOptions options = nullptr;
};
#ifndef QT_NO_DEBUG_STREAM
@@ -134,7 +134,7 @@ private:
class QOpenGLStaticContext : public QWindowsStaticOpenGLContext
{
- Q_DISABLE_COPY(QOpenGLStaticContext)
+ Q_DISABLE_COPY_MOVE(QOpenGLStaticContext)
QOpenGLStaticContext();
public:
enum Extensions
@@ -222,7 +222,7 @@ private:
typedef GLenum (APIENTRY *GlGetGraphicsResetStatusArbType)();
inline void releaseDCs();
- bool updateObtainedParams(HDC hdc, int *obtainedSwapInterval = 0);
+ bool updateObtainedParams(HDC hdc, int *obtainedSwapInterval = nullptr);
QOpenGLStaticContext *m_staticContext;
QOpenGLContext *m_context;
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.h b/src/plugins/platforms/windows/qwindowsinputcontext.h
index a47585c29e..857706bcb9 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.h
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.h
@@ -53,12 +53,12 @@ class QWindowsWindow;
class QWindowsInputContext : public QPlatformInputContext
{
- Q_DISABLE_COPY(QWindowsInputContext)
+ Q_DISABLE_COPY_MOVE(QWindowsInputContext)
Q_OBJECT
struct CompositionContext
{
- HWND hwnd = 0;
+ HWND hwnd = nullptr;
QString composition;
int position = 0;
bool isComposing = false;
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index e896f9f0ee..f0754e3e57 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -133,7 +133,7 @@ QT_BEGIN_NAMESPACE
struct QWindowsIntegrationPrivate
{
- Q_DISABLE_COPY(QWindowsIntegrationPrivate)
+ Q_DISABLE_COPY_MOVE(QWindowsIntegrationPrivate)
explicit QWindowsIntegrationPrivate(const QStringList &paramList);
~QWindowsIntegrationPrivate();
@@ -217,6 +217,8 @@ static inline unsigned parseOptions(const QStringList &paramList,
options |= QWindowsIntegration::NoNativeMenus;
} else if (param == QLatin1String("nowmpointer")) {
options |= QWindowsIntegration::DontUseWMPointer;
+ } else if (param == QLatin1String("reverse")) {
+ options |= QWindowsIntegration::RtlEnabled;
} else {
qWarning() << "Unknown option" << param;
}
@@ -353,6 +355,9 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
QWindowsWindow *result = createPlatformWindowHelper(window, obtained);
Q_ASSERT(result);
+ if (window->isTopLevel() && !QWindowsContext::shouldHaveNonClientDpiScaling(window))
+ result->setFlag(QWindowsWindow::DisableNonClientScaling);
+
if (QWindowsMenuBar *menuBarToBeInstalled = QWindowsMenuBar::menuBarOf(window))
menuBarToBeInstalled->install(result);
diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h
index e28b2c2fb3..b49d21022b 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.h
+++ b/src/plugins/platforms/windows/qwindowsintegration.h
@@ -54,7 +54,7 @@ class QWindowsStaticOpenGLContext;
class QWindowsIntegration : public QPlatformIntegration
{
- Q_DISABLE_COPY(QWindowsIntegration)
+ Q_DISABLE_COPY_MOVE(QWindowsIntegration)
public:
enum Options { // Options to be passed on command line.
FontDatabaseFreeType = 0x1,
@@ -69,7 +69,8 @@ public:
AlwaysUseNativeMenus = 0x100,
NoNativeMenus = 0x200,
DontUseWMPointer = 0x400,
- DetectAltGrModifier = 0x800
+ DetectAltGrModifier = 0x800,
+ RtlEnabled = 0x1000
};
explicit QWindowsIntegration(const QStringList &paramList);
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.h b/src/plugins/platforms/windows/qwindowskeymapper.h
index a454f0f973..b1ada1d373 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.h
+++ b/src/plugins/platforms/windows/qwindowskeymapper.h
@@ -71,7 +71,7 @@ struct KeyboardLayoutItem {
class QWindowsKeyMapper
{
- Q_DISABLE_COPY(QWindowsKeyMapper)
+ Q_DISABLE_COPY_MOVE(QWindowsKeyMapper)
public:
explicit QWindowsKeyMapper();
~QWindowsKeyMapper();
diff --git a/src/plugins/platforms/windows/qwindowsmime.h b/src/plugins/platforms/windows/qwindowsmime.h
index 6bbbae1a0e..1c389e8800 100644
--- a/src/plugins/platforms/windows/qwindowsmime.h
+++ b/src/plugins/platforms/windows/qwindowsmime.h
@@ -53,7 +53,7 @@ class QMimeData;
class QWindowsMime
{
- Q_DISABLE_COPY(QWindowsMime)
+ Q_DISABLE_COPY_MOVE(QWindowsMime)
public:
QWindowsMime();
virtual ~QWindowsMime();
@@ -73,7 +73,7 @@ public:
class QWindowsMimeConverter
{
- Q_DISABLE_COPY(QWindowsMimeConverter)
+ Q_DISABLE_COPY_MOVE(QWindowsMimeConverter)
public:
QWindowsMimeConverter();
~QWindowsMimeConverter();
@@ -85,7 +85,7 @@ public:
// Convenience.
QVariant convertToMime(const QStringList &mimeTypes, IDataObject *pDataObj, QVariant::Type preferredType,
- QString *format = 0) const;
+ QString *format = nullptr) const;
void registerMime(QWindowsMime *mime);
void unregisterMime(QWindowsMime *mime) { m_mimes.removeOne(mime); }
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
index c4d53855a5..97e1319e8d 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
@@ -106,7 +106,7 @@ static inline void compressMouseMove(MSG *msg)
// 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));
+ clientToScreen(msg->hwnd, &(msg->pt));
// Remove the mouse move message
PeekMessage(&mouseMsg, msg->hwnd, WM_MOUSEMOVE,
WM_MOUSEMOVE, PM_REMOVE);
@@ -157,6 +157,12 @@ QTouchDevice *QWindowsMouseHandler::ensureTouchDevice()
return m_touchDevice;
}
+void QWindowsMouseHandler::clearEvents()
+{
+ m_lastEventType = QEvent::None;
+ m_lastEventButton = Qt::NoButton;
+}
+
Qt::MouseButtons QWindowsMouseHandler::queryMouseButtons()
{
Qt::MouseButtons result = nullptr;
@@ -262,7 +268,13 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
if (et == QtWindows::MouseWheelEvent)
return translateMouseWheelEvent(window, hwnd, msg, result);
- const QPoint winEventPosition(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
+ 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) {
@@ -287,8 +299,6 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized;
- const MouseEvent mouseEvent = eventFromMsg(msg);
-
// Check for events synthesized from touch. Lower byte is touch index, 0 means pen.
static const bool passSynthesizedMouseEvents =
!(QWindowsIntegration::instance()->options() & QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch);
@@ -305,13 +315,40 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
}
}
+ const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::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) {
+ if (mouseEvent.type == QEvent::NonClientAreaMouseMove) {
+ QWindowSystemInterface::handleFrameStrutMouseEvent(window, clientPosition, globalPosition, buttons, m_lastEventButton,
+ QEvent::NonClientAreaMouseButtonRelease, keyModifiers, source);
+ } else {
+ QWindowSystemInterface::handleMouseEvent(window, clientPosition, globalPosition, buttons, m_lastEventButton,
+ QEvent::MouseButtonRelease, keyModifiers, source);
+ }
+ }
+ m_lastEventType = mouseEvent.type;
+ m_lastEventButton = mouseEvent.button;
+
if (mouseEvent.type >= QEvent::NonClientAreaMouseMove && mouseEvent.type <= QEvent::NonClientAreaMouseButtonDblClick) {
- const Qt::MouseButtons buttons = QWindowsMouseHandler::queryMouseButtons();
QWindowSystemInterface::handleFrameStrutMouseEvent(window, clientPosition,
globalPosition, buttons,
mouseEvent.button, mouseEvent.type,
- QWindowsKeyMapper::queryKeyboardModifiers(),
- source);
+ keyModifiers, source);
return false; // Allow further event processing (dragging of windows).
}
@@ -334,7 +371,6 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
}
QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
- const Qt::MouseButtons buttons = keyStateToMouseButtons(int(msg.wParam));
// If the window was recently resized via mouse doubleclick on the frame or title bar,
// we don't get WM_LBUTTONDOWN or WM_LBUTTONDBLCLK for the second click,
@@ -461,8 +497,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
if (!discardEvent && mouseEvent.type != QEvent::None) {
QWindowSystemInterface::handleMouseEvent(window, winEventPosition, globalPosition, buttons,
mouseEvent.button, mouseEvent.type,
- QWindowsKeyMapper::queryKeyboardModifiers(),
- source);
+ keyModifiers, source);
}
m_previousCaptureWindow = hasCapture ? window : nullptr;
// QTBUG-48117, force synchronous handling for the extra buttons so that WM_APPCOMMAND
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.h b/src/plugins/platforms/windows/qwindowsmousehandler.h
index 480662c9bf..1d3d1f4761 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.h
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.h
@@ -45,6 +45,7 @@
#include <QtCore/qpointer.h>
#include <QtCore/qhash.h>
+#include <QtGui/qevent.h>
QT_BEGIN_NAMESPACE
@@ -53,7 +54,7 @@ class QTouchDevice;
class QWindowsMouseHandler
{
- Q_DISABLE_COPY(QWindowsMouseHandler)
+ Q_DISABLE_COPY_MOVE(QWindowsMouseHandler)
public:
QWindowsMouseHandler();
@@ -72,13 +73,14 @@ public:
bool translateScrollEvent(QWindow *window, HWND hwnd,
MSG msg, LRESULT *result);
- static inline Qt::MouseButtons keyStateToMouseButtons(int);
+ 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 = 0; }
+ void clearWindowUnderMouse() { m_windowUnderMouse = nullptr; }
+ void clearEvents();
private:
inline bool translateMouseWheelEvent(QWindow *window, HWND hwnd,
@@ -91,9 +93,11 @@ private:
QTouchDevice *m_touchDevice = nullptr;
bool m_leftButtonDown = false;
QWindow *m_previousCaptureWindow = nullptr;
+ QEvent::Type m_lastEventType = QEvent::None;
+ Qt::MouseButton m_lastEventButton = Qt::NoButton;
};
-Qt::MouseButtons QWindowsMouseHandler::keyStateToMouseButtons(int wParam)
+Qt::MouseButtons QWindowsMouseHandler::keyStateToMouseButtons(WPARAM wParam)
{
Qt::MouseButtons mb(Qt::NoButton);
if (wParam & MK_LBUTTON)
diff --git a/src/plugins/platforms/windows/qwindowsopenglcontext.h b/src/plugins/platforms/windows/qwindowsopenglcontext.h
index cc6d93d35e..1416a7e575 100644
--- a/src/plugins/platforms/windows/qwindowsopenglcontext.h
+++ b/src/plugins/platforms/windows/qwindowsopenglcontext.h
@@ -51,7 +51,7 @@ class QWindowsOpenGLContext;
class QWindowsStaticOpenGLContext
{
- Q_DISABLE_COPY(QWindowsStaticOpenGLContext)
+ Q_DISABLE_COPY_MOVE(QWindowsStaticOpenGLContext)
public:
static QWindowsStaticOpenGLContext *create();
virtual ~QWindowsStaticOpenGLContext() = default;
@@ -63,7 +63,7 @@ public:
// If the windowing system interface needs explicitly created window surfaces (like EGL),
// reimplement these.
- virtual void *createWindowSurface(void * /*nativeWindow*/, void * /*nativeConfig*/, int * /*err*/) { return 0; }
+ virtual void *createWindowSurface(void * /*nativeWindow*/, void * /*nativeConfig*/, int * /*err*/) { return nullptr; }
virtual void destroyWindowSurface(void * /*nativeSurface*/) { }
protected:
@@ -75,14 +75,14 @@ private:
class QWindowsOpenGLContext : public QPlatformOpenGLContext
{
- Q_DISABLE_COPY(QWindowsOpenGLContext)
+ Q_DISABLE_COPY_MOVE(QWindowsOpenGLContext)
public:
// Returns the native context handle (e.g. HGLRC for WGL, EGLContext for EGL).
virtual void *nativeContext() const = 0;
// These should be implemented only for some winsys interfaces, for example EGL.
// For others, like WGL, they are not relevant.
- virtual void *nativeDisplay() const { return 0; }
+ virtual void *nativeDisplay() const { return nullptr; }
virtual void *nativeConfig() const { return 0; }
protected:
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp
index 35418a18e7..ff495c8290 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.cpp
+++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp
@@ -83,7 +83,7 @@ static GpuDescription adapterIdentifierToGpuDescription(const D3DADAPTER_IDENTIF
class QDirect3D9Handle
{
public:
- Q_DISABLE_COPY(QDirect3D9Handle)
+ Q_DISABLE_COPY_MOVE(QDirect3D9Handle)
QDirect3D9Handle();
~QDirect3D9Handle();
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
index 7da87a32d5..36c614af34 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
@@ -336,6 +336,12 @@ QTouchDevice *QWindowsPointerHandler::ensureTouchDevice()
return m_touchDevice;
}
+void QWindowsPointerHandler::clearEvents()
+{
+ m_lastEventType = QEvent::None;
+ m_lastEventButton = Qt::NoButton;
+}
+
void QWindowsPointerHandler::handleCaptureRelease(QWindow *window,
QWindow *currentWindowUnderPointer,
HWND hwnd,
@@ -474,7 +480,7 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
<< " message=" << Qt::hex << msg.message
<< " count=" << Qt::dec << count;
- Qt::TouchPointStates allStates = 0;
+ Qt::TouchPointStates allStates = nullptr;
for (quint32 i = 0; i < count; ++i) {
if (QWindowsContext::verbose > 1)
@@ -614,6 +620,9 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
if (m_needsEnterOnPointerUpdate) {
m_needsEnterOnPointerUpdate = false;
if (window != m_currentWindow) {
+ // make sure we subscribe to leave events for this window
+ trackLeave(hwnd);
+
QWindowSystemInterface::handleEnterEvent(window, localPos, globalPos);
m_currentWindow = window;
if (QWindowsWindow *wumPlatformWindow = QWindowsWindow::windowsWindowOf(target))
@@ -685,7 +694,13 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
{
*result = 0;
- const QPoint eventPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
+ QPoint eventPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam));
+ if ((et & QtWindows::NonClientEventFlag) == 0 && QWindowsBaseWindow::isRtlLayout(hwnd)) {
+ RECT clientArea;
+ GetClientRect(hwnd, &clientArea);
+ eventPos.setX(clientArea.right - eventPos.x());
+ }
+
QPoint localPos;
QPoint globalPos;
@@ -723,10 +738,35 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
}
const MouseEvent mouseEvent = eventFromMsg(msg);
+ Qt::MouseButtons mouseButtons;
+
+ if (mouseEvent.type >= QEvent::NonClientAreaMouseMove && mouseEvent.type <= QEvent::NonClientAreaMouseButtonDblClick)
+ mouseButtons = queryMouseButtons();
+ else
+ mouseButtons = mouseButtonsFromKeyState(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 & mouseButtons) == 0) {
+ if (mouseEvent.type == QEvent::NonClientAreaMouseMove) {
+ QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, mouseButtons, m_lastEventButton,
+ QEvent::NonClientAreaMouseButtonRelease, keyModifiers, source);
+ } else {
+ QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos, mouseButtons, m_lastEventButton,
+ QEvent::MouseButtonRelease, keyModifiers, source);
+ }
+ }
+ m_lastEventType = mouseEvent.type;
+ m_lastEventButton = mouseEvent.button;
if (mouseEvent.type >= QEvent::NonClientAreaMouseMove && mouseEvent.type <= QEvent::NonClientAreaMouseButtonDblClick) {
- const Qt::MouseButtons nonclientButtons = queryMouseButtons();
- QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, nonclientButtons,
+ QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, mouseButtons,
mouseEvent.button, mouseEvent.type, keyModifiers, source);
return false; // Allow further event processing
}
@@ -742,8 +782,6 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
return true;
}
- const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam);
-
handleCaptureRelease(window, currentWindowUnderPointer, hwnd, mouseEvent.type, mouseButtons);
handleEnterLeave(window, currentWindowUnderPointer, globalPos);
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.h b/src/plugins/platforms/windows/qwindowspointerhandler.h
index aebef062bc..068e804007 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.h
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.h
@@ -46,7 +46,7 @@
#include <QtCore/qpointer.h>
#include <QtCore/qscopedpointer.h>
#include <QtCore/qhash.h>
-#include <qpa/qwindowsysteminterface.h>
+#include <QtGui/qevent.h>
QT_BEGIN_NAMESPACE
@@ -55,7 +55,7 @@ class QTouchDevice;
class QWindowsPointerHandler
{
- Q_DISABLE_COPY(QWindowsPointerHandler)
+ Q_DISABLE_COPY_MOVE(QWindowsPointerHandler)
public:
QWindowsPointerHandler() = default;
bool translatePointerEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result);
@@ -64,6 +64,7 @@ public:
QTouchDevice *ensureTouchDevice();
QWindow *windowUnderMouse() const { return m_windowUnderPointer.data(); }
void clearWindowUnderMouse() { m_windowUnderPointer = nullptr; }
+ void clearEvents();
private:
bool translateTouchEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, PVOID vTouchInfo, unsigned int count);
@@ -79,6 +80,8 @@ private:
QPointer<QWindow> m_currentWindow;
QWindow *m_previousCaptureWindow = nullptr;
bool m_needsEnterOnPointerUpdate = false;
+ QEvent::Type m_lastEventType = QEvent::None;
+ Qt::MouseButton m_lastEventButton = Qt::NoButton;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index b70b0bbe31..2f8850cbe0 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -240,7 +240,8 @@ QWindow *QWindowsScreen::topLevelAt(const QPoint &point) const
QWindow *result = nullptr;
if (QWindow *child = QWindowsScreen::windowAt(point, CWP_SKIPINVISIBLE))
result = QWindowsWindow::topLevelOf(child);
- qCDebug(lcQpaWindows) <<__FUNCTION__ << point << result;
+ if (QWindowsContext::verbose > 1)
+ qCDebug(lcQpaWindows) <<__FUNCTION__ << point << result;
return result;
}
@@ -250,7 +251,8 @@ QWindow *QWindowsScreen::windowAt(const QPoint &screenPoint, unsigned flags)
if (QPlatformWindow *bw = QWindowsContext::instance()->
findPlatformWindowAt(GetDesktopWindow(), screenPoint, flags))
result = bw->window();
- qCDebug(lcQpaWindows) <<__FUNCTION__ << screenPoint << " returns " << result;
+ if (QWindowsContext::verbose > 1)
+ qCDebug(lcQpaWindows) <<__FUNCTION__ << screenPoint << " returns " << result;
return result;
}
@@ -438,6 +440,12 @@ QPlatformScreen::SubpixelAntialiasingType QWindowsScreen::subpixelAntialiasingTy
QWindowsScreenManager::QWindowsScreenManager() = default;
+
+bool QWindowsScreenManager::isSingleScreen()
+{
+ return QWindowsContext::instance()->screenManager().screens().size() < 2;
+}
+
/*!
\brief Triggers synchronization of screens (WM_DISPLAYCHANGE).
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index 33c9effa2a..3eb2d35b27 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -140,6 +140,8 @@ public:
const QWindowsScreen *screenAtDp(const QPoint &p) const;
const QWindowsScreen *screenForHwnd(HWND hwnd) const;
+ static bool isSingleScreen();
+
private:
void removeScreen(int index);
diff --git a/src/plugins/platforms/windows/qwindowssessionmanager.h b/src/plugins/platforms/windows/qwindowssessionmanager.h
index 4c4256f2b0..0769ed1fce 100644
--- a/src/plugins/platforms/windows/qwindowssessionmanager.h
+++ b/src/plugins/platforms/windows/qwindowssessionmanager.h
@@ -79,7 +79,7 @@ private:
bool m_blockUserInput = false;
bool m_canceled = false;
- Q_DISABLE_COPY(QWindowsSessionManager)
+ Q_DISABLE_COPY_MOVE(QWindowsSessionManager)
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
index 84c963af94..cd5a78abb6 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
@@ -435,6 +435,27 @@ bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, L
m_currentDevice = m_devices.size();
m_devices.push_back(tabletInit(uniqueId, cursorType));
}
+
+ /**
+ * We should check button map for changes on every proximity event, not
+ * only during initialization phase.
+ *
+ * WARNING: in 2016 there were some Wacom table drivers, which could mess up
+ * button mapping if the remapped button was pressed, while the
+ * application **didn't have input focus**. This bug is somehow
+ * related to the fact that Wacom drivers allow user to configure
+ * per-application button-mappings. If the bug shows up again,
+ * just move this button-map fetching into initialization block.
+ *
+ * See https://bugs.kde.org/show_bug.cgi?id=359561
+ */
+ BYTE logicalButtons[32];
+ memset(logicalButtons, 0, 32);
+ m_winTab32DLL.wTInfo(WTI_CURSORS + currentCursor, CSR_SYSBTNMAP, &logicalButtons);
+ m_devices[m_currentDevice].buttonsMap[0x1] = logicalButtons[0];
+ m_devices[m_currentDevice].buttonsMap[0x2] = logicalButtons[1];
+ m_devices[m_currentDevice].buttonsMap[0x4] = logicalButtons[2];
+
m_devices[m_currentDevice].currentPointerType = pointerType(currentCursor);
m_state = PenProximity;
qCDebug(lcQpaTablet) << "enter proximity for device #"
@@ -446,6 +467,52 @@ bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, L
return true;
}
+Qt::MouseButton buttonValueToEnum(DWORD button,
+ const QWindowsTabletDeviceData &tdd) {
+
+ enum : unsigned {
+ leftButtonValue = 0x1,
+ middleButtonValue = 0x2,
+ rightButtonValue = 0x4,
+ doubleClickButtonValue = 0x7
+ };
+
+ button = tdd.buttonsMap.value(button);
+
+ return button == leftButtonValue ? Qt::LeftButton :
+ button == rightButtonValue ? Qt::RightButton :
+ button == doubleClickButtonValue ? Qt::MiddleButton :
+ button == middleButtonValue ? Qt::MiddleButton :
+ button ? Qt::LeftButton /* fallback item */ :
+ Qt::NoButton;
+}
+
+Qt::MouseButtons convertTabletButtons(DWORD btnNew,
+ const QWindowsTabletDeviceData &tdd) {
+
+ Qt::MouseButtons buttons = Qt::NoButton;
+ for (unsigned int i = 0; i < 3; i++) {
+ unsigned int btn = 0x1 << i;
+
+ if (btn & btnNew) {
+ Qt::MouseButton convertedButton =
+ buttonValueToEnum(btn, tdd);
+
+ buttons |= convertedButton;
+
+ /**
+ * If a button that is present in hardware input is
+ * mapped to a Qt::NoButton, it means that it is going
+ * to be eaten by the driver, for example by its
+ * "Pan/Scroll" feature. Therefore we shouldn't handle
+ * any of the events associated to it. We'll just return
+ * Qt::NoButtons here.
+ */
+ }
+ }
+ return buttons;
+}
+
bool QWindowsTabletSupport::translateTabletPacketEvent()
{
static PACKET localPacketBuf[TabletPacketQSize]; // our own tablet packet queue.
@@ -552,9 +619,12 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
<< tiltY << "tanP:" << tangentialPressure << "rotation:" << rotation;
}
+ Qt::MouseButtons buttons =
+ convertTabletButtons(packet.pkButtons, m_devices.at(m_currentDevice));
+
QWindowSystemInterface::handleTabletEvent(target, packet.pkTime, QPointF(localPos), globalPosF,
currentDevice, currentPointer,
- static_cast<Qt::MouseButtons>(packet.pkButtons),
+ buttons,
pressureNew, tiltX, tiltY,
tangentialPressure, rotation, z,
uniqueId,
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.h b/src/plugins/platforms/windows/qwindowstabletsupport.h
index d91701d6a5..6bcf3357a5 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.h
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.h
@@ -45,6 +45,7 @@
#include <QtCore/qvector.h>
#include <QtCore/qpoint.h>
+#include <QtCore/qhash.h>
#include <wintab.h>
@@ -100,6 +101,7 @@ struct QWindowsTabletDeviceData
qint64 uniqueId = 0;
int currentDevice = 0;
int currentPointerType = 0;
+ QHash<quint8, quint8> buttonsMap;
};
#ifndef QT_NO_DEBUG_STREAM
@@ -108,7 +110,7 @@ QDebug operator<<(QDebug d, const QWindowsTabletDeviceData &t);
class QWindowsTabletSupport
{
- Q_DISABLE_COPY(QWindowsTabletSupport)
+ Q_DISABLE_COPY_MOVE(QWindowsTabletSupport)
explicit QWindowsTabletSupport(HWND window, HCTX context);
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index a6b9781252..b75c64c40e 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -170,15 +170,9 @@ public:
if (m_params) {
const QString fileName = m_params->fileName;
SHFILEINFO info;
-#ifndef Q_OS_WINCE
- const UINT oldErrorMode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
-#endif
const bool result = SHGetFileInfo(reinterpret_cast<const wchar_t *>(fileName.utf16()),
m_params->attributes, &info, sizeof(SHFILEINFO),
m_params->flags);
-#ifndef Q_OS_WINCE
- SetErrorMode(oldErrorMode);
-#endif
m_doneMutex.lock();
if (!m_cancelled.load()) {
*m_params->result = result;
diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h
index c132f20167..4e24308445 100644
--- a/src/plugins/platforms/windows/qwindowstheme.h
+++ b/src/plugins/platforms/windows/qwindowstheme.h
@@ -51,7 +51,7 @@ class QWindow;
class QWindowsTheme : public QPlatformTheme
{
- Q_DISABLE_COPY(QWindowsTheme)
+ Q_DISABLE_COPY_MOVE(QWindowsTheme)
public:
QWindowsTheme();
~QWindowsTheme() override;
@@ -71,7 +71,7 @@ public:
QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const override;
- QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions = 0) const override;
+ QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions = nullptr) const override;
void windowsThemeChanged(QWindow *window);
void displayChanged() { refreshIconPixmapSizes(); }
diff --git a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h
index 731e4b5432..ffe2e62069 100644
--- a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h
+++ b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h
@@ -59,7 +59,7 @@ QT_BEGIN_NAMESPACE
*/
class QWindowsThreadPoolRunner
{
- Q_DISABLE_COPY(QWindowsThreadPoolRunner)
+ Q_DISABLE_COPY_MOVE(QWindowsThreadPoolRunner)
#if QT_CONFIG(thread)
template <class RunnableFunction> // nested class implementing QRunnable to execute a function.
diff --git a/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp b/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp
index 7a01483abd..812ea8193a 100644
--- a/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp
+++ b/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp
@@ -81,7 +81,7 @@ bool QWindowsVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice,
VkSurfaceKHR QWindowsVulkanInstance::createSurface(HWND win)
{
- VkSurfaceKHR surface = 0;
+ VkSurfaceKHR surface = VK_NULL_HANDLE;
if (!m_createSurface) {
m_createSurface = reinterpret_cast<PFN_vkCreateWin32SurfaceKHR>(
diff --git a/src/plugins/platforms/windows/qwindowsvulkaninstance.h b/src/plugins/platforms/windows/qwindowsvulkaninstance.h
index 3292137c39..cc7ef476d4 100644
--- a/src/plugins/platforms/windows/qwindowsvulkaninstance.h
+++ b/src/plugins/platforms/windows/qwindowsvulkaninstance.h
@@ -53,7 +53,7 @@ QT_BEGIN_NAMESPACE
class QWindowsVulkanInstance : public QBasicPlatformVulkanInstance
{
- Q_DISABLE_COPY(QWindowsVulkanInstance)
+ Q_DISABLE_COPY_MOVE(QWindowsVulkanInstance)
public:
QWindowsVulkanInstance(QVulkanInstance *instance);
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index d55545af42..74c295d155 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -134,6 +134,10 @@ static QByteArray debugWinExStyle(DWORD exStyle)
rc += " WS_EX_LAYERED";
if (exStyle & WS_EX_DLGMODALFRAME)
rc += " WS_EX_DLGMODALFRAME";
+ if (exStyle & WS_EX_LAYOUTRTL)
+ rc += " WS_EX_LAYOUTRTL";
+ if (exStyle & WS_EX_NOINHERITLAYOUT)
+ rc += " WS_EX_NOINHERITLAYOUT";
return rc;
}
@@ -184,6 +188,7 @@ static inline RECT RECTfromQRect(const QRect &rect)
return result;
}
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const RECT &r)
{
@@ -262,6 +267,16 @@ QDebug operator<<(QDebug d, const GUID &guid)
}
#endif // !QT_NO_DEBUG_STREAM
+static void formatBriefRectangle(QDebug &d, const QRect &r)
+{
+ d << r.width() << 'x' << r.height() << Qt::forcesign << r.x() << r.y() << Qt::noforcesign;
+}
+
+static void formatBriefMargins(QDebug &d, const QMargins &m)
+{
+ d << m.left() << ", " << m.top() << ", " << m.right() << ", " << m.bottom();
+}
+
// QTBUG-43872, for windows that do not have WS_EX_TOOLWINDOW set, WINDOWPLACEMENT
// is in workspace/available area coordinates.
static QPoint windowPlacementOffset(HWND hwnd, const QPoint &point)
@@ -296,7 +311,7 @@ static inline QRect frameGeometry(HWND hwnd, bool topLevel)
const int width = rect.right - rect.left;
const int height = rect.bottom - rect.top;
POINT leftTop = { rect.left, rect.top };
- ScreenToClient(parent, &leftTop);
+ screenToClient(parent, &leftTop);
rect.left = leftTop.x;
rect.top = leftTop.y;
rect.right = leftTop.x + width;
@@ -656,6 +671,17 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
if ((flags & Qt::MSWindowsFixedSizeDialogHint))
dialog = true;
+ // This causes the title bar to drawn RTL and the close button
+ // to be left. Note that this causes:
+ // - All DCs created on the Window to have RTL layout (see SetLayout)
+ // - ClientToScreen() and ScreenToClient() to work in reverse as well.
+ // - Mouse event coordinates to be mirrored.
+ // - Positioning of child Windows.
+ if (QGuiApplication::layoutDirection() == Qt::RightToLeft
+ && (QWindowsIntegration::instance()->options() & QWindowsIntegration::RtlEnabled) != 0) {
+ exStyle |= WS_EX_LAYOUTRTL | WS_EX_NOINHERITLAYOUT;
+ }
+
// Parent: Use transient parent for top levels.
if (popup) {
flags |= Qt::WindowStaysOnTopHint; // a popup stays on top, no parent.
@@ -761,6 +787,16 @@ QWindowsWindowData
QPoint pos = calcPosition(w, context, invMargins);
+ // Mirror the position when creating on a parent in RTL mode, ditto for the obtained geometry.
+ int mirrorParentWidth = 0;
+ if (!w->isTopLevel() && QWindowsBaseWindow::isRtlLayout(parentHandle)) {
+ RECT rect;
+ GetClientRect(parentHandle, &rect);
+ mirrorParentWidth = rect.right;
+ }
+ if (mirrorParentWidth != 0 && pos.x() != CW_USEDEFAULT && context->frameWidth != CW_USEDEFAULT)
+ pos.setX(mirrorParentWidth - context->frameWidth - pos.x());
+
result.hwnd = CreateWindowEx(exStyle, classNameUtf16, titleUtf16,
style,
pos.x(), pos.y(),
@@ -768,14 +804,21 @@ QWindowsWindowData
parentHandle, nullptr, appinst, nullptr);
qCDebug(lcQpaWindows).nospace()
<< "CreateWindowEx: returns " << w << ' ' << result.hwnd << " obtained geometry: "
- << context->obtainedGeometry << ' ' << context->margins;
+ << context->obtainedPos << context->obtainedSize << ' ' << context->margins;
if (!result.hwnd) {
qErrnoWarning("%s: CreateWindowEx failed", __FUNCTION__);
return result;
}
- result.geometry = context->obtainedGeometry;
+ if (mirrorParentWidth != 0) {
+ context->obtainedPos.setX(mirrorParentWidth - context->obtainedSize.width()
+ - context->obtainedPos.x());
+ }
+
+ QRect obtainedGeometry(context->obtainedPos, context->obtainedSize);
+
+ result.geometry = obtainedGeometry;
result.fullFrameMargins = context->margins;
result.embedded = embedded;
result.hasFrame = hasFrame;
@@ -859,35 +902,78 @@ static QSize toNativeSizeConstrained(QSize dip, const QWindow *w)
\ingroup qt-lighthouse-win
*/
-QWindowsGeometryHint::QWindowsGeometryHint(const QWindow *w, const QMargins &cm) :
- minimumSize(toNativeSizeConstrained(w->minimumSize(), w)),
- maximumSize(toNativeSizeConstrained(w->maximumSize(), w)),
- customMargins(cm)
+QMargins QWindowsGeometryHint::frameOnPrimaryScreen(DWORD style, DWORD exStyle)
{
+ RECT rect = {0,0,0,0};
+ style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
+ if (AdjustWindowRectEx(&rect, style, FALSE, exStyle) == FALSE)
+ qErrnoWarning("%s: AdjustWindowRectEx failed", __FUNCTION__);
+ const QMargins result(qAbs(rect.left), qAbs(rect.top),
+ qAbs(rect.right), qAbs(rect.bottom));
+ qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << " style="
+ << Qt::showbase << Qt::hex << style << " exStyle=" << exStyle << Qt::dec << Qt::noshowbase
+ << ' ' << rect << ' ' << result;
+ return result;
}
-bool QWindowsGeometryHint::validSize(const QSize &s) const
+QMargins QWindowsGeometryHint::frameOnPrimaryScreen(HWND hwnd)
{
- const int width = s.width();
- const int height = s.height();
- return width >= minimumSize.width() && width <= maximumSize.width()
- && height >= minimumSize.height() && height <= maximumSize.height();
+ return frameOnPrimaryScreen(DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)),
+ DWORD(GetWindowLongPtr(hwnd, GWL_EXSTYLE)));
}
-QMargins QWindowsGeometryHint::frame(DWORD style, DWORD exStyle)
+QMargins QWindowsGeometryHint::frame(DWORD style, DWORD exStyle, qreal dpi)
{
+ if (QWindowsContext::user32dll.adjustWindowRectExForDpi == nullptr)
+ return frameOnPrimaryScreen(style, exStyle);
RECT rect = {0,0,0,0};
- style &= ~(WS_OVERLAPPED); // Not permitted, see docs.
- if (!AdjustWindowRectEx(&rect, style, FALSE, exStyle))
- qErrnoWarning("%s: AdjustWindowRectEx failed", __FUNCTION__);
+ style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
+ if (QWindowsContext::user32dll.adjustWindowRectExForDpi(&rect, style, FALSE, exStyle,
+ unsigned(qRound(dpi))) == FALSE) {
+ qErrnoWarning("%s: AdjustWindowRectExForDpi failed", __FUNCTION__);
+ }
const QMargins result(qAbs(rect.left), qAbs(rect.top),
qAbs(rect.right), qAbs(rect.bottom));
qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << " style="
<< Qt::showbase << Qt::hex << style << " exStyle=" << exStyle << Qt::dec << Qt::noshowbase
+ << " dpi=" << dpi
<< ' ' << rect << ' ' << result;
return result;
}
+QMargins QWindowsGeometryHint::frame(HWND hwnd, DWORD style, DWORD exStyle)
+{
+ if (QWindowsScreenManager::isSingleScreen())
+ return frameOnPrimaryScreen(style, exStyle);
+ auto screenManager = QWindowsContext::instance()->screenManager();
+ auto screen = screenManager.screenForHwnd(hwnd);
+ if (!screen)
+ screen = screenManager.screens().value(0);
+ const auto dpi = screen ? screen->logicalDpi().first : qreal(96);
+ return frame(style, exStyle, dpi);
+}
+
+// For newly created windows.
+QMargins QWindowsGeometryHint::frame(const QWindow *w, const QRect &geometry,
+ DWORD style, DWORD exStyle)
+{
+ if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint))
+ return {};
+ if (!QWindowsContext::user32dll.adjustWindowRectExForDpi
+ || QWindowsScreenManager::isSingleScreen()
+ || !QWindowsContext::shouldHaveNonClientDpiScaling(w)) {
+ return frameOnPrimaryScreen(style, exStyle);
+ }
+ qreal dpi = 96;
+ auto screenManager = QWindowsContext::instance()->screenManager();
+ auto screen = screenManager.screenAtDp(geometry.center());
+ if (!screen)
+ screen = screenManager.screens().value(0);
+ if (screen)
+ dpi = screen->logicalDpi().first;
+ return QWindowsGeometryHint::frame(style, exStyle, dpi);
+}
+
bool QWindowsGeometryHint::handleCalculateSize(const QMargins &customMargins, const MSG &msg, LRESULT *result)
{
// NCCALCSIZE_PARAMS structure if wParam==TRUE
@@ -907,36 +993,50 @@ bool QWindowsGeometryHint::handleCalculateSize(const QMargins &customMargins, co
return true;
}
-void QWindowsGeometryHint::applyToMinMaxInfo(HWND hwnd, MINMAXINFO *mmi) const
+void QWindowsGeometryHint::frameSizeConstraints(const QWindow *w, const QMargins &margins,
+ QSize *minimumSize, QSize *maximumSize)
{
- return applyToMinMaxInfo(DWORD(GetWindowLong(hwnd, GWL_STYLE)),
- DWORD(GetWindowLong(hwnd, GWL_EXSTYLE)), mmi);
+ *minimumSize = toNativeSizeConstrained(w->minimumSize(), w);
+ *maximumSize = toNativeSizeConstrained(w->maximumSize(), w);
+
+ const int maximumWidth = qMax(maximumSize->width(), minimumSize->width());
+ const int maximumHeight = qMax(maximumSize->height(), minimumSize->height());
+ const int frameWidth = margins.left() + margins.right();
+ const int frameHeight = margins.top() + margins.bottom();
+
+ if (minimumSize->width() > 0)
+ minimumSize->rwidth() += frameWidth;
+ if (minimumSize->height() > 0)
+ minimumSize->rheight() += frameHeight;
+ if (maximumWidth < QWINDOWSIZE_MAX)
+ maximumSize->setWidth(maximumWidth + frameWidth);
+ if (maximumHeight < QWINDOWSIZE_MAX)
+ maximumSize->setHeight(maximumHeight + frameHeight);
}
-void QWindowsGeometryHint::applyToMinMaxInfo(DWORD style, DWORD exStyle, MINMAXINFO *mmi) const
+void QWindowsGeometryHint::applyToMinMaxInfo(const QWindow *w,
+ const QMargins &margins,
+ MINMAXINFO *mmi)
{
+ QSize minimumSize;
+ QSize maximumSize;
+ frameSizeConstraints(w, margins, &minimumSize, &maximumSize);
qCDebug(lcQpaWindows).nospace() << '>' << __FUNCTION__ << '<' << " min="
<< minimumSize.width() << ',' << minimumSize.height()
<< " max=" << maximumSize.width() << ',' << maximumSize.height()
+ << " margins=" << margins
<< " in " << *mmi;
- const QMargins margins = QWindowsGeometryHint::frame(style, exStyle);
- const int frameWidth = margins.left() + margins.right() + customMargins.left() + customMargins.right();
- const int frameHeight = margins.top() + margins.bottom() + customMargins.top() + customMargins.bottom();
if (minimumSize.width() > 0)
- mmi->ptMinTrackSize.x = minimumSize.width() + frameWidth;
+ mmi->ptMinTrackSize.x = minimumSize.width();
if (minimumSize.height() > 0)
- mmi->ptMinTrackSize.y = minimumSize.height() + frameHeight;
+ mmi->ptMinTrackSize.y = minimumSize.height();
- const int maximumWidth = qMax(maximumSize.width(), minimumSize.width());
- const int maximumHeight = qMax(maximumSize.height(), minimumSize.height());
- if (maximumWidth < QWINDOWSIZE_MAX)
- mmi->ptMaxTrackSize.x = maximumWidth + frameWidth;
- if (maximumHeight < QWINDOWSIZE_MAX)
- mmi->ptMaxTrackSize.y = maximumHeight + frameHeight;
- qCDebug(lcQpaWindows).nospace() << '<' << __FUNCTION__
- << " frame=" << margins << ' ' << frameWidth << ',' << frameHeight
- << " out " << *mmi;
+ if (maximumSize.width() < QWINDOWSIZE_MAX)
+ mmi->ptMaxTrackSize.x = maximumSize.width();
+ if (maximumSize.height() < QWINDOWSIZE_MAX)
+ mmi->ptMaxTrackSize.y = maximumSize.height();
+ qCDebug(lcQpaWindows).nospace() << '<' << __FUNCTION__ << " out " << *mmi;
}
bool QWindowsGeometryHint::positionIncludesFrame(const QWindow *w)
@@ -963,6 +1063,11 @@ bool QWindowsGeometryHint::positionIncludesFrame(const QWindow *w)
\ingroup qt-lighthouse-win
*/
+bool QWindowsBaseWindow::isRtlLayout(HWND hwnd)
+{
+ return (GetWindowLongPtrW(hwnd, GWL_EXSTYLE) & WS_EX_LAYOUTRTL) != 0;
+}
+
QWindowsBaseWindow *QWindowsBaseWindow::baseWindowOf(const QWindow *w)
{
if (w) {
@@ -996,7 +1101,7 @@ QRect QWindowsBaseWindow::geometry_sys() const
QMargins QWindowsBaseWindow::frameMargins_sys() const
{
- return QWindowsGeometryHint::frame(style(), exStyle());
+ return QWindowsGeometryHint::frame(handle(), style(), exStyle());
}
void QWindowsBaseWindow::hide_sys() // Normal hide, do not activate other windows.
@@ -1122,11 +1227,14 @@ void QWindowsForeignWindow::setVisible(bool visible)
QWindowCreationContext::QWindowCreationContext(const QWindow *w,
const QRect &geometryIn, const QRect &geometry,
const QMargins &cm,
- DWORD style_, DWORD exStyle_) :
- geometryHint(w, cm), window(w), style(style_), exStyle(exStyle_),
+ DWORD style, DWORD exStyle) :
+ window(w),
requestedGeometryIn(geometryIn),
- requestedGeometry(geometry), obtainedGeometry(geometry),
- margins(QWindowsGeometryHint::frame(style, exStyle)), customMargins(cm)
+ requestedGeometry(geometry),
+ obtainedPos(geometryIn.topLeft()),
+ obtainedSize(geometryIn.size()),
+ margins(QWindowsGeometryHint::frame(w, geometry, style, exStyle)),
+ customMargins(cm)
{
// Geometry of toplevels does not consider window frames.
// TODO: No concept of WA_wasMoved yet that would indicate a
@@ -1155,8 +1263,12 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w,
<< " pos incl. frame=" << QWindowsGeometryHint::positionIncludesFrame(w)
<< " frame=" << frameWidth << 'x' << frameHeight << '+'
<< frameX << '+' << frameY
- << " min=" << geometryHint.minimumSize << " max=" << geometryHint.maximumSize
- << " custom margins=" << customMargins;
+ << " margins=" << margins << " custom margins=" << customMargins;
+}
+
+void QWindowCreationContext::applyToMinMaxInfo(MINMAXINFO *mmi) const
+{
+ QWindowsGeometryHint::applyToMinMaxInfo(window, margins + customMargins, mmi);
}
/*!
@@ -1191,7 +1303,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
m_cursor(new CursorHandle),
m_format(aWindow->requestedFormat())
#if QT_CONFIG(vulkan)
- , m_vkSurface(0)
+ , m_vkSurface(VK_NULL_HANDLE)
#endif
{
QWindowsContext::instance()->addWindow(m_data.hwnd, this);
@@ -1248,11 +1360,12 @@ void QWindowsWindow::initialize()
// will send the message) and screen change signals of QWindow.
if (w->type() != Qt::Desktop) {
const Qt::WindowState state = w->windowState();
+ const QRect obtainedGeometry(creationContext->obtainedPos, creationContext->obtainedSize);
if (state != Qt::WindowMaximized && state != Qt::WindowFullScreen
- && creationContext->requestedGeometryIn != creationContext->obtainedGeometry) {
- QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(w, creationContext->obtainedGeometry);
+ && creationContext->requestedGeometryIn != obtainedGeometry) {
+ QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(w, obtainedGeometry);
}
- QPlatformScreen *obtainedScreen = screenForGeometry(creationContext->obtainedGeometry);
+ QPlatformScreen *obtainedScreen = screenForGeometry(obtainedGeometry);
if (obtainedScreen && screen() != obtainedScreen)
QWindowSystemInterface::handleWindowScreenChanged<QWindowSystemInterface::SynchronousDelivery>(w, obtainedScreen->screen());
}
@@ -1291,14 +1404,14 @@ void QWindowsWindow::destroyWindow()
QVulkanInstance *inst = window()->vulkanInstance();
if (inst)
static_cast<QWindowsVulkanInstance *>(inst->handle())->destroySurface(m_vkSurface);
- m_vkSurface = 0;
+ m_vkSurface = VK_NULL_HANDLE;
}
#endif
#ifndef QT_NO_OPENGL
if (m_surface) {
if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext())
staticOpenGLContext->destroyWindowSurface(m_surface);
- m_surface = 0;
+ m_surface = nullptr;
}
#endif
DestroyWindow(m_data.hwnd);
@@ -1672,10 +1785,57 @@ QRect QWindowsWindow::normalGeometry() const
const bool fakeFullScreen =
m_savedFrameGeometry.isValid() && (window()->windowStates() & Qt::WindowFullScreen);
const QRect frame = fakeFullScreen ? m_savedFrameGeometry : normalFrameGeometry(m_data.hwnd);
- const QMargins margins = fakeFullScreen ? QWindowsGeometryHint::frame(m_savedStyle, 0) : fullFrameMargins();
+ const QMargins margins = fakeFullScreen
+ ? QWindowsGeometryHint::frame(handle(), m_savedStyle, 0)
+ : fullFrameMargins();
return frame.isValid() ? frame.marginsRemoved(margins) : frame;
}
+static QString msgUnableToSetGeometry(const QWindowsWindow *platformWindow,
+ const QRect &requestedRect,
+ const QRect &obtainedRect,
+ const QMargins &fullMargins,
+ const QMargins &customMargins)
+{
+ QString result;
+ QDebug debug(&result);
+ debug.nospace();
+ debug.noquote();
+ const auto window = platformWindow->window();
+ debug << "Unable to set geometry ";
+ formatBriefRectangle(debug, requestedRect);
+ debug << " (frame: ";
+ formatBriefRectangle(debug, requestedRect + fullMargins);
+ debug << ") on " << window->metaObject()->className() << "/\""
+ << window->objectName() << "\" on \"" << window->screen()->name()
+ << "\". Resulting geometry: ";
+ formatBriefRectangle(debug, obtainedRect);
+ debug << " (frame: ";
+ formatBriefRectangle(debug, obtainedRect + fullMargins);
+ debug << ") margins: ";
+ formatBriefMargins(debug, fullMargins);
+ if (!customMargins.isNull()) {
+ debug << " custom margin: ";
+ formatBriefMargins(debug, customMargins);
+ }
+ const auto minimumSize = window->minimumSize();
+ const bool hasMinimumSize = !minimumSize.isEmpty();
+ if (hasMinimumSize)
+ debug << " minimum size: " << minimumSize.width() << 'x' << minimumSize.height();
+ const auto maximumSize = window->maximumSize();
+ const bool hasMaximumSize = maximumSize.width() != QWINDOWSIZE_MAX || maximumSize.height() != QWINDOWSIZE_MAX;
+ if (hasMaximumSize)
+ debug << " maximum size: " << maximumSize.width() << 'x' << maximumSize.height();
+ if (hasMinimumSize || hasMaximumSize) {
+ MINMAXINFO minmaxInfo;
+ memset(&minmaxInfo, 0, sizeof(minmaxInfo));
+ platformWindow->getSizeHints(&minmaxInfo);
+ debug << ' ' << minmaxInfo;
+ }
+ debug << ')';
+ return result;
+}
+
void QWindowsWindow::setGeometry(const QRect &rectIn)
{
QRect rect = rectIn;
@@ -1695,21 +1855,10 @@ void QWindowsWindow::setGeometry(const QRect &rectIn)
setGeometry_sys(rect);
clearFlag(WithinSetGeometry);
if (m_data.geometry != rect && (isVisible() || QLibraryInfo::isDebugBuild())) {
- qWarning("%s: Unable to set geometry %dx%d+%d+%d on %s/'%s'."
- " Resulting geometry: %dx%d+%d+%d "
- "(frame: %d, %d, %d, %d, custom margin: %d, %d, %d, %d"
- ", minimum size: %dx%d, maximum size: %dx%d).",
- __FUNCTION__,
- rect.width(), rect.height(), rect.x(), rect.y(),
- window()->metaObject()->className(), qPrintable(window()->objectName()),
- m_data.geometry.width(), m_data.geometry.height(),
- m_data.geometry.x(), m_data.geometry.y(),
- m_data.fullFrameMargins.left(), m_data.fullFrameMargins.top(),
- m_data.fullFrameMargins.right(), m_data.fullFrameMargins.bottom(),
- m_data.customMargins.left(), m_data.customMargins.top(),
- m_data.customMargins.right(), m_data.customMargins.bottom(),
- window()->minimumWidth(), window()->minimumHeight(),
- window()->maximumWidth(), window()->maximumHeight());
+ const auto warning =
+ msgUnableToSetGeometry(this, rectIn, m_data.geometry,
+ m_data.fullFrameMargins, m_data.customMargins);
+ qWarning("%s: %s", __FUNCTION__, qPrintable(warning));
}
} else {
QPlatformWindow::setGeometry(rect);
@@ -1753,27 +1902,41 @@ void QWindowsWindow::handleResized(int wParam)
}
}
-void QWindowsWindow::checkForScreenChanged()
+static inline bool equalDpi(const QDpi &d1, const QDpi &d2)
+{
+ return qFuzzyCompare(d1.first, d2.first) && qFuzzyCompare(d1.second, d2.second);
+}
+
+void QWindowsWindow::checkForScreenChanged(ScreenChangeMode mode)
{
- if (parent())
+ if (parent() || QWindowsScreenManager::isSingleScreen())
return;
QPlatformScreen *currentScreen = screen();
- const auto &screenManager = QWindowsContext::instance()->screenManager();
- const QWindowsScreen *newScreen = screenManager.screenForHwnd(m_data.hwnd);
- if (newScreen != nullptr && newScreen != currentScreen) {
- qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__
- << ' ' << window() << " \"" << currentScreen->name()
- << "\"->\"" << newScreen->name() << '"';
- setFlag(SynchronousGeometryChangeEvent);
- QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
+ const QWindowsScreen *newScreen =
+ QWindowsContext::instance()->screenManager().screenForHwnd(m_data.hwnd);
+ if (newScreen == nullptr || newScreen == currentScreen)
+ return;
+ // For screens with different DPI: postpone until WM_DPICHANGE
+ if (mode == FromGeometryChange
+ && !equalDpi(currentScreen->logicalDpi(), newScreen->logicalDpi())) {
+ return;
}
+ qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__
+ << ' ' << window() << " \"" << currentScreen->name()
+ << "\"->\"" << newScreen->name() << '"';
+ if (mode == FromGeometryChange)
+ setFlag(SynchronousGeometryChangeEvent);
+ updateFullFrameMargins();
+ QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
}
void QWindowsWindow::handleGeometryChange()
{
const QRect previousGeometry = m_data.geometry;
m_data.geometry = geometry_sys();
+ if (testFlag(WithinDpiChanged))
+ return; // QGuiApplication will send resize
QWindowSystemInterface::handleGeometryChange(window(), m_data.geometry);
// QTBUG-32121: OpenGL/normal windows (with exception of ANGLE) do not receive
// expose events when shrinking, synthesize.
@@ -1819,7 +1982,16 @@ void QWindowsBaseWindow::setGeometry_sys(const QRect &rect) const
windowPlacement.showCmd = windowPlacement.showCmd == SW_SHOWMINIMIZED ? SW_SHOWMINIMIZED : SW_HIDE;
result = SetWindowPlacement(hwnd, &windowPlacement);
} else {
- result = MoveWindow(hwnd, frameGeometry.x(), frameGeometry.y(),
+ int x = frameGeometry.x();
+ if (!window()->isTopLevel()) {
+ const HWND parentHandle = GetParent(hwnd);
+ if (isRtlLayout(parentHandle)) {
+ RECT rect;
+ GetClientRect(parentHandle, &rect);
+ x = rect.right - frameGeometry.width() - x;
+ }
+ }
+ result = MoveWindow(hwnd, x, frameGeometry.y(),
frameGeometry.width(), frameGeometry.height(), true);
}
qCDebug(lcQpaWindows) << '<' << __FUNCTION__ << window()
@@ -1835,8 +2007,11 @@ void QWindowsBaseWindow::setGeometry_sys(const QRect &rect) const
HDC QWindowsWindow::getDC()
{
- if (!m_hdc)
+ if (!m_hdc) {
m_hdc = GetDC(handle());
+ if (QGuiApplication::layoutDirection() == Qt::RightToLeft)
+ SetLayout(m_hdc, 0); // Clear RTL layout
+ }
return m_hdc;
}
@@ -1876,6 +2051,9 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message,
{
if (message == WM_ERASEBKGND) // Backing store - ignored.
return true;
+ // QTBUG-75455: Suppress WM_PAINT sent to invisible windows when setting WS_EX_LAYERED
+ if (!window()->isVisible() && (GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_LAYERED) != 0)
+ return false;
// Ignore invalid update bounding rectangles
RECT updateRect;
if (!GetUpdateRect(m_data.hwnd, &updateRect, FALSE))
@@ -2233,6 +2411,15 @@ void QWindowsWindow::setFullFrameMargins(const QMargins &newMargins)
}
}
+void QWindowsWindow::updateFullFrameMargins()
+{
+ // Normally obtained from WM_NCCALCSIZE
+ const auto systemMargins = testFlag(DisableNonClientScaling)
+ ? QWindowsGeometryHint::frameOnPrimaryScreen(m_data.hwnd)
+ : frameMargins_sys();
+ setFullFrameMargins(systemMargins + m_data.customMargins);
+}
+
QMargins QWindowsWindow::frameMargins() const
{
QMargins result = fullFrameMargins();
@@ -2443,10 +2630,8 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
{
// We don't apply the min/max size hint as we change the dpi, because we did not adjust the
// QScreen of the window yet so we don't have the min/max with the right ratio
- if (!testFlag(QWindowsWindow::WithinDpiChanged)) {
- const QWindowsGeometryHint hint(window(), m_data.customMargins);
- hint.applyToMinMaxInfo(m_data.hwnd, mmi);
- }
+ if (!testFlag(QWindowsWindow::WithinDpiChanged))
+ QWindowsGeometryHint::applyToMinMaxInfo(window(), fullFrameMargins(), mmi);
// This block fixes QTBUG-8361, QTBUG-4362: Frameless/title-less windows shouldn't cover the
// taskbar when maximized
@@ -2758,14 +2943,14 @@ void QWindowsWindow::invalidateSurface()
QVulkanInstance *inst = window()->vulkanInstance();
if (inst)
static_cast<QWindowsVulkanInstance *>(inst->handle())->destroySurface(m_vkSurface);
- m_vkSurface = 0;
+ m_vkSurface = VK_NULL_HANDLE;
}
#endif
#ifndef QT_NO_OPENGL
if (m_surface) {
if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext())
staticOpenGLContext->destroyWindowSurface(m_surface);
- m_surface = 0;
+ m_surface = nullptr;
}
#endif // QT_NO_OPENGL
}
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index 0d8096ddfa..7efbcf900c 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -59,24 +59,23 @@ class QDebug;
struct QWindowsGeometryHint
{
- QWindowsGeometryHint() = default;
- explicit QWindowsGeometryHint(const QWindow *w, const QMargins &customMargins);
- static QMargins frame(DWORD style, DWORD exStyle);
+ static QMargins frameOnPrimaryScreen(DWORD style, DWORD exStyle);
+ static QMargins frameOnPrimaryScreen(HWND hwnd);
+ static QMargins frame(DWORD style, DWORD exStyle, qreal dpi);
+ static QMargins frame(HWND hwnd, DWORD style, DWORD exStyle);
+ static QMargins frame(const QWindow *w, const QRect &geometry,
+ DWORD style, DWORD exStyle);
static bool handleCalculateSize(const QMargins &customMargins, const MSG &msg, LRESULT *result);
- void applyToMinMaxInfo(DWORD style, DWORD exStyle, MINMAXINFO *mmi) const;
- void applyToMinMaxInfo(HWND hwnd, MINMAXINFO *mmi) const;
- bool validSize(const QSize &s) const;
-
+ static void applyToMinMaxInfo(const QWindow *w, const QMargins &margins,
+ MINMAXINFO *mmi);
+ static void frameSizeConstraints(const QWindow *w, const QMargins &margins,
+ QSize *minimumSize, QSize *maximumSize);
static inline QPoint mapToGlobal(HWND hwnd, const QPoint &);
static inline QPoint mapToGlobal(const QWindow *w, const QPoint &);
static inline QPoint mapFromGlobal(const HWND hwnd, const QPoint &);
static inline QPoint mapFromGlobal(const QWindow *w, const QPoint &);
static bool positionIncludesFrame(const QWindow *w);
-
- QSize minimumSize;
- QSize maximumSize;
- QMargins customMargins;
};
struct QWindowCreationContext
@@ -85,16 +84,13 @@ struct QWindowCreationContext
const QRect &geometryIn, const QRect &geometry,
const QMargins &customMargins,
DWORD style, DWORD exStyle);
- void applyToMinMaxInfo(MINMAXINFO *mmi) const
- { geometryHint.applyToMinMaxInfo(style, exStyle, mmi); }
+ void applyToMinMaxInfo(MINMAXINFO *mmi) const;
- QWindowsGeometryHint geometryHint;
const QWindow *window;
- DWORD style;
- DWORD exStyle;
QRect requestedGeometryIn; // QWindow scaled
QRect requestedGeometry; // after QPlatformWindow::initialGeometry()
- QRect obtainedGeometry;
+ QPoint obtainedPos;
+ QSize obtainedSize;
QMargins margins;
QMargins customMargins; // User-defined, additional frame for WM_NCCALCSIZE
int frameX = CW_USEDEFAULT; // Passed on to CreateWindowEx(), including frame.
@@ -110,7 +106,7 @@ struct QWindowsWindowData
QRect geometry;
QMargins fullFrameMargins; // Do not use directly for windows, see FrameDirty.
QMargins customMargins; // User-defined, additional frame for NCCALCSIZE
- HWND hwnd = 0;
+ HWND hwnd = nullptr;
bool embedded = false;
bool hasFrame = false;
@@ -121,7 +117,7 @@ struct QWindowsWindowData
class QWindowsBaseWindow : public QPlatformWindow
{
- Q_DISABLE_COPY(QWindowsBaseWindow)
+ Q_DISABLE_COPY_MOVE(QWindowsBaseWindow)
public:
explicit QWindowsBaseWindow(QWindow *window) : QPlatformWindow(window) {}
@@ -139,6 +135,7 @@ public:
unsigned style() const { return GetWindowLongPtr(handle(), GWL_STYLE); }
unsigned exStyle() const { return GetWindowLongPtr(handle(), GWL_EXSTYLE); }
+ static bool isRtlLayout(HWND hwnd);
static QWindowsBaseWindow *baseWindowOf(const QWindow *w);
static HWND handleOf(const QWindow *w);
@@ -221,7 +218,8 @@ public:
HasBorderInFullScreen = 0x200000,
WithinDpiChanged = 0x400000,
VulkanSurface = 0x800000,
- ResizeMoveActive = 0x1000000
+ ResizeMoveActive = 0x1000000,
+ DisableNonClientScaling = 0x2000000
};
QWindowsWindow(QWindow *window, const QWindowsWindowData &data);
@@ -262,6 +260,7 @@ public:
QMargins frameMargins() const override;
QMargins fullFrameMargins() const override;
void setFullFrameMargins(const QMargins &newMargins);
+ void updateFullFrameMargins();
void setOpacity(qreal level) override;
void setMask(const QRegion &region) override;
@@ -337,7 +336,8 @@ public:
void alertWindow(int durationMs = 0);
void stopAlertWindow();
- void checkForScreenChanged();
+ enum ScreenChangeMode { FromGeometryChange, FromDpiChange };
+ void checkForScreenChanged(ScreenChangeMode mode = FromGeometryChange);
static void setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes);
void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch);
@@ -357,7 +357,7 @@ private:
inline void setParent_sys(const QPlatformWindow *parent);
inline void updateTransientParent() const;
void destroyWindow();
- inline bool isDropSiteEnabled() const { return m_dropTarget != 0; }
+ inline bool isDropSiteEnabled() const { return m_dropTarget != nullptr; }
void setDropSiteEnabled(bool enabled);
void updateDropSite(bool topLevel);
void handleGeometryChange();
@@ -368,7 +368,7 @@ private:
mutable QWindowsWindowData m_data;
QPointer<QWindowsMenuBar> m_menuBar;
mutable unsigned m_flags = WithinCreate;
- HDC m_hdc = 0;
+ HDC m_hdc = nullptr;
Qt::WindowStates m_windowState = Qt::WindowNoState;
qreal m_opacity = 1;
#ifndef QT_NO_CURSOR
@@ -378,15 +378,15 @@ private:
unsigned m_savedStyle = 0;
QRect m_savedFrameGeometry;
const QSurfaceFormat m_format;
- HICON m_iconSmall = 0;
- HICON m_iconBig = 0;
+ HICON m_iconSmall = nullptr;
+ HICON m_iconBig = nullptr;
void *m_surface = nullptr;
static bool m_screenForGLInitialized;
#if QT_CONFIG(vulkan)
// note: intentionally not using void * in order to avoid breaking x86
- VkSurfaceKHR m_vkSurface = 0;
+ VkSurfaceKHR m_vkSurface = VK_NULL_HANDLE;
#endif
static bool m_borderInFullScreenDefault;
};
@@ -401,18 +401,38 @@ QDebug operator<<(QDebug d, const WINDOWPOS &);
QDebug operator<<(QDebug d, const GUID &guid);
#endif // !QT_NO_DEBUG_STREAM
+static inline void clientToScreen(HWND hwnd, POINT *wP)
+{
+ if (QWindowsBaseWindow::isRtlLayout(hwnd)) {
+ RECT clientArea;
+ GetClientRect(hwnd, &clientArea);
+ wP->x = clientArea.right - wP->x;
+ }
+ ClientToScreen(hwnd, wP);
+}
+
+static inline void screenToClient(HWND hwnd, POINT *wP)
+{
+ ScreenToClient(hwnd, wP);
+ if (QWindowsBaseWindow::isRtlLayout(hwnd)) {
+ RECT clientArea;
+ GetClientRect(hwnd, &clientArea);
+ wP->x = clientArea.right - wP->x;
+ }
+}
+
// ---------- QWindowsGeometryHint inline functions.
QPoint QWindowsGeometryHint::mapToGlobal(HWND hwnd, const QPoint &qp)
{
POINT p = { qp.x(), qp.y() };
- ClientToScreen(hwnd, &p);
+ clientToScreen(hwnd, &p);
return QPoint(p.x, p.y);
}
QPoint QWindowsGeometryHint::mapFromGlobal(const HWND hwnd, const QPoint &qp)
{
POINT p = { qp.x(), qp.y() };
- ScreenToClient(hwnd, &p);
+ screenToClient(hwnd, &p);
return QPoint(p.x, p.y);
}
@@ -451,11 +471,11 @@ inline void QWindowsWindow::destroyIcon()
{
if (m_iconBig) {
DestroyIcon(m_iconBig);
- m_iconBig = 0;
+ m_iconBig = nullptr;
}
if (m_iconSmall) {
DestroyIcon(m_iconSmall);
- m_iconSmall = 0;
+ m_iconSmall = nullptr;
}
}
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h
index 9caa7d6898..a20df28e3f 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiabaseprovider.h
@@ -57,7 +57,7 @@ class QAccessibleInterface;
class QWindowsUiaBaseProvider : public QObject
{
Q_OBJECT
- Q_DISABLE_COPY(QWindowsUiaBaseProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaBaseProvider)
public:
explicit QWindowsUiaBaseProvider(QAccessible::Id id);
virtual ~QWindowsUiaBaseProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h
index 3d17056d38..3244122038 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagriditemprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaGridItemProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<IGridItemProvider>
{
- Q_DISABLE_COPY(QWindowsUiaGridItemProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaGridItemProvider)
public:
explicit QWindowsUiaGridItemProvider(QAccessible::Id id);
virtual ~QWindowsUiaGridItemProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h
index b96fc1a93c..0e5f81108e 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiagridprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaGridProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<IGridProvider>
{
- Q_DISABLE_COPY(QWindowsUiaGridProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaGridProvider)
public:
explicit QWindowsUiaGridProvider(QAccessible::Id id);
virtual ~QWindowsUiaGridProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h
index 5fb509c5f3..7d646894a1 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiainvokeprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaInvokeProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<IInvokeProvider>
{
- Q_DISABLE_COPY(QWindowsUiaInvokeProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaInvokeProvider)
public:
explicit QWindowsUiaInvokeProvider(QAccessible::Id id);
virtual ~QWindowsUiaInvokeProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
index 44328492a6..a427e553f0 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
@@ -52,6 +52,7 @@
#include "qwindowsuiatableitemprovider.h"
#include "qwindowsuiagridprovider.h"
#include "qwindowsuiagriditemprovider.h"
+#include "qwindowsuiawindowprovider.h"
#include "qwindowscombase.h"
#include "qwindowscontext.h"
#include "qwindowsuiautils.h"
@@ -263,6 +264,11 @@ HRESULT QWindowsUiaMainProvider::GetPatternProvider(PATTERNID idPattern, IUnknow
return UIA_E_ELEMENTNOTAVAILABLE;
switch (idPattern) {
+ case UIA_WindowPatternId:
+ if (accessible->parent() && (accessible->parent()->role() == QAccessible::Application)) {
+ *pRetVal = new QWindowsUiaWindowProvider(id());
+ }
+ break;
case UIA_TextPatternId:
case UIA_TextPattern2Id:
// All text controls.
@@ -352,8 +358,7 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR
if (!accessible)
return UIA_E_ELEMENTNOTAVAILABLE;
- bool clientTopLevel = (accessible->role() == QAccessible::Client)
- && accessible->parent() && (accessible->parent()->role() == QAccessible::Application);
+ bool topLevelWindow = accessible->parent() && (accessible->parent()->role() == QAccessible::Application);
switch (idProp) {
case UIA_ProcessIdPropertyId:
@@ -379,7 +384,7 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR
setVariantString(QStringLiteral("Qt"), pRetVal);
break;
case UIA_ControlTypePropertyId:
- if (clientTopLevel) {
+ if (topLevelWindow) {
// Reports a top-level widget as a window, instead of "custom".
setVariantI4(UIA_WindowControlTypeId, pRetVal);
} else {
@@ -391,10 +396,20 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR
setVariantString(accessible->text(QAccessible::Help), pRetVal);
break;
case UIA_HasKeyboardFocusPropertyId:
- setVariantBool(accessible->state().focused, pRetVal);
+ if (topLevelWindow) {
+ // Windows set the active state to true when they are focused
+ setVariantBool(accessible->state().active, pRetVal);
+ } else {
+ setVariantBool(accessible->state().focused, pRetVal);
+ }
break;
case UIA_IsKeyboardFocusablePropertyId:
- setVariantBool(accessible->state().focusable, pRetVal);
+ if (topLevelWindow) {
+ // Windows should always be focusable
+ setVariantBool(true, pRetVal);
+ } else {
+ setVariantBool(accessible->state().focusable, pRetVal);
+ }
break;
case UIA_IsOffscreenPropertyId:
setVariantBool(accessible->state().offscreen, pRetVal);
@@ -424,7 +439,7 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR
break;
case UIA_NamePropertyId: {
QString name = accessible->text(QAccessible::Name);
- if (name.isEmpty() && clientTopLevel)
+ if (name.isEmpty() && topLevelWindow)
name = QCoreApplication::applicationName();
setVariantString(name, pRetVal);
break;
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
index df0d60f9c9..cdc239ed99 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
@@ -60,7 +60,7 @@ class QWindowsUiaMainProvider :
public IRawElementProviderFragmentRoot
{
Q_OBJECT
- Q_DISABLE_COPY(QWindowsUiaMainProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaMainProvider)
public:
static QWindowsUiaMainProvider *providerForAccessible(QAccessibleInterface *accessible);
explicit QWindowsUiaMainProvider(QAccessibleInterface *a, int initialRefCount = 1);
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h
index c5e0a03ee5..fc82d3a2cc 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiarangevalueprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaRangeValueProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<IRangeValueProvider>
{
- Q_DISABLE_COPY(QWindowsUiaRangeValueProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaRangeValueProvider)
public:
explicit QWindowsUiaRangeValueProvider(QAccessible::Id id);
virtual ~QWindowsUiaRangeValueProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h
index 1f2605188b..4b59c4e40f 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionitemprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaSelectionItemProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<ISelectionItemProvider>
{
- Q_DISABLE_COPY(QWindowsUiaSelectionItemProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaSelectionItemProvider)
public:
explicit QWindowsUiaSelectionItemProvider(QAccessible::Id id);
virtual ~QWindowsUiaSelectionItemProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h
index 0376d25804..ee1044ec7a 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaselectionprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaSelectionProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<ISelectionProvider>
{
- Q_DISABLE_COPY(QWindowsUiaSelectionProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaSelectionProvider)
public:
explicit QWindowsUiaSelectionProvider(QAccessible::Id id);
virtual ~QWindowsUiaSelectionProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h
index bf4b52ee0b..9804c35f8e 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableitemprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaTableItemProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<ITableItemProvider>
{
- Q_DISABLE_COPY(QWindowsUiaTableItemProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaTableItemProvider)
public:
explicit QWindowsUiaTableItemProvider(QAccessible::Id id);
virtual ~QWindowsUiaTableItemProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h
index 94c8ab93a7..a8b16035ec 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatableprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaTableProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<ITableProvider>
{
- Q_DISABLE_COPY(QWindowsUiaTableProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaTableProvider)
public:
explicit QWindowsUiaTableProvider(QAccessible::Id id);
virtual ~QWindowsUiaTableProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h
index a9be70fa16..ffab48b0e8 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.h
@@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaTextProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<ITextProvider2>
{
- Q_DISABLE_COPY(QWindowsUiaTextProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaTextProvider)
public:
explicit QWindowsUiaTextProvider(QAccessible::Id id);
~QWindowsUiaTextProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h
index 39b9069fc0..3b4ec63ceb 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaTextRangeProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<ITextRangeProvider>
{
- Q_DISABLE_COPY(QWindowsUiaTextRangeProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaTextRangeProvider)
public:
explicit QWindowsUiaTextRangeProvider(QAccessible::Id id, int startOffset, int endOffset);
virtual ~QWindowsUiaTextRangeProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h
index 2bed6f7e36..892b635b41 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatoggleprovider.h
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaToggleProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<IToggleProvider>
{
- Q_DISABLE_COPY(QWindowsUiaToggleProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaToggleProvider)
public:
explicit QWindowsUiaToggleProvider(QAccessible::Id id);
virtual ~QWindowsUiaToggleProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h
index 334a17e51d..3edfe7a08b 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiavalueprovider.h
@@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE
class QWindowsUiaValueProvider : public QWindowsUiaBaseProvider,
public QWindowsComBase<IValueProvider>
{
- Q_DISABLE_COPY(QWindowsUiaValueProvider)
+ Q_DISABLE_COPY_MOVE(QWindowsUiaValueProvider)
public:
explicit QWindowsUiaValueProvider(QAccessible::Id id);
virtual ~QWindowsUiaValueProvider();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiawindowprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiawindowprovider.cpp
new file mode 100644
index 0000000000..3738aa72ff
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiawindowprovider.cpp
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwindowsuiawindowprovider.h"
+#include "qwindowsuiautils.h"
+#include "qwindowscontext.h"
+
+#include <QtGui/qaccessible.h>
+#include <QtGui/private/qwindow_p.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qstring.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QWindowsUiAutomation;
+
+
+QWindowsUiaWindowProvider::QWindowsUiaWindowProvider(QAccessible::Id id) :
+ QWindowsUiaBaseProvider(id)
+{
+}
+
+QWindowsUiaWindowProvider::~QWindowsUiaWindowProvider()
+{
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaWindowProvider::SetVisualState(WindowVisualState state) {
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible || !accessible->window())
+ return UIA_E_ELEMENTNOTAVAILABLE;
+ auto window = accessible->window();
+ switch (state) {
+ case WindowVisualState_Normal:
+ window->showNormal();
+ break;
+ case WindowVisualState_Maximized:
+ window->showMaximized();
+ break;
+ case WindowVisualState_Minimized:
+ window->showMinimized();
+ break;
+ }
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaWindowProvider::Close() {
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible || !accessible->window())
+ return UIA_E_ELEMENTNOTAVAILABLE;
+ accessible->window()->close();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaWindowProvider::WaitForInputIdle(int milliseconds, __RPC__out BOOL *pRetVal) {
+ Q_UNUSED(milliseconds);
+ Q_UNUSED(pRetVal);
+ return UIA_E_NOTSUPPORTED;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaWindowProvider::get_CanMaximize(__RPC__out BOOL *pRetVal) {
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible || !accessible->window())
+ return UIA_E_ELEMENTNOTAVAILABLE;
+
+ auto window = accessible->window();
+ auto flags = window->flags();
+
+ *pRetVal = (!(flags & Qt::MSWindowsFixedSizeDialogHint)
+ && (flags & Qt::WindowMaximizeButtonHint)
+ && ((flags & Qt::CustomizeWindowHint)
+ || window->maximumSize() == QSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX)));
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaWindowProvider::get_CanMinimize(__RPC__out BOOL *pRetVal) {
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible || !accessible->window())
+ return UIA_E_ELEMENTNOTAVAILABLE;
+ *pRetVal = accessible->window()->flags() & Qt::WindowMinimizeButtonHint;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaWindowProvider::get_IsModal(__RPC__out BOOL *pRetVal) {
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible || !accessible->window())
+ return UIA_E_ELEMENTNOTAVAILABLE;
+ *pRetVal = accessible->window()->isModal();
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaWindowProvider::get_WindowVisualState(__RPC__out enum WindowVisualState *pRetVal) {
+ qCDebug(lcQpaUiAutomation) << __FUNCTION__;
+ QAccessibleInterface *accessible = accessibleInterface();
+ if (!accessible || !accessible->window())
+ return UIA_E_ELEMENTNOTAVAILABLE;
+ auto visibility = accessible->window()->visibility();
+ switch (visibility) {
+ case QWindow::FullScreen:
+ case QWindow::Maximized:
+ *pRetVal = WindowVisualState_Maximized;
+ break;
+ case QWindow::Minimized:
+ *pRetVal = WindowVisualState_Minimized;
+ break;
+ default:
+ *pRetVal = WindowVisualState_Normal;
+ break;
+ }
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaWindowProvider::get_WindowInteractionState(__RPC__out enum WindowInteractionState *pRetVal) {
+ Q_UNUSED(pRetVal);
+ return UIA_E_NOTSUPPORTED;
+}
+
+HRESULT STDMETHODCALLTYPE QWindowsUiaWindowProvider::get_IsTopmost(__RPC__out BOOL *pRetVal) {
+ Q_UNUSED(pRetVal);
+ return UIA_E_NOTSUPPORTED;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiawindowprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiawindowprovider.h
new file mode 100644
index 0000000000..343fb275f7
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiawindowprovider.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSUIAWINDOWPROVIDER_H
+#define QWINDOWSUIAWINDOWPROVIDER_H
+
+#include <QtGui/qtguiglobal.h>
+#if QT_CONFIG(accessibility)
+
+#include "qwindowsuiabaseprovider.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsUiaWindowProvider : public QWindowsUiaBaseProvider,
+ public QWindowsComBase<IWindowProvider>
+{
+ Q_DISABLE_COPY(QWindowsUiaWindowProvider)
+public:
+ explicit QWindowsUiaWindowProvider(QAccessible::Id id);
+ ~QWindowsUiaWindowProvider() override;
+
+ HRESULT STDMETHODCALLTYPE SetVisualState(WindowVisualState state) override;
+ HRESULT STDMETHODCALLTYPE Close( void) override;
+ HRESULT STDMETHODCALLTYPE WaitForInputIdle(int milliseconds, __RPC__out BOOL *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_CanMaximize(__RPC__out BOOL *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_CanMinimize(__RPC__out BOOL *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_IsModal(__RPC__out BOOL *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_WindowVisualState(__RPC__out WindowVisualState *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_WindowInteractionState(__RPC__out WindowInteractionState *pRetVal) override;
+ HRESULT STDMETHODCALLTYPE get_IsTopmost(__RPC__out BOOL *pRetVal) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(accessibility)
+
+#endif // QWINDOWSUIAWINDOWPROVIDER_H
diff --git a/src/plugins/platforms/windows/uiautomation/uiautomation.pri b/src/plugins/platforms/windows/uiautomation/uiautomation.pri
index b79e42cdec..ee9332e7ea 100644
--- a/src/plugins/platforms/windows/uiautomation/uiautomation.pri
+++ b/src/plugins/platforms/windows/uiautomation/uiautomation.pri
@@ -18,6 +18,7 @@ SOURCES += \
$$PWD/qwindowsuiatableitemprovider.cpp \
$$PWD/qwindowsuiagridprovider.cpp \
$$PWD/qwindowsuiagriditemprovider.cpp \
+ $$PWD/qwindowsuiawindowprovider.cpp \
$$PWD/qwindowsuiautils.cpp
HEADERS += \
@@ -37,6 +38,7 @@ HEADERS += \
$$PWD/qwindowsuiatableitemprovider.h \
$$PWD/qwindowsuiagridprovider.h \
$$PWD/qwindowsuiagriditemprovider.h \
+ $$PWD/qwindowsuiawindowprovider.h \
$$PWD/qwindowsuiautils.h
mingw: QMAKE_USE *= uuid