mirror of
https://github.com/GerbilSoft/rvthtool.git
synced 2025-06-18 11:35:33 -04:00

This is a diff between qtbase-6.8.3 upstream and the version from: https://github.com/crystalidea/qt6windows7
2630 lines
112 KiB
Diff
Vendored
2630 lines
112 KiB
Diff
Vendored
Source: https://github.com/crystalidea/qt6windows7
|
|
Release 6.8.3
|
|
|
|
diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp
|
|
index 805ce65a5ac..6ed351d2e82 100644
|
|
--- a/src/corelib/io/qstandardpaths_win.cpp
|
|
+++ b/src/corelib/io/qstandardpaths_win.cpp
|
|
@@ -12,6 +12,7 @@
|
|
|
|
#include <qt_windows.h>
|
|
#include <shlobj.h>
|
|
+#include <versionhelpers.h>
|
|
#include <intshcut.h>
|
|
#include <qvarlengtharray.h>
|
|
|
|
@@ -60,20 +61,26 @@ static inline void appendTestMode(QString &path)
|
|
|
|
static bool isProcessLowIntegrity()
|
|
{
|
|
+ if (!IsWindows8OrGreater())
|
|
+ return false;
|
|
+
|
|
// same as GetCurrentProcessToken()
|
|
const auto process_token = HANDLE(quintptr(-4));
|
|
|
|
QVarLengthArray<char,256> token_info_buf(256);
|
|
auto* token_info = reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_info_buf.data());
|
|
DWORD token_info_length = token_info_buf.size();
|
|
- if (!GetTokenInformation(process_token, TokenIntegrityLevel, token_info, token_info_length, &token_info_length)) {
|
|
+ if (!GetTokenInformation(process_token, TokenIntegrityLevel, token_info, token_info_length, &token_info_length)
|
|
+ && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
|
// grow buffer and retry GetTokenInformation
|
|
token_info_buf.resize(token_info_length);
|
|
token_info = reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_info_buf.data());
|
|
if (!GetTokenInformation(process_token, TokenIntegrityLevel, token_info, token_info_length, &token_info_length))
|
|
return false; // assume "normal" process
|
|
}
|
|
-
|
|
+ else
|
|
+ return false;
|
|
+
|
|
// The GetSidSubAuthorityCount return-code is undefined on failure, so
|
|
// there's no point in checking before dereferencing
|
|
DWORD integrity_level = *GetSidSubAuthority(token_info->Label.Sid, *GetSidSubAuthorityCount(token_info->Label.Sid) - 1);
|
|
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
|
|
index a7663b24813..8459cd5cad0 100644
|
|
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
|
|
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
|
|
@@ -360,10 +360,15 @@ void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t)
|
|
ok = t->fastTimerId;
|
|
}
|
|
|
|
- if (!ok) {
|
|
+ typedef BOOL (WINAPI *SetCoalescableTimerFunc) (HWND, UINT_PTR, UINT, TIMERPROC, ULONG);
|
|
+ static SetCoalescableTimerFunc mySetCoalescableTimerFunc =
|
|
+ (SetCoalescableTimerFunc)::GetProcAddress(::GetModuleHandle(L"User32"), "SetCoalescableTimer");
|
|
+
|
|
+ if (!ok && mySetCoalescableTimerFunc) {
|
|
// user normal timers for (Very)CoarseTimers, or if no more multimedia timers available
|
|
- ok = SetCoalescableTimer(internalHwnd, t->timerId, interval, nullptr, tolerance);
|
|
+ ok = mySetCoalescableTimerFunc(internalHwnd, t->timerId, interval, nullptr, tolerance);
|
|
}
|
|
+
|
|
if (!ok)
|
|
ok = SetTimer(internalHwnd, t->timerId, interval, nullptr);
|
|
|
|
diff --git a/src/corelib/kernel/qfunctions_win.cpp b/src/corelib/kernel/qfunctions_win.cpp
|
|
index 048fdbc934c..e715093d27b 100644
|
|
--- a/src/corelib/kernel/qfunctions_win.cpp
|
|
+++ b/src/corelib/kernel/qfunctions_win.cpp
|
|
@@ -44,10 +44,17 @@ QComHelper::~QComHelper()
|
|
*/
|
|
bool qt_win_hasPackageIdentity()
|
|
{
|
|
+ typedef BOOL (WINAPI *GetCurrentPackageFullNameFunc) (UINT32 *, PWSTR);
|
|
+ static GetCurrentPackageFullNameFunc myGetCurrentPackageFullName =
|
|
+ (GetCurrentPackageFullNameFunc)::GetProcAddress(::GetModuleHandle(L"kernel32"), "GetCurrentPackageFullName");
|
|
+
|
|
+ if (myGetCurrentPackageFullName)
|
|
+ {
|
|
#if defined(HAS_APPMODEL)
|
|
+
|
|
static const bool hasPackageIdentity = []() {
|
|
UINT32 length = 0;
|
|
- switch (const auto result = GetCurrentPackageFullName(&length, nullptr)) {
|
|
+ switch (const auto result = myGetCurrentPackageFullName(&length, nullptr)) {
|
|
case ERROR_INSUFFICIENT_BUFFER:
|
|
return true;
|
|
case APPMODEL_ERROR_NO_PACKAGE:
|
|
@@ -61,6 +68,9 @@ bool qt_win_hasPackageIdentity()
|
|
#else
|
|
return false;
|
|
#endif
|
|
+ }
|
|
+
|
|
+ return false;
|
|
}
|
|
|
|
QT_END_NAMESPACE
|
|
diff --git a/src/corelib/thread/qfutex_p.h b/src/corelib/thread/qfutex_p.h
|
|
index 8ba798f9209..f6a8dda6b81 100644
|
|
--- a/src/corelib/thread/qfutex_p.h
|
|
+++ b/src/corelib/thread/qfutex_p.h
|
|
@@ -40,8 +40,8 @@ QT_END_NAMESPACE
|
|
#elif defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
|
|
// use Linux mutexes everywhere except for LSB builds
|
|
# include "qfutex_linux_p.h"
|
|
-#elif defined(Q_OS_WIN)
|
|
-# include "qfutex_win_p.h"
|
|
+//#elif defined(Q_OS_WIN)
|
|
+//# include "qfutex_win_p.h"
|
|
#else
|
|
QT_BEGIN_NAMESPACE
|
|
namespace QtFutex = QtDummyFutex;
|
|
diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp
|
|
index 1b8f76f1230..9e2fe83968c 100644
|
|
--- a/src/corelib/thread/qmutex.cpp
|
|
+++ b/src/corelib/thread/qmutex.cpp
|
|
@@ -915,6 +915,8 @@ QT_END_NAMESPACE
|
|
// nothing
|
|
#elif defined(Q_OS_DARWIN)
|
|
# include "qmutex_mac.cpp"
|
|
+#elif defined(Q_OS_WIN)
|
|
+# include "qmutex_win.cpp"
|
|
#else
|
|
# include "qmutex_unix.cpp"
|
|
#endif
|
|
diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h
|
|
index aabb66fa550..a16d5082154 100644
|
|
--- a/src/corelib/thread/qmutex_p.h
|
|
+++ b/src/corelib/thread/qmutex_p.h
|
|
@@ -86,6 +86,8 @@ public:
|
|
semaphore_t mach_semaphore;
|
|
#elif defined(Q_OS_UNIX)
|
|
sem_t semaphore;
|
|
+#elif defined(Q_OS_WIN)
|
|
+ Qt::HANDLE event;
|
|
#endif
|
|
};
|
|
|
|
diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp
|
|
new file mode 100644
|
|
index 00000000000..9186f89a341
|
|
--- /dev/null
|
|
+++ b/src/corelib/thread/qmutex_win.cpp
|
|
@@ -0,0 +1,30 @@
|
|
+// Copyright (C) 2016 The Qt Company Ltd.
|
|
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
|
+
|
|
+#include "qmutex.h"
|
|
+#include <qatomic.h>
|
|
+#include "qmutex_p.h"
|
|
+#include <qt_windows.h>
|
|
+
|
|
+QT_BEGIN_NAMESPACE
|
|
+
|
|
+QMutexPrivate::QMutexPrivate()
|
|
+{
|
|
+ event = CreateEvent(0, FALSE, FALSE, 0);
|
|
+
|
|
+ if (!event)
|
|
+ qWarning("QMutexPrivate::QMutexPrivate: Cannot create event");
|
|
+}
|
|
+
|
|
+QMutexPrivate::~QMutexPrivate()
|
|
+{ CloseHandle(event); }
|
|
+
|
|
+bool QMutexPrivate::wait(QDeadlineTimer timeout)
|
|
+{
|
|
+ return (WaitForSingleObjectEx(event, timeout.isForever() ? INFINITE : timeout.remainingTime(), FALSE) == WAIT_OBJECT_0);
|
|
+}
|
|
+
|
|
+void QMutexPrivate::wakeUp() noexcept
|
|
+{ SetEvent(event); }
|
|
+
|
|
+QT_END_NAMESPACE
|
|
\ No newline at end of file
|
|
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
|
|
index 88ba6dc8f62..c544d972f68 100644
|
|
--- a/src/corelib/thread/qthread_win.cpp
|
|
+++ b/src/corelib/thread/qthread_win.cpp
|
|
@@ -227,6 +227,62 @@ DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID)
|
|
return 0;
|
|
}
|
|
|
|
+#ifndef Q_OS_WIN64
|
|
+# define ULONG_PTR DWORD
|
|
+#endif
|
|
+
|
|
+typedef struct tagTHREADNAME_INFO
|
|
+{
|
|
+ DWORD dwType; // must be 0x1000
|
|
+ LPCSTR szName; // pointer to name (in user addr space)
|
|
+ HANDLE dwThreadID; // thread ID (-1=caller thread)
|
|
+ DWORD dwFlags; // reserved for future use, must be zero
|
|
+} THREADNAME_INFO;
|
|
+
|
|
+typedef HRESULT(WINAPI* SetThreadDescriptionFunc)(HANDLE, PCWSTR);
|
|
+
|
|
+#if defined(Q_CC_MSVC)
|
|
+
|
|
+// Helper function to set the thread name using RaiseException and __try
|
|
+static void setThreadNameUsingException(HANDLE threadId, LPCSTR threadName) {
|
|
+ THREADNAME_INFO info;
|
|
+ info.dwType = 0x1000;
|
|
+ info.szName = threadName;
|
|
+ info.dwThreadID = threadId;
|
|
+ info.dwFlags = 0;
|
|
+
|
|
+ __try {
|
|
+ RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD),
|
|
+ reinterpret_cast<const ULONG_PTR*>(&info));
|
|
+ }
|
|
+ __except (EXCEPTION_CONTINUE_EXECUTION) {
|
|
+ }
|
|
+}
|
|
+
|
|
+#endif // Q_CC_MSVC
|
|
+
|
|
+void qt_set_thread_name(HANDLE threadId, const QString &name)
|
|
+{
|
|
+ HMODULE hKernel32 = GetModuleHandleW(L"Kernel32.dll");
|
|
+
|
|
+ SetThreadDescriptionFunc pSetThreadDescription =
|
|
+ reinterpret_cast<SetThreadDescriptionFunc>(GetProcAddress(hKernel32, "SetThreadDescription"));
|
|
+
|
|
+ if (pSetThreadDescription) {
|
|
+ pSetThreadDescription(threadId, reinterpret_cast<const wchar_t *>(name.utf16()) );
|
|
+ }
|
|
+ else {
|
|
+
|
|
+ #if defined(Q_CC_MSVC)
|
|
+
|
|
+ std::string stdStr = name.toStdString();
|
|
+ LPCSTR threadName = stdStr.c_str();
|
|
+ setThreadNameUsingException(threadId, threadName);
|
|
+
|
|
+ #endif // Q_CC_MSVC
|
|
+ }
|
|
+}
|
|
+
|
|
/**************************************************************************
|
|
** QThreadPrivate
|
|
*************************************************************************/
|
|
@@ -264,7 +320,7 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
|
|
QString threadName = std::exchange(thr->d_func()->objectName, {});
|
|
if (Q_LIKELY(threadName.isEmpty()))
|
|
threadName = QString::fromUtf8(thr->metaObject()->className());
|
|
- SetThreadDescription(GetCurrentThread(), reinterpret_cast<const wchar_t *>(threadName.utf16()));
|
|
+ qt_set_thread_name(GetCurrentThread(), threadName);
|
|
|
|
emit thr->started(QThread::QPrivateSignal());
|
|
QThread::setTerminationEnabled(true);
|
|
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
|
|
index 9e2e0c4e81c..eae05a0e61a 100644
|
|
--- a/src/gui/rhi/qrhid3d11.cpp
|
|
+++ b/src/gui/rhi/qrhid3d11.cpp
|
|
@@ -12,6 +12,8 @@
|
|
|
|
#include <cstdio>
|
|
|
|
+#include <versionhelpers.h>
|
|
+
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
using namespace Qt::StringLiterals;
|
|
@@ -184,13 +186,22 @@ inline Int aligned(Int v, Int byteAlign)
|
|
|
|
static IDXGIFactory1 *createDXGIFactory2()
|
|
{
|
|
+ typedef HRESULT(WINAPI* CreateDXGIFactory2Func) (UINT flags, REFIID riid, void** factory);
|
|
+ static CreateDXGIFactory2Func myCreateDXGIFactory2 =
|
|
+ (CreateDXGIFactory2Func)::GetProcAddress(::GetModuleHandle(L"dxgi"), "CreateDXGIFactory2");
|
|
+
|
|
IDXGIFactory1 *result = nullptr;
|
|
- const HRESULT hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&result));
|
|
- if (FAILED(hr)) {
|
|
- qWarning("CreateDXGIFactory2() failed to create DXGI factory: %s",
|
|
- qPrintable(QSystemError::windowsComString(hr)));
|
|
- result = nullptr;
|
|
+
|
|
+ if (myCreateDXGIFactory2)
|
|
+ {
|
|
+ const HRESULT hr = myCreateDXGIFactory2(0, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&result));
|
|
+ if (FAILED(hr)) {
|
|
+ qWarning("CreateDXGIFactory2() failed to create DXGI factory: %s",
|
|
+ qPrintable(QSystemError::windowsComString(hr)));
|
|
+ result = nullptr;
|
|
+ }
|
|
}
|
|
+
|
|
return result;
|
|
}
|
|
|
|
@@ -5103,6 +5114,15 @@ static const DXGI_FORMAT DEFAULT_SRGB_FORMAT = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
|
|
|
bool QD3D11SwapChain::createOrResize()
|
|
{
|
|
+ if (IsWindows10OrGreater())
|
|
+ {
|
|
+ // continue
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ return createOrResizeWin7();
|
|
+ }
|
|
+
|
|
// Can be called multiple times due to window resizes - that is not the
|
|
// same as a simple destroy+create (as with other resources). Just need to
|
|
// resize the buffers then.
|
|
@@ -5427,4 +5447,9 @@ bool QD3D11SwapChain::createOrResize()
|
|
return true;
|
|
}
|
|
|
|
+bool QD3D11SwapChain::createOrResizeWin7()
|
|
+{
|
|
+ return false; // not implemented yet ;(
|
|
+}
|
|
+
|
|
QT_END_NAMESPACE
|
|
diff --git a/src/gui/rhi/qrhid3d11_p.h b/src/gui/rhi/qrhid3d11_p.h
|
|
index 44ad7017d9f..7f232f1ae9c 100644
|
|
--- a/src/gui/rhi/qrhid3d11_p.h
|
|
+++ b/src/gui/rhi/qrhid3d11_p.h
|
|
@@ -596,6 +596,7 @@ struct QD3D11SwapChain : public QRhiSwapChain
|
|
|
|
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
|
|
bool createOrResize() override;
|
|
+ bool createOrResizeWin7();
|
|
|
|
void releaseBuffers();
|
|
bool newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc,
|
|
diff --git a/src/gui/rhi/qrhid3d12.cpp b/src/gui/rhi/qrhid3d12.cpp
|
|
index 0662c53ed65..1039914d57f 100644
|
|
--- a/src/gui/rhi/qrhid3d12.cpp
|
|
+++ b/src/gui/rhi/qrhid3d12.cpp
|
|
@@ -203,19 +203,35 @@ static inline QD3D12RenderTargetData *rtData(QRhiRenderTarget *rt)
|
|
|
|
bool QRhiD3D12::create(QRhi::Flags flags)
|
|
{
|
|
+ typedef HRESULT(WINAPI* CreateDXGIFactory2Func) (UINT flags, REFIID riid, void** factory);
|
|
+ typedef HRESULT(WINAPI* D3D12CreateDeviceFunc) (IUnknown *, D3D_FEATURE_LEVEL, REFIID, void **);
|
|
+ typedef HRESULT(WINAPI* D3D12GetDebugInterfaceFunc) (REFIID, void **);
|
|
+
|
|
+ static CreateDXGIFactory2Func myCreateDXGIFactory2 =
|
|
+ (CreateDXGIFactory2Func)::GetProcAddress(::GetModuleHandle(L"dxgi"), "CreateDXGIFactory2");
|
|
+
|
|
+ static D3D12CreateDeviceFunc myD3D12CreateDevice =
|
|
+ (D3D12CreateDeviceFunc)::GetProcAddress(::GetModuleHandle(L"D3d12"), "D3D12CreateDevice");
|
|
+
|
|
+ static D3D12GetDebugInterfaceFunc myD3D12GetDebugInterface =
|
|
+ (D3D12GetDebugInterfaceFunc)::GetProcAddress(::GetModuleHandle(L"D3d12"), "D3D12GetDebugInterface");
|
|
+
|
|
+ if (!myCreateDXGIFactory2 || !myD3D12CreateDevice || !myD3D12GetDebugInterface)
|
|
+ return false;
|
|
+
|
|
rhiFlags = flags;
|
|
|
|
UINT factoryFlags = 0;
|
|
if (debugLayer)
|
|
factoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
|
|
- HRESULT hr = CreateDXGIFactory2(factoryFlags, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&dxgiFactory));
|
|
+ HRESULT hr = myCreateDXGIFactory2(factoryFlags, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&dxgiFactory));
|
|
if (FAILED(hr)) {
|
|
// retry without debug, if it was requested (to match D3D11 backend behavior)
|
|
if (debugLayer) {
|
|
qCDebug(QRHI_LOG_INFO, "Debug layer was requested but is not available. "
|
|
"Attempting to create DXGIFactory2 without it.");
|
|
factoryFlags &= ~DXGI_CREATE_FACTORY_DEBUG;
|
|
- hr = CreateDXGIFactory2(factoryFlags, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&dxgiFactory));
|
|
+ hr = myCreateDXGIFactory2(factoryFlags, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&dxgiFactory));
|
|
}
|
|
if (SUCCEEDED(hr)) {
|
|
debugLayer = false;
|
|
@@ -242,7 +258,7 @@ bool QRhiD3D12::create(QRhi::Flags flags)
|
|
|
|
if (debugLayer) {
|
|
ID3D12Debug1 *debug = nullptr;
|
|
- if (SUCCEEDED(D3D12GetDebugInterface(__uuidof(ID3D12Debug1), reinterpret_cast<void **>(&debug)))) {
|
|
+ if (SUCCEEDED(myD3D12GetDebugInterface(__uuidof(ID3D12Debug1), reinterpret_cast<void **>(&debug)))) {
|
|
qCDebug(QRHI_LOG_INFO, "Enabling D3D12 debug layer");
|
|
debug->EnableDebugLayer();
|
|
debug->Release();
|
|
@@ -310,7 +326,7 @@ bool QRhiD3D12::create(QRhi::Flags flags)
|
|
if (minimumFeatureLevel == 0)
|
|
minimumFeatureLevel = MIN_FEATURE_LEVEL;
|
|
|
|
- hr = D3D12CreateDevice(activeAdapter,
|
|
+ hr = myD3D12CreateDevice(activeAdapter,
|
|
minimumFeatureLevel,
|
|
__uuidof(ID3D12Device2),
|
|
reinterpret_cast<void **>(&dev));
|
|
@@ -2762,6 +2778,9 @@ QD3D12Descriptor QD3D12SamplerManager::getShaderVisibleDescriptor(const D3D12_SA
|
|
return descriptor;
|
|
}
|
|
|
|
+typedef HRESULT(WINAPI* D3D12SerializeVersionedRootSignatureFunc) (const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *, ID3DBlob **, ID3DBlob **);
|
|
+D3D12SerializeVersionedRootSignatureFunc myD3D12SerializeVersionedRootSignature = nullptr;
|
|
+
|
|
bool QD3D12MipmapGenerator::create(QRhiD3D12 *rhiD)
|
|
{
|
|
this->rhiD = rhiD;
|
|
@@ -2807,8 +2826,15 @@ bool QD3D12MipmapGenerator::create(QRhiD3D12 *rhiD)
|
|
rsDesc.Desc_1_1.NumStaticSamplers = 1;
|
|
rsDesc.Desc_1_1.pStaticSamplers = &samplerDesc;
|
|
|
|
+ if (!myD3D12SerializeVersionedRootSignature)
|
|
+ myD3D12SerializeVersionedRootSignature =
|
|
+ (D3D12SerializeVersionedRootSignatureFunc)::GetProcAddress(::GetModuleHandle(L"D3d12"), "D3D12SerializeVersionedRootSignature");
|
|
+
|
|
+ if (!myD3D12SerializeVersionedRootSignature)
|
|
+ return false;
|
|
+
|
|
ID3DBlob *signature = nullptr;
|
|
- HRESULT hr = D3D12SerializeVersionedRootSignature(&rsDesc, &signature, nullptr);
|
|
+ HRESULT hr = myD3D12SerializeVersionedRootSignature(&rsDesc, &signature, nullptr);
|
|
if (FAILED(hr)) {
|
|
qWarning("Failed to serialize root signature: %s", qPrintable(QSystemError::windowsComString(hr)));
|
|
return false;
|
|
@@ -4219,7 +4245,7 @@ bool QD3D12Texture::prepareCreate(QSize *adjustedSize)
|
|
else
|
|
srvFormat = toD3DTextureFormat(m_readViewFormat.format, m_readViewFormat.srgb ? sRGB : Flags());
|
|
}
|
|
-
|
|
+
|
|
mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
|
|
sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount, dxgiFormat);
|
|
if (sampleDesc.Count > 1) {
|
|
@@ -5001,6 +5027,9 @@ QD3D12ObjectHandle QD3D12ShaderResourceBindings::createRootSignature(const QD3D1
|
|
{
|
|
QRHI_RES_RHI(QRhiD3D12);
|
|
|
|
+ if (!myD3D12SerializeVersionedRootSignature)
|
|
+ return {};
|
|
+
|
|
// It's not just that the root signature has to be tied to the pipeline
|
|
// (cannot just freely create it like e.g. with Vulkan where one just
|
|
// creates a descriptor layout 1:1 with the QRhiShaderResourceBindings'
|
|
@@ -5085,7 +5114,7 @@ QD3D12ObjectHandle QD3D12ShaderResourceBindings::createRootSignature(const QD3D1
|
|
rsDesc.Desc_1_1.Flags = D3D12_ROOT_SIGNATURE_FLAGS(rsFlags);
|
|
|
|
ID3DBlob *signature = nullptr;
|
|
- HRESULT hr = D3D12SerializeVersionedRootSignature(&rsDesc, &signature, nullptr);
|
|
+ HRESULT hr = myD3D12SerializeVersionedRootSignature(&rsDesc, &signature, nullptr);
|
|
if (FAILED(hr)) {
|
|
qWarning("Failed to serialize root signature: %s", qPrintable(QSystemError::windowsComString(hr)));
|
|
return {};
|
|
diff --git a/src/gui/text/windows/qwindowsfontdatabasebase.cpp b/src/gui/text/windows/qwindowsfontdatabasebase.cpp
|
|
index 84e619b0d93..e751d4b1fb7 100644
|
|
--- a/src/gui/text/windows/qwindowsfontdatabasebase.cpp
|
|
+++ b/src/gui/text/windows/qwindowsfontdatabasebase.cpp
|
|
@@ -715,7 +715,16 @@ QFont QWindowsFontDatabaseBase::systemDefaultFont()
|
|
// Qt 6: Obtain default GUI font (typically "Segoe UI, 9pt", see QTBUG-58610)
|
|
NONCLIENTMETRICS ncm = {};
|
|
ncm.cbSize = sizeof(ncm);
|
|
- SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0, defaultVerticalDPI());
|
|
+
|
|
+ typedef BOOL (WINAPI *SystemParametersInfoForDpiFunc) (UINT, UINT, PVOID, UINT, UINT);
|
|
+ static SystemParametersInfoForDpiFunc mySystemParametersInfoForDpi =
|
|
+ (SystemParametersInfoForDpiFunc)::GetProcAddress(::GetModuleHandle(L"user32"), "SystemParametersInfoForDpi");
|
|
+
|
|
+ if (mySystemParametersInfoForDpi)
|
|
+ mySystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0, defaultVerticalDPI());
|
|
+ else
|
|
+ SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0);
|
|
+
|
|
const QFont systemFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMessageFont);
|
|
qCDebug(lcQpaFonts) << __FUNCTION__ << systemFont;
|
|
return systemFont;
|
|
diff --git a/src/network/kernel/qdnslookup_win.cpp b/src/network/kernel/qdnslookup_win.cpp
|
|
index 1b07776db9d..5410edab880 100644
|
|
--- a/src/network/kernel/qdnslookup_win.cpp
|
|
+++ b/src/network/kernel/qdnslookup_win.cpp
|
|
@@ -5,11 +5,9 @@
|
|
#include <winsock2.h>
|
|
#include "qdnslookup_p.h"
|
|
|
|
-#include <qendian.h>
|
|
+#include <qurl.h>
|
|
#include <private/qnativesocketengine_p.h>
|
|
#include <private/qsystemerror_p.h>
|
|
-#include <qurl.h>
|
|
-#include <qspan.h>
|
|
|
|
#include <qt_windows.h>
|
|
#include <windns.h>
|
|
@@ -65,100 +63,103 @@ DNS_STATUS WINAPI DnsQueryEx(PDNS_QUERY_REQUEST pQueryRequest,
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
-static DNS_STATUS sendAlternate(QDnsLookupRunnable *self, QDnsLookupReply *reply,
|
|
- PDNS_QUERY_REQUEST request, PDNS_QUERY_RESULT results)
|
|
-{
|
|
- // WinDNS wants MTU - IP Header - UDP header for some reason, in spite
|
|
- // of never needing that much
|
|
- QVarLengthArray<unsigned char, 1472> query(1472);
|
|
-
|
|
- auto dnsBuffer = new (query.data()) DNS_MESSAGE_BUFFER;
|
|
- DWORD dnsBufferSize = query.size();
|
|
- WORD xid = 0;
|
|
- bool recursionDesired = true;
|
|
-
|
|
- SetLastError(ERROR_SUCCESS);
|
|
-
|
|
- // MinGW winheaders incorrectly declare the third parameter as LPWSTR
|
|
- if (!DnsWriteQuestionToBuffer_W(dnsBuffer, &dnsBufferSize,
|
|
- const_cast<LPWSTR>(request->QueryName), request->QueryType,
|
|
- xid, recursionDesired)) {
|
|
- // let's try reallocating
|
|
- query.resize(dnsBufferSize);
|
|
- if (!DnsWriteQuestionToBuffer_W(dnsBuffer, &dnsBufferSize,
|
|
- const_cast<LPWSTR>(request->QueryName), request->QueryType,
|
|
- xid, recursionDesired)) {
|
|
- return GetLastError();
|
|
- }
|
|
- }
|
|
-
|
|
- // set AD bit: we want to trust this server
|
|
- dnsBuffer->MessageHead.AuthenticatedData = true;
|
|
-
|
|
- QDnsLookupRunnable::ReplyBuffer replyBuffer;
|
|
- if (!self->sendDnsOverTls(reply, { query.data(), qsizetype(dnsBufferSize) }, replyBuffer))
|
|
- return DNS_STATUS(-1); // error set in reply
|
|
-
|
|
- // interpret the RCODE in the reply
|
|
- auto response = reinterpret_cast<PDNS_MESSAGE_BUFFER>(replyBuffer.data());
|
|
- DNS_HEADER *header = &response->MessageHead;
|
|
- if (!header->IsResponse)
|
|
- return DNS_ERROR_BAD_PACKET; // not a reply
|
|
-
|
|
- // Convert the byte order for the 16-bit quantities in the header, so
|
|
- // DnsExtractRecordsFromMessage can parse the contents.
|
|
- //header->Xid = qFromBigEndian(header->Xid);
|
|
- header->QuestionCount = qFromBigEndian(header->QuestionCount);
|
|
- header->AnswerCount = qFromBigEndian(header->AnswerCount);
|
|
- header->NameServerCount = qFromBigEndian(header->NameServerCount);
|
|
- header->AdditionalCount = qFromBigEndian(header->AdditionalCount);
|
|
-
|
|
- results->QueryOptions = request->QueryOptions;
|
|
- return DnsExtractRecordsFromMessage_W(response, replyBuffer.size(), &results->pQueryRecords);
|
|
-}
|
|
-
|
|
void QDnsLookupRunnable::query(QDnsLookupReply *reply)
|
|
{
|
|
- // Perform DNS query.
|
|
- alignas(DNS_ADDR_ARRAY) uchar dnsAddresses[sizeof(DNS_ADDR_ARRAY) + sizeof(DNS_ADDR)];
|
|
- DNS_QUERY_REQUEST request = {};
|
|
- request.Version = 1;
|
|
- request.QueryName = reinterpret_cast<const wchar_t *>(requestName.constData());
|
|
- request.QueryType = requestType;
|
|
- request.QueryOptions = DNS_QUERY_STANDARD | DNS_QUERY_TREAT_AS_FQDN;
|
|
+ typedef BOOL (WINAPI *DnsQueryExFunc) (PDNS_QUERY_REQUEST, PDNS_QUERY_RESULT, PDNS_QUERY_CANCEL);
|
|
+ static DnsQueryExFunc myDnsQueryEx =
|
|
+ (DnsQueryExFunc)::GetProcAddress(::GetModuleHandle(L"Dnsapi"), "DnsQueryEx");
|
|
+
|
|
+ PDNS_RECORD ptrStart = nullptr;
|
|
+
|
|
+ if (myDnsQueryEx)
|
|
+ {
|
|
+ // Perform DNS query.
|
|
+ alignas(DNS_ADDR_ARRAY) uchar dnsAddresses[sizeof(DNS_ADDR_ARRAY) + sizeof(DNS_ADDR)];
|
|
+ DNS_QUERY_REQUEST request = {};
|
|
+ request.Version = 1;
|
|
+ request.QueryName = reinterpret_cast<const wchar_t *>(requestName.constData());
|
|
+ request.QueryType = requestType;
|
|
+ request.QueryOptions = DNS_QUERY_STANDARD | DNS_QUERY_TREAT_AS_FQDN;
|
|
+
|
|
+ if (!nameserver.isNull()) {
|
|
+ memset(dnsAddresses, 0, sizeof(dnsAddresses));
|
|
+ request.pDnsServerList = new (dnsAddresses) DNS_ADDR_ARRAY;
|
|
+ auto addr = new (request.pDnsServerList->AddrArray) DNS_ADDR[1];
|
|
+ auto sa = new (addr[0].MaxSa) sockaddr;
|
|
+ request.pDnsServerList->MaxCount = sizeof(dnsAddresses);
|
|
+ request.pDnsServerList->AddrCount = 1;
|
|
+ // ### setting port 53 seems to cause some systems to fail
|
|
+ setSockaddr(sa, nameserver, port == DnsPort ? 0 : port);
|
|
+ request.pDnsServerList->Family = sa->sa_family;
|
|
+ }
|
|
|
|
- if (protocol == QDnsLookup::Standard && !nameserver.isNull()) {
|
|
- memset(dnsAddresses, 0, sizeof(dnsAddresses));
|
|
- request.pDnsServerList = new (dnsAddresses) DNS_ADDR_ARRAY;
|
|
- auto addr = new (request.pDnsServerList->AddrArray) DNS_ADDR[1];
|
|
- auto sa = new (addr[0].MaxSa) sockaddr;
|
|
- request.pDnsServerList->MaxCount = sizeof(dnsAddresses);
|
|
- request.pDnsServerList->AddrCount = 1;
|
|
- // ### setting port 53 seems to cause some systems to fail
|
|
- setSockaddr(sa, nameserver, port == DnsPort ? 0 : port);
|
|
- request.pDnsServerList->Family = sa->sa_family;
|
|
+ DNS_QUERY_RESULT results = {};
|
|
+ results.Version = 1;
|
|
+ const DNS_STATUS status = myDnsQueryEx(&request, &results, nullptr);
|
|
+ if (status >= DNS_ERROR_RCODE_FORMAT_ERROR && status <= DNS_ERROR_RCODE_LAST)
|
|
+ return reply->makeDnsRcodeError(status - DNS_ERROR_RCODE_FORMAT_ERROR + 1);
|
|
+ else if (status == ERROR_TIMEOUT)
|
|
+ return reply->makeTimeoutError();
|
|
+ else if (status != ERROR_SUCCESS)
|
|
+ return reply->makeResolverSystemError(status);
|
|
+
|
|
+ ptrStart = results.pQueryRecords;
|
|
}
|
|
+ else
|
|
+ {
|
|
+ // Perform DNS query.
|
|
+ PDNS_RECORD dns_records = 0;
|
|
+ QByteArray requestNameUTF8 = requestName.toUtf8();
|
|
+ const QString requestNameUtf16 = QString::fromUtf8(requestNameUTF8.data(), requestNameUTF8.size());
|
|
+ IP4_ARRAY srvList;
|
|
+ memset(&srvList, 0, sizeof(IP4_ARRAY));
|
|
+ if (!nameserver.isNull()) {
|
|
+ if (nameserver.protocol() == QAbstractSocket::IPv4Protocol) {
|
|
+ // The below code is referenced from: http://support.microsoft.com/kb/831226
|
|
+ srvList.AddrCount = 1;
|
|
+ srvList.AddrArray[0] = htonl(nameserver.toIPv4Address());
|
|
+ } else if (nameserver.protocol() == QAbstractSocket::IPv6Protocol) {
|
|
+ // For supporting IPv6 nameserver addresses, we'll need to switch
|
|
+ // from DnsQuey() to DnsQueryEx() as it supports passing an IPv6
|
|
+ // address in the nameserver list
|
|
+ qWarning("%s", "IPv6 addresses for nameservers are currently not supported");
|
|
+ reply->error = QDnsLookup::ResolverError;
|
|
+ reply->errorString = tr("IPv6 addresses for nameservers are currently not supported");
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+ const DNS_STATUS status = DnsQuery_W(reinterpret_cast<const wchar_t*>(requestNameUtf16.utf16()), requestType, DNS_QUERY_STANDARD, &srvList, &dns_records, NULL);
|
|
+ switch (status) {
|
|
+ case ERROR_SUCCESS:
|
|
+ break;
|
|
+ case DNS_ERROR_RCODE_FORMAT_ERROR:
|
|
+ reply->error = QDnsLookup::InvalidRequestError;
|
|
+ reply->errorString = tr("Server could not process query");
|
|
+ return;
|
|
+ case DNS_ERROR_RCODE_SERVER_FAILURE:
|
|
+ case DNS_ERROR_RCODE_NOT_IMPLEMENTED:
|
|
+ reply->error = QDnsLookup::ServerFailureError;
|
|
+ reply->errorString = tr("Server failure");
|
|
+ return;
|
|
+ case DNS_ERROR_RCODE_NAME_ERROR:
|
|
+ reply->error = QDnsLookup::NotFoundError;
|
|
+ reply->errorString = tr("Non existent domain");
|
|
+ return;
|
|
+ case DNS_ERROR_RCODE_REFUSED:
|
|
+ reply->error = QDnsLookup::ServerRefusedError;
|
|
+ reply->errorString = tr("Server refused to answer");
|
|
+ return;
|
|
+ default:
|
|
+ reply->error = QDnsLookup::InvalidReplyError;
|
|
+ reply->errorString = QSystemError(status, QSystemError::NativeError).toString();
|
|
+ return;
|
|
+ }
|
|
|
|
- DNS_QUERY_RESULT results = {};
|
|
- results.Version = 1;
|
|
- DNS_STATUS status = ERROR_INVALID_PARAMETER;
|
|
- switch (protocol) {
|
|
- case QDnsLookup::Standard:
|
|
- status = DnsQueryEx(&request, &results, nullptr);
|
|
- break;
|
|
- case QDnsLookup::DnsOverTls:
|
|
- status = sendAlternate(this, reply, &request, &results);
|
|
- break;
|
|
+ ptrStart = dns_records;
|
|
}
|
|
|
|
- if (status == DNS_STATUS(-1))
|
|
- return; // error already set in reply
|
|
- if (status >= DNS_ERROR_RCODE_FORMAT_ERROR && status <= DNS_ERROR_RCODE_LAST)
|
|
- return reply->makeDnsRcodeError(status - DNS_ERROR_RCODE_FORMAT_ERROR + 1);
|
|
- else if (status == ERROR_TIMEOUT)
|
|
- return reply->makeTimeoutError();
|
|
- else if (status != ERROR_SUCCESS)
|
|
- return reply->makeResolverSystemError(status);
|
|
+ if (!ptrStart)
|
|
+ return;
|
|
|
|
QStringView lastEncodedName;
|
|
QString cachedDecodedName;
|
|
@@ -170,9 +171,9 @@ void QDnsLookupRunnable::query(QDnsLookupReply *reply)
|
|
auto extractMaybeCachedHost = [&](QStringView name) -> const QString & {
|
|
return lastEncodedName == name ? cachedDecodedName : extractAndCacheHost(name);
|
|
};
|
|
-
|
|
+
|
|
// Extract results.
|
|
- for (PDNS_RECORD ptr = results.pQueryRecords; ptr != NULL; ptr = ptr->pNext) {
|
|
+ for (PDNS_RECORD ptr = ptrStart; ptr != NULL; ptr = ptr->pNext) {
|
|
// warning: always assign name to the record before calling extractXxxHost() again
|
|
const QString &name = extractMaybeCachedHost(ptr->pName);
|
|
if (ptr->wType == QDnsLookup::A) {
|
|
@@ -224,25 +225,6 @@ void QDnsLookupRunnable::query(QDnsLookupReply *reply)
|
|
record.d->timeToLive = ptr->dwTtl;
|
|
record.d->weight = ptr->Data.Srv.wWeight;
|
|
reply->serviceRecords.append(record);
|
|
- } else if (ptr->wType == QDnsLookup::TLSA) {
|
|
- // Note: untested, because the DNS_RECORD reply appears to contain
|
|
- // no records relating to TLSA. Maybe WinDNS filters them out of
|
|
- // zones without DNSSEC.
|
|
- QDnsTlsAssociationRecord record;
|
|
- record.d->name = name;
|
|
- record.d->timeToLive = ptr->dwTtl;
|
|
-
|
|
- const auto &tlsa = ptr->Data.Tlsa;
|
|
- const quint8 usage = tlsa.bCertUsage;
|
|
- const quint8 selector = tlsa.bSelector;
|
|
- const quint8 matchType = tlsa.bMatchingType;
|
|
-
|
|
- record.d->usage = QDnsTlsAssociationRecord::CertificateUsage(usage);
|
|
- record.d->selector = QDnsTlsAssociationRecord::Selector(selector);
|
|
- record.d->matchType = QDnsTlsAssociationRecord::MatchingType(matchType);
|
|
- record.d->value.assign(tlsa.bCertificateAssociationData,
|
|
- tlsa.bCertificateAssociationData + tlsa.bCertificateAssociationDataLength);
|
|
- reply->tlsAssociationRecords.append(std::move(record));
|
|
} else if (ptr->wType == QDnsLookup::TXT) {
|
|
QDnsTextRecord record;
|
|
record.d->name = name;
|
|
@@ -254,7 +236,7 @@ void QDnsLookupRunnable::query(QDnsLookupReply *reply)
|
|
}
|
|
}
|
|
|
|
- DnsRecordListFree(results.pQueryRecords, DnsFreeRecordList);
|
|
+ DnsRecordListFree(ptrStart, DnsFreeRecordList);
|
|
}
|
|
|
|
QT_END_NAMESPACE
|
|
diff --git a/src/plugins/platforms/windows/qwin10helpers.cpp b/src/plugins/platforms/windows/qwin10helpers.cpp
|
|
index 026e81cb0c7..3bbc974b744 100644
|
|
--- a/src/plugins/platforms/windows/qwin10helpers.cpp
|
|
+++ b/src/plugins/platforms/windows/qwin10helpers.cpp
|
|
@@ -58,43 +58,73 @@ public:
|
|
} // namespace ABI
|
|
#endif // HAS_UI_VIEW_SETTINGS
|
|
|
|
+// based on SDL approach
|
|
+// see SDL_windows_gaming_input.c, SDL_windows.c
|
|
+
|
|
+void * WIN_LoadComBaseFunction(const char *name)
|
|
+{
|
|
+ static bool s_bLoaded = false;
|
|
+ static HMODULE s_hComBase = NULL;
|
|
+
|
|
+ if (!s_bLoaded) {
|
|
+ s_hComBase = ::LoadLibraryEx(L"combase.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
|
+ s_bLoaded = true;
|
|
+ }
|
|
+ if (s_hComBase) {
|
|
+ return (void *) ::GetProcAddress(s_hComBase, name);
|
|
+ } else {
|
|
+ return NULL;
|
|
+ }
|
|
+}
|
|
+
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
// Return tablet mode, note: Does not work for GetDesktopWindow().
|
|
bool qt_windowsIsTabletMode(HWND hwnd)
|
|
{
|
|
- bool result = false;
|
|
-
|
|
- const wchar_t uiViewSettingsId[] = L"Windows.UI.ViewManagement.UIViewSettings";
|
|
- HSTRING_HEADER uiViewSettingsIdRefHeader;
|
|
- HSTRING uiViewSettingsIdHs = nullptr;
|
|
- const auto uiViewSettingsIdLen = UINT32(sizeof(uiViewSettingsId) / sizeof(uiViewSettingsId[0]) - 1);
|
|
- if (FAILED(WindowsCreateStringReference(uiViewSettingsId, uiViewSettingsIdLen, &uiViewSettingsIdRefHeader, &uiViewSettingsIdHs)))
|
|
- return false;
|
|
-
|
|
- IUIViewSettingsInterop *uiViewSettingsInterop = nullptr;
|
|
- // __uuidof(IUIViewSettingsInterop);
|
|
- const GUID uiViewSettingsInteropRefId = {0x3694dbf9, 0x8f68, 0x44be,{0x8f, 0xf5, 0x19, 0x5c, 0x98, 0xed, 0xe8, 0xa6}};
|
|
-
|
|
- HRESULT hr = RoGetActivationFactory(uiViewSettingsIdHs, uiViewSettingsInteropRefId,
|
|
- reinterpret_cast<void **>(&uiViewSettingsInterop));
|
|
- if (FAILED(hr))
|
|
- return false;
|
|
-
|
|
- // __uuidof(ABI::Windows::UI::ViewManagement::IUIViewSettings);
|
|
- const GUID uiViewSettingsRefId = {0xc63657f6, 0x8850, 0x470d,{0x88, 0xf8, 0x45, 0x5e, 0x16, 0xea, 0x2c, 0x26}};
|
|
- ABI::Windows::UI::ViewManagement::IUIViewSettings *viewSettings = nullptr;
|
|
- hr = uiViewSettingsInterop->GetForWindow(hwnd, uiViewSettingsRefId,
|
|
- reinterpret_cast<void **>(&viewSettings));
|
|
- if (SUCCEEDED(hr)) {
|
|
- ABI::Windows::UI::ViewManagement::UserInteractionMode currentMode;
|
|
- hr = viewSettings->get_UserInteractionMode(¤tMode);
|
|
- if (SUCCEEDED(hr))
|
|
- result = currentMode == 1; // Touch, 1
|
|
- viewSettings->Release();
|
|
+ typedef HRESULT (WINAPI *WindowsCreateStringReference_t)(PCWSTR sourceString, UINT32 length, HSTRING_HEADER *hstringHeader, HSTRING* string);
|
|
+ typedef HRESULT (WINAPI *RoGetActivationFactory_t)(HSTRING activatableClassId, REFIID iid, void** factory);
|
|
+
|
|
+ WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)WIN_LoadComBaseFunction("WindowsCreateStringReference");
|
|
+ RoGetActivationFactory_t RoGetActivationFactoryFunc = (RoGetActivationFactory_t)WIN_LoadComBaseFunction("RoGetActivationFactory");
|
|
+
|
|
+ if (WindowsCreateStringReferenceFunc && RoGetActivationFactoryFunc)
|
|
+ {
|
|
+ bool result = false;
|
|
+
|
|
+ const wchar_t uiViewSettingsId[] = L"Windows.UI.ViewManagement.UIViewSettings";
|
|
+ HSTRING_HEADER uiViewSettingsIdRefHeader;
|
|
+ HSTRING uiViewSettingsIdHs = nullptr;
|
|
+ const auto uiViewSettingsIdLen = UINT32(sizeof(uiViewSettingsId) / sizeof(uiViewSettingsId[0]) - 1);
|
|
+ if (FAILED(WindowsCreateStringReferenceFunc(uiViewSettingsId, uiViewSettingsIdLen, &uiViewSettingsIdRefHeader, &uiViewSettingsIdHs)))
|
|
+ return false;
|
|
+
|
|
+ IUIViewSettingsInterop *uiViewSettingsInterop = nullptr;
|
|
+ // __uuidof(IUIViewSettingsInterop);
|
|
+ const GUID uiViewSettingsInteropRefId = {0x3694dbf9, 0x8f68, 0x44be,{0x8f, 0xf5, 0x19, 0x5c, 0x98, 0xed, 0xe8, 0xa6}};
|
|
+
|
|
+ HRESULT hr = RoGetActivationFactoryFunc(uiViewSettingsIdHs, uiViewSettingsInteropRefId,
|
|
+ reinterpret_cast<void **>(&uiViewSettingsInterop));
|
|
+ if (FAILED(hr))
|
|
+ return false;
|
|
+
|
|
+ // __uuidof(ABI::Windows::UI::ViewManagement::IUIViewSettings);
|
|
+ const GUID uiViewSettingsRefId = {0xc63657f6, 0x8850, 0x470d,{0x88, 0xf8, 0x45, 0x5e, 0x16, 0xea, 0x2c, 0x26}};
|
|
+ ABI::Windows::UI::ViewManagement::IUIViewSettings *viewSettings = nullptr;
|
|
+ hr = uiViewSettingsInterop->GetForWindow(hwnd, uiViewSettingsRefId,
|
|
+ reinterpret_cast<void **>(&viewSettings));
|
|
+ if (SUCCEEDED(hr)) {
|
|
+ ABI::Windows::UI::ViewManagement::UserInteractionMode currentMode;
|
|
+ hr = viewSettings->get_UserInteractionMode(¤tMode);
|
|
+ if (SUCCEEDED(hr))
|
|
+ result = currentMode == 1; // Touch, 1
|
|
+ viewSettings->Release();
|
|
+ }
|
|
+ uiViewSettingsInterop->Release();
|
|
+ return result;
|
|
}
|
|
- uiViewSettingsInterop->Release();
|
|
- return result;
|
|
+
|
|
+ return false;
|
|
}
|
|
|
|
-QT_END_NAMESPACE
|
|
+QT_END_NAMESPACE
|
|
\ No newline at end of file
|
|
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
|
|
index 88e9da5557c..7df58793707 100644
|
|
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
|
|
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
|
|
@@ -43,6 +43,7 @@
|
|
#include <QtCore/qsysinfo.h>
|
|
#include <QtCore/qscopedpointer.h>
|
|
#include <QtCore/quuid.h>
|
|
+#include <QtCore/private/qsystemlibrary_p.h>
|
|
#include <QtCore/private/qwinregistry_p.h>
|
|
#if QT_CONFIG(cpp_winrt)
|
|
# include <QtCore/private/qfactorycacheregistration_p.h>
|
|
@@ -59,6 +60,8 @@
|
|
#include <wtsapi32.h>
|
|
#include <shellscalingapi.h>
|
|
|
|
+#include "vxkex.h"
|
|
+
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
using namespace Qt::StringLiterals;
|
|
@@ -120,6 +123,77 @@ static inline bool sessionManagerInteractionBlocked()
|
|
static inline bool sessionManagerInteractionBlocked() { return false; }
|
|
#endif
|
|
|
|
+/*!
|
|
+ \class QWindowsUser32DLL
|
|
+ \brief Struct that contains dynamically resolved symbols of User32.dll.
|
|
+ The stub libraries shipped with the MinGW compiler miss some of the
|
|
+ functions. They need to be retrieved dynamically.
|
|
+ In addition, touch-related functions are available only from Windows onwards.
|
|
+ These need to resolved dynamically for Q_CC_MSVC as well.
|
|
+ \sa QWindowsShell32DLL
|
|
+ \internal
|
|
+*/
|
|
+
|
|
+void QWindowsUser32DLL::init()
|
|
+{
|
|
+ QSystemLibrary library(QStringLiteral("user32"));
|
|
+ setProcessDPIAware = (SetProcessDPIAware)library.resolve("SetProcessDPIAware");
|
|
+ setProcessDpiAwarenessContext = (SetProcessDpiAwarenessContext)library.resolve("SetProcessDpiAwarenessContext");
|
|
+ getThreadDpiAwarenessContext = (GetThreadDpiAwarenessContext)library.resolve("GetThreadDpiAwarenessContext");
|
|
+ isValidDpiAwarenessContext = (IsValidDpiAwarenessContext)library.resolve("IsValidDpiAwarenessContext");
|
|
+ areDpiAwarenessContextsEqual = (AreDpiAwarenessContextsEqual)library.resolve("AreDpiAwarenessContextsEqual");
|
|
+
|
|
+ addClipboardFormatListener = (AddClipboardFormatListener)library.resolve("AddClipboardFormatListener");
|
|
+ removeClipboardFormatListener = (RemoveClipboardFormatListener)library.resolve("RemoveClipboardFormatListener");
|
|
+
|
|
+ getDisplayAutoRotationPreferences = (GetDisplayAutoRotationPreferences)library.resolve("GetDisplayAutoRotationPreferences");
|
|
+ setDisplayAutoRotationPreferences = (SetDisplayAutoRotationPreferences)library.resolve("SetDisplayAutoRotationPreferences");
|
|
+
|
|
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8) {
|
|
+ enableMouseInPointer = (EnableMouseInPointer)library.resolve("EnableMouseInPointer");
|
|
+ getPointerType = (GetPointerType)library.resolve("GetPointerType");
|
|
+ getPointerInfo = (GetPointerInfo)library.resolve("GetPointerInfo");
|
|
+ getPointerDeviceRects = (GetPointerDeviceRects)library.resolve("GetPointerDeviceRects");
|
|
+ getPointerTouchInfo = (GetPointerTouchInfo)library.resolve("GetPointerTouchInfo");
|
|
+ getPointerFrameTouchInfo = (GetPointerFrameTouchInfo)library.resolve("GetPointerFrameTouchInfo");
|
|
+ getPointerFrameTouchInfoHistory = (GetPointerFrameTouchInfoHistory)library.resolve("GetPointerFrameTouchInfoHistory");
|
|
+ getPointerPenInfo = (GetPointerPenInfo)library.resolve("GetPointerPenInfo");
|
|
+ getPointerPenInfoHistory = (GetPointerPenInfoHistory)library.resolve("GetPointerPenInfoHistory");
|
|
+ skipPointerFrameMessages = (SkipPointerFrameMessages)library.resolve("SkipPointerFrameMessages");
|
|
+ }
|
|
+
|
|
+ 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");
|
|
+ systemParametersInfoForDpi = (SystemParametersInfoForDpi)library.resolve("SystemParametersInfoForDpi");
|
|
+ getDpiForWindow = (GetDpiForWindow)library.resolve("GetDpiForWindow");
|
|
+ getSystemMetricsForDpi = (GetSystemMetricsForDpi)library.resolve("GetSystemMetricsForDpi");
|
|
+ }
|
|
+}
|
|
+
|
|
+bool QWindowsUser32DLL::supportsPointerApi()
|
|
+{
|
|
+ return enableMouseInPointer && getPointerType && getPointerInfo && getPointerDeviceRects
|
|
+ && getPointerTouchInfo && getPointerFrameTouchInfo && getPointerFrameTouchInfoHistory
|
|
+ && getPointerPenInfo && getPointerPenInfoHistory && skipPointerFrameMessages;
|
|
+}
|
|
+
|
|
+void QWindowsShcoreDLL::init()
|
|
+{
|
|
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8_1)
|
|
+ return;
|
|
+ QSystemLibrary library(QStringLiteral("SHCore"));
|
|
+ getProcessDpiAwareness = (GetProcessDpiAwareness)library.resolve("GetProcessDpiAwareness");
|
|
+ setProcessDpiAwareness = (SetProcessDpiAwareness)library.resolve("SetProcessDpiAwareness");
|
|
+ getDpiForMonitor = (GetDpiForMonitor)library.resolve("GetDpiForMonitor");
|
|
+}
|
|
+
|
|
+QWindowsUser32DLL QWindowsContext::user32dll;
|
|
+QWindowsShcoreDLL QWindowsContext::shcoredll;
|
|
+
|
|
QWindowsContext *QWindowsContext::m_instance = nullptr;
|
|
|
|
/*!
|
|
@@ -160,6 +234,9 @@ bool QWindowsContextPrivate::m_v2DpiAware = false;
|
|
QWindowsContextPrivate::QWindowsContextPrivate()
|
|
: m_oleInitializeResult(OleInitialize(nullptr))
|
|
{
|
|
+ QWindowsContext::user32dll.init();
|
|
+ QWindowsContext::shcoredll.init();
|
|
+
|
|
if (m_pointerHandler.touchDevice())
|
|
m_systemInfo |= QWindowsContext::SI_SupportsTouch;
|
|
m_displayContext = GetDC(nullptr);
|
|
@@ -338,19 +415,39 @@ void QWindowsContext::setDetectAltGrModifier(bool a)
|
|
[[nodiscard]] static inline QtWindows::DpiAwareness
|
|
dpiAwarenessContextToQtDpiAwareness(DPI_AWARENESS_CONTEXT context)
|
|
{
|
|
- // IsValidDpiAwarenessContext() will handle the NULL pointer case.
|
|
- if (!IsValidDpiAwarenessContext(context))
|
|
- return QtWindows::DpiAwareness::Invalid;
|
|
- if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED))
|
|
- return QtWindows::DpiAwareness::Unaware_GdiScaled;
|
|
- if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
|
|
- return QtWindows::DpiAwareness::PerMonitorVersion2;
|
|
- if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE))
|
|
- return QtWindows::DpiAwareness::PerMonitor;
|
|
- if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))
|
|
- return QtWindows::DpiAwareness::System;
|
|
- if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE))
|
|
- return QtWindows::DpiAwareness::Unaware;
|
|
+ if (QWindowsContext::user32dll.isValidDpiAwarenessContext && QWindowsContext::user32dll.areDpiAwarenessContextsEqual)
|
|
+ {
|
|
+ // IsValidDpiAwarenessContext() will handle the NULL pointer case.
|
|
+ if (!QWindowsContext::user32dll.isValidDpiAwarenessContext(context))
|
|
+ return QtWindows::DpiAwareness::Invalid;
|
|
+ if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED))
|
|
+ return QtWindows::DpiAwareness::Unaware_GdiScaled;
|
|
+ if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
|
|
+ return QtWindows::DpiAwareness::PerMonitorVersion2;
|
|
+ if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE))
|
|
+ return QtWindows::DpiAwareness::PerMonitor;
|
|
+ if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))
|
|
+ return QtWindows::DpiAwareness::System;
|
|
+ if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE))
|
|
+ return QtWindows::DpiAwareness::Unaware;
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ // IsValidDpiAwarenessContext() will handle the NULL pointer case.
|
|
+ if (!vxkex::IsValidDpiAwarenessContext(context))
|
|
+ return QtWindows::DpiAwareness::Invalid;
|
|
+ if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED))
|
|
+ return QtWindows::DpiAwareness::Unaware_GdiScaled;
|
|
+ if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
|
|
+ return QtWindows::DpiAwareness::PerMonitorVersion2;
|
|
+ if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE))
|
|
+ return QtWindows::DpiAwareness::PerMonitor;
|
|
+ if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))
|
|
+ return QtWindows::DpiAwareness::System;
|
|
+ if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE))
|
|
+ return QtWindows::DpiAwareness::Unaware;
|
|
+ }
|
|
+
|
|
return QtWindows::DpiAwareness::Invalid;
|
|
}
|
|
|
|
@@ -358,7 +455,11 @@ QtWindows::DpiAwareness QWindowsContext::windowDpiAwareness(HWND hwnd)
|
|
{
|
|
if (!hwnd)
|
|
return QtWindows::DpiAwareness::Invalid;
|
|
- const auto context = GetWindowDpiAwarenessContext(hwnd);
|
|
+
|
|
+ const auto context = QWindowsContext::user32dll.getWindowDpiAwarenessContext ?
|
|
+ QWindowsContext::user32dll.getWindowDpiAwarenessContext(hwnd) :
|
|
+ vxkex::GetWindowDpiAwarenessContext(hwnd);
|
|
+
|
|
return dpiAwarenessContextToQtDpiAwareness(context);
|
|
}
|
|
|
|
@@ -371,7 +472,9 @@ QtWindows::DpiAwareness QWindowsContext::processDpiAwareness()
|
|
// return the default DPI_AWARENESS_CONTEXT for the process if
|
|
// SetThreadDpiAwarenessContext() was never called. So we can use
|
|
// it as an equivalent.
|
|
- const auto context = GetThreadDpiAwarenessContext();
|
|
+ const DPI_AWARENESS_CONTEXT context = QWindowsContext::user32dll.getThreadDpiAwarenessContext ?
|
|
+ QWindowsContext::user32dll.getThreadDpiAwarenessContext() :
|
|
+ vxkex::GetThreadDpiAwarenessContext();
|
|
return dpiAwarenessContextToQtDpiAwareness(context);
|
|
}
|
|
|
|
@@ -431,11 +534,21 @@ bool QWindowsContext::setProcessDpiAwareness(QtWindows::DpiAwareness dpiAwarenes
|
|
if (processDpiAwareness() == dpiAwareness)
|
|
return true;
|
|
const auto context = qtDpiAwarenessToDpiAwarenessContext(dpiAwareness);
|
|
- if (!IsValidDpiAwarenessContext(context)) {
|
|
+
|
|
+ BOOL bResultIsValid = QWindowsContext::user32dll.isValidDpiAwarenessContext ?
|
|
+ QWindowsContext::user32dll.isValidDpiAwarenessContext(context) :
|
|
+ vxkex::IsValidDpiAwarenessContext(context);
|
|
+
|
|
+ if (!bResultIsValid) {
|
|
qCWarning(lcQpaWindow) << dpiAwareness << "is not supported by current system.";
|
|
return false;
|
|
}
|
|
- if (!SetProcessDpiAwarenessContext(context)) {
|
|
+
|
|
+ BOOL bResultSet = QWindowsContext::user32dll.setProcessDpiAwarenessContext ?
|
|
+ QWindowsContext::user32dll.setProcessDpiAwarenessContext(context) :
|
|
+ vxkex::SetProcessDpiAwarenessContext(context);
|
|
+
|
|
+ if (!bResultSet) {
|
|
qCWarning(lcQpaWindow).noquote().nospace()
|
|
<< "SetProcessDpiAwarenessContext() failed: "
|
|
<< QSystemError::windowsString()
|
|
@@ -868,9 +981,9 @@ void QWindowsContext::forceNcCalcSize(HWND hwnd)
|
|
bool QWindowsContext::systemParametersInfo(unsigned action, unsigned param, void *out,
|
|
unsigned dpi)
|
|
{
|
|
- const BOOL result = dpi != 0
|
|
- ? SystemParametersInfoForDpi(action, param, out, 0, dpi)
|
|
- : SystemParametersInfo(action, param, out, 0);
|
|
+ const BOOL result = (QWindowsContext::user32dll.systemParametersInfoForDpi != nullptr && dpi != 0)
|
|
+ ? QWindowsContext::user32dll.systemParametersInfoForDpi(action, param, out, 0, dpi)
|
|
+ : vxkex::SystemParametersInfoForDpi(action, param, out, 0, dpi);
|
|
return result == TRUE;
|
|
}
|
|
|
|
@@ -957,7 +1070,10 @@ static bool enableNonClientDpiScaling(HWND hwnd)
|
|
{
|
|
bool result = false;
|
|
if (QWindowsContext::windowDpiAwareness(hwnd) == QtWindows::DpiAwareness::PerMonitor) {
|
|
- result = EnableNonClientDpiScaling(hwnd) != FALSE;
|
|
+ result = QWindowsContext::user32dll.enableNonClientDpiScaling ?
|
|
+ (QWindowsContext::user32dll.enableNonClientDpiScaling(hwnd) != FALSE) :
|
|
+ (vxkex::EnableNonClientDpiScaling(hwnd) != FALSE);
|
|
+
|
|
if (!result) {
|
|
const DWORD errorCode = GetLastError();
|
|
qErrnoWarning(int(errorCode), "EnableNonClientDpiScaling() failed for HWND %p (%lu)",
|
|
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
|
|
index 4e9be1af967..357f7839353 100644
|
|
--- a/src/plugins/platforms/windows/qwindowscontext.h
|
|
+++ b/src/plugins/platforms/windows/qwindowscontext.h
|
|
@@ -14,6 +14,7 @@
|
|
#define STRICT_TYPED_ITEMIDS
|
|
#include <shlobj.h>
|
|
#include <shlwapi.h>
|
|
+#include <shellscalingapi.h>
|
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
@@ -44,6 +45,95 @@ struct QWindowsContextPrivate;
|
|
class QPoint;
|
|
class QKeyEvent;
|
|
class QPointingDevice;
|
|
+
|
|
+struct QWindowsUser32DLL
|
|
+{
|
|
+ inline void init();
|
|
+ inline bool supportsPointerApi();
|
|
+
|
|
+ typedef BOOL (WINAPI *EnableMouseInPointer)(BOOL);
|
|
+ typedef BOOL (WINAPI *GetPointerType)(UINT32, PVOID);
|
|
+ typedef BOOL (WINAPI *GetPointerInfo)(UINT32, PVOID);
|
|
+ typedef BOOL (WINAPI *GetPointerDeviceRects)(HANDLE, RECT *, RECT *);
|
|
+ typedef BOOL (WINAPI *GetPointerTouchInfo)(UINT32, PVOID);
|
|
+ typedef BOOL (WINAPI *GetPointerFrameTouchInfo)(UINT32, UINT32 *, PVOID);
|
|
+ typedef BOOL (WINAPI *GetPointerFrameTouchInfoHistory)(UINT32, UINT32 *, UINT32 *, PVOID);
|
|
+ typedef BOOL (WINAPI *GetPointerPenInfo)(UINT32, PVOID);
|
|
+ typedef BOOL (WINAPI *GetPointerPenInfoHistory)(UINT32, UINT32 *, PVOID);
|
|
+ typedef BOOL (WINAPI *SkipPointerFrameMessages)(UINT32);
|
|
+ typedef BOOL (WINAPI *SetProcessDPIAware)();
|
|
+ typedef BOOL (WINAPI *SetProcessDpiAwarenessContext)(HANDLE);
|
|
+ typedef BOOL (WINAPI *AddClipboardFormatListener)(HWND);
|
|
+ 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 DPI_AWARENESS_CONTEXT (WINAPI *GetWindowDpiAwarenessContext)(HWND);
|
|
+ typedef DPI_AWARENESS (WINAPI *GetAwarenessFromDpiAwarenessContext)(int);
|
|
+ typedef BOOL (WINAPI *SystemParametersInfoForDpi)(UINT, UINT, PVOID, UINT, UINT);
|
|
+ typedef int (WINAPI *GetDpiForWindow)(HWND);
|
|
+ typedef BOOL (WINAPI *GetSystemMetricsForDpi)(INT, UINT);
|
|
+ typedef BOOL (WINAPI *AreDpiAwarenessContextsEqual)(DPI_AWARENESS_CONTEXT, DPI_AWARENESS_CONTEXT);
|
|
+ typedef DPI_AWARENESS_CONTEXT (WINAPI *GetThreadDpiAwarenessContext)();
|
|
+ typedef BOOL (WINAPI *IsValidDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
|
|
+
|
|
+ // Windows pointer functions (Windows 8 or later).
|
|
+ EnableMouseInPointer enableMouseInPointer = nullptr;
|
|
+ GetPointerType getPointerType = nullptr;
|
|
+ GetPointerInfo getPointerInfo = nullptr;
|
|
+ GetPointerDeviceRects getPointerDeviceRects = nullptr;
|
|
+ GetPointerTouchInfo getPointerTouchInfo = nullptr;
|
|
+ GetPointerFrameTouchInfo getPointerFrameTouchInfo = nullptr;
|
|
+ GetPointerFrameTouchInfoHistory getPointerFrameTouchInfoHistory = nullptr;
|
|
+ GetPointerPenInfo getPointerPenInfo = nullptr;
|
|
+ GetPointerPenInfoHistory getPointerPenInfoHistory = nullptr;
|
|
+ SkipPointerFrameMessages skipPointerFrameMessages = nullptr;
|
|
+
|
|
+ // Windows Vista onwards
|
|
+ SetProcessDPIAware setProcessDPIAware = nullptr;
|
|
+
|
|
+ // Windows 10 version 1607 onwards
|
|
+ GetDpiForWindow getDpiForWindow = nullptr;
|
|
+ GetThreadDpiAwarenessContext getThreadDpiAwarenessContext = nullptr;
|
|
+ IsValidDpiAwarenessContext isValidDpiAwarenessContext = nullptr;
|
|
+
|
|
+ // Windows 10 version 1703 onwards
|
|
+ SetProcessDpiAwarenessContext setProcessDpiAwarenessContext = nullptr;
|
|
+ AreDpiAwarenessContextsEqual areDpiAwarenessContextsEqual = nullptr;
|
|
+
|
|
+ // Clipboard listeners are present on Windows Vista onwards
|
|
+ // but missing in MinGW 4.9 stub libs. Can be removed in MinGW 5.
|
|
+ AddClipboardFormatListener addClipboardFormatListener = nullptr;
|
|
+ RemoveClipboardFormatListener removeClipboardFormatListener = nullptr;
|
|
+
|
|
+ // Rotation API
|
|
+ GetDisplayAutoRotationPreferences getDisplayAutoRotationPreferences = nullptr;
|
|
+ SetDisplayAutoRotationPreferences setDisplayAutoRotationPreferences = nullptr;
|
|
+
|
|
+ AdjustWindowRectExForDpi adjustWindowRectExForDpi = nullptr;
|
|
+ EnableNonClientDpiScaling enableNonClientDpiScaling = nullptr;
|
|
+ GetWindowDpiAwarenessContext getWindowDpiAwarenessContext = nullptr;
|
|
+ GetAwarenessFromDpiAwarenessContext getAwarenessFromDpiAwarenessContext = nullptr;
|
|
+ SystemParametersInfoForDpi systemParametersInfoForDpi = nullptr;
|
|
+ GetSystemMetricsForDpi getSystemMetricsForDpi = nullptr;
|
|
+};
|
|
+
|
|
+// Shell scaling library (Windows 8.1 onwards)
|
|
+struct QWindowsShcoreDLL
|
|
+{
|
|
+ void init();
|
|
+ inline bool isValid() const { return getProcessDpiAwareness && setProcessDpiAwareness && getDpiForMonitor; }
|
|
+
|
|
+ typedef HRESULT (WINAPI *GetProcessDpiAwareness)(HANDLE,PROCESS_DPI_AWARENESS *);
|
|
+ typedef HRESULT (WINAPI *SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
|
|
+ typedef HRESULT (WINAPI *GetDpiForMonitor)(HMONITOR,int,UINT *,UINT *);
|
|
+
|
|
+ GetProcessDpiAwareness getProcessDpiAwareness = nullptr;
|
|
+ SetProcessDpiAwareness setProcessDpiAwareness = nullptr;
|
|
+ GetDpiForMonitor getDpiForMonitor = nullptr;
|
|
+};
|
|
+
|
|
class QWindowsContext
|
|
{
|
|
Q_DISABLE_COPY_MOVE(QWindowsContext)
|
|
@@ -134,6 +224,9 @@ public:
|
|
QWindowsScreenManager &screenManager();
|
|
QWindowsTabletSupport *tabletSupport() const;
|
|
|
|
+ static QWindowsUser32DLL user32dll;
|
|
+ static QWindowsShcoreDLL shcoredll;
|
|
+
|
|
bool asyncExpose() const;
|
|
void setAsyncExpose(bool value);
|
|
|
|
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
|
|
index 5d3a47c22fd..563b22a831f 100644
|
|
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
|
|
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
|
|
@@ -33,6 +33,8 @@
|
|
|
|
#include <shlobj.h>
|
|
|
|
+#include "vxkex.h"
|
|
+
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
/*!
|
|
@@ -674,7 +676,11 @@ static HRESULT startDoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource,
|
|
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
|
|
|
|
POINTER_INFO pointerInfo{};
|
|
- if (!GetPointerInfo(pointerId, &pointerInfo))
|
|
+ BOOL bResultPointerInfo = QWindowsContext::user32dll.getPointerInfo ?
|
|
+ QWindowsContext::user32dll.getPointerInfo(pointerId, &pointerInfo) :
|
|
+ vxkex::GetPointerInfo(pointerId, &pointerInfo);
|
|
+
|
|
+ if (!bResultPointerInfo)
|
|
return E_FAIL;
|
|
|
|
if (pointerInfo.pointerFlags & POINTER_FLAG_PRIMARY) {
|
|
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
|
|
index a9fcf711edd..3a08bd35363 100644
|
|
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
|
|
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
|
|
@@ -140,6 +140,7 @@ static inline unsigned parseOptions(const QStringList ¶mList,
|
|
DarkModeHandling *darkModeHandling)
|
|
{
|
|
unsigned options = 0;
|
|
+
|
|
for (const QString ¶m : paramList) {
|
|
if (param.startsWith(u"fontengine=")) {
|
|
if (param.endsWith(u"gdi")) {
|
|
@@ -485,7 +486,14 @@ QPlatformFontDatabase *QWindowsIntegration::fontDatabase() const
|
|
else
|
|
#endif // QT_NO_FREETYPE
|
|
#if QT_CONFIG(directwrite3)
|
|
- if (!(d->m_options & (QWindowsIntegration::FontDatabaseGDI | QWindowsIntegration::DontUseDirectWriteFonts)))
|
|
+
|
|
+ /* IDWriteFontFace3 is only reportedly available starting with Windows 10. This change is necessary starting
|
|
+ with Qt 6.8, where DirectWrite is used by default to populate the font database.
|
|
+ More info: https://github.com/videolan/vlc/blob/master/contrib/src/qt/0001-Use-DirectWrite-font-database-only-with-Windows-10-a.patch
|
|
+ */
|
|
+
|
|
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10 &&
|
|
+ !(d->m_options & (QWindowsIntegration::FontDatabaseGDI | QWindowsIntegration::DontUseDirectWriteFonts)))
|
|
d->m_fontDatabase = new QWindowsDirectWriteFontDatabase;
|
|
else
|
|
#endif
|
|
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
|
|
index 5b8e4e58ffe..5c84b47794e 100644
|
|
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
|
|
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
|
|
@@ -17,6 +17,8 @@
|
|
#include <QtCore/private/qdebug_p.h>
|
|
#include <QtCore/private/qtools_p.h>
|
|
|
|
+#include "vxkex.h"
|
|
+
|
|
#if defined(WM_APPCOMMAND)
|
|
# ifndef FAPPCOMMAND_MOUSE
|
|
# define FAPPCOMMAND_MOUSE 0x8000
|
|
@@ -732,14 +734,17 @@ static inline QString messageKeyText(const MSG &msg)
|
|
|
|
[[nodiscard]] static inline int getTitleBarHeight(const HWND hwnd)
|
|
{
|
|
- const UINT dpi = GetDpiForWindow(hwnd);
|
|
- const int captionHeight = GetSystemMetricsForDpi(SM_CYCAPTION, dpi);
|
|
+ const BOOL bNewAPI = (QWindowsContext::user32dll.getSystemMetricsForDpi != nullptr);
|
|
+ const UINT dpi = bNewAPI ? QWindowsContext::user32dll.getDpiForWindow(hwnd) : vxkex::GetDpiForWindow(hwnd);
|
|
+ const int captionHeight = bNewAPI ? QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYCAPTION, dpi) : vxkex::GetSystemMetricsForDpi(SM_CYCAPTION, dpi);
|
|
if (IsZoomed(hwnd))
|
|
return captionHeight;
|
|
// The frame height should also be taken into account if the window
|
|
// is not maximized.
|
|
- const int frameHeight = GetSystemMetricsForDpi(SM_CYSIZEFRAME, dpi)
|
|
- + GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
|
+ const int frameHeight = bNewAPI ?
|
|
+ (QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYSIZEFRAME, dpi) + QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi))
|
|
+ : (vxkex::GetSystemMetricsForDpi(SM_CYSIZEFRAME, dpi) + vxkex::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi));
|
|
+
|
|
return captionHeight + frameHeight;
|
|
}
|
|
|
|
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
|
|
index 7995716444a..fab22b394ab 100644
|
|
--- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp
|
|
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
|
|
@@ -26,6 +26,8 @@
|
|
|
|
#include <windowsx.h>
|
|
|
|
+#include "vxkex.h"
|
|
+
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
enum {
|
|
@@ -55,7 +57,11 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
|
*result = 0;
|
|
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
|
|
|
|
- if (!GetPointerType(pointerId, &m_pointerType)) {
|
|
+ BOOL bResultPt = QWindowsContext::user32dll.getPointerType ?
|
|
+ QWindowsContext::user32dll.getPointerType(pointerId, &m_pointerType) :
|
|
+ vxkex::GetPointerType(pointerId, &m_pointerType);
|
|
+
|
|
+ if (!bResultPt) {
|
|
qWarning() << "GetPointerType() failed:" << qt_error_string();
|
|
return false;
|
|
}
|
|
@@ -69,12 +75,21 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
|
}
|
|
case QT_PT_TOUCH: {
|
|
quint32 pointerCount = 0;
|
|
- if (!GetPointerFrameTouchInfo(pointerId, &pointerCount, nullptr)) {
|
|
+ BOOL bResultPointerTouchInfo = QWindowsContext::user32dll.getPointerFrameTouchInfo ?
|
|
+ QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, nullptr) :
|
|
+ vxkex::GetPointerFrameTouchInfo(pointerId, &pointerCount, nullptr);
|
|
+
|
|
+ if (!bResultPointerTouchInfo) {
|
|
qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
|
|
return false;
|
|
}
|
|
QVarLengthArray<POINTER_TOUCH_INFO, 10> touchInfo(pointerCount);
|
|
- if (!GetPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data())) {
|
|
+
|
|
+ bResultPointerTouchInfo = QWindowsContext::user32dll.getPointerFrameTouchInfo ?
|
|
+ QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data()) :
|
|
+ vxkex::GetPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data());
|
|
+
|
|
+ if (!bResultPointerTouchInfo) {
|
|
qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
|
|
return false;
|
|
}
|
|
@@ -87,10 +102,12 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
|
// dispatch any skipped frames if event compression is disabled by the app
|
|
if (historyCount > 1 && !QCoreApplication::testAttribute(Qt::AA_CompressHighFrequencyEvents)) {
|
|
touchInfo.resize(pointerCount * historyCount);
|
|
- if (!GetPointerFrameTouchInfoHistory(pointerId,
|
|
- &historyCount,
|
|
- &pointerCount,
|
|
- touchInfo.data())) {
|
|
+
|
|
+ BOOL bResultTouchHistory = QWindowsContext::user32dll.getPointerFrameTouchInfoHistory ?
|
|
+ QWindowsContext::user32dll.getPointerFrameTouchInfoHistory(pointerId, &historyCount, &pointerCount, touchInfo.data()) :
|
|
+ vxkex::GetPointerFrameTouchInfoHistory(pointerId, &historyCount, &pointerCount, touchInfo.data());
|
|
+
|
|
+ if (!bResultTouchHistory) {
|
|
qWarning() << "GetPointerFrameTouchInfoHistory() failed:" << qt_error_string();
|
|
return false;
|
|
}
|
|
@@ -108,7 +125,11 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
|
}
|
|
case QT_PT_PEN: {
|
|
POINTER_PEN_INFO penInfo;
|
|
- if (!GetPointerPenInfo(pointerId, &penInfo)) {
|
|
+
|
|
+ BOOL bResultPenInfo = QWindowsContext::user32dll.getPointerPenInfo ?
|
|
+ QWindowsContext::user32dll.getPointerPenInfo(pointerId, &penInfo) : vxkex::GetPointerPenInfo(pointerId, &penInfo);
|
|
+
|
|
+ if (!bResultPenInfo) {
|
|
qWarning() << "GetPointerPenInfo() failed:" << qt_error_string();
|
|
return false;
|
|
}
|
|
@@ -120,7 +141,11 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
|
|| !QCoreApplication::testAttribute(Qt::AA_CompressTabletEvents))) {
|
|
QVarLengthArray<POINTER_PEN_INFO, 10> penInfoHistory(historyCount);
|
|
|
|
- if (!GetPointerPenInfoHistory(pointerId, &historyCount, penInfoHistory.data())) {
|
|
+ BOOL bResultPenInfoHistory = QWindowsContext::user32dll.getPointerPenInfoHistory ?
|
|
+ QWindowsContext::user32dll.getPointerPenInfoHistory(pointerId, &historyCount, penInfoHistory.data()) :
|
|
+ vxkex::GetPointerPenInfoHistory(pointerId, &historyCount, penInfoHistory.data());
|
|
+
|
|
+ if (!bResultPenInfoHistory) {
|
|
qWarning() << "GetPointerPenInfoHistory() failed:" << qt_error_string();
|
|
return false;
|
|
}
|
|
@@ -527,7 +552,10 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
|
|
inputIds.insert(touchPoint.id);
|
|
|
|
// Avoid getting repeated messages for this frame if there are multiple pointerIds
|
|
- SkipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
|
|
+ if (QWindowsContext::user32dll.skipPointerFrameMessages)
|
|
+ QWindowsContext::user32dll.skipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
|
|
+ else
|
|
+ vxkex::SkipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
|
|
}
|
|
|
|
// Some devices send touches for each finger in a different message/frame, instead of consolidating
|
|
@@ -574,7 +602,12 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
|
|
auto *penInfo = static_cast<POINTER_PEN_INFO *>(vPenInfo);
|
|
|
|
RECT pRect, dRect;
|
|
- if (!GetPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect))
|
|
+
|
|
+ BOOL bResultDeviceRects = QWindowsContext::user32dll.getPointerDeviceRects ?
|
|
+ QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect) :
|
|
+ vxkex::GetPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect);
|
|
+
|
|
+ if (!bResultDeviceRects)
|
|
return false;
|
|
|
|
const auto systemId = (qint64)penInfo->pointerInfo.sourceDevice;
|
|
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
|
|
index 6c86c47caac..24588473185 100644
|
|
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
|
|
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
|
|
@@ -32,6 +32,8 @@
|
|
#include <setupapi.h>
|
|
#include <shellscalingapi.h>
|
|
|
|
+#include "vxkex.h"
|
|
+
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
using namespace Qt::StringLiterals;
|
|
@@ -45,7 +47,15 @@ static inline QDpi monitorDPI(HMONITOR hMonitor)
|
|
{
|
|
UINT dpiX;
|
|
UINT dpiY;
|
|
- if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY)))
|
|
+
|
|
+ HRESULT hr = S_OK;
|
|
+
|
|
+ if (QWindowsContext::shcoredll.isValid())
|
|
+ hr = QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
|
|
+ else
|
|
+ hr = vxkex::GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
|
|
+
|
|
+ if (SUCCEEDED(hr))
|
|
return QDpi(dpiX, dpiY);
|
|
return {0, 0};
|
|
}
|
|
@@ -609,7 +619,10 @@ bool QWindowsScreen::setOrientationPreference(Qt::ScreenOrientation o)
|
|
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED;
|
|
break;
|
|
}
|
|
- result = SetDisplayAutoRotationPreferences(orientationPreference);
|
|
+ if (QWindowsContext::user32dll.setDisplayAutoRotationPreferences)
|
|
+ result = QWindowsContext::user32dll.setDisplayAutoRotationPreferences(orientationPreference);
|
|
+ else
|
|
+ result = vxkex::SetDisplayAutoRotationPreferences(orientationPreference);
|
|
return result;
|
|
}
|
|
|
|
@@ -617,7 +630,15 @@ Qt::ScreenOrientation QWindowsScreen::orientationPreference()
|
|
{
|
|
Qt::ScreenOrientation result = Qt::PrimaryOrientation;
|
|
ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
|
- if (GetDisplayAutoRotationPreferences(&orientationPreference)) {
|
|
+
|
|
+ BOOL bResult = TRUE;
|
|
+
|
|
+ if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences)
|
|
+ bResult = QWindowsContext::user32dll.getDisplayAutoRotationPreferences((DWORD *)&orientationPreference);
|
|
+ else
|
|
+ bResult = vxkex::GetDisplayAutoRotationPreferences(&orientationPreference);
|
|
+
|
|
+ if (bResult) {
|
|
switch (orientationPreference) {
|
|
case ORIENTATION_PREFERENCE_NONE:
|
|
break;
|
|
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
|
|
index 97b2dd339be..2d6dbf36adc 100644
|
|
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
|
|
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
|
|
@@ -45,6 +45,8 @@
|
|
|
|
#include <algorithm>
|
|
|
|
+#include "vxkex.h"
|
|
+
|
|
#if QT_CONFIG(cpp_winrt)
|
|
# include <QtCore/private/qt_winrtbase_p.h>
|
|
|
|
@@ -97,36 +99,52 @@ static constexpr QColor getSysColor(winrt::Windows::UI::Color &&color)
|
|
|
|
[[maybe_unused]] [[nodiscard]] static inline QColor qt_accentColor(AccentColorLevel level)
|
|
{
|
|
+ QColor accent;
|
|
+ QColor accentLight;
|
|
+ QColor accentLighter;
|
|
+ QColor accentLightest;
|
|
+ QColor accentDark;
|
|
+ QColor accentDarker;
|
|
+ QColor accentDarkest;
|
|
+
|
|
#if QT_CONFIG(cpp_winrt)
|
|
- using namespace winrt::Windows::UI::ViewManagement;
|
|
- const auto settings = UISettings();
|
|
- const QColor accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
|
|
- const QColor accentLight = getSysColor(settings.GetColorValue(UIColorType::AccentLight1));
|
|
- const QColor accentLighter = getSysColor(settings.GetColorValue(UIColorType::AccentLight2));
|
|
- const QColor accentLightest = getSysColor(settings.GetColorValue(UIColorType::AccentLight3));
|
|
- const QColor accentDark = getSysColor(settings.GetColorValue(UIColorType::AccentDark1));
|
|
- const QColor accentDarker = getSysColor(settings.GetColorValue(UIColorType::AccentDark2));
|
|
- const QColor accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
|
|
-#else
|
|
- const QWinRegistryKey registry(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\DWM)");
|
|
- if (!registry.isValid())
|
|
- return {};
|
|
- const QVariant value = registry.value(L"AccentColor");
|
|
- if (!value.isValid())
|
|
- return {};
|
|
- // The retrieved value is in the #AABBGGRR format, we need to
|
|
- // convert it to the #AARRGGBB format which Qt expects.
|
|
- const QColor abgr = QColor::fromRgba(qvariant_cast<DWORD>(value));
|
|
- if (!abgr.isValid())
|
|
- return {};
|
|
- const QColor accent = QColor::fromRgb(abgr.blue(), abgr.green(), abgr.red(), abgr.alpha());
|
|
- const QColor accentLight = accent.lighter(120);
|
|
- const QColor accentLighter = accentLight.lighter(120);
|
|
- const QColor accentLightest = accentLighter.lighter(120);
|
|
- const QColor accentDark = accent.darker(120);
|
|
- const QColor accentDarker = accentDark.darker(120);
|
|
- const QColor accentDarkest = accentDarker.darker(120);
|
|
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10)
|
|
+ {
|
|
+ using namespace winrt::Windows::UI::ViewManagement;
|
|
+ const auto settings = UISettings();
|
|
+ accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
|
|
+ accentLight = getSysColor(settings.GetColorValue(UIColorType::AccentLight1));
|
|
+ accentLighter = getSysColor(settings.GetColorValue(UIColorType::AccentLight2));
|
|
+ accentLightest = getSysColor(settings.GetColorValue(UIColorType::AccentLight3));
|
|
+ accentDark = getSysColor(settings.GetColorValue(UIColorType::AccentDark1));
|
|
+ accentDarker = getSysColor(settings.GetColorValue(UIColorType::AccentDark2));
|
|
+ accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
|
|
+ }
|
|
#endif
|
|
+
|
|
+ if (!accent.isValid())
|
|
+ {
|
|
+ const QWinRegistryKey registry(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\DWM)");
|
|
+ if (!registry.isValid())
|
|
+ return {};
|
|
+ const QVariant value = registry.value(L"AccentColor");
|
|
+ if (!value.isValid())
|
|
+ return {};
|
|
+ // The retrieved value is in the #AABBGGRR format, we need to
|
|
+ // convert it to the #AARRGGBB format which Qt expects.
|
|
+ const QColor abgr = QColor::fromRgba(qvariant_cast<DWORD>(value));
|
|
+ if (!abgr.isValid())
|
|
+ return {};
|
|
+ accent = QColor::fromRgb(abgr.blue(), abgr.green(), abgr.red(), abgr.alpha());
|
|
+ accentLight = accent.lighter(120);
|
|
+ accentLighter = accentLight.lighter(120);
|
|
+ accentLightest = accentLighter.lighter(120);
|
|
+ accentDarkest = accent.darker(120 * 120 * 120);
|
|
+ accentDark = accent.darker(120);
|
|
+ accentDarker = accentDark.darker(120);
|
|
+ accentDarkest = accentDarker.darker(120);
|
|
+ }
|
|
+
|
|
switch (level) {
|
|
case AccentColorDarkest:
|
|
return accentDarkest;
|
|
@@ -154,6 +172,7 @@ static inline QColor getSysColor(int index)
|
|
// QTBUG-48823/Windows 10: SHGetFileInfo() (as called by item views on file system
|
|
// models has been observed to trigger a WM_PAINT on the mainwindow. Suppress the
|
|
// behavior by running it in a thread.
|
|
+
|
|
class QShGetFileInfoThread : public QThread
|
|
{
|
|
public:
|
|
@@ -326,46 +345,45 @@ void QWindowsTheme::populateLightSystemBasePalette(QPalette &result)
|
|
|
|
void QWindowsTheme::populateDarkSystemBasePalette(QPalette &result)
|
|
{
|
|
- QColor foreground, background,
|
|
- accent, accentDark, accentDarker, accentDarkest,
|
|
- accentLight, accentLighter, accentLightest;
|
|
+ QColor foreground = Qt::white;
|
|
+ QColor background = QColor(0x1E, 0x1E, 0x1E);
|
|
+ QColor accent = qt_accentColor(AccentColorNormal);
|
|
+ QColor accentDark = accent.darker(120);
|
|
+ QColor accentDarker = accentDark.darker(120);
|
|
+ QColor accentDarkest = accentDarker.darker(120);
|
|
+ QColor accentLight = accent.lighter(120);
|
|
+ QColor accentLighter = accentLight.lighter(120);
|
|
+ QColor accentLightest = accentLighter.lighter(120);
|
|
+
|
|
#if QT_CONFIG(cpp_winrt)
|
|
- using namespace winrt::Windows::UI::ViewManagement;
|
|
- const auto settings = UISettings();
|
|
-
|
|
- // We have to craft a palette from these colors. The settings.UIElementColor(UIElementType) API
|
|
- // returns the old system colors, not the dark mode colors. If the background is black (which it
|
|
- // usually), then override it with a dark gray instead so that we can go up and down the lightness.
|
|
- if (QWindowsTheme::queryColorScheme() == Qt::ColorScheme::Dark) {
|
|
- // the system is actually running in dark mode, so UISettings will give us dark colors
|
|
- foreground = getSysColor(settings.GetColorValue(UIColorType::Foreground));
|
|
- background = [&settings]() -> QColor {
|
|
- auto systemBackground = getSysColor(settings.GetColorValue(UIColorType::Background));
|
|
- if (systemBackground == Qt::black)
|
|
- systemBackground = QColor(0x1E, 0x1E, 0x1E);
|
|
- return systemBackground;
|
|
- }();
|
|
- accent = qt_accentColor(AccentColorNormal);
|
|
- accentDark = qt_accentColor(AccentColorDark);
|
|
- accentDarker = qt_accentColor(AccentColorDarker);
|
|
- accentDarkest = qt_accentColor(AccentColorDarkest);
|
|
- accentLight = qt_accentColor(AccentColorLight);
|
|
- accentLighter = qt_accentColor(AccentColorLighter);
|
|
- accentLightest = qt_accentColor(AccentColorLightest);
|
|
- } else
|
|
-#endif
|
|
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10)
|
|
{
|
|
- // If the system is running in light mode, then we need to make up our own dark palette
|
|
- foreground = Qt::white;
|
|
- background = QColor(0x1E, 0x1E, 0x1E);
|
|
- accent = qt_accentColor(AccentColorNormal);
|
|
- accentDark = accent.darker(120);
|
|
- accentDarker = accentDark.darker(120);
|
|
- accentDarkest = accentDarker.darker(120);
|
|
- accentLight = accent.lighter(120);
|
|
- accentLighter = accentLight.lighter(120);
|
|
- accentLightest = accentLighter.lighter(120);
|
|
+ using namespace winrt::Windows::UI::ViewManagement;
|
|
+ const auto settings = UISettings();
|
|
+
|
|
+ // We have to craft a palette from these colors. The settings.UIElementColor(UIElementType) API
|
|
+ // returns the old system colors, not the dark mode colors. If the background is black (which it
|
|
+ // usually), then override it with a dark gray instead so that we can go up and down the lightness.
|
|
+ if (QWindowsTheme::queryColorScheme() == Qt::ColorScheme::Dark) {
|
|
+ // the system is actually running in dark mode, so UISettings will give us dark colors
|
|
+ foreground = getSysColor(settings.GetColorValue(UIColorType::Foreground));
|
|
+ background = [&settings]() -> QColor {
|
|
+ auto systemBackground = getSysColor(settings.GetColorValue(UIColorType::Background));
|
|
+ if (systemBackground == Qt::black)
|
|
+ systemBackground = QColor(0x1E, 0x1E, 0x1E);
|
|
+ return systemBackground;
|
|
+ }();
|
|
+ accent = qt_accentColor(AccentColorNormal);
|
|
+ accentDark = qt_accentColor(AccentColorDark);
|
|
+ accentDarker = qt_accentColor(AccentColorDarker);
|
|
+ accentDarkest = qt_accentColor(AccentColorDarkest);
|
|
+ accentLight = qt_accentColor(AccentColorLight);
|
|
+ accentLighter = qt_accentColor(AccentColorLighter);
|
|
+ accentLightest = qt_accentColor(AccentColorLightest);
|
|
+ }
|
|
}
|
|
+#endif
|
|
+
|
|
const QColor linkColor = accentLightest;
|
|
const QColor buttonColor = background.lighter(200);
|
|
|
|
@@ -738,7 +756,10 @@ void QWindowsTheme::refreshFonts()
|
|
fixedFont.setStyleHint(QFont::TypeWriter);
|
|
|
|
LOGFONT lfIconTitleFont;
|
|
- SystemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
|
|
+ if (QWindowsContext::user32dll.systemParametersInfoForDpi)
|
|
+ QWindowsContext::user32dll.systemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
|
|
+ else
|
|
+ vxkex::SystemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
|
|
const QFont iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont, dpi);
|
|
|
|
m_fonts[SystemFont] = new QFont(QWindowsFontDatabase::systemDefaultFont());
|
|
@@ -1001,6 +1022,7 @@ public:
|
|
static QPixmap pixmapFromShellImageList(int iImageList, int iIcon)
|
|
{
|
|
QPixmap result;
|
|
+
|
|
// For MinGW:
|
|
static const IID iID_IImageList = {0x46eb5926, 0x582e, 0x4017, {0x9f, 0xdf, 0xe8, 0x99, 0x8d, 0xaa, 0x9, 0x50}};
|
|
|
|
@@ -1015,6 +1037,7 @@ static QPixmap pixmapFromShellImageList(int iImageList, int iIcon)
|
|
DestroyIcon(hIcon);
|
|
}
|
|
imageList->Release();
|
|
+
|
|
return result;
|
|
}
|
|
|
|
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
|
|
index f44a28f5636..6d6409c7878 100644
|
|
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
|
|
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
|
|
@@ -46,6 +46,8 @@
|
|
|
|
#include <shellscalingapi.h>
|
|
|
|
+#include "vxkex.h"
|
|
+
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
using QWindowCreationContextPtr = QSharedPointer<QWindowCreationContext>;
|
|
@@ -522,11 +524,15 @@ static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::Windo
|
|
|
|
[[nodiscard]] static inline int getResizeBorderThickness(const UINT dpi)
|
|
{
|
|
- // The width of the padded border will always be 0 if DWM composition is
|
|
- // disabled, but since it will always be enabled and can't be programtically
|
|
- // disabled from Windows 8, we are safe to go.
|
|
- return GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi)
|
|
- + GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
|
+ if (QWindowsContext::user32dll.getSystemMetricsForDpi) {
|
|
+ // The width of the padded border will always be 0 if DWM composition is
|
|
+ // disabled, but since it will always be enabled and can't be programtically
|
|
+ // disabled from Windows 8, we are safe to go.
|
|
+ return QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi)
|
|
+ + QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
|
+ }
|
|
+ else
|
|
+ return vxkex::GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + vxkex::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
|
}
|
|
|
|
/*!
|
|
@@ -538,11 +544,21 @@ static QMargins invisibleMargins(QPoint screenPoint)
|
|
{
|
|
POINT pt = {screenPoint.x(), screenPoint.y()};
|
|
if (HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
|
|
- UINT dpiX;
|
|
- UINT dpiY;
|
|
- if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY))) {
|
|
- const int gap = getResizeBorderThickness(dpiX);
|
|
- return QMargins(gap, 0, gap, gap);
|
|
+ if (QWindowsContext::shcoredll.isValid()) {
|
|
+ UINT dpiX;
|
|
+ UINT dpiY;
|
|
+
|
|
+ HRESULT hr = S_OK;
|
|
+
|
|
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10)
|
|
+ hr = QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
|
|
+ else
|
|
+ hr = vxkex::GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
|
|
+
|
|
+ if (SUCCEEDED(hr)) {
|
|
+ const int gap = getResizeBorderThickness(dpiX);
|
|
+ return QMargins(gap, 0, gap, gap);
|
|
+ }
|
|
}
|
|
}
|
|
return QMargins();
|
|
@@ -550,7 +566,8 @@ static QMargins invisibleMargins(QPoint screenPoint)
|
|
|
|
[[nodiscard]] static inline QMargins invisibleMargins(const HWND hwnd)
|
|
{
|
|
- const UINT dpi = GetDpiForWindow(hwnd);
|
|
+ const UINT dpi = (QWindowsContext::user32dll.getDpiForWindow) ? QWindowsContext::user32dll.getDpiForWindow(hwnd) : vxkex::GetDpiForWindow(hwnd);
|
|
+
|
|
const int gap = getResizeBorderThickness(dpi);
|
|
return QMargins(gap, 0, gap, gap);
|
|
}
|
|
@@ -851,7 +868,7 @@ static inline bool shouldApplyDarkFrame(const QWindow *w)
|
|
{
|
|
if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint))
|
|
return false;
|
|
-
|
|
+
|
|
// the user of the application has explicitly opted out of dark frames
|
|
if (!QWindowsIntegration::instance()->darkModeHandling().testFlag(QWindowsApplication::DarkModeWindowFrames))
|
|
return false;
|
|
@@ -1071,9 +1088,17 @@ QMargins QWindowsGeometryHint::frame(const QWindow *w, DWORD style, DWORD exStyl
|
|
return {};
|
|
RECT rect = {0,0,0,0};
|
|
style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
|
|
- if (AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi))) == FALSE) {
|
|
- qErrnoWarning("%s: AdjustWindowRectExForDpi failed", __FUNCTION__);
|
|
+ if (QWindowsContext::user32dll.adjustWindowRectExForDpi)
|
|
+ {
|
|
+ if (QWindowsContext::user32dll.adjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi))) == FALSE)
|
|
+ qErrnoWarning("%s: AdjustWindowRectExForDpi failed", __FUNCTION__);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ if (vxkex::AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi))) == FALSE)
|
|
+ qErrnoWarning("%s: vxkex::AdjustWindowRectExForDpi failed", __FUNCTION__);
|
|
}
|
|
+
|
|
const QMargins result(qAbs(rect.left), qAbs(rect.top),
|
|
qAbs(rect.right), qAbs(rect.bottom));
|
|
qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << " style="
|
|
@@ -1380,7 +1405,7 @@ void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow)
|
|
qCDebug(lcQpaWindow) << __FUNCTION__ << window() << "newParent="
|
|
<< newParentWindow << newParent << "oldStyle=" << debugWinStyle(oldStyle);
|
|
|
|
- auto updateWindowFlags = [&] {
|
|
+ auto updateWindowFlags = [&]{
|
|
// Top level window flags need to be set/cleared manually.
|
|
DWORD newStyle = oldStyle;
|
|
if (isTopLevel) {
|
|
@@ -1588,7 +1613,8 @@ void QWindowsWindow::initialize()
|
|
QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(w, obtainedGeometry);
|
|
}
|
|
}
|
|
- QWindowsWindow::setSavedDpi(GetDpiForWindow(handle()));
|
|
+ QWindowsWindow::setSavedDpi(QWindowsContext::user32dll.getDpiForWindow ?
|
|
+ QWindowsContext::user32dll.getDpiForWindow(handle()) : vxkex::GetDpiForWindow(handle()));
|
|
}
|
|
|
|
QSurfaceFormat QWindowsWindow::format() const
|
|
@@ -2083,7 +2109,7 @@ void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|
|
|
void QWindowsWindow::handleDpiChangedAfterParent(HWND hwnd)
|
|
{
|
|
- const UINT dpi = GetDpiForWindow(hwnd);
|
|
+ const UINT dpi = QWindowsContext::user32dll.getDpiForWindow ? QWindowsContext::user32dll.getDpiForWindow(hwnd) : vxkex::GetDpiForWindow(hwnd);
|
|
const qreal scale = dpiRelativeScale(dpi);
|
|
setSavedDpi(dpi);
|
|
|
|
@@ -2177,6 +2203,7 @@ void QWindowsWindow::setGeometry(const QRect &rectIn)
|
|
}
|
|
if (m_windowState & Qt::WindowMinimized)
|
|
m_data.geometry = rect; // Otherwise set by handleGeometryChange() triggered by event.
|
|
+
|
|
if (m_data.hwnd) {
|
|
// A ResizeEvent with resulting geometry will be sent. If we cannot
|
|
// achieve that size (for example, window title minimal constraint),
|
|
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
|
|
index 638d684ce4f..1c89fd87ede 100644
|
|
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
|
|
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
|
|
@@ -15,6 +15,8 @@
|
|
#include <QtGui/private/qguiapplication_p.h>
|
|
#include <QtCore/qt_windows.h>
|
|
#include <qpa/qplatformintegration.h>
|
|
+#include "qwindowsuiawrapper_p.h"
|
|
+#include "qwindowsuiawrapper.cpp"
|
|
|
|
#include <QtCore/private/qwinregistry_p.h>
|
|
|
|
@@ -47,7 +49,7 @@ bool QWindowsUiaAccessibility::handleWmGetObject(HWND hwnd, WPARAM wParam, LPARA
|
|
if (QWindow *window = QWindowsContext::instance()->findWindow(hwnd)) {
|
|
if (QAccessibleInterface *accessible = window->accessibleRoot()) {
|
|
auto provider = QWindowsUiaMainProvider::providerForAccessible(accessible);
|
|
- *lResult = UiaReturnRawElementProvider(hwnd, wParam, lParam, provider.Get());
|
|
+ *lResult = QWindowsUiaWrapper::instance()->returnRawElementProvider(hwnd, wParam, lParam, provider.Get());
|
|
return true;
|
|
}
|
|
}
|
|
@@ -122,8 +124,12 @@ void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event
|
|
if (!isActive() || !accessible || !accessible->isValid())
|
|
return;
|
|
|
|
+ // Ensures QWindowsUiaWrapper is properly initialized.
|
|
+ if (!QWindowsUiaWrapper::instance()->ready())
|
|
+ return;
|
|
+
|
|
// No need to do anything when nobody is listening.
|
|
- if (!UiaClientsAreListening())
|
|
+ if (!QWindowsUiaWrapper::instance()->clientsAreListening())
|
|
return;
|
|
|
|
switch (event->type()) {
|
|
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
|
|
index f01c594b6cd..02e853da78b 100644
|
|
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
|
|
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
|
|
@@ -21,6 +21,7 @@
|
|
#include "qwindowscontext.h"
|
|
#include "qwindowsuiautils.h"
|
|
#include "qwindowsuiaprovidercache.h"
|
|
+#include "qwindowsuiawrapper_p.h"
|
|
|
|
#include <QtCore/qloggingcategory.h>
|
|
#include <QtGui/private/qaccessiblebridgeutils_p.h>
|
|
@@ -75,7 +76,7 @@ void QWindowsUiaMainProvider::notifyFocusChange(QAccessibleEvent *event)
|
|
accessible = child;
|
|
}
|
|
if (auto provider = providerForAccessible(accessible))
|
|
- UiaRaiseAutomationEvent(provider.Get(), UIA_AutomationFocusChangedEventId);
|
|
+ QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider.Get(), UIA_AutomationFocusChangedEventId);
|
|
}
|
|
}
|
|
|
|
@@ -92,7 +93,7 @@ void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *eve
|
|
|
|
QComVariant oldVal;
|
|
QComVariant newVal{toggleState};
|
|
- UiaRaiseAutomationPropertyChangedEvent(
|
|
+ QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(
|
|
provider.Get(), UIA_ToggleToggleStatePropertyId, oldVal.get(), newVal.get());
|
|
}
|
|
}
|
|
@@ -102,15 +103,15 @@ void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *eve
|
|
// Notifies window opened/closed.
|
|
if (auto provider = providerForAccessible(accessible)) {
|
|
if (accessible->state().active) {
|
|
- UiaRaiseAutomationEvent(provider.Get(), UIA_Window_WindowOpenedEventId);
|
|
+ QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider.Get(), UIA_Window_WindowOpenedEventId);
|
|
if (QAccessibleInterface *focused = accessible->focusChild()) {
|
|
if (auto focusedProvider = providerForAccessible(focused)) {
|
|
- UiaRaiseAutomationEvent(focusedProvider.Get(),
|
|
+ QWindowsUiaWrapper::instance()->raiseAutomationEvent(focusedProvider.Get(),
|
|
UIA_AutomationFocusChangedEventId);
|
|
}
|
|
}
|
|
} else {
|
|
- UiaRaiseAutomationEvent(provider.Get(), UIA_Window_WindowClosedEventId);
|
|
+ QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider.Get(), UIA_Window_WindowClosedEventId);
|
|
}
|
|
}
|
|
}
|
|
@@ -142,7 +143,7 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve
|
|
// Notifies changes in string values.
|
|
const QComVariant oldVal;
|
|
const QComVariant newVal{ event->value().toString() };
|
|
- UiaRaiseAutomationPropertyChangedEvent(provider.Get(), UIA_ValueValuePropertyId,
|
|
+ QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider.Get(), UIA_ValueValuePropertyId,
|
|
oldVal.get(), newVal.get());
|
|
}
|
|
} else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
|
|
@@ -150,7 +151,7 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve
|
|
// Notifies changes in values of controls supporting the value interface.
|
|
const QComVariant oldVal;
|
|
const QComVariant newVal{ valueInterface->currentValue().toDouble() };
|
|
- UiaRaiseAutomationPropertyChangedEvent(
|
|
+ QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(
|
|
provider.Get(), UIA_RangeValueValuePropertyId, oldVal.get(), newVal.get());
|
|
}
|
|
}
|
|
@@ -166,7 +167,7 @@ void QWindowsUiaMainProvider::notifyNameChange(QAccessibleEvent *event)
|
|
if (auto provider = providerForAccessible(accessible)) {
|
|
QComVariant oldVal;
|
|
QComVariant newVal{ accessible->text(QAccessible::Name) };
|
|
- UiaRaiseAutomationPropertyChangedEvent(provider.Get(), UIA_NamePropertyId,
|
|
+ QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider.Get(), UIA_NamePropertyId,
|
|
oldVal.get(), newVal.get());
|
|
}
|
|
}
|
|
@@ -177,7 +178,7 @@ void QWindowsUiaMainProvider::notifySelectionChange(QAccessibleEvent *event)
|
|
{
|
|
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
|
|
if (auto provider = providerForAccessible(accessible))
|
|
- UiaRaiseAutomationEvent(provider.Get(), UIA_SelectionItem_ElementSelectedEventId);
|
|
+ QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider.Get(), UIA_SelectionItem_ElementSelectedEventId);
|
|
}
|
|
}
|
|
|
|
@@ -188,14 +189,14 @@ void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event)
|
|
if (accessible->textInterface()) {
|
|
if (auto provider = providerForAccessible(accessible)) {
|
|
if (event->type() == QAccessible::TextSelectionChanged) {
|
|
- UiaRaiseAutomationEvent(provider.Get(), UIA_Text_TextSelectionChangedEventId);
|
|
+ QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider.Get(), UIA_Text_TextSelectionChangedEventId);
|
|
} else if (event->type() == QAccessible::TextCaretMoved) {
|
|
if (!accessible->state().readOnly) {
|
|
- UiaRaiseAutomationEvent(provider.Get(),
|
|
+ QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider.Get(),
|
|
UIA_Text_TextSelectionChangedEventId);
|
|
}
|
|
} else {
|
|
- UiaRaiseAutomationEvent(provider.Get(), UIA_Text_TextChangedEventId);
|
|
+ QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider.Get(), UIA_Text_TextChangedEventId);
|
|
}
|
|
}
|
|
}
|
|
@@ -212,7 +213,7 @@ void QWindowsUiaMainProvider::raiseNotification(QAccessibleAnnouncementEvent *ev
|
|
? NotificationProcessing_ImportantAll
|
|
: NotificationProcessing_All;
|
|
QBStr activityId{ QString::fromLatin1("") };
|
|
- UiaRaiseNotificationEvent(provider.Get(), NotificationKind_Other, processing, message.bstr(),
|
|
+ QWindowsUiaWrapper::instance()->raiseNotificationEvent(provider.Get(), NotificationKind_Other, processing, message.bstr(),
|
|
activityId.bstr());
|
|
|
|
}
|
|
@@ -615,7 +616,7 @@ HRESULT QWindowsUiaMainProvider::get_HostRawElementProvider(IRawElementProviderS
|
|
// Returns a host provider only for controls associated with a native window handle. Others should return NULL.
|
|
if (QAccessibleInterface *accessible = accessibleInterface()) {
|
|
if (HWND hwnd = hwndForAccessible(accessible)) {
|
|
- return UiaHostProviderFromHwnd(hwnd, pRetVal);
|
|
+ return QWindowsUiaWrapper::instance()->hostProviderFromHwnd(hwnd, pRetVal);
|
|
}
|
|
}
|
|
return S_OK;
|
|
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiawrapper.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiawrapper.cpp
|
|
new file mode 100644
|
|
index 00000000000..caeb8e1da48
|
|
--- /dev/null
|
|
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiawrapper.cpp
|
|
@@ -0,0 +1,89 @@
|
|
+// Copyright (C) 2017 The Qt Company Ltd.
|
|
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
|
+
|
|
+#include <initguid.h>
|
|
+
|
|
+#include "qwindowsuiawrapper_p.h"
|
|
+#include <QtCore/private/qsystemlibrary_p.h>
|
|
+
|
|
+QT_BEGIN_NAMESPACE
|
|
+
|
|
+// private constructor
|
|
+QWindowsUiaWrapper::QWindowsUiaWrapper()
|
|
+{
|
|
+ QSystemLibrary uiaLib(QStringLiteral("UIAutomationCore"));
|
|
+ if (uiaLib.load()) {
|
|
+ m_pUiaReturnRawElementProvider = reinterpret_cast<PtrUiaReturnRawElementProvider>(uiaLib.resolve("UiaReturnRawElementProvider"));
|
|
+ m_pUiaHostProviderFromHwnd = reinterpret_cast<PtrUiaHostProviderFromHwnd>(uiaLib.resolve("UiaHostProviderFromHwnd"));
|
|
+ m_pUiaRaiseAutomationPropertyChangedEvent = reinterpret_cast<PtrUiaRaiseAutomationPropertyChangedEvent>(uiaLib.resolve("UiaRaiseAutomationPropertyChangedEvent"));
|
|
+ m_pUiaRaiseAutomationEvent = reinterpret_cast<PtrUiaRaiseAutomationEvent>(uiaLib.resolve("UiaRaiseAutomationEvent"));
|
|
+ m_pUiaRaiseNotificationEvent = reinterpret_cast<PtrUiaRaiseNotificationEvent>(uiaLib.resolve("UiaRaiseNotificationEvent"));
|
|
+ m_pUiaClientsAreListening = reinterpret_cast<PtrUiaClientsAreListening>(uiaLib.resolve("UiaClientsAreListening"));
|
|
+ }
|
|
+}
|
|
+
|
|
+QWindowsUiaWrapper::~QWindowsUiaWrapper()
|
|
+{
|
|
+}
|
|
+
|
|
+// shared instance
|
|
+QWindowsUiaWrapper *QWindowsUiaWrapper::instance()
|
|
+{
|
|
+ static QWindowsUiaWrapper wrapper;
|
|
+ return &wrapper;
|
|
+}
|
|
+
|
|
+// True if all symbols resolved.
|
|
+BOOL QWindowsUiaWrapper::ready()
|
|
+{
|
|
+ return m_pUiaReturnRawElementProvider
|
|
+ && m_pUiaHostProviderFromHwnd
|
|
+ && m_pUiaRaiseAutomationPropertyChangedEvent
|
|
+ && m_pUiaRaiseAutomationEvent
|
|
+ && m_pUiaClientsAreListening;
|
|
+}
|
|
+
|
|
+BOOL QWindowsUiaWrapper::clientsAreListening()
|
|
+{
|
|
+ if (!m_pUiaClientsAreListening)
|
|
+ return FALSE;
|
|
+ return m_pUiaClientsAreListening();
|
|
+}
|
|
+
|
|
+LRESULT QWindowsUiaWrapper::returnRawElementProvider(HWND hwnd, WPARAM wParam, LPARAM lParam, IRawElementProviderSimple *el)
|
|
+{
|
|
+ if (!m_pUiaReturnRawElementProvider)
|
|
+ return static_cast<LRESULT>(NULL);
|
|
+ return m_pUiaReturnRawElementProvider(hwnd, wParam, lParam, el);
|
|
+}
|
|
+
|
|
+HRESULT QWindowsUiaWrapper::hostProviderFromHwnd(HWND hwnd, IRawElementProviderSimple **ppProvider)
|
|
+{
|
|
+ if (!m_pUiaHostProviderFromHwnd)
|
|
+ return UIA_E_NOTSUPPORTED;
|
|
+ return m_pUiaHostProviderFromHwnd(hwnd, ppProvider);
|
|
+}
|
|
+
|
|
+HRESULT QWindowsUiaWrapper::raiseAutomationPropertyChangedEvent(IRawElementProviderSimple *pProvider, PROPERTYID id, VARIANT oldValue, VARIANT newValue)
|
|
+{
|
|
+ if (!m_pUiaRaiseAutomationPropertyChangedEvent)
|
|
+ return UIA_E_NOTSUPPORTED;
|
|
+ return m_pUiaRaiseAutomationPropertyChangedEvent(pProvider, id, oldValue, newValue);
|
|
+}
|
|
+
|
|
+HRESULT QWindowsUiaWrapper::raiseAutomationEvent(IRawElementProviderSimple *pProvider, EVENTID id)
|
|
+{
|
|
+ if (!m_pUiaRaiseAutomationEvent)
|
|
+ return UIA_E_NOTSUPPORTED;
|
|
+ return m_pUiaRaiseAutomationEvent(pProvider, id);
|
|
+}
|
|
+
|
|
+HRESULT QWindowsUiaWrapper::raiseNotificationEvent(IRawElementProviderSimple *pProvider, NotificationKind notificationKind, NotificationProcessing notificationProcessing, BSTR displayString, BSTR activityId)
|
|
+{
|
|
+ if (!m_pUiaRaiseNotificationEvent)
|
|
+ return UIA_E_NOTSUPPORTED;
|
|
+ return m_pUiaRaiseNotificationEvent(pProvider, notificationKind, notificationProcessing, displayString, activityId);
|
|
+}
|
|
+
|
|
+QT_END_NAMESPACE
|
|
+
|
|
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiawrapper_p.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiawrapper_p.h
|
|
new file mode 100644
|
|
index 00000000000..e005318114c
|
|
--- /dev/null
|
|
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiawrapper_p.h
|
|
@@ -0,0 +1,57 @@
|
|
+// Copyright (C) 2017 The Qt Company Ltd.
|
|
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
|
+
|
|
+#ifndef QWINDOWSUIAWRAPPER_H
|
|
+#define QWINDOWSUIAWRAPPER_H
|
|
+
|
|
+//
|
|
+// W A R N I N G
|
|
+// -------------
|
|
+//
|
|
+// This file is not part of the Qt API. It exists for the convenience
|
|
+// of other Qt classes. This header file may change from version to
|
|
+// version without notice, or even be removed.
|
|
+//
|
|
+// We mean it.
|
|
+//
|
|
+
|
|
+#include <QtGui/private/qtguiglobal_p.h>
|
|
+
|
|
+QT_REQUIRE_CONFIG(accessibility);
|
|
+
|
|
+QT_BEGIN_NAMESPACE
|
|
+
|
|
+class QWindowsUiaWrapper
|
|
+{
|
|
+ QWindowsUiaWrapper();
|
|
+ virtual ~QWindowsUiaWrapper();
|
|
+public:
|
|
+ static QWindowsUiaWrapper *instance();
|
|
+ BOOL ready();
|
|
+ BOOL clientsAreListening();
|
|
+ LRESULT returnRawElementProvider(HWND hwnd, WPARAM wParam, LPARAM lParam, IRawElementProviderSimple *el);
|
|
+ HRESULT hostProviderFromHwnd(HWND hwnd, IRawElementProviderSimple **ppProvider);
|
|
+ HRESULT raiseAutomationPropertyChangedEvent(IRawElementProviderSimple *pProvider, PROPERTYID id, VARIANT oldValue, VARIANT newValue);
|
|
+ HRESULT raiseAutomationEvent(IRawElementProviderSimple *pProvider, EVENTID id);
|
|
+ HRESULT raiseNotificationEvent(IRawElementProviderSimple *pProvider, NotificationKind notificationKind, NotificationProcessing notificationProcessing, BSTR displayString, BSTR activityId);
|
|
+
|
|
+private:
|
|
+ typedef LRESULT (WINAPI *PtrUiaReturnRawElementProvider)(HWND, WPARAM, LPARAM, IRawElementProviderSimple *);
|
|
+ typedef HRESULT (WINAPI *PtrUiaHostProviderFromHwnd)(HWND, IRawElementProviderSimple **);
|
|
+ typedef HRESULT (WINAPI *PtrUiaRaiseAutomationPropertyChangedEvent)(IRawElementProviderSimple *, PROPERTYID, VARIANT, VARIANT);
|
|
+ typedef HRESULT (WINAPI *PtrUiaRaiseAutomationEvent)(IRawElementProviderSimple *, EVENTID);
|
|
+ typedef HRESULT (WINAPI *PtrUiaRaiseNotificationEvent)(IRawElementProviderSimple *, NotificationKind, NotificationProcessing, BSTR, BSTR);
|
|
+
|
|
+ typedef BOOL (WINAPI *PtrUiaClientsAreListening)();
|
|
+ PtrUiaReturnRawElementProvider m_pUiaReturnRawElementProvider = nullptr;
|
|
+ PtrUiaHostProviderFromHwnd m_pUiaHostProviderFromHwnd = nullptr;
|
|
+ PtrUiaRaiseAutomationPropertyChangedEvent m_pUiaRaiseAutomationPropertyChangedEvent = nullptr;
|
|
+ PtrUiaRaiseAutomationEvent m_pUiaRaiseAutomationEvent = nullptr;
|
|
+ PtrUiaRaiseNotificationEvent m_pUiaRaiseNotificationEvent = nullptr;
|
|
+ PtrUiaClientsAreListening m_pUiaClientsAreListening = nullptr;
|
|
+};
|
|
+
|
|
+QT_END_NAMESPACE
|
|
+
|
|
+#endif //QWINDOWSUIAWRAPPER_H
|
|
+
|
|
diff --git a/src/plugins/platforms/windows/vxkex.h b/src/plugins/platforms/windows/vxkex.h
|
|
new file mode 100644
|
|
index 00000000000..6bbf2209f43
|
|
--- /dev/null
|
|
+++ b/src/plugins/platforms/windows/vxkex.h
|
|
@@ -0,0 +1,426 @@
|
|
+#pragma once
|
|
+
|
|
+#include <shtypes.h>
|
|
+#include <winuser.h>
|
|
+#include <windef.h>
|
|
+#include <shellscalingapi.h>
|
|
+
|
|
+#define MDT_MAXIMUM_DPI 3
|
|
+
|
|
+namespace vxkex {
|
|
+
|
|
+static INT GetSystemMetricsForDpi(
|
|
+ IN INT Index,
|
|
+ IN UINT Dpi)
|
|
+{
|
|
+ INT Value;
|
|
+
|
|
+ Value = GetSystemMetrics(Index);
|
|
+
|
|
+ switch (Index) {
|
|
+ case SM_CXVSCROLL:
|
|
+ case SM_CYHSCROLL:
|
|
+ case SM_CYCAPTION:
|
|
+ case SM_CYVTHUMB:
|
|
+ case SM_CXHTHUMB:
|
|
+ case SM_CXICON:
|
|
+ case SM_CYICON:
|
|
+ case SM_CXCURSOR:
|
|
+ case SM_CYCURSOR:
|
|
+ case SM_CYMENU:
|
|
+ case SM_CYVSCROLL:
|
|
+ case SM_CXHSCROLL:
|
|
+ case SM_CXMIN:
|
|
+ case SM_CXMINTRACK:
|
|
+ case SM_CYMIN:
|
|
+ case SM_CYMINTRACK:
|
|
+ case SM_CXSIZE:
|
|
+ case SM_CXFRAME:
|
|
+ case SM_CYFRAME:
|
|
+ case SM_CXICONSPACING:
|
|
+ case SM_CYICONSPACING:
|
|
+ case SM_CXSMICON:
|
|
+ case SM_CYSMICON:
|
|
+ case SM_CYSMCAPTION:
|
|
+ case SM_CXSMSIZE:
|
|
+ case SM_CYSMSIZE:
|
|
+ case SM_CXMENUSIZE:
|
|
+ case SM_CYMENUSIZE:
|
|
+ case SM_CXMENUCHECK:
|
|
+ case SM_CYMENUCHECK:
|
|
+ // These are pixel values that have to be scaled according to DPI.
|
|
+ Value *= Dpi;
|
|
+ Value /= USER_DEFAULT_SCREEN_DPI;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ return Value;
|
|
+}
|
|
+
|
|
+static BOOL SystemParametersInfoForDpi(
|
|
+ IN UINT Action,
|
|
+ IN UINT Parameter,
|
|
+ IN OUT PVOID Data,
|
|
+ IN UINT WinIni,
|
|
+ IN UINT Dpi)
|
|
+{
|
|
+ switch (Action) {
|
|
+ case SPI_GETICONTITLELOGFONT:
|
|
+ return SystemParametersInfo(Action, Parameter, Data, 0);
|
|
+ case SPI_GETICONMETRICS:
|
|
+ {
|
|
+ BOOL Success;
|
|
+ PICONMETRICS IconMetrics;
|
|
+
|
|
+ Success = SystemParametersInfo(Action, Parameter, Data, 0);
|
|
+
|
|
+ if (Success) {
|
|
+ IconMetrics = (PICONMETRICS) Data;
|
|
+
|
|
+ IconMetrics->iHorzSpacing *= Dpi;
|
|
+ IconMetrics->iVertSpacing *= Dpi;
|
|
+ IconMetrics->iHorzSpacing /= USER_DEFAULT_SCREEN_DPI;
|
|
+ IconMetrics->iVertSpacing /= USER_DEFAULT_SCREEN_DPI;
|
|
+ }
|
|
+
|
|
+ return Success;
|
|
+ }
|
|
+ case SPI_GETNONCLIENTMETRICS:
|
|
+ {
|
|
+ BOOL Success;
|
|
+ PNONCLIENTMETRICS NonClientMetrics;
|
|
+
|
|
+ Success = SystemParametersInfo(Action, Parameter, Data, 0);
|
|
+
|
|
+ if (Success) {
|
|
+ NonClientMetrics = (PNONCLIENTMETRICS) Data;
|
|
+
|
|
+ NonClientMetrics->iBorderWidth *= Dpi;
|
|
+ NonClientMetrics->iScrollWidth *= Dpi;
|
|
+ NonClientMetrics->iScrollHeight *= Dpi;
|
|
+ NonClientMetrics->iCaptionWidth *= Dpi;
|
|
+ NonClientMetrics->iCaptionHeight *= Dpi;
|
|
+ NonClientMetrics->iSmCaptionWidth *= Dpi;
|
|
+ NonClientMetrics->iSmCaptionHeight *= Dpi;
|
|
+ NonClientMetrics->iMenuWidth *= Dpi;
|
|
+ NonClientMetrics->iMenuHeight *= Dpi;
|
|
+ NonClientMetrics->iPaddedBorderWidth *= Dpi;
|
|
+
|
|
+ NonClientMetrics->iBorderWidth /= USER_DEFAULT_SCREEN_DPI;
|
|
+ NonClientMetrics->iScrollWidth /= USER_DEFAULT_SCREEN_DPI;
|
|
+ NonClientMetrics->iScrollHeight /= USER_DEFAULT_SCREEN_DPI;
|
|
+ NonClientMetrics->iCaptionWidth /= USER_DEFAULT_SCREEN_DPI;
|
|
+ NonClientMetrics->iCaptionHeight /= USER_DEFAULT_SCREEN_DPI;
|
|
+ NonClientMetrics->iSmCaptionWidth /= USER_DEFAULT_SCREEN_DPI;
|
|
+ NonClientMetrics->iSmCaptionHeight /= USER_DEFAULT_SCREEN_DPI;
|
|
+ NonClientMetrics->iMenuWidth /= USER_DEFAULT_SCREEN_DPI;
|
|
+ NonClientMetrics->iMenuHeight /= USER_DEFAULT_SCREEN_DPI;
|
|
+ NonClientMetrics->iPaddedBorderWidth /= USER_DEFAULT_SCREEN_DPI;
|
|
+ }
|
|
+
|
|
+ return Success;
|
|
+ }
|
|
+ default:
|
|
+ SetLastError(ERROR_INVALID_PARAMETER);
|
|
+ return FALSE;
|
|
+ }
|
|
+}
|
|
+
|
|
+static HRESULT GetScaleFactorForMonitor(
|
|
+ IN HMONITOR Monitor,
|
|
+ OUT DEVICE_SCALE_FACTOR *ScaleFactor)
|
|
+{
|
|
+ HDC DeviceContext;
|
|
+ ULONG LogPixelsX;
|
|
+
|
|
+ DeviceContext = GetDC(NULL);
|
|
+ if (!DeviceContext) {
|
|
+ *ScaleFactor = SCALE_100_PERCENT;
|
|
+ return S_OK;
|
|
+ }
|
|
+
|
|
+ LogPixelsX = GetDeviceCaps(DeviceContext, LOGPIXELSX);
|
|
+ ReleaseDC(NULL, DeviceContext);
|
|
+
|
|
+ *ScaleFactor = (DEVICE_SCALE_FACTOR) (9600 / LogPixelsX);
|
|
+ return S_OK;
|
|
+}
|
|
+
|
|
+static HRESULT GetDpiForMonitor(
|
|
+ IN HMONITOR Monitor,
|
|
+ IN MONITOR_DPI_TYPE DpiType,
|
|
+ OUT UINT * DpiX,
|
|
+ OUT UINT * DpiY)
|
|
+{
|
|
+ HDC DeviceContext;
|
|
+
|
|
+ if (DpiType >= MDT_MAXIMUM_DPI) {
|
|
+ return E_INVALIDARG;
|
|
+ }
|
|
+
|
|
+ if (!DpiX || !DpiY) {
|
|
+ return E_INVALIDARG;
|
|
+ }
|
|
+
|
|
+ if (!IsProcessDPIAware()) {
|
|
+ *DpiX = USER_DEFAULT_SCREEN_DPI;
|
|
+ *DpiY = USER_DEFAULT_SCREEN_DPI;
|
|
+ return S_OK;
|
|
+ }
|
|
+
|
|
+ DeviceContext = GetDC(NULL);
|
|
+ if (!DeviceContext) {
|
|
+ *DpiX = USER_DEFAULT_SCREEN_DPI;
|
|
+ *DpiY = USER_DEFAULT_SCREEN_DPI;
|
|
+ return S_OK;
|
|
+ }
|
|
+
|
|
+ *DpiX = GetDeviceCaps(DeviceContext, LOGPIXELSX);
|
|
+ *DpiY = GetDeviceCaps(DeviceContext, LOGPIXELSY);
|
|
+
|
|
+ if (DpiType == MDT_EFFECTIVE_DPI) {
|
|
+ DEVICE_SCALE_FACTOR ScaleFactor;
|
|
+
|
|
+ // We have to multiply the DPI values by the scaling factor.
|
|
+ vxkex::GetScaleFactorForMonitor(Monitor, &ScaleFactor);
|
|
+
|
|
+ *DpiX *= ScaleFactor;
|
|
+ *DpiY *= ScaleFactor;
|
|
+ *DpiX /= 100;
|
|
+ *DpiY /= 100;
|
|
+ }
|
|
+
|
|
+ ReleaseDC(NULL, DeviceContext);
|
|
+ return S_OK;
|
|
+}
|
|
+
|
|
+static UINT GetDpiForSystem(
|
|
+ VOID)
|
|
+{
|
|
+ HDC DeviceContext;
|
|
+ ULONG LogPixelsX;
|
|
+
|
|
+ if (!IsProcessDPIAware()) {
|
|
+ return 96;
|
|
+ }
|
|
+
|
|
+ DeviceContext = GetDC(NULL);
|
|
+ if (!DeviceContext) {
|
|
+ return 96;
|
|
+ }
|
|
+
|
|
+ LogPixelsX = GetDeviceCaps(DeviceContext, LOGPIXELSX);
|
|
+ ReleaseDC(NULL, DeviceContext);
|
|
+
|
|
+ return LogPixelsX;
|
|
+}
|
|
+
|
|
+static UINT GetDpiForWindow(
|
|
+ IN HWND Window)
|
|
+{
|
|
+ if (!IsWindow(Window)) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return vxkex::GetDpiForSystem();
|
|
+}
|
|
+
|
|
+static BOOL AdjustWindowRectExForDpi(
|
|
+ IN OUT LPRECT Rect,
|
|
+ IN ULONG WindowStyle,
|
|
+ IN BOOL HasMenu,
|
|
+ IN ULONG WindowExStyle,
|
|
+ IN ULONG Dpi)
|
|
+{
|
|
+ // I'm not sure how to implement this function properly.
|
|
+ // If it turns out to be important, I'll have to do some testing
|
|
+ // on a Win10 VM.
|
|
+
|
|
+ return AdjustWindowRectEx(
|
|
+ Rect,
|
|
+ WindowStyle,
|
|
+ HasMenu,
|
|
+ WindowExStyle);
|
|
+}
|
|
+
|
|
+static BOOL SetDisplayAutoRotationPreferences(
|
|
+ IN ORIENTATION_PREFERENCE Orientation)
|
|
+{
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static BOOL GetDisplayAutoRotationPreferences(
|
|
+ OUT ORIENTATION_PREFERENCE * Orientation)
|
|
+{
|
|
+ *Orientation = ORIENTATION_PREFERENCE_NONE;
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+// scaling.c
|
|
+
|
|
+static BOOL SetProcessDpiAwarenessContext(
|
|
+ IN DPI_AWARENESS_CONTEXT DpiContext)
|
|
+{
|
|
+ if ((ULONG_PTR)DpiContext == (ULONG_PTR)DPI_AWARENESS_CONTEXT_UNAWARE) {
|
|
+ //NOTHING;
|
|
+ } else if ((ULONG_PTR)DpiContext == (ULONG_PTR)DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ||
|
|
+ (ULONG_PTR)DpiContext == (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ||
|
|
+ (ULONG_PTR)DpiContext == (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) {
|
|
+ SetProcessDPIAware();
|
|
+ } else {
|
|
+ return FALSE;
|
|
+ }
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static BOOL AreDpiAwarenessContextsEqual(
|
|
+ IN DPI_AWARENESS_CONTEXT Value1,
|
|
+ IN DPI_AWARENESS_CONTEXT Value2)
|
|
+{
|
|
+ return (Value1 == Value2);
|
|
+}
|
|
+
|
|
+static BOOL IsValidDpiAwarenessContext(
|
|
+ IN DPI_AWARENESS_CONTEXT Value)
|
|
+{
|
|
+ if ((ULONG_PTR)Value == (ULONG_PTR)DPI_AWARENESS_CONTEXT_UNAWARE ||
|
|
+ (ULONG_PTR)Value == (ULONG_PTR)DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED ||
|
|
+ (ULONG_PTR)Value == (ULONG_PTR)DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ||
|
|
+ (ULONG_PTR)Value == (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ||
|
|
+ (ULONG_PTR)Value == (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) {
|
|
+ return TRUE;
|
|
+ } else {
|
|
+ return FALSE;
|
|
+ }
|
|
+}
|
|
+
|
|
+static BOOL EnableNonClientDpiScaling(
|
|
+ IN HWND Window)
|
|
+{
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static DPI_AWARENESS_CONTEXT GetThreadDpiAwarenessContext(
|
|
+ VOID)
|
|
+{
|
|
+ if (IsProcessDPIAware()) {
|
|
+ return DPI_AWARENESS_CONTEXT_SYSTEM_AWARE;
|
|
+ } else {
|
|
+ return DPI_AWARENESS_CONTEXT_UNAWARE;
|
|
+ }
|
|
+}
|
|
+
|
|
+static DPI_AWARENESS_CONTEXT GetWindowDpiAwarenessContext(
|
|
+ IN HWND Window)
|
|
+{
|
|
+ ULONG WindowThreadId;
|
|
+ ULONG WindowProcessId;
|
|
+
|
|
+ WindowThreadId = GetWindowThreadProcessId(Window, &WindowProcessId);
|
|
+ if (!WindowThreadId) {
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ // looks like there's a bug in vxkex, here should be == instead of =
|
|
+ // and if is always true
|
|
+ // anyway I don't want to deal with Windows kernel mode structures here
|
|
+
|
|
+ if (1) { //if (WindowProcessId = (ULONG) NtCurrentTeb()->ClientId.UniqueProcess) {
|
|
+ return vxkex::GetThreadDpiAwarenessContext();
|
|
+ }
|
|
+
|
|
+ return DPI_AWARENESS_CONTEXT_UNAWARE;
|
|
+}
|
|
+
|
|
+// pointer.c
|
|
+
|
|
+static BOOL GetPointerType(
|
|
+ IN UINT32 PointerId,
|
|
+ OUT POINTER_INPUT_TYPE *PointerType)
|
|
+{
|
|
+ *PointerType = PT_MOUSE;
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static BOOL GetPointerFrameTouchInfo(
|
|
+ IN UINT32 PointerId,
|
|
+ IN OUT UINT32 *PointerCount,
|
|
+ OUT LPVOID TouchInfo)
|
|
+{
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+static BOOL GetPointerFrameTouchInfoHistory(
|
|
+ IN UINT32 PointerId,
|
|
+ IN OUT UINT32 *EntriesCount,
|
|
+ IN OUT UINT32 *PointerCount,
|
|
+ OUT LPVOID TouchInfo)
|
|
+{
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+static BOOL GetPointerPenInfo(
|
|
+ IN UINT32 PointerId,
|
|
+ OUT LPVOID PenInfo)
|
|
+{
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+static BOOL GetPointerPenInfoHistory(
|
|
+ IN UINT32 PointerId,
|
|
+ IN OUT UINT32 *EntriesCount,
|
|
+ OUT LPVOID PenInfo)
|
|
+{
|
|
+ return FALSE;
|
|
+}
|
|
+
|
|
+static BOOL SkipPointerFrameMessages(
|
|
+ IN UINT32 PointerId)
|
|
+{
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static BOOL GetPointerDeviceRects(
|
|
+ IN HANDLE Device,
|
|
+ OUT LPRECT PointerDeviceRect,
|
|
+ OUT LPRECT DisplayRect)
|
|
+{
|
|
+ PointerDeviceRect->top = 0;
|
|
+ PointerDeviceRect->left = 0;
|
|
+ PointerDeviceRect->bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
|
+ PointerDeviceRect->right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
|
+
|
|
+ DisplayRect->top = 0;
|
|
+ DisplayRect->left = 0;
|
|
+ DisplayRect->bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
|
+ DisplayRect->right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+static BOOL GetPointerInfo(
|
|
+ IN DWORD PointerId,
|
|
+ OUT POINTER_INFO *PointerInfo)
|
|
+{
|
|
+ PointerInfo->pointerType = PT_MOUSE;
|
|
+ PointerInfo->pointerId = PointerId;
|
|
+ PointerInfo->frameId = 0;
|
|
+ PointerInfo->pointerFlags = POINTER_FLAG_NONE;
|
|
+ PointerInfo->sourceDevice = NULL;
|
|
+ PointerInfo->hwndTarget = NULL;
|
|
+ GetCursorPos(&PointerInfo->ptPixelLocation);
|
|
+ GetCursorPos(&PointerInfo->ptHimetricLocation);
|
|
+ GetCursorPos(&PointerInfo->ptPixelLocationRaw);
|
|
+ GetCursorPos(&PointerInfo->ptHimetricLocationRaw);
|
|
+ PointerInfo->dwTime = 0;
|
|
+ PointerInfo->historyCount = 1;
|
|
+ PointerInfo->InputData = 0;
|
|
+ PointerInfo->dwKeyStates = 0;
|
|
+ PointerInfo->PerformanceCount = 0;
|
|
+ PointerInfo->ButtonChangeType = POINTER_CHANGE_NONE;
|
|
+
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+} // namespace vxkex
|
|
diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp
|
|
index a8407add019..a8097330210 100644
|
|
--- a/src/widgets/styles/qwindowsstyle.cpp
|
|
+++ b/src/widgets/styles/qwindowsstyle.cpp
|
|
@@ -59,6 +59,10 @@
|
|
|
|
#include <algorithm>
|
|
|
|
+#if defined(Q_OS_WIN)
|
|
+#include "../../plugins/platforms/windows/vxkex.h"
|
|
+#endif
|
|
+
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
#if defined(Q_OS_WIN)
|
|
@@ -254,6 +258,11 @@ void QWindowsStyle::polish(QPalette &pal)
|
|
QCommonStyle::polish(pal);
|
|
}
|
|
|
|
+#if defined(Q_OS_WIN)
|
|
+typedef BOOL (WINAPI *GetSystemMetricsForDpiFunc)(int, UINT);
|
|
+typedef BOOL (WINAPI *SystemParametersInfoForDpiFunc)(UINT, UINT, PVOID, UINT, UINT);
|
|
+#endif
|
|
+
|
|
int QWindowsStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *, const QWidget *widget)
|
|
{
|
|
#if defined(Q_OS_WIN)
|
|
@@ -261,29 +270,43 @@ int QWindowsStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, const
|
|
// hardcode DPI to 1x 96 DPI.
|
|
const int dpi = 96;
|
|
|
|
+ static GetSystemMetricsForDpiFunc myGetSystemMetricsForDpi =
|
|
+ (GetSystemMetricsForDpiFunc)::GetProcAddress(::GetModuleHandle(L"User32"), "GetSystemMetricsForDpi");
|
|
+
|
|
+ static SystemParametersInfoForDpiFunc mySystemParametersInfoForDpi =
|
|
+ (SystemParametersInfoForDpiFunc)::GetProcAddress(::GetModuleHandle(L"User32"), "SystemParametersInfoForDpi");
|
|
+
|
|
switch (pm) {
|
|
case QStyle::PM_DockWidgetFrameWidth:
|
|
- return GetSystemMetricsForDpi(SM_CXFRAME, dpi);
|
|
+ return myGetSystemMetricsForDpi ? myGetSystemMetricsForDpi(SM_CXFRAME, dpi) : vxkex::GetSystemMetricsForDpi(SM_CXFRAME, dpi);
|
|
|
|
case QStyle::PM_TitleBarHeight: {
|
|
- const int resizeBorderThickness =
|
|
- GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
|
+ const int resizeBorderThickness = myGetSystemMetricsForDpi ?
|
|
+ (myGetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + myGetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi)) :
|
|
+ (vxkex::GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + vxkex::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi)) ;
|
|
if (widget && (widget->windowType() == Qt::Tool))
|
|
- return GetSystemMetricsForDpi(SM_CYSMCAPTION, dpi) + resizeBorderThickness;
|
|
- return GetSystemMetricsForDpi(SM_CYCAPTION, dpi) + resizeBorderThickness;
|
|
+ return myGetSystemMetricsForDpi ?
|
|
+ (myGetSystemMetricsForDpi(SM_CYSMCAPTION, dpi) + resizeBorderThickness) :
|
|
+ (vxkex::GetSystemMetricsForDpi(SM_CYSMCAPTION, dpi) + resizeBorderThickness);
|
|
+ return myGetSystemMetricsForDpi ?
|
|
+ (myGetSystemMetricsForDpi(SM_CYCAPTION, dpi) + resizeBorderThickness) :
|
|
+ (vxkex::GetSystemMetricsForDpi(SM_CYCAPTION, dpi) + resizeBorderThickness);
|
|
}
|
|
|
|
case QStyle::PM_ScrollBarExtent:
|
|
{
|
|
NONCLIENTMETRICS ncm;
|
|
ncm.cbSize = sizeof(NONCLIENTMETRICS);
|
|
- if (SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0, dpi))
|
|
+ BOOL bResult = mySystemParametersInfoForDpi
|
|
+ ? mySystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0, dpi)
|
|
+ : vxkex::SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0, dpi);
|
|
+ if (bResult)
|
|
return qMax(ncm.iScrollHeight, ncm.iScrollWidth);
|
|
}
|
|
break;
|
|
|
|
case QStyle::PM_MdiSubWindowFrameWidth:
|
|
- return GetSystemMetricsForDpi(SM_CYFRAME, dpi);
|
|
+ return myGetSystemMetricsForDpi ? myGetSystemMetricsForDpi(SM_CYFRAME, dpi) : vxkex::GetSystemMetricsForDpi(SM_CYFRAME, dpi);
|
|
|
|
default:
|
|
break;
|