mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2024-11-22 19:49:59 +08:00
6.6.1 patched files
This commit is contained in:
parent
b752f623ec
commit
161231b111
@ -1,4 +1,4 @@
|
||||
This is Qt 6.6.1 backport that runs on Windows 7 (what?). The repository is the qtbase module source code with all required modifications already applied.
|
||||
This is Qt 6.6.1 backport that runs on Windows 7 (what?). The repository contains patched source files from the qtbase module.
|
||||
Approach is based on this [forum thread](https://forum.qt.io/topic/133002/qt-creator-6-0-1-and-qt-6-2-2-running-on-windows-7/60) but better: many improvements amongst important fallbacks to default Qt 6 behaviour when running on newer Windows.
|
||||
|
||||
You can use [our prebuild binaries](https://github.com/crystalidea/qt6windows7/releases) (we used Visual C++ 2019 with OpenSSL 1.1.1k statically linked, see [compile_win.pl](https://github.com/crystalidea/qt-build-tools/tree/master/6.6.1) script) or compile Qt yourself.
|
||||
|
@ -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);
|
||||
|
@ -361,10 +361,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);
|
||||
|
||||
|
@ -43,23 +43,33 @@ 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)) {
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
return true;
|
||||
case APPMODEL_ERROR_NO_PACKAGE:
|
||||
return false;
|
||||
default:
|
||||
qWarning("Failed to resolve package identity (error code %ld)", result);
|
||||
return false;
|
||||
}
|
||||
}();
|
||||
return hasPackageIdentity;
|
||||
|
||||
static const bool hasPackageIdentity = []() {
|
||||
UINT32 length = 0;
|
||||
switch (const auto result = myGetCurrentPackageFullName(&length, nullptr)) {
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
return true;
|
||||
case APPMODEL_ERROR_NO_PACKAGE:
|
||||
return false;
|
||||
default:
|
||||
qWarning("Failed to resolve package identity (error code %ld)", result);
|
||||
return false;
|
||||
}
|
||||
}();
|
||||
return hasPackageIdentity;
|
||||
#else
|
||||
return false;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -107,39 +107,6 @@ namespace QtLinuxFutex {
|
||||
}
|
||||
namespace QtFutex = QtLinuxFutex;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#elif defined(Q_OS_WIN)
|
||||
# include <qt_windows.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace QtWindowsFutex {
|
||||
#define QT_ALWAYS_USE_FUTEX
|
||||
constexpr inline bool futexAvailable() { return true; }
|
||||
|
||||
template <typename Atomic>
|
||||
inline void futexWait(Atomic &futex, typename Atomic::Type expectedValue)
|
||||
{
|
||||
QtTsan::futexRelease(&futex);
|
||||
WaitOnAddress(&futex, &expectedValue, sizeof(expectedValue), INFINITE);
|
||||
QtTsan::futexAcquire(&futex);
|
||||
}
|
||||
template <typename Atomic>
|
||||
inline bool futexWait(Atomic &futex, typename Atomic::Type expectedValue, qint64 nstimeout)
|
||||
{
|
||||
BOOL r = WaitOnAddress(&futex, &expectedValue, sizeof(expectedValue), DWORD(nstimeout / 1000 / 1000));
|
||||
return r || GetLastError() != ERROR_TIMEOUT;
|
||||
}
|
||||
template <typename Atomic> inline void futexWakeAll(Atomic &futex)
|
||||
{
|
||||
WakeByAddressAll(&futex);
|
||||
}
|
||||
template <typename Atomic> inline void futexWakeOne(Atomic &futex)
|
||||
{
|
||||
WakeByAddressSingle(&futex);
|
||||
}
|
||||
}
|
||||
namespace QtFutex = QtWindowsFutex;
|
||||
QT_END_NAMESPACE
|
||||
#else
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
@ -915,8 +915,10 @@ QT_END_NAMESPACE
|
||||
|
||||
#if defined(QT_ALWAYS_USE_FUTEX)
|
||||
// nothing
|
||||
#elif defined(Q_OS_DARWIN)
|
||||
#elif defined(Q_OS_MAC)
|
||||
# include "qmutex_mac.cpp"
|
||||
#elif defined(Q_OS_WIN)
|
||||
# include "qmutex_win.cpp"
|
||||
#else
|
||||
# include "qmutex_unix.cpp"
|
||||
#endif
|
||||
#endif
|
@ -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
|
||||
};
|
||||
|
||||
|
30
qtbase/src/corelib/thread/qmutex_win.cpp
Normal file
30
qtbase/src/corelib/thread/qmutex_win.cpp
Normal file
@ -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
|
@ -10,6 +10,8 @@
|
||||
#include <QtCore/private/qsystemerror_p.h>
|
||||
#include "qrhid3dhelpers_p.h"
|
||||
|
||||
#include <VersionHelpers.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
@ -155,13 +157,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;
|
||||
}
|
||||
|
||||
@ -4999,6 +5010,14 @@ 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.
|
||||
@ -5267,4 +5286,9 @@ bool QD3D11SwapChain::createOrResize()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QD3D11SwapChain::createOrResizeWin7()
|
||||
{
|
||||
return false; // not implemented yet ;(
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -586,7 +586,8 @@ 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,
|
||||
ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv) const;
|
||||
|
@ -169,12 +169,28 @@ 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)) {
|
||||
qWarning("CreateDXGIFactory2() failed to create DXGI factory: %s",
|
||||
qPrintable(QSystemError::windowsComString(hr)));
|
||||
@ -192,7 +208,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();
|
||||
@ -262,7 +278,7 @@ bool QRhiD3D12::create(QRhi::Flags flags)
|
||||
if (minimumFeatureLevel == 0)
|
||||
minimumFeatureLevel = MIN_FEATURE_LEVEL;
|
||||
|
||||
hr = D3D12CreateDevice(activeAdapter,
|
||||
hr = myD3D12CreateDevice(activeAdapter,
|
||||
minimumFeatureLevel,
|
||||
__uuidof(ID3D12Device),
|
||||
reinterpret_cast<void **>(&dev));
|
||||
@ -2520,6 +2536,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;
|
||||
@ -2564,8 +2583,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;
|
||||
@ -4834,8 +4860,15 @@ QD3D12ObjectHandle QD3D12ShaderResourceBindings::createRootSignature(const QD3D1
|
||||
}
|
||||
rsDesc.Desc_1_1.Flags = D3D12_ROOT_SIGNATURE_FLAGS(rsFlags);
|
||||
|
||||
if (!myD3D12SerializeVersionedRootSignature)
|
||||
myD3D12SerializeVersionedRootSignature =
|
||||
(D3D12SerializeVersionedRootSignatureFunc)::GetProcAddress(::GetModuleHandle(L"D3d12"), "D3D12SerializeVersionedRootSignature");
|
||||
|
||||
if (!myD3D12SerializeVersionedRootSignature)
|
||||
return {};
|
||||
|
||||
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 {};
|
||||
|
@ -685,7 +685,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;
|
||||
|
@ -65,35 +65,101 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
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");
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
ptrStart = dns_records;
|
||||
}
|
||||
|
||||
DNS_QUERY_RESULT results = {};
|
||||
results.Version = 1;
|
||||
const DNS_STATUS status = DnsQueryEx(&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);
|
||||
if (!ptrStart)
|
||||
return;
|
||||
|
||||
QStringView lastEncodedName;
|
||||
QString cachedDecodedName;
|
||||
@ -105,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) {
|
||||
@ -170,7 +236,7 @@ void QDnsLookupRunnable::query(QDnsLookupReply *reply)
|
||||
}
|
||||
}
|
||||
|
||||
DnsRecordListFree(results.pQueryRecords, DnsFreeRecordList);
|
||||
DnsRecordListFree(ptrStart, DnsFreeRecordList);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -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 ::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;
|
||||
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);
|
||||
|
||||
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;
|
||||
WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)WIN_LoadComBaseFunction("WindowsCreateStringReference");
|
||||
RoGetActivationFactory_t RoGetActivationFactoryFunc = (RoGetActivationFactory_t)WIN_LoadComBaseFunction("RoGetActivationFactory");
|
||||
|
||||
IUIViewSettingsInterop *uiViewSettingsInterop = nullptr;
|
||||
// __uuidof(IUIViewSettingsInterop);
|
||||
const GUID uiViewSettingsInteropRefId = {0x3694dbf9, 0x8f68, 0x44be,{0x8f, 0xf5, 0x19, 0x5c, 0x98, 0xed, 0xe8, 0xa6}};
|
||||
if (WindowsCreateStringReferenceFunc && RoGetActivationFactoryFunc)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
HRESULT hr = RoGetActivationFactory(uiViewSettingsIdHs, uiViewSettingsInteropRefId,
|
||||
reinterpret_cast<void **>(&uiViewSettingsInterop));
|
||||
if (FAILED(hr))
|
||||
return 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;
|
||||
|
||||
// __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();
|
||||
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
|
@ -44,6 +44,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>
|
||||
#include <QtCore/private/qfactorycacheregistration_p.h>
|
||||
#include <QtCore/private/qsystemerror_p.h>
|
||||
@ -118,6 +119,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;
|
||||
|
||||
/*!
|
||||
@ -161,6 +233,9 @@ bool QWindowsContextPrivate::m_v2DpiAware = false;
|
||||
QWindowsContextPrivate::QWindowsContextPrivate()
|
||||
: m_oleInitializeResult(OleInitialize(nullptr))
|
||||
{
|
||||
QWindowsContext::user32dll.init();
|
||||
QWindowsContext::shcoredll.init();
|
||||
|
||||
if (m_pointerHandler.touchDevice() || m_mouseHandler.touchDevice())
|
||||
m_systemInfo |= QWindowsContext::SI_SupportsTouch;
|
||||
m_displayContext = GetDC(nullptr);
|
||||
@ -279,6 +354,12 @@ bool QWindowsContext::initPointer(unsigned integrationOptions)
|
||||
if (integrationOptions & QWindowsIntegration::DontUseWMPointer)
|
||||
return false;
|
||||
|
||||
if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8)
|
||||
return false;
|
||||
|
||||
if (!QWindowsContext::user32dll.supportsPointerApi())
|
||||
return false;
|
||||
|
||||
d->m_systemInfo |= QWindowsContext::SI_SupportsPointer;
|
||||
return true;
|
||||
}
|
||||
@ -349,41 +430,58 @@ 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))
|
||||
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;
|
||||
|
||||
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;
|
||||
return QtWindows::DpiAwareness::Invalid;
|
||||
}
|
||||
|
||||
return QtWindows::DpiAwareness::Unaware; // Windows 7
|
||||
}
|
||||
|
||||
QtWindows::DpiAwareness QWindowsContext::windowDpiAwareness(HWND hwnd)
|
||||
{
|
||||
if (!hwnd)
|
||||
return QtWindows::DpiAwareness::Invalid;
|
||||
const auto context = GetWindowDpiAwarenessContext(hwnd);
|
||||
return dpiAwarenessContextToQtDpiAwareness(context);
|
||||
|
||||
if (QWindowsContext::user32dll.getWindowDpiAwarenessContext)
|
||||
{
|
||||
const auto context = QWindowsContext::user32dll.getWindowDpiAwarenessContext(hwnd);
|
||||
return dpiAwarenessContextToQtDpiAwareness(context);
|
||||
}
|
||||
|
||||
return dpiAwarenessContextToQtDpiAwareness(DPI_AWARENESS_CONTEXT_UNAWARE);
|
||||
}
|
||||
|
||||
QtWindows::DpiAwareness QWindowsContext::processDpiAwareness()
|
||||
{
|
||||
// Although we have GetDpiAwarenessContextForProcess(), however,
|
||||
// it's only available on Win10 1903+, which is a little higher
|
||||
// than Qt's minimum supported version (1809), so we can't use it.
|
||||
// Luckily, MS docs said GetThreadDpiAwarenessContext() will also
|
||||
// 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();
|
||||
return dpiAwarenessContextToQtDpiAwareness(context);
|
||||
if (QWindowsContext::user32dll.getThreadDpiAwarenessContext)
|
||||
{
|
||||
// Although we have GetDpiAwarenessContextForProcess(), however,
|
||||
// it's only available on Win10 1903+, which is a little higher
|
||||
// than Qt's minimum supported version (1809), so we can't use it.
|
||||
// Luckily, MS docs said GetThreadDpiAwarenessContext() will also
|
||||
// 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 = QWindowsContext::user32dll.getThreadDpiAwarenessContext();
|
||||
return dpiAwarenessContextToQtDpiAwareness(context);
|
||||
}
|
||||
|
||||
return dpiAwarenessContextToQtDpiAwareness(DPI_AWARENESS_CONTEXT_UNAWARE);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline DPI_AWARENESS_CONTEXT
|
||||
@ -442,23 +540,29 @@ bool QWindowsContext::setProcessDpiAwareness(QtWindows::DpiAwareness dpiAwarenes
|
||||
if (processDpiAwareness() == dpiAwareness)
|
||||
return true;
|
||||
const auto context = qtDpiAwarenessToDpiAwarenessContext(dpiAwareness);
|
||||
if (!IsValidDpiAwarenessContext(context)) {
|
||||
qCWarning(lcQpaWindow) << dpiAwareness << "is not supported by current system.";
|
||||
return false;
|
||||
|
||||
if (QWindowsContext::user32dll.isValidDpiAwarenessContext && QWindowsContext::user32dll.setProcessDpiAwarenessContext)
|
||||
{
|
||||
if (!QWindowsContext::user32dll.isValidDpiAwarenessContext(context)) {
|
||||
qCWarning(lcQpaWindow) << dpiAwareness << "is not supported by current system.";
|
||||
return false;
|
||||
}
|
||||
if (!QWindowsContext::user32dll.setProcessDpiAwarenessContext(context)) {
|
||||
qCWarning(lcQpaWindow).noquote().nospace()
|
||||
<< "SetProcessDpiAwarenessContext() failed: "
|
||||
<< QSystemError::windowsString()
|
||||
<< "\nQt's default DPI awareness context is "
|
||||
<< "DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2. If you know what you "
|
||||
<< "are doing, you can overwrite this default using qt.conf "
|
||||
<< "(https://doc.qt.io/qt-6/highdpi.html#configuring-windows).";
|
||||
return false;
|
||||
}
|
||||
QWindowsContextPrivate::m_v2DpiAware
|
||||
= processDpiAwareness() == QtWindows::DpiAwareness::PerMonitorVersion2;
|
||||
return true;
|
||||
}
|
||||
if (!SetProcessDpiAwarenessContext(context)) {
|
||||
qCWarning(lcQpaWindow).noquote().nospace()
|
||||
<< "SetProcessDpiAwarenessContext() failed: "
|
||||
<< QSystemError::windowsString()
|
||||
<< "\nQt's default DPI awareness context is "
|
||||
<< "DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2. If you know what you "
|
||||
<< "are doing, you can overwrite this default using qt.conf "
|
||||
<< "(https://doc.qt.io/qt-6/highdpi.html#configuring-windows).";
|
||||
return false;
|
||||
}
|
||||
QWindowsContextPrivate::m_v2DpiAware
|
||||
= processDpiAwareness() == QtWindows::DpiAwareness::PerMonitorVersion2;
|
||||
return true;
|
||||
|
||||
return false; // Windows 7
|
||||
}
|
||||
|
||||
bool QWindowsContext::isDarkMode()
|
||||
@ -886,8 +990,8 @@ 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)
|
||||
const BOOL result = (QWindowsContext::user32dll.systemParametersInfoForDpi != nullptr && dpi != 0)
|
||||
? QWindowsContext::user32dll.systemParametersInfoForDpi(action, param, out, 0, dpi)
|
||||
: SystemParametersInfo(action, param, out, 0);
|
||||
return result == TRUE;
|
||||
}
|
||||
@ -974,8 +1078,8 @@ static inline bool isInputMessage(UINT m)
|
||||
static bool enableNonClientDpiScaling(HWND hwnd)
|
||||
{
|
||||
bool result = false;
|
||||
if (QWindowsContext::windowDpiAwareness(hwnd) == QtWindows::DpiAwareness::PerMonitor) {
|
||||
result = EnableNonClientDpiScaling(hwnd) != FALSE;
|
||||
if (QWindowsContext::user32dll.enableNonClientDpiScaling && QWindowsContext::windowDpiAwareness(hwnd) == QtWindows::DpiAwareness::PerMonitor) {
|
||||
result = QWindowsContext::user32dll.enableNonClientDpiScaling(hwnd) != FALSE;
|
||||
if (!result) {
|
||||
const DWORD errorCode = GetLastError();
|
||||
qErrnoWarning(int(errorCode), "EnableNonClientDpiScaling() failed for HWND %p (%lu)",
|
||||
|
@ -14,6 +14,7 @@
|
||||
#define STRICT_TYPED_ITEMIDS
|
||||
#include <shlobj.h>
|
||||
#include <shlwapi.h>
|
||||
#include <shellscalingapi.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -44,6 +45,94 @@ 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)
|
||||
@ -138,6 +227,9 @@ public:
|
||||
QWindowsScreenManager &screenManager();
|
||||
QWindowsTabletSupport *tabletSupport() const;
|
||||
|
||||
static QWindowsUser32DLL user32dll;
|
||||
static QWindowsShcoreDLL shcoredll;
|
||||
|
||||
bool asyncExpose() const;
|
||||
void setAsyncExpose(bool value);
|
||||
|
||||
|
@ -670,7 +670,7 @@ static HRESULT startDoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource,
|
||||
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
|
||||
|
||||
POINTER_INFO pointerInfo{};
|
||||
if (!GetPointerInfo(pointerId, &pointerInfo))
|
||||
if (!QWindowsContext::user32dll.getPointerInfo || !QWindowsContext::user32dll.getPointerInfo(pointerId, &pointerInfo))
|
||||
return E_FAIL;
|
||||
|
||||
if (pointerInfo.pointerFlags & POINTER_FLAG_PRIMARY) {
|
||||
|
@ -751,15 +751,28 @@ 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);
|
||||
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);
|
||||
return captionHeight + frameHeight;
|
||||
if (QWindowsContext::user32dll.getDpiForWindow && QWindowsContext::user32dll.getSystemMetricsForDpi)
|
||||
{
|
||||
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
|
||||
const int captionHeight = QWindowsContext::user32dll.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 = QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYSIZEFRAME, dpi)
|
||||
+ QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
||||
return captionHeight + frameHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int captionHeight = GetSystemMetrics(SM_CYCAPTION);
|
||||
if (IsZoomed(hwnd))
|
||||
return captionHeight;
|
||||
// The frame height should also be taken into account if the window
|
||||
// is not maximized.
|
||||
const int frameHeight = GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
|
||||
return captionHeight + frameHeight;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool isSystemMenuOffsetNeeded(const Qt::WindowFlags flags)
|
||||
|
@ -48,7 +48,7 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
||||
*result = 0;
|
||||
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
|
||||
|
||||
if (!GetPointerType(pointerId, &m_pointerType)) {
|
||||
if (!QWindowsContext::user32dll.getPointerType(pointerId, &m_pointerType)) {
|
||||
qWarning() << "GetPointerType() failed:" << qt_error_string();
|
||||
return false;
|
||||
}
|
||||
@ -62,12 +62,12 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
||||
}
|
||||
case QT_PT_TOUCH: {
|
||||
quint32 pointerCount = 0;
|
||||
if (!GetPointerFrameTouchInfo(pointerId, &pointerCount, nullptr)) {
|
||||
if (!QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, nullptr)) {
|
||||
qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
|
||||
return false;
|
||||
}
|
||||
QVarLengthArray<POINTER_TOUCH_INFO, 10> touchInfo(pointerCount);
|
||||
if (!GetPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data())) {
|
||||
if (!QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data())) {
|
||||
qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
|
||||
return false;
|
||||
}
|
||||
@ -80,10 +80,10 @@ 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())) {
|
||||
if (!QWindowsContext::user32dll.getPointerFrameTouchInfoHistory(pointerId,
|
||||
&historyCount,
|
||||
&pointerCount,
|
||||
touchInfo.data())) {
|
||||
qWarning() << "GetPointerFrameTouchInfoHistory() failed:" << qt_error_string();
|
||||
return false;
|
||||
}
|
||||
@ -101,7 +101,7 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
||||
}
|
||||
case QT_PT_PEN: {
|
||||
POINTER_PEN_INFO penInfo;
|
||||
if (!GetPointerPenInfo(pointerId, &penInfo)) {
|
||||
if (!QWindowsContext::user32dll.getPointerPenInfo(pointerId, &penInfo)) {
|
||||
qWarning() << "GetPointerPenInfo() failed:" << qt_error_string();
|
||||
return false;
|
||||
}
|
||||
@ -113,7 +113,7 @@ 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())) {
|
||||
if (!QWindowsContext::user32dll.getPointerPenInfoHistory(pointerId, &historyCount, penInfoHistory.data())) {
|
||||
qWarning() << "GetPointerPenInfoHistory() failed:" << qt_error_string();
|
||||
return false;
|
||||
}
|
||||
@ -519,7 +519,7 @@ 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);
|
||||
QWindowsContext::user32dll.skipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
|
||||
}
|
||||
|
||||
// Some devices send touches for each finger in a different message/frame, instead of consolidating
|
||||
@ -565,7 +565,7 @@ 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))
|
||||
if (!QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect))
|
||||
return false;
|
||||
|
||||
const auto systemId = (qint64)penInfo->pointerInfo.sourceDevice;
|
||||
|
@ -42,10 +42,12 @@ static inline QDpi deviceDPI(HDC hdc)
|
||||
|
||||
static inline QDpi monitorDPI(HMONITOR hMonitor)
|
||||
{
|
||||
UINT dpiX;
|
||||
UINT dpiY;
|
||||
if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY)))
|
||||
return QDpi(dpiX, dpiY);
|
||||
if (QWindowsContext::shcoredll.isValid()) {
|
||||
UINT dpiX;
|
||||
UINT dpiY;
|
||||
if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY)))
|
||||
return QDpi(dpiX, dpiY);
|
||||
}
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
@ -570,47 +572,51 @@ QRect QWindowsScreen::virtualGeometry(const QPlatformScreen *screen) // cf QScre
|
||||
bool QWindowsScreen::setOrientationPreference(Qt::ScreenOrientation o)
|
||||
{
|
||||
bool result = false;
|
||||
ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
||||
switch (o) {
|
||||
case Qt::PrimaryOrientation:
|
||||
break;
|
||||
case Qt::PortraitOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_PORTRAIT;
|
||||
break;
|
||||
case Qt::LandscapeOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE;
|
||||
break;
|
||||
case Qt::InvertedPortraitOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED;
|
||||
break;
|
||||
case Qt::InvertedLandscapeOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED;
|
||||
break;
|
||||
if (QWindowsContext::user32dll.setDisplayAutoRotationPreferences) {
|
||||
ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
||||
switch (o) {
|
||||
case Qt::PrimaryOrientation:
|
||||
break;
|
||||
case Qt::PortraitOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_PORTRAIT;
|
||||
break;
|
||||
case Qt::LandscapeOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE;
|
||||
break;
|
||||
case Qt::InvertedPortraitOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED;
|
||||
break;
|
||||
case Qt::InvertedLandscapeOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED;
|
||||
break;
|
||||
}
|
||||
result = QWindowsContext::user32dll.setDisplayAutoRotationPreferences(orientationPreference);
|
||||
}
|
||||
result = SetDisplayAutoRotationPreferences(orientationPreference);
|
||||
return result;
|
||||
}
|
||||
|
||||
Qt::ScreenOrientation QWindowsScreen::orientationPreference()
|
||||
{
|
||||
Qt::ScreenOrientation result = Qt::PrimaryOrientation;
|
||||
ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
||||
if (GetDisplayAutoRotationPreferences(&orientationPreference)) {
|
||||
switch (orientationPreference) {
|
||||
case ORIENTATION_PREFERENCE_NONE:
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_LANDSCAPE:
|
||||
result = Qt::LandscapeOrientation;
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_PORTRAIT:
|
||||
result = Qt::PortraitOrientation;
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED:
|
||||
result = Qt::InvertedLandscapeOrientation;
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED:
|
||||
result = Qt::InvertedPortraitOrientation;
|
||||
break;
|
||||
if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences) {
|
||||
DWORD orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
||||
if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences(&orientationPreference)) {
|
||||
switch (orientationPreference) {
|
||||
case ORIENTATION_PREFERENCE_NONE:
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_LANDSCAPE:
|
||||
result = Qt::LandscapeOrientation;
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_PORTRAIT:
|
||||
result = Qt::PortraitOrientation;
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED:
|
||||
result = Qt::InvertedLandscapeOrientation;
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED:
|
||||
result = Qt::InvertedPortraitOrientation;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -42,6 +42,8 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <VersionHelpers.h>
|
||||
|
||||
#if QT_CONFIG(cpp_winrt)
|
||||
# include <QtCore/private/qt_winrtbase_p.h>
|
||||
|
||||
@ -243,19 +245,21 @@ static QColor placeHolderColor(QColor textColor)
|
||||
*/
|
||||
static void populateLightSystemBasePalette(QPalette &result)
|
||||
{
|
||||
const QColor background = getSysColor(COLOR_BTNFACE);
|
||||
const QColor textColor = getSysColor(COLOR_WINDOWTEXT);
|
||||
QColor background = getSysColor(COLOR_BTNFACE);
|
||||
QColor textColor = getSysColor(COLOR_WINDOWTEXT);
|
||||
QColor accent = qt_accentColor();
|
||||
QColor accentDarkest = accent.darker(120 * 120 * 120);
|
||||
|
||||
#if QT_CONFIG(cpp_winrt)
|
||||
// respect the Windows 11 accent color
|
||||
using namespace winrt::Windows::UI::ViewManagement;
|
||||
const auto settings = UISettings();
|
||||
if (IsWindows10OrGreater())
|
||||
{
|
||||
// respect the Windows 11 accent color
|
||||
using namespace winrt::Windows::UI::ViewManagement;
|
||||
const auto settings = UISettings();
|
||||
|
||||
const QColor accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
|
||||
const QColor accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
|
||||
#else
|
||||
const QColor accent = qt_accentColor();
|
||||
const QColor accentDarkest = accent.darker(120 * 120 * 120);
|
||||
accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
|
||||
accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
|
||||
}
|
||||
#endif
|
||||
|
||||
const QColor linkColor = accent;
|
||||
@ -292,39 +296,43 @@ static void populateLightSystemBasePalette(QPalette &result)
|
||||
|
||||
static void populateDarkSystemBasePalette(QPalette &result)
|
||||
{
|
||||
QColor foreground = Qt::white;
|
||||
QColor background = QColor(0x1E, 0x1E, 0x1E);
|
||||
QColor accent = qt_accentColor();
|
||||
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();
|
||||
if (IsWindows10OrGreater())
|
||||
{
|
||||
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.
|
||||
const QColor foreground = getSysColor(settings.GetColorValue(UIColorType::Foreground));
|
||||
const QColor background = [&settings]() -> QColor {
|
||||
auto systemBackground = getSysColor(settings.GetColorValue(UIColorType::Background));
|
||||
if (systemBackground == Qt::black)
|
||||
systemBackground = QColor(0x1E, 0x1E, 0x1E);
|
||||
return systemBackground;
|
||||
}();
|
||||
// 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.
|
||||
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;
|
||||
}();
|
||||
|
||||
const QColor accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
|
||||
const QColor accentDark = getSysColor(settings.GetColorValue(UIColorType::AccentDark1));
|
||||
const QColor accentDarker = getSysColor(settings.GetColorValue(UIColorType::AccentDark2));
|
||||
const QColor accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
|
||||
const QColor accentLight = getSysColor(settings.GetColorValue(UIColorType::AccentLight1));
|
||||
const QColor accentLighter = getSysColor(settings.GetColorValue(UIColorType::AccentLight2));
|
||||
const QColor accentLightest = getSysColor(settings.GetColorValue(UIColorType::AccentLight3));
|
||||
#else
|
||||
const QColor foreground = Qt::white;
|
||||
const QColor background = QColor(0x1E, 0x1E, 0x1E);
|
||||
const QColor accent = qt_accentColor();
|
||||
const QColor accentDark = accent.darker(120);
|
||||
const QColor accentDarker = accentDark.darker(120);
|
||||
const QColor accentDarkest = accentDarker.darker(120);
|
||||
const QColor accentLight = accent.lighter(120);
|
||||
const QColor accentLighter = accentLight.lighter(120);
|
||||
const QColor accentLightest = accentLighter.lighter(120);
|
||||
accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
|
||||
accentDark = getSysColor(settings.GetColorValue(UIColorType::AccentDark1));
|
||||
accentDarker = getSysColor(settings.GetColorValue(UIColorType::AccentDark2));
|
||||
accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
|
||||
accentLight = getSysColor(settings.GetColorValue(UIColorType::AccentLight1));
|
||||
accentLighter = getSysColor(settings.GetColorValue(UIColorType::AccentLight2));
|
||||
accentLightest = getSysColor(settings.GetColorValue(UIColorType::AccentLight3));
|
||||
}
|
||||
#endif
|
||||
|
||||
const QColor linkColor = accent;
|
||||
const QColor buttonColor = background.lighter(200);
|
||||
|
||||
@ -551,16 +559,19 @@ void QWindowsTheme::refreshPalettes()
|
||||
m_palettes[MenuPalette] = new QPalette(menuPalette(*m_palettes[SystemPalette], light));
|
||||
m_palettes[MenuBarPalette] = menuBarPalette(*m_palettes[MenuPalette], light);
|
||||
if (!light) {
|
||||
QColor accent = qt_accentColor();
|
||||
QColor accentLight = accent.lighter(120);
|
||||
QColor accentDarkest = accent.darker(120 * 120 * 120);
|
||||
|
||||
#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 accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
|
||||
#else
|
||||
const QColor accent = qt_accentColor();
|
||||
const QColor accentLight = accent.lighter(120);
|
||||
const QColor accentDarkest = accent.darker(120 * 120 * 120);
|
||||
if (IsWindows10OrGreater())
|
||||
{
|
||||
using namespace winrt::Windows::UI::ViewManagement;
|
||||
const auto settings = UISettings();
|
||||
accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
|
||||
accentLight = getSysColor(settings.GetColorValue(UIColorType::AccentLight1));
|
||||
accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
|
||||
}
|
||||
#endif
|
||||
m_palettes[CheckBoxPalette] = new QPalette(*m_palettes[SystemPalette]);
|
||||
m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Base, accent);
|
||||
@ -664,8 +675,14 @@ void QWindowsTheme::refreshFonts()
|
||||
fixedFont.setStyleHint(QFont::TypeWriter);
|
||||
|
||||
LOGFONT lfIconTitleFont;
|
||||
SystemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
|
||||
const QFont iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont, dpi);
|
||||
QFont iconTitleFont;
|
||||
if (QWindowsContext::user32dll.systemParametersInfoForDpi) {
|
||||
QWindowsContext::user32dll.systemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
|
||||
iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont, dpi);
|
||||
} else {
|
||||
SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
|
||||
iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont);
|
||||
}
|
||||
|
||||
m_fonts[SystemFont] = new QFont(QWindowsFontDatabase::systemDefaultFont());
|
||||
m_fonts[MenuFont] = new QFont(menuFont);
|
||||
|
@ -523,11 +523,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);
|
||||
}
|
||||
|
||||
return GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -537,13 +541,17 @@ static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::Windo
|
||||
|
||||
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 (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10) {
|
||||
POINT pt = {screenPoint.x(), screenPoint.y()};
|
||||
if (HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
|
||||
if (QWindowsContext::shcoredll.isValid()) {
|
||||
UINT dpiX;
|
||||
UINT dpiY;
|
||||
if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY))) {
|
||||
const int gap = getResizeBorderThickness(dpiX);
|
||||
return QMargins(gap, 0, gap, gap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return QMargins();
|
||||
@ -551,9 +559,12 @@ static QMargins invisibleMargins(QPoint screenPoint)
|
||||
|
||||
[[nodiscard]] static inline QMargins invisibleMargins(const HWND hwnd)
|
||||
{
|
||||
const UINT dpi = GetDpiForWindow(hwnd);
|
||||
const int gap = getResizeBorderThickness(dpi);
|
||||
return QMargins(gap, 0, gap, gap);
|
||||
if (QWindowsContext::user32dll.getDpiForWindow) {
|
||||
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
|
||||
const int gap = getResizeBorderThickness(dpi);
|
||||
return QMargins(gap, 0, gap, gap);
|
||||
}
|
||||
return QMargins();
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -1054,7 +1065,8 @@ 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) {
|
||||
if (QWindowsContext::user32dll.adjustWindowRectExForDpi &&
|
||||
QWindowsContext::user32dll.adjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi))) == FALSE) {
|
||||
qErrnoWarning("%s: AdjustWindowRectExForDpi failed", __FUNCTION__);
|
||||
}
|
||||
const QMargins result(qAbs(rect.left), qAbs(rect.top),
|
||||
@ -1548,7 +1560,8 @@ void QWindowsWindow::initialize()
|
||||
QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(w, obtainedGeometry);
|
||||
}
|
||||
}
|
||||
QWindowsWindow::setSavedDpi(GetDpiForWindow(handle()));
|
||||
QWindowsWindow::setSavedDpi(QWindowsContext::user32dll.getDpiForWindow ?
|
||||
QWindowsContext::user32dll.getDpiForWindow(handle()) : 96);
|
||||
}
|
||||
|
||||
QSurfaceFormat QWindowsWindow::format() const
|
||||
@ -2040,17 +2053,20 @@ void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||
|
||||
void QWindowsWindow::handleDpiChangedAfterParent(HWND hwnd)
|
||||
{
|
||||
const UINT dpi = GetDpiForWindow(hwnd);
|
||||
const qreal scale = dpiRelativeScale(dpi);
|
||||
setSavedDpi(dpi);
|
||||
if (QWindowsContext::user32dll.getDpiForWindow)
|
||||
{
|
||||
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
|
||||
const qreal scale = dpiRelativeScale(dpi);
|
||||
setSavedDpi(dpi);
|
||||
|
||||
checkForScreenChanged(QWindowsWindow::FromDpiChange);
|
||||
checkForScreenChanged(QWindowsWindow::FromDpiChange);
|
||||
|
||||
// Child windows do not get WM_GETDPISCALEDSIZE messages to inform
|
||||
// Windows about the new size, so we need to manually scale them.
|
||||
QRect currentGeometry = geometry();
|
||||
QRect scaledGeometry = QRect(currentGeometry.topLeft() * scale, currentGeometry.size() * scale);
|
||||
setGeometry(scaledGeometry);
|
||||
// Child windows do not get WM_GETDPISCALEDSIZE messages to inform
|
||||
// Windows about the new size, so we need to manually scale them.
|
||||
QRect currentGeometry = geometry();
|
||||
QRect scaledGeometry = QRect(currentGeometry.topLeft() * scale, currentGeometry.size() * scale);
|
||||
setGeometry(scaledGeometry);
|
||||
}
|
||||
}
|
||||
|
||||
static QRect normalFrameGeometry(HWND hwnd)
|
||||
|
Loading…
Reference in New Issue
Block a user