6.6.1 works

This commit is contained in:
kleuter 2023-12-04 20:06:20 +01:00
parent 8490fae44c
commit d32a416512
21 changed files with 735 additions and 301 deletions

View File

@ -12,6 +12,7 @@
#include <qt_windows.h>
#include <shlobj.h>
#include <VersionHelpers.h>
#include <intshcut.h>
#include <qvarlengtharray.h>
@ -60,19 +61,25 @@ 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

View File

@ -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);

View File

@ -43,10 +43,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:
@ -60,6 +67,9 @@ bool qt_win_hasPackageIdentity()
#else
return false;
#endif
}
return false;
}
QT_END_NAMESPACE

View File

@ -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

View File

@ -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

View File

@ -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
};

View 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

View File

@ -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 (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

View File

@ -586,6 +586,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,

View File

@ -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 {};

View File

@ -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;

View File

@ -65,6 +65,14 @@ QT_BEGIN_NAMESPACE
void QDnsLookupRunnable::query(QDnsLookupReply *reply)
{
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 = {};
@ -87,7 +95,7 @@ void QDnsLookupRunnable::query(QDnsLookupReply *reply)
DNS_QUERY_RESULT results = {};
results.Version = 1;
const DNS_STATUS status = DnsQueryEx(&request, &results, nullptr);
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)
@ -95,6 +103,64 @@ void QDnsLookupRunnable::query(QDnsLookupReply *reply)
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;
}
if (!ptrStart)
return;
QStringView lastEncodedName;
QString cachedDecodedName;
auto extractAndCacheHost = [&](QStringView name) -> const QString & {
@ -107,7 +173,7 @@ void QDnsLookupRunnable::query(QDnsLookupReply *reply)
};
// 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

View File

@ -58,25 +58,52 @@ 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)
{
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(WindowsCreateStringReference(uiViewSettingsId, uiViewSettingsIdLen, &uiViewSettingsIdRefHeader, &uiViewSettingsIdHs)))
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 = RoGetActivationFactory(uiViewSettingsIdHs, uiViewSettingsInteropRefId,
HRESULT hr = RoGetActivationFactoryFunc(uiViewSettingsIdHs, uiViewSettingsInteropRefId,
reinterpret_cast<void **>(&uiViewSettingsInterop));
if (FAILED(hr))
return false;
@ -95,6 +122,9 @@ bool qt_windowsIsTabletMode(HWND hwnd)
}
uiViewSettingsInterop->Release();
return result;
}
return false;
}
QT_END_NAMESPACE

View File

@ -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,32 +430,46 @@ void QWindowsContext::setDetectAltGrModifier(bool a)
[[nodiscard]] static inline QtWindows::DpiAwareness
dpiAwarenessContextToQtDpiAwareness(DPI_AWARENESS_CONTEXT context)
{
if (QWindowsContext::user32dll.isValidDpiAwarenessContext && QWindowsContext::user32dll.areDpiAwarenessContextsEqual)
{
// IsValidDpiAwarenessContext() will handle the NULL pointer case.
if (!IsValidDpiAwarenessContext(context))
if (!QWindowsContext::user32dll.isValidDpiAwarenessContext(context))
return QtWindows::DpiAwareness::Invalid;
if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED))
if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED))
return QtWindows::DpiAwareness::Unaware_GdiScaled;
if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
return QtWindows::DpiAwareness::PerMonitorVersion2;
if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE))
if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE))
return QtWindows::DpiAwareness::PerMonitor;
if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))
if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))
return QtWindows::DpiAwareness::System;
if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE))
if (QWindowsContext::user32dll.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);
if (QWindowsContext::user32dll.getWindowDpiAwarenessContext)
{
const auto context = QWindowsContext::user32dll.getWindowDpiAwarenessContext(hwnd);
return dpiAwarenessContextToQtDpiAwareness(context);
}
return dpiAwarenessContextToQtDpiAwareness(DPI_AWARENESS_CONTEXT_UNAWARE);
}
QtWindows::DpiAwareness QWindowsContext::processDpiAwareness()
{
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.
@ -382,8 +477,11 @@ 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 auto context = QWindowsContext::user32dll.getThreadDpiAwarenessContext();
return dpiAwarenessContextToQtDpiAwareness(context);
}
return dpiAwarenessContextToQtDpiAwareness(DPI_AWARENESS_CONTEXT_UNAWARE);
}
[[nodiscard]] static inline DPI_AWARENESS_CONTEXT
@ -442,11 +540,14 @@ bool QWindowsContext::setProcessDpiAwareness(QtWindows::DpiAwareness dpiAwarenes
if (processDpiAwareness() == dpiAwareness)
return true;
const auto context = qtDpiAwarenessToDpiAwarenessContext(dpiAwareness);
if (!IsValidDpiAwarenessContext(context)) {
if (QWindowsContext::user32dll.isValidDpiAwarenessContext && QWindowsContext::user32dll.setProcessDpiAwarenessContext)
{
if (!QWindowsContext::user32dll.isValidDpiAwarenessContext(context)) {
qCWarning(lcQpaWindow) << dpiAwareness << "is not supported by current system.";
return false;
}
if (!SetProcessDpiAwarenessContext(context)) {
if (!QWindowsContext::user32dll.setProcessDpiAwarenessContext(context)) {
qCWarning(lcQpaWindow).noquote().nospace()
<< "SetProcessDpiAwarenessContext() failed: "
<< QSystemError::windowsString()
@ -459,6 +560,9 @@ bool QWindowsContext::setProcessDpiAwareness(QtWindows::DpiAwareness dpiAwarenes
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)",

View File

@ -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);

View File

@ -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) {

View File

@ -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 (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 = GetSystemMetricsForDpi(SM_CYSIZEFRAME, dpi)
+ GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
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)

View File

@ -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,7 +80,7 @@ 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,
if (!QWindowsContext::user32dll.getPointerFrameTouchInfoHistory(pointerId,
&historyCount,
&pointerCount,
touchInfo.data())) {
@ -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;

View File

@ -42,10 +42,12 @@ static inline QDpi deviceDPI(HDC hdc)
static inline QDpi monitorDPI(HMONITOR hMonitor)
{
if (QWindowsContext::shcoredll.isValid()) {
UINT dpiX;
UINT dpiY;
if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY)))
if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY)))
return QDpi(dpiX, dpiY);
}
return {0, 0};
}
@ -570,6 +572,7 @@ QRect QWindowsScreen::virtualGeometry(const QPlatformScreen *screen) // cf QScre
bool QWindowsScreen::setOrientationPreference(Qt::ScreenOrientation o)
{
bool result = false;
if (QWindowsContext::user32dll.setDisplayAutoRotationPreferences) {
ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
switch (o) {
case Qt::PrimaryOrientation:
@ -587,15 +590,17 @@ bool QWindowsScreen::setOrientationPreference(Qt::ScreenOrientation o)
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED;
break;
}
result = SetDisplayAutoRotationPreferences(orientationPreference);
result = QWindowsContext::user32dll.setDisplayAutoRotationPreferences(orientationPreference);
}
return result;
}
Qt::ScreenOrientation QWindowsScreen::orientationPreference()
{
Qt::ScreenOrientation result = Qt::PrimaryOrientation;
ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
if (GetDisplayAutoRotationPreferences(&orientationPreference)) {
if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences) {
DWORD orientationPreference = ORIENTATION_PREFERENCE_NONE;
if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences(&orientationPreference)) {
switch (orientationPreference) {
case ORIENTATION_PREFERENCE_NONE:
break;
@ -613,6 +618,7 @@ Qt::ScreenOrientation QWindowsScreen::orientationPreference()
break;
}
}
}
return result;
}

View File

@ -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)
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)
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 {
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)
if (IsWindows10OrGreater())
{
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);
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);

View File

@ -523,11 +523,15 @@ static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::Windo
[[nodiscard]] static inline int getResizeBorderThickness(const UINT 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 GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi)
+ GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
return QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi)
+ QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
}
return GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
}
/*!
@ -537,23 +541,30 @@ static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::Windo
static QMargins invisibleMargins(QPoint screenPoint)
{
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(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &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();
}
[[nodiscard]] static inline QMargins invisibleMargins(const HWND hwnd)
{
const UINT dpi = GetDpiForWindow(hwnd);
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,7 +2053,9 @@ void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
void QWindowsWindow::handleDpiChangedAfterParent(HWND hwnd)
{
const UINT dpi = GetDpiForWindow(hwnd);
if (QWindowsContext::user32dll.getDpiForWindow)
{
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
const qreal scale = dpiRelativeScale(dpi);
setSavedDpi(dpi);
@ -2051,6 +2066,7 @@ void QWindowsWindow::handleDpiChangedAfterParent(HWND hwnd)
QRect currentGeometry = geometry();
QRect scaledGeometry = QRect(currentGeometry.topLeft() * scale, currentGeometry.size() * scale);
setGeometry(scaledGeometry);
}
}
static QRect normalFrameGeometry(HWND hwnd)