[*] Windows 7 build regressions from 6.4 to 6.6

Change-Id: Icf3726ba501cf6e818741e5e62085a079c824ce3
This commit is contained in:
Reece Wilson 2023-11-30 03:59:03 +00:00
parent dfb37c4e24
commit a95f64ef44
20 changed files with 876 additions and 592 deletions

View File

@ -43,7 +43,7 @@ QComHelper::~QComHelper()
*/
bool qt_win_hasPackageIdentity()
{
#if defined(HAS_APPMODEL)
#if defined(HAS_APPMODEL) && 0
static const bool hasPackageIdentity = []() {
UINT32 length = 0;
switch (const auto result = GetCurrentPackageFullName(&length, nullptr)) {

View File

@ -24,7 +24,7 @@ namespace QtDummyFutex {
constexpr inline bool futexAvailable() { return false; }
template <typename Atomic>
inline bool futexWait(Atomic &, typename Atomic::Type, int = 0)
{ Q_UNREACHABLE(); return false; }
{ Q_UNREACHABLE_RETURN(false); }
template <typename Atomic> inline void futexWakeOne(Atomic &)
{ Q_UNREACHABLE(); }
template <typename Atomic> inline void futexWakeAll(Atomic &)
@ -113,30 +113,26 @@ QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
namespace QtWindowsFutex {
//#define QT_ALWAYS_USE_FUTEX
constexpr inline bool futexAvailable() { return true; }
constexpr inline bool futexAvailable() { return false; }
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)
{
return false;
//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;
@ -148,4 +144,4 @@ namespace QtFutex = QtDummyFutex;
QT_END_NAMESPACE
#endif
#endif // QFUTEX_P_H
#endif // QFUTEX_P_H

View File

@ -675,6 +675,8 @@ bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXC
if (deadlineTimer.hasExpired())
return false;
#if defined(QT_ALWAYS_USE_FUTEX)
if (futexAvailable()) {
if (Q_UNLIKELY(deadlineTimer.isForever())) {
lockInternal();
@ -701,6 +703,8 @@ bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXC
return false;
}
}
#endif
#if !defined(QT_ALWAYS_USE_FUTEX)
while (!fastTryLock()) {
@ -909,7 +913,35 @@ void QMutexPrivate::derefWaiters(int value) noexcept
QT_END_NAMESPACE
#if defined(QT_ALWAYS_USE_FUTEX)
// nothing
//
#elif defined(Q_OS_WIN)
#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)
{
if (timeout.isForever()) return (WaitForSingleObjectEx(event, INFINITE, FALSE) == WAIT_OBJECT_0);
auto a = timeout.remainingTime();
if (a == 0) return false;
return (WaitForSingleObjectEx(event, a, FALSE) == WAIT_OBJECT_0);
}
void QMutexPrivate::wakeUp() noexcept
{ SetEvent(event); }
QT_END_NAMESPACE
#elif defined(Q_OS_DARWIN)
# include "qmutex_mac.cpp"
#else

View File

@ -86,6 +86,8 @@ public:
semaphore_t mach_semaphore;
#elif defined(Q_OS_UNIX)
sem_t semaphore;
#else
void* event;
#endif
};

View File

@ -149,6 +149,7 @@ template <bool IsTimed> bool
futexSemaphoreTryAcquire_loop(QBasicAtomicInteger<quintptr> &u, quintptr curValue, quintptr nn,
QDeadlineTimer timer)
{
#if 0
using namespace std::chrono;
int n = int(unsigned(nn));
@ -187,6 +188,9 @@ futexSemaphoreTryAcquire_loop(QBasicAtomicInteger<quintptr> &u, quintptr curValu
if (IsTimed && timer.hasExpired())
return false;
}
#else
return false;
#endif
}
static constexpr QDeadlineTimer::ForeverConstant Expired =

View File

@ -155,7 +155,7 @@ inline Int aligned(Int v, Int byteAlign)
typedef HRESULT (__stdcall * Annoying_f)(UINT Flags, REFIID riid, void **ppFactory) ;
static IDXGIFactory1 *createDXGIFactory2()
IDXGIFactory1 *createDXGIFactory2()
{
IDXGIFactory1 *result = nullptr;
@ -174,6 +174,24 @@ static IDXGIFactory1 *createDXGIFactory2()
return result;
}
IDXGIFactory2 *createDXGIFactory2Ex(UINT factoryFlags)
{
IDXGIFactory2 *result = nullptr;
auto hDXGI = LoadLibraryW(L"DXGI.dll");
auto pCreateDXGIFactory2 = reinterpret_cast<Annoying_f>(GetProcAddress(hDXGI, "CreateDXGIFactory2"));
if (!pCreateDXGIFactory2) {
return nullptr;
}
const HRESULT hr = pCreateDXGIFactory2(factoryFlags, __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;
}
bool QRhiD3D11::create(QRhi::Flags flags)
{
rhiFlags = flags;

View File

@ -147,6 +147,49 @@ QRhiD3D12::QRhiD3D12(QRhiD3D12InitParams *params, QRhiD3D12NativeHandles *import
}
}
typedef HRESULT (__stdcall * D3D12SerializeVersionedRootSignature2_f)(
const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *pRootSignature,
ID3DBlob **ppBlob,
ID3DBlob **ppErrorBlob);
HRESULT D3D12SerializeVersionedRootSignature2(
const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *pRootSignature,
ID3DBlob **ppBlob,
ID3DBlob **ppErrorBlob
)
{
auto hD3D12 = LoadLibraryW(L"D3D12.dll");
auto pD3D12SerializeVersionedRootSignature = reinterpret_cast<D3D12SerializeVersionedRootSignature2_f>(GetProcAddress(hD3D12, "D3D12SerializeVersionedRootSignature"));
if (!pD3D12SerializeVersionedRootSignature) {
return (HRESULT)1;
}
return pD3D12SerializeVersionedRootSignature(pRootSignature, ppBlob, ppErrorBlob);
}
typedef HRESULT (__stdcall * D3D12CreateDevice_f)(
IUnknown *pAdapter,
D3D_FEATURE_LEVEL MinimumFeatureLevel,
REFIID riid,
void **ppDevice
);
HRESULT D3D12CreateDevice2(
IUnknown *pAdapter,
D3D_FEATURE_LEVEL MinimumFeatureLevel,
REFIID riid,
void **ppDevice
)
{
auto hD3D12 = LoadLibraryW(L"D3D12.dll");
auto pD3D12CreateDevice = reinterpret_cast<D3D12CreateDevice_f>(GetProcAddress(hD3D12, "D3D12CreateDevice"));
if (!pD3D12CreateDevice) {
return E_FAIL;
}
return pD3D12CreateDevice(pAdapter, MinimumFeatureLevel, riid, ppDevice);
}
template <class Int>
inline Int aligned(Int v, Int byteAlign)
{
@ -172,6 +215,8 @@ static inline QD3D12RenderTargetData *rtData(QRhiRenderTarget *rt)
Q_UNREACHABLE_RETURN(nullptr);
}
IDXGIFactory2 *createDXGIFactory2Ex(UINT factoryFlags);
bool QRhiD3D12::create(QRhi::Flags flags)
{
rhiFlags = flags;
@ -179,6 +224,9 @@ bool QRhiD3D12::create(QRhi::Flags flags)
UINT factoryFlags = 0;
if (debugLayer)
factoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
HRESULT hr {};
#if 0
HRESULT hr = CreateDXGIFactory2(factoryFlags, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&dxgiFactory));
if (FAILED(hr)) {
// retry without debug, if it was requested (to match D3D11 backend behavior)
@ -196,6 +244,17 @@ bool QRhiD3D12::create(QRhi::Flags flags)
return false;
}
}
#endif
this->dxgiFactory = createDXGIFactory2Ex(factoryFlags);
if (!this->dxgiFactory) {
if (debugLayer) {
this->dxgiFactory = createDXGIFactory2Ex(0);
}
if (!this->dxgiFactory) {
return false;
}
}
supportsAllowTearing = false;
IDXGIFactory5 *factory5 = nullptr;
@ -206,6 +265,7 @@ bool QRhiD3D12::create(QRhi::Flags flags)
factory5->Release();
}
#if 0
if (debugLayer) {
ID3D12Debug1 *debug = nullptr;
if (SUCCEEDED(D3D12GetDebugInterface(__uuidof(ID3D12Debug1), reinterpret_cast<void **>(&debug)))) {
@ -214,6 +274,7 @@ bool QRhiD3D12::create(QRhi::Flags flags)
debug->Release();
}
}
#endif
if (!importedDevice) {
IDXGIAdapter1 *adapter;
@ -276,10 +337,10 @@ bool QRhiD3D12::create(QRhi::Flags flags)
if (minimumFeatureLevel == 0)
minimumFeatureLevel = MIN_FEATURE_LEVEL;
hr = D3D12CreateDevice(activeAdapter,
minimumFeatureLevel,
__uuidof(ID3D12Device2),
reinterpret_cast<void **>(&dev));
hr = D3D12CreateDevice2(activeAdapter,
minimumFeatureLevel,
__uuidof(ID3D12Device2),
reinterpret_cast<void **>(&dev));
if (FAILED(hr)) {
qWarning("Failed to create D3D12 device: %s", qPrintable(QSystemError::windowsComString(hr)));
return false;
@ -2747,7 +2808,7 @@ bool QD3D12MipmapGenerator::create(QRhiD3D12 *rhiD)
rsDesc.Desc_1_1.pStaticSamplers = &samplerDesc;
ID3DBlob *signature = nullptr;
HRESULT hr = D3D12SerializeVersionedRootSignature(&rsDesc, &signature, nullptr);
HRESULT hr = D3D12SerializeVersionedRootSignature2(&rsDesc, &signature, nullptr);
if (FAILED(hr)) {
qWarning("Failed to serialize root signature: %s", qPrintable(QSystemError::windowsComString(hr)));
return false;
@ -5007,7 +5068,7 @@ QD3D12ObjectHandle QD3D12ShaderResourceBindings::createRootSignature(const QD3D1
rsDesc.Desc_1_1.Flags = D3D12_ROOT_SIGNATURE_FLAGS(rsFlags);
ID3DBlob *signature = nullptr;
HRESULT hr = D3D12SerializeVersionedRootSignature(&rsDesc, &signature, nullptr);
HRESULT hr = D3D12SerializeVersionedRootSignature2(&rsDesc, &signature, nullptr);
if (FAILED(hr)) {
qWarning("Failed to serialize root signature: %s", qPrintable(QSystemError::windowsComString(hr)));
return {};

View File

@ -17,10 +17,30 @@
# include "qwindowsfontenginedirectwrite_p.h"
#endif
#include <windows.h>
typedef BOOL(__stdcall *SystemParametersInfoForDpi_f)(UINT uiAction, UINT uiParam, PVOID pvParam,
UINT fWinIni, UINT dpi);
inline BOOL SystemParametersInfoForDpi2(
UINT uiAction,
UINT uiParam,
PVOID pvParam,
UINT fWinIni,
UINT dpi
)
{
static auto pSystemParametersInfoForDpi = reinterpret_cast<SystemParametersInfoForDpi_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "SystemParametersInfoForDpi"));
return pSystemParametersInfoForDpi
? pSystemParametersInfoForDpi(uiAction, uiParam, pvParam, fWinIni, dpi)
: SystemParametersInfo(uiAction, uiParam, pvParam, fWinIni);
}
QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
// Helper classes for creating font engines directly from font data
namespace {
@ -689,7 +709,7 @@ 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());
SystemParametersInfoForDpi2(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0, defaultVerticalDPI());
const QFont systemFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMessageFont);
qCDebug(lcQpaFonts) << __FUNCTION__ << systemFont;
return systemFont;

View File

@ -65,51 +65,53 @@ 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;
IP4_ARRAY srvList;
memset(&srvList, 0, sizeof(IP4_ARRAY));
if (!nameserver.isNull()) {
memset(dnsAddresses, 0, sizeof(dnsAddresses));
request.pDnsServerList = new (dnsAddresses) DNS_ADDR_ARRAY;
auto addr = new (request.pDnsServerList->AddrArray) DNS_ADDR[1];
auto sa = new (addr[0].MaxSa) sockaddr;
request.pDnsServerList->MaxCount = sizeof(dnsAddresses);
request.pDnsServerList->AddrCount = 1;
// ### setting port 53 seems to cause some systems to fail
setSockaddr(sa, nameserver, port == DnsPort ? 0 : port);
request.pDnsServerList->Family = sa->sa_family;
if (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 supoprting IPv6 nameserver addresses, we'll need to switch
// from DnsQuey() to DnsQueryEx() as it supports passing an IPv6
// address in the nameserver list
reply->error = QDnsLookup::ResolverError;
reply->errorString = tr("no IPv6");
return;
}
}
PDNS_RECORD dns_records = 0;
const DNS_STATUS status = DnsQuery_W(reinterpret_cast<const wchar_t *>(requestName.constData()), 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:
reply->error = QDnsLookup::ServerFailureError;
reply->errorString = tr("Server failure");
return;
case DNS_ERROR_RCODE_NAME_ERROR:
reply->error = QDnsLookup::NotFoundError;
reply->errorString = tr("Non existent domain");
return;
case DNS_ERROR_RCODE_REFUSED:
reply->error = QDnsLookup::ServerRefusedError;
reply->errorString = tr("Server refused to answer");
return;
default:
reply->error = QDnsLookup::InvalidReplyError;
reply->errorString = QSystemError(status, QSystemError::NativeError).toString();
return;
}
DNS_QUERY_RESULT results = {};
results.Version = 1;
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);
QStringView lastEncodedName;
QString cachedDecodedName;
auto extractAndCacheHost = [&](QStringView name) -> const QString & {
lastEncodedName = name;
cachedDecodedName = decodeLabel(name);
return cachedDecodedName;
};
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) {
// warning: always assign name to the record before calling extractXxxHost() again
const QString &name = extractMaybeCachedHost(ptr->pName);
for (PDNS_RECORD ptr = dns_records; ptr != NULL; ptr = ptr->pNext) {
const QString name = QUrl::fromAce( QString::fromWCharArray( ptr->pName ).toLatin1() );
if (ptr->wType == QDnsLookup::A) {
QDnsHostAddressRecord record;
record.d->name = name;
@ -129,12 +131,12 @@ void QDnsLookupRunnable::query(QDnsLookupReply *reply)
QDnsDomainNameRecord record;
record.d->name = name;
record.d->timeToLive = ptr->dwTtl;
record.d->value = extractAndCacheHost(ptr->Data.Cname.pNameHost);
record.d->value = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Cname.pNameHost).toLatin1());
reply->canonicalNameRecords.append(record);
} else if (ptr->wType == QDnsLookup::MX) {
QDnsMailExchangeRecord record;
record.d->name = name;
record.d->exchange = decodeLabel(QStringView(ptr->Data.Mx.pNameExchange));
record.d->exchange = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Mx.pNameExchange).toLatin1());
record.d->preference = ptr->Data.Mx.wPreference;
record.d->timeToLive = ptr->dwTtl;
reply->mailExchangeRecords.append(record);
@ -142,18 +144,18 @@ void QDnsLookupRunnable::query(QDnsLookupReply *reply)
QDnsDomainNameRecord record;
record.d->name = name;
record.d->timeToLive = ptr->dwTtl;
record.d->value = decodeLabel(QStringView(ptr->Data.Ns.pNameHost));
record.d->value = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Ns.pNameHost).toLatin1());
reply->nameServerRecords.append(record);
} else if (ptr->wType == QDnsLookup::PTR) {
QDnsDomainNameRecord record;
record.d->name = name;
record.d->timeToLive = ptr->dwTtl;
record.d->value = decodeLabel(QStringView(ptr->Data.Ptr.pNameHost));
record.d->value = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Ptr.pNameHost).toLatin1());
reply->pointerRecords.append(record);
} else if (ptr->wType == QDnsLookup::SRV) {
QDnsServiceRecord record;
record.d->name = name;
record.d->target = decodeLabel(QStringView(ptr->Data.Srv.pNameTarget));
record.d->target = QUrl::fromAce(QString::fromWCharArray(ptr->Data.Srv.pNameTarget).toLatin1());
record.d->port = ptr->Data.Srv.wPort;
record.d->priority = ptr->Data.Srv.wPriority;
record.d->timeToLive = ptr->dwTtl;
@ -164,13 +166,13 @@ void QDnsLookupRunnable::query(QDnsLookupReply *reply)
record.d->name = name;
record.d->timeToLive = ptr->dwTtl;
for (unsigned int i = 0; i < ptr->Data.Txt.dwStringCount; ++i) {
record.d->values << QStringView(ptr->Data.Txt.pStringArray[i]).toLatin1();
record.d->values << QString::fromWCharArray((ptr->Data.Txt.pStringArray[i])).toLatin1();;
}
reply->textRecords.append(record);
}
}
DnsRecordListFree(results.pQueryRecords, DnsFreeRecordList);
DnsRecordListFree(dns_records, DnsFreeRecordList);
}
QT_END_NAMESPACE

View File

@ -25,38 +25,6 @@
# include <uiviewsettingsinterop.h>
#endif
#ifndef HAS_UI_VIEW_SETTINGS_INTEROP
MIDL_INTERFACE("3694dbf9-8f68-44be-8ff5-195c98ede8a6")
IUIViewSettingsInterop : public IInspectable
{
public:
virtual HRESULT STDMETHODCALLTYPE GetForWindow(
__RPC__in HWND hwnd,
__RPC__in REFIID riid,
__RPC__deref_out_opt void **ppv) = 0;
};
#endif // !HAS_UI_VIEW_SETTINGS_INTEROP
#ifndef HAS_UI_VIEW_SETTINGS
namespace ABI {
namespace Windows {
namespace UI {
namespace ViewManagement {
enum UserInteractionMode { Mouse, Touch };
MIDL_INTERFACE("C63657F6-8850-470D-88F8-455E16EA2C26")
IUIViewSettings : public IInspectable
{
public:
virtual HRESULT STDMETHODCALLTYPE get_UserInteractionMode(UserInteractionMode *value) = 0;
};
} // namespace ViewManagement
} // namespace UI
} // namespace Windows
} // namespace ABI
#endif // HAS_UI_VIEW_SETTINGS
QT_BEGIN_NAMESPACE

View File

@ -11,7 +11,7 @@
#include "qwindowspointerhandler.h"
#include "qtwindowsglobal.h"
#include "qwindowsmenu.h"
#include "qwindowsmime.h"
#include "qwindowsmimeregistry.h"
#include "qwindowsinputcontext.h"
#if QT_CONFIG(tabletevent)
# include "qwindowstabletsupport.h"
@ -45,8 +45,11 @@
#include <QtCore/qscopedpointer.h>
#include <QtCore/quuid.h>
#include <QtCore/private/qwinregistry_p.h>
#include <QtCore/private/qfactorycacheregistration_p.h>
#include <QtCore/private/qsystemerror_p.h>
#include <QtGui/private/qwindowsguieventdispatcher_p.h>
#include <QtGui/private/qwindowsthemecache_p.h>
#include <stdlib.h>
#include <stdio.h>
@ -67,7 +70,7 @@ typedef DPI_AWARENESS (__stdcall * GetAwarenessFromDpiAwarenessContext_f)(DPI_AW
using namespace Qt::StringLiterals;
Q_LOGGING_CATEGORY(lcQpaWindows, "qt.qpa.windows")
Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window")
Q_LOGGING_CATEGORY(lcQpaEvents, "qt.qpa.events")
Q_LOGGING_CATEGORY(lcQpaGl, "qt.qpa.gl")
Q_LOGGING_CATEGORY(lcQpaMime, "qt.qpa.mime")
@ -80,12 +83,90 @@ Q_LOGGING_CATEGORY(lcQpaUiAutomation, "qt.qpa.uiautomation")
Q_LOGGING_CATEGORY(lcQpaTrayIcon, "qt.qpa.trayicon")
Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen")
typedef BOOL (__stdcall *SystemParametersInfoForDpi_f)(
UINT uiAction,
UINT uiParam,
PVOID pvParam,
UINT fWinIni,
UINT dpi
);
BOOL SystemParametersInfoForDpi2(
UINT uiAction,
UINT uiParam,
PVOID pvParam,
UINT fWinIni,
UINT dpi
)
{
static auto pSystemParametersInfoForDpi = reinterpret_cast<SystemParametersInfoForDpi_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "SystemParametersInfoForDpi"));
return pSystemParametersInfoForDpi
? pSystemParametersInfoForDpi(uiAction, uiParam, pvParam, fWinIni, dpi)
: SystemParametersInfo(uiAction, uiParam, pvParam, fWinIni);
}
bool QWindowsContext::systemParametersInfo(unsigned action, unsigned param, void *out,
unsigned dpi)
{
return SystemParametersInfoForDpi2(action, param, out, 0, dpi) == TRUE;
}
DPI_AWARENESS GetAwarenessFromDpiAwarenessContext2(DPI_AWARENESS_CONTEXT context)
{
switch ((ULONG_PTR)context)
{
case 0x10:
case 0x11:
case 0x12:
case 0x80000010:
case 0x80000011:
case 0x80000012:
return (DPI_AWARENESS)((int)context & 3);
case (DPI_AWARENESS)(int)DPI_AWARENESS_CONTEXT_UNAWARE:
case (DPI_AWARENESS)(int)DPI_AWARENESS_CONTEXT_SYSTEM_AWARE:
case (DPI_AWARENESS)(int)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE:
return DPI_AWARENESS(~(ULONG_PTR)context);
default:
return DPI_AWARENESS_INVALID;
}
}
BOOL AreDpiAwarenessContextsEqual2(DPI_AWARENESS_CONTEXT ctx1, DPI_AWARENESS_CONTEXT ctx2)
{
auto aware1 = GetAwarenessFromDpiAwarenessContext2(ctx1);
auto aware2 = GetAwarenessFromDpiAwarenessContext2(ctx2);
return aware1 != DPI_AWARENESS_INVALID && aware1 == aware2;
}
[[nodiscard]] static inline QtWindows::DpiAwareness
dpiAwarenessContextToQtDpiAwareness(DPI_AWARENESS_CONTEXT context)
{
if (!IsValidDpiAwarenessContext(context))
return QtWindows::DpiAwareness::Invalid;
if (AreDpiAwarenessContextsEqual2(context, DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED))
return QtWindows::DpiAwareness::Unaware_GdiScaled;
if (AreDpiAwarenessContextsEqual2(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
return QtWindows::DpiAwareness::PerMonitorVersion2;
if (AreDpiAwarenessContextsEqual2(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE))
return QtWindows::DpiAwareness::PerMonitor;
if (AreDpiAwarenessContextsEqual2(context, DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))
return QtWindows::DpiAwareness::System;
if (AreDpiAwarenessContextsEqual2(context, DPI_AWARENESS_CONTEXT_UNAWARE))
return QtWindows::DpiAwareness::Unaware;
return QtWindows::DpiAwareness::Invalid;
}
int QWindowsContext::verbose = 0;
#if !defined(LANG_SYRIAC)
# define LANG_SYRIAC 0x5a
#endif
class QDebug __cdecl operator<<(class QDebug e,enum QtWindows::DpiAwareness)
{
return e;
}
static inline bool useRTL_Extensions()
{
// Since the IsValidLanguageGroup/IsValidLocale functions always return true on
@ -126,12 +207,12 @@ static inline bool sessionManagerInteractionBlocked() { return false; }
static inline int windowDpiAwareness(HWND hwnd)
{
auto pGetAwarenessFromDpiAwarenessContext = reinterpret_cast<GetAwarenessFromDpiAwarenessContext_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "GetAwarenessFromDpiAwarenessContext"));
static auto pGetAwarenessFromDpiAwarenessContext = reinterpret_cast<GetAwarenessFromDpiAwarenessContext_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "GetAwarenessFromDpiAwarenessContext"));
if (!pGetAwarenessFromDpiAwarenessContext) {
return false;
}
auto pGetWindowDpiAwarenessContext = reinterpret_cast<GetWindowDpiAwarenessContext_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "GetWindowDpiAwarenessContext"));
static auto pGetWindowDpiAwarenessContext = reinterpret_cast<GetWindowDpiAwarenessContext_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "GetWindowDpiAwarenessContext"));
if (!pGetWindowDpiAwarenessContext) {
return false;
}
@ -181,7 +262,7 @@ struct QWindowsContextPrivate {
QWindowsKeyMapper m_keyMapper;
QWindowsMouseHandler m_mouseHandler;
QWindowsPointerHandler m_pointerHandler;
QWindowsMimeConverter m_mimeConverter;
QWindowsMimeRegistry m_mimeConverter;
QWindowsScreenManager m_screenManager;
QSharedPointer<QWindowCreationContext> m_creationContext;
#if QT_CONFIG(tabletevent)
@ -213,7 +294,7 @@ QWindowsContextPrivate::QWindowsContextPrivate()
m_darkMode = QWindowsTheme::queryDarkMode();
if (FAILED(m_oleInitializeResult)) {
qWarning() << "QWindowsContext: OleInitialize() failed: "
<< QWindowsContext::comErrorString(m_oleInitializeResult);
<< QSystemError::windowsComString(m_oleInitializeResult);
}
}
@ -286,7 +367,7 @@ void QWindowsContext::registerTouchWindows()
{
if (QGuiApplicationPrivate::is_app_running
&& (d->m_systemInfo & QWindowsContext::SI_SupportsTouch) != 0) {
for (QWindowsWindow *w : qAsConst(d->m_windows))
for (QWindowsWindow *w : std::as_const(d->m_windows))
w->registerTouchWindow();
}
}
@ -378,68 +459,97 @@ void QWindowsContext::setTabletAbsoluteRange(int a)
#endif
}
QWindowsKeyMapper *QWindowsContext::keyMapper() const
{
return &d->m_keyMapper;
}
void QWindowsContext::setDetectAltGrModifier(bool a)
{
d->m_keyMapper.setDetectAltGrModifier(a);
}
int QWindowsContext::processDpiAwareness()
[[nodiscard]] static inline DPI_AWARENESS_CONTEXT
qtDpiAwarenessToDpiAwarenessContext(QtWindows::DpiAwareness dpiAwareness)
{
PROCESS_DPI_AWARENESS result;
switch (dpiAwareness) {
case QtWindows::DpiAwareness::Invalid:
return nullptr;
case QtWindows::DpiAwareness::Unaware:
return DPI_AWARENESS_CONTEXT_UNAWARE;
case QtWindows::DpiAwareness::System:
return DPI_AWARENESS_CONTEXT_SYSTEM_AWARE;
case QtWindows::DpiAwareness::PerMonitor:
return DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE;
case QtWindows::DpiAwareness::PerMonitorVersion2:
return DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2;
case QtWindows::DpiAwareness::Unaware_GdiScaled:
return DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED;
}
return nullptr;
}
typedef DPI_AWARENESS_CONTEXT (__stdcall *GetThreadDpiAwarenessContext_f)();
typedef HRESULT (__stdcall *GetProcessDpiAwarenessContext_f)(HANDLE hprocess, PROCESS_DPI_AWARENESS *value);
QtWindows::DpiAwareness QWindowsContext::processDpiAwareness()
{
PROCESS_DPI_AWARENESS awareness;
auto pGetDPIAwareness = reinterpret_cast<GetProcessDpiAwareness_f>(GetProcAddress(LoadLibraryW(L"api-ms-win-shcore-scaling-l1-1-1.dll"), "GetProcessDpiAwareness"));
static auto pGetDPIAwareness = reinterpret_cast<GetProcessDpiAwareness_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "GetProcessDpiAwareness"));
if (!pGetDPIAwareness) {
return 0;
return (QtWindows::DpiAwareness)0;
}
if (SUCCEEDED(pGetDPIAwareness(nullptr, &result))) {
return static_cast<int>(result);
static auto pGetThreadDpiAwarenessContext = reinterpret_cast<GetThreadDpiAwarenessContext_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "GetThreadDpiAwarenessContext"));
if (pGetThreadDpiAwarenessContext) {
return dpiAwarenessContextToQtDpiAwareness(pGetThreadDpiAwarenessContext());
}
return -1;
static auto pGetProcessDpiAwarenessContext = reinterpret_cast<GetProcessDpiAwarenessContext_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "GetProcessDpiAwarenessContext"));
if (pGetProcessDpiAwarenessContext) {
if (SUCCEEDED(pGetProcessDpiAwarenessContext(NULL, &awareness))) {
return (QtWindows::DpiAwareness)awareness;
}
}
if (SUCCEEDED(pGetDPIAwareness(nullptr, &awareness))) {
return (QtWindows::DpiAwareness)awareness;
}
return (QtWindows::DpiAwareness)0;
}
void QWindowsContext::setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness)
bool QWindowsContext::setProcessDpiAwareness(QtWindows::DpiAwareness dpiAwareness)
{
PROCESS_DPI_AWARENESS result;
auto pSetProcessDpiAwareness = reinterpret_cast<SetProcessDpiAwareness_f>(GetProcAddress(LoadLibraryW(L"api-ms-win-shcore-scaling-l1-1-1.dll"), "SetProcessDpiAwareness"));
QWindowsContextPrivate::m_v2DpiAware = false;
static auto pSetProcessDpiAwareness = reinterpret_cast<SetProcessDpiAwareness_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "SetProcessDpiAwareness"));
if (!pSetProcessDpiAwareness) {
return;
}
qCDebug(lcQpaWindows) << __FUNCTION__ << dpiAwareness;
const HRESULT hr = pSetProcessDpiAwareness(static_cast<PROCESS_DPI_AWARENESS>(dpiAwareness));
// E_ACCESSDENIED means set externally (MSVC manifest or external app loading Qt plugin).n
// Silence warning in that case unless debug is enabled.
if (FAILED(hr) && (hr != E_ACCESSDENIED || lcQpaWindows().isDebugEnabled())) {
qWarning().noquote().nospace() << "SetProcessDpiAwareness("
<< dpiAwareness << ") failed: " << QWindowsContext::comErrorString(hr)
<< ", using " << QWindowsContext::processDpiAwareness();
}
}
bool QWindowsContext::setProcessDpiV2Awareness()
{
auto pSetProcessDpiAwarenessContext = reinterpret_cast<SetProcessDpiAwarenessContext_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "SetProcessDpiAwarenessContext"));
if (!pSetProcessDpiAwarenessContext) {
return false;
}
qCDebug(lcQpaWindows) << __FUNCTION__;
const BOOL ok = pSetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
if (!ok) {
const HRESULT errorCode = GetLastError();
qCWarning(lcQpaWindows).noquote().nospace() << "setProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) failed: "
<< QWindowsContext::comErrorString(errorCode);
return false;
if (dpiAwareness != QtWindows::DpiAwareness::PerMonitorVersion2) {
const HRESULT hr = pSetProcessDpiAwareness(static_cast<PROCESS_DPI_AWARENESS>(dpiAwareness));
if (FAILED(hr)) {
return false;
} else {
return true;
}
}
static auto pSetProcessDpiAwarenessContext = reinterpret_cast<SetProcessDpiAwarenessContext_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "SetProcessDpiAwarenessContext"));
if (pSetProcessDpiAwarenessContext) {
const BOOL ok = pSetProcessDpiAwarenessContext(qtDpiAwarenessToDpiAwarenessContext(dpiAwareness));
if (ok) {
QWindowsContextPrivate::m_v2DpiAware = true;
}
}
QWindowsContextPrivate::m_v2DpiAware = true;
return true;
}
bool QWindowsContext::isDarkMode()
{
return QWindowsContextPrivate::m_darkMode;
@ -574,7 +684,7 @@ QString QWindowsContext::registerWindowClass(const QWindow *w)
if (icon)
cname += "Icon"_L1;
return registerWindowClass(cname, qWindowsWndProc, style, GetSysColorBrush(COLOR_WINDOW), icon);
return registerWindowClass(cname, qWindowsWndProc, style, nullptr, icon);
}
QString QWindowsContext::registerWindowClass(QString cname,
@ -633,7 +743,7 @@ QString QWindowsContext::registerWindowClass(QString cname,
qPrintable(cname));
d->m_registeredWindowClassNames.insert(cname);
qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << ' ' << cname
qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << ' ' << cname
<< " style=0x" << Qt::hex << style << Qt::dec
<< " brush=" << brush << " icon=" << icon << " atom=" << atom;
return cname;
@ -643,7 +753,7 @@ void QWindowsContext::unregisterWindowClasses()
{
const auto appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
for (const QString &name : qAsConst(d->m_registeredWindowClassNames)) {
for (const QString &name : std::as_const(d->m_registeredWindowClassNames)) {
if (!UnregisterClass(reinterpret_cast<LPCWSTR>(name.utf16()), appInstance) && QWindowsContext::verbose)
qErrnoWarning("UnregisterClass failed for '%s'", qPrintable(name));
}
@ -655,23 +765,6 @@ int QWindowsContext::screenDepth() const
return GetDeviceCaps(d->m_displayContext, BITSPIXEL);
}
QString QWindowsContext::windowsErrorMessage(unsigned long errorCode)
{
QString rc = QString::fromLatin1("#%1: ").arg(errorCode);
char16_t *lpMsgBuf;
const DWORD len = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, errorCode, 0, reinterpret_cast<LPTSTR>(&lpMsgBuf), 0, nullptr);
if (len) {
rc = QString::fromUtf16(lpMsgBuf, int(len));
LocalFree(lpMsgBuf);
} else {
rc += QString::fromLatin1("<unknown error>");
}
return rc;
}
void QWindowsContext::addWindow(HWND hwnd, QWindowsWindow *w)
{
d->m_windows.insert(hwnd, w);
@ -834,7 +927,7 @@ bool QWindowsContext::isSessionLocked()
return result;
}
QWindowsMimeConverter &QWindowsContext::mimeConverter() const
QWindowsMimeRegistry &QWindowsContext::mimeConverter() const
{
return d->m_mimeConverter;
}
@ -872,79 +965,6 @@ HWND QWindowsContext::createDummyWindow(const QString &classNameIn,
HWND_MESSAGE, nullptr, static_cast<HINSTANCE>(GetModuleHandle(nullptr)), nullptr);
}
/*!
\brief Common COM error strings.
*/
QByteArray QWindowsContext::comErrorString(HRESULT hr)
{
QByteArray result = QByteArrayLiteral("COM error 0x")
+ QByteArray::number(quintptr(hr), 16) + ' ';
switch (hr) {
case S_OK:
result += QByteArrayLiteral("S_OK");
break;
case S_FALSE:
result += QByteArrayLiteral("S_FALSE");
break;
case E_UNEXPECTED:
result += QByteArrayLiteral("E_UNEXPECTED");
break;
case E_ACCESSDENIED:
result += QByteArrayLiteral("E_ACCESSDENIED");
break;
case CO_E_ALREADYINITIALIZED:
result += QByteArrayLiteral("CO_E_ALREADYINITIALIZED");
break;
case CO_E_NOTINITIALIZED:
result += QByteArrayLiteral("CO_E_NOTINITIALIZED");
break;
case RPC_E_CHANGED_MODE:
result += QByteArrayLiteral("RPC_E_CHANGED_MODE");
break;
case OLE_E_WRONGCOMPOBJ:
result += QByteArrayLiteral("OLE_E_WRONGCOMPOBJ");
break;
case CO_E_NOT_SUPPORTED:
result += QByteArrayLiteral("CO_E_NOT_SUPPORTED");
break;
case E_NOTIMPL:
result += QByteArrayLiteral("E_NOTIMPL");
break;
case E_INVALIDARG:
result += QByteArrayLiteral("E_INVALIDARG");
break;
case E_NOINTERFACE:
result += QByteArrayLiteral("E_NOINTERFACE");
break;
case E_POINTER:
result += QByteArrayLiteral("E_POINTER");
break;
case E_HANDLE:
result += QByteArrayLiteral("E_HANDLE");
break;
case E_ABORT:
result += QByteArrayLiteral("E_ABORT");
break;
case E_FAIL:
result += QByteArrayLiteral("E_FAIL");
break;
case RPC_E_WRONG_THREAD:
result += QByteArrayLiteral("RPC_E_WRONG_THREAD");
break;
case RPC_E_THREAD_NOT_INIT:
result += QByteArrayLiteral("RPC_E_THREAD_NOT_INIT");
break;
default:
break;
}
_com_error error(hr);
result += QByteArrayLiteral(" (");
result += QString::fromWCharArray(error.ErrorMessage()).toUtf8();
result += ')';
return result;
}
void QWindowsContext::forceNcCalcSize(HWND hwnd)
{
// Force WM_NCCALCSIZE to adjust margin
@ -952,25 +972,6 @@ void QWindowsContext::forceNcCalcSize(HWND hwnd)
SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
}
typedef BOOL (__stdcall *SystemParametersInfoForDpi_f)(
UINT uiAction,
UINT uiParam,
PVOID pvParam,
UINT fWinIni,
UINT dpi
);
bool QWindowsContext::systemParametersInfo(unsigned action, unsigned param, void *out,
unsigned dpi)
{
auto pSystemParametersInfoForDpi = reinterpret_cast<SystemParametersInfoForDpi_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "SystemParametersInfoForDpi"));
const BOOL result = dpi != 0 && pSystemParametersInfoForDpi
? pSystemParametersInfoForDpi(action, param, out, 0, dpi)
: SystemParametersInfo(action, param, out, 0);
return result == TRUE;
}
bool QWindowsContext::systemParametersInfoForScreen(unsigned action, unsigned param, void *out,
const QPlatformScreen *screen)
{
@ -1181,7 +1182,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
d->m_creationContext->applyToMinMaxInfo(reinterpret_cast<MINMAXINFO *>(lParam));
return true;
case QtWindows::ResizeEvent:
d->m_creationContext->obtainedSize = QSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
d->m_creationContext->obtainedSize = QSize(LOWORD(lParam), HIWORD(lParam));
return true;
case QtWindows::MoveEvent:
d->m_creationContext->obtainedPos = QPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
@ -1224,7 +1225,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
if (wParam == DBT_DEVNODES_CHANGED)
initTouch();
break;
case QtWindows::KeyboardLayoutChangeEvent:
case QtWindows::InputLanguageChangeEvent:
if (QWindowsInputContext *wic = windowsInputContext())
wic->handleInputLanguageChanged(wParam, lParam);
Q_FALLTHROUGH();
@ -1254,7 +1255,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
platformWindow->handleMoved();
return true;
case QtWindows::ResizeEvent:
platformWindow->handleResized(static_cast<int>(wParam));
platformWindow->handleResized(static_cast<int>(wParam), lParam);
return true;
case QtWindows::QuerySizeHints:
platformWindow->getSizeHints(reinterpret_cast<MINMAXINFO *>(lParam));
@ -1268,21 +1269,29 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::ExposeEvent:
return platformWindow->handleWmPaint(hwnd, message, wParam, lParam, result);
case QtWindows::NonClientMouseEvent:
if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled())
if (!platformWindow->frameStrutEventsEnabled())
break;
if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
else
return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
case QtWindows::NonClientPointerEvent:
if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled())
if (!platformWindow->frameStrutEventsEnabled())
break;
if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
return sessionManagerInteractionBlocked() || d->m_pointerHandler.translatePointerEvent(platformWindow->window(), hwnd, et, msg, result);
break;
case QtWindows::EnterSizeMoveEvent:
platformWindow->setFlag(QWindowsWindow::ResizeMoveActive);
if (!IsZoomed(hwnd))
platformWindow->updateRestoreGeometry();
return true;
case QtWindows::ExitSizeMoveEvent:
platformWindow->clearFlag(QWindowsWindow::ResizeMoveActive);
platformWindow->checkForScreenChanged();
handleExitSizeMove(platformWindow->window());
if (!IsZoomed(hwnd))
platformWindow->updateRestoreGeometry();
return true;
case QtWindows::ScrollEvent:
if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
@ -1328,6 +1337,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
QWindowSystemInterface::handleCloseEvent(platformWindow->window());
return true;
case QtWindows::ThemeChanged: {
QWindowsThemeCache::clearThemeCache(platformWindow->handle());
// Switch from Aero to Classic changes margins.
if (QWindowsTheme *theme = QWindowsTheme::instance())
theme->windowsThemeChanged(platformWindow->window());
@ -1419,6 +1429,11 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
return true;
}
#endif // !defined(QT_NO_SESSIONMANAGER)
case QtWindows::TaskbarButtonCreated:
// Apply application badge if this is the first time we have a taskbar
// button, or after Explorer restart.
QWindowsIntegration::instance()->updateApplicationBadge();
break;
default:
break;
}
@ -1461,7 +1476,7 @@ void QWindowsContext::handleFocusEvent(QtWindows::WindowsEventType et,
}
if (nextActiveWindow != d->m_lastActiveWindow) {
d->m_lastActiveWindow = nextActiveWindow;
QWindowSystemInterface::handleWindowActivated(nextActiveWindow, Qt::ActiveWindowFocusReason);
QWindowSystemInterface::handleFocusWindowChanged(nextActiveWindow, Qt::ActiveWindowFocusReason);
}
}
@ -1616,7 +1631,7 @@ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPAR
marginsFromRects(ncCalcSizeFrame, rectFromNcCalcSize(message, wParam, lParam, 0));
if (margins.left() >= 0) {
if (platformWindow) {
qCDebug(lcQpaWindows) << __FUNCTION__ << "WM_NCCALCSIZE for" << hwnd << margins;
qCDebug(lcQpaWindow) << __FUNCTION__ << "WM_NCCALCSIZE for" << hwnd << margins;
platformWindow->setFullFrameMargins(margins);
} else {
const QSharedPointer<QWindowCreationContext> ctx = QWindowsContext::instance()->windowCreationContext();

View File

@ -33,7 +33,6 @@ Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen)
class QWindow;
class QPlatformScreen;
class QPlatformWindow;
class QPlatformKeyMapper;
class QWindowsMenuBar;
class QWindowsScreenManager;
class QWindowsTabletSupport;
@ -41,9 +40,11 @@ class QWindowsWindow;
class QWindowsMimeRegistry;
struct QWindowCreationContext;
struct QWindowsContextPrivate;
class QWindowsKeyMapper;
class QPoint;
class QKeyEvent;
class QPointingDevice;
class QWindowsContext
{
Q_DISABLE_COPY_MOVE(QWindowsContext)
@ -128,7 +129,7 @@ public:
unsigned systemInfo() const;
bool useRTLExtensions() const;
QPlatformKeyMapper *keyMapper() const;
QList<int> possibleKeys(const QKeyEvent *e) const;
HandleBaseWindowHash &windows();
@ -138,6 +139,7 @@ public:
QWindowsScreenManager &screenManager();
QWindowsTabletSupport *tabletSupport() const;
QWindowsKeyMapper *keyMapper() const;
bool asyncExpose() const;
void setAsyncExpose(bool value);

View File

@ -666,6 +666,7 @@ static HRESULT startDoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource,
return ::DoDragDrop(pDataObj, pDropSource, dwOKEffects, pdwEffect);
}
#if 0
if (msg.message == WM_POINTERUPDATE) {
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
@ -711,7 +712,9 @@ static HRESULT startDoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource,
}
}
}
} else {
} else
#endif
{
// Handle other messages.
qWindowsWndProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);

View File

@ -55,6 +55,8 @@
#include <limits.h>
#define QT_FEATURE_cpp_winrt 2
#if !defined(QT_NO_OPENGL)
# include "qwindowsglcontext.h"
#endif
@ -243,8 +245,8 @@ void QWindowsIntegrationPrivate::parseOptions(QWindowsIntegration *q, const QStr
if (!dpiAwarenessSet) { // Set only once in case of repeated instantiations of QGuiApplication.
if (!QCoreApplication::testAttribute(Qt::AA_PluginApplication)) {
m_context.setProcessDpiAwareness(dpiAwareness);
qCDebug(lcQpaWindow) << "DpiAwareness=" << dpiAwareness
<< "effective process DPI awareness=" << QWindowsContext::processDpiAwareness();
// qCDebug(lcQpaWindow) << "DpiAwareness=" << dpiAwareness
// << "effective process DPI awareness=" << QWindowsContext::processDpiAwareness();
}
dpiAwarenessSet = true;
}
@ -567,7 +569,8 @@ QVariant QWindowsIntegration::styleHint(QPlatformIntegration::StyleHint hint) co
QPlatformKeyMapper *QWindowsIntegration::keyMapper() const
{
return d->m_context.keyMapper();
// TOOD: ?
return (QPlatformKeyMapper *)d->m_context.keyMapper();
}
#if QT_CONFIG(clipboard)

View File

@ -60,6 +60,16 @@ QT_BEGIN_NAMESPACE
static void clearKeyRecorderOnApplicationInActive(Qt::ApplicationState state);
UINT GetDpiForWindow2(HWND hwnd);
BOOL SystemParametersInfoForDpi2(
UINT uiAction,
UINT uiParam,
PVOID pvParam,
UINT fWinIni,
UINT dpi);
int GetSystemMetricsForDpi2(int a, UINT dpi);
QWindowsKeyMapper::QWindowsKeyMapper()
: m_useRTLExtensions(false), m_keyGrabber(nullptr)
{
@ -88,17 +98,9 @@ QWindowsKeyMapper::~QWindowsKeyMapper()= default;
#define VK_OEM_3 0xC0
#endif
// Get scancode from the given message
static constexpr quint32 getScancode(const MSG &msg)
{
const auto keyFlags = HIWORD(msg.lParam);
quint32 scancode = LOBYTE(keyFlags);
// if extended-key flag is on, the scan code consists of a sequence of two bytes,
// where the first byte has a value of 0xe0.
if ((keyFlags & KF_EXTENDED) != 0)
scancode |= 0xE000;
return scancode;
}
// We not only need the scancode itself but also the extended bit of key messages. Thus we need
// the additional bit when masking the scancode.
enum { scancodeBitmask = 0x1ff };
// Key recorder ------------------------------------------------------------------------[ start ] --
struct KeyRecord {
@ -540,6 +542,33 @@ QDebug operator<<(QDebug d, const KeyboardLayoutItem &k)
d << ')';
return d;
}
// Helpers to format a list of int as Qt key sequence
class formatKeys
{
public:
explicit formatKeys(const QList<int> &keys) : m_keys(keys) {}
private:
friend QDebug operator<<(QDebug d, const formatKeys &keys);
const QList<int> &m_keys;
};
QDebug operator<<(QDebug d, const formatKeys &k)
{
QDebugStateSaver saver(d);
d.nospace();
d << '(';
for (int i =0, size = k.m_keys.size(); i < size; ++i) {
if (i)
d << ", ";
d << QKeySequence(k.m_keys.at(i));
}
d << ')';
return d;
}
#else // !QT_NO_DEBUG_STREAM
static int formatKeys(const QList<int> &) { return 0; }
#endif // QT_NO_DEBUG_STREAM
/**
@ -637,7 +666,7 @@ void QWindowsKeyMapper::updateKeyMap(const MSG &msg)
{
unsigned char kbdBuffer[256]; // Will hold the complete keyboard state
GetKeyboardState(kbdBuffer);
const quint32 scancode = getScancode(msg);
const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask;
updatePossibleKeyCodes(kbdBuffer, scancode, quint32(msg.wParam));
}
@ -730,40 +759,17 @@ static inline QString messageKeyText(const MSG &msg)
return ch.isNull() ? QString() : QString(ch);
}
UINT GetDpiForWindow2(HWND hwnd);
typedef int (__stdcall *GetSystemMetricsForDpi_f)(int, UINT);
typedef int (__stdcall *GetSystemMetrics_f)(int);
[[nodiscard]] static inline int getTitleBarHeight(const HWND hwnd)
{
const UINT dpi = GetDpiForWindow2(hwnd);
auto pGetSystemMetricsForDpi = reinterpret_cast<GetSystemMetricsForDpi_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "GetSystemMetricsForDpi"));
auto pGetSystemMetrics = reinterpret_cast<GetSystemMetrics_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "GetSystemMetrics"));
if (pGetSystemMetricsForDpi)
{
const int captionHeight = pGetSystemMetricsForDpi(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 = pGetSystemMetricsForDpi(SM_CYSIZEFRAME, dpi)
+ pGetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
return captionHeight + frameHeight;
}
else
{
const int captionHeight = pGetSystemMetrics(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 = pGetSystemMetrics(SM_CYSIZEFRAME)
+ pGetSystemMetrics(SM_CXPADDEDBORDER);
return captionHeight + frameHeight;
}
const int captionHeight = GetSystemMetricsForDpi2(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 = GetSystemMetricsForDpi2(SM_CYSIZEFRAME, dpi)
+ GetSystemMetricsForDpi2(SM_CXPADDEDBORDER, dpi);
return captionHeight + frameHeight;
}
[[nodiscard]] static inline bool isSystemMenuOffsetNeeded(const Qt::WindowFlags flags)
@ -946,7 +952,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
m_seenAltGr = true;
const UINT msgType = msg.message;
const quint32 scancode = getScancode(msg);
const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask;
auto vk_key = quint32(msg.wParam);
quint32 nModifiers = 0;
@ -1343,7 +1349,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
return result;
}
Qt::KeyboardModifiers QWindowsKeyMapper::queryKeyboardModifiers() const
Qt::KeyboardModifiers QWindowsKeyMapper::queryKeyboardModifiers()
{
Qt::KeyboardModifiers modifiers = Qt::NoModifier;
if (GetKeyState(VK_SHIFT) < 0)
@ -1357,9 +1363,9 @@ Qt::KeyboardModifiers QWindowsKeyMapper::queryKeyboardModifiers() const
return modifiers;
}
QList<QKeyCombination> QWindowsKeyMapper::possibleKeyCombinations(const QKeyEvent *e) const
QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const
{
QList<QKeyCombination> result;
QList<int> result;
const quint32 nativeVirtualKey = e->nativeVirtualKey();
@ -1373,34 +1379,31 @@ QList<QKeyCombination> QWindowsKeyMapper::possibleKeyCombinations(const QKeyEven
quint32 baseKey = kbItem.qtKey[0];
Qt::KeyboardModifiers keyMods = e->modifiers();
if (baseKey == Qt::Key_Return && (e->nativeModifiers() & ExtendedKey)) {
result << (Qt::Key_Enter | keyMods);
result << (Qt::Key_Enter | keyMods).toCombined();
return result;
}
// The base key is _always_ valid, of course
result << QKeyCombination::fromCombined(int(baseKey) + int(keyMods));
result << int(baseKey) + int(keyMods); // The base key is _always_ valid, of course
for (size_t i = 1; i < NumMods; ++i) {
Qt::KeyboardModifiers neededMods = ModsTbl[i];
quint32 key = kbItem.qtKey[i];
if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) {
const Qt::KeyboardModifiers missingMods = keyMods & ~neededMods;
const auto matchedKey = QKeyCombination::fromCombined(int(key) + int(missingMods));
const auto it = std::find_if(result.begin(), result.end(),
[key](auto keyCombination) {
return keyCombination.key() == key;
});
const int matchedKey = int(key) + int(missingMods);
const auto it =
std::find_if(result.begin(), result.end(),
[key] (int k) { return (k & ~Qt::KeyboardModifierMask) == key; });
// QTBUG-67200: Use the match with the least modifiers (prefer
// Shift+9 over Alt + Shift + 9) resulting in more missing modifiers.
if (it == result.end())
result << matchedKey;
else if (missingMods > it->keyboardModifiers())
else if (missingMods > Qt::KeyboardModifiers(*it & Qt::KeyboardModifierMask))
*it = matchedKey;
}
}
qCDebug(lcQpaEvents) << __FUNCTION__ << e << "nativeVirtualKey="
<< Qt::showbase << Qt::hex << e->nativeVirtualKey() << Qt::dec << Qt::noshowbase
<< e->modifiers() << kbItem << "\n returns" << result;
<< e->modifiers() << kbItem << "\n returns" << formatKeys(result);
return result;
}

View File

@ -9,7 +9,6 @@
#include <QtCore/qlocale.h>
#include <qpa/qplatformkeymapper.h>
QT_BEGIN_NAMESPACE
class QKeyEvent;
@ -35,7 +34,7 @@ struct KeyboardLayoutItem {
quint32 qtKey[NumQtKeys]; // Can by any Qt::Key_<foo>, or unicode character
};
class QWindowsKeyMapper : public QPlatformKeyMapper
class QWindowsKeyMapper : public QPlatformKeyMapper
{
Q_DISABLE_COPY_MOVE(QWindowsKeyMapper)
public:
@ -55,8 +54,8 @@ public:
QWindow *keyGrabber() const { return m_keyGrabber; }
void setKeyGrabber(QWindow *w) { m_keyGrabber = w; }
Qt::KeyboardModifiers queryKeyboardModifiers() const override;
QList<QKeyCombination> possibleKeyCombinations(const QKeyEvent *e) const override;
static Qt::KeyboardModifiers queryKeyboardModifiers();
QList<int> possibleKeys(const QKeyEvent *e) const;
private:
bool translateKeyEventInternal(QWindow *receiver, MSG msg, bool grab, LRESULT *lResult);

View File

@ -421,6 +421,7 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
QtWindows::WindowsEventType et,
MSG msg, PVOID vTouchInfo, quint32 count)
{
#if 0
Q_UNUSED(hwnd);
auto *touchInfo = static_cast<POINTER_TOUCH_INFO *>(vTouchInfo);
@ -547,6 +548,7 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
const auto *keyMapper = QWindowsContext::instance()->keyMapper();
QWindowSystemInterface::handleTouchEvent(window, m_touchDevice.data(), touchPoints,
keyMapper->queryKeyboardModifiers());
#endif
return false; // Allow mouse messages to be generated.
}

View File

@ -44,6 +44,8 @@
#include <algorithm>
#define QT_FEATURE_cpp_winrt 2
#if QT_CONFIG(cpp_winrt)
# include <QtCore/private/qt_winrtbase_p.h>
@ -58,6 +60,15 @@ QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
BOOL SystemParametersInfoForDpi2(
UINT uiAction,
UINT uiParam,
PVOID pvParam,
UINT fWinIni,
UINT dpi
);
static inline bool booleanSystemParametersInfo(UINT what, bool defaultValue)
{
BOOL result;
@ -768,7 +779,7 @@ void QWindowsTheme::refreshFonts()
fixedFont.setStyleHint(QFont::TypeWriter);
LOGFONT lfIconTitleFont;
SystemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
SystemParametersInfoForDpi2(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
const QFont iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont, dpi);
m_fonts[SystemFont] = new QFont(QWindowsFontDatabase::systemDefaultFont());

File diff suppressed because it is too large Load Diff

View File

@ -86,6 +86,36 @@ enum QSliderDirection { SlUp, SlDown, SlLeft, SlRight };
\internal
*/
typedef BOOL (__stdcall *SystemParametersInfoForDpi_f)(
UINT uiAction,
UINT uiParam,
PVOID pvParam,
UINT fWinIni,
UINT dpi
);
BOOL SystemParametersInfoForDpi2(
UINT uiAction,
UINT uiParam,
PVOID pvParam,
UINT fWinIni,
UINT dpi
)
{
auto pSystemParametersInfoForDpi = reinterpret_cast<SystemParametersInfoForDpi_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "SystemParametersInfoForDpi"));
return dpi != 0 && pSystemParametersInfoForDpi
? pSystemParametersInfoForDpi(uiAction, uiParam, pvParam, fWinIni, dpi)
: SystemParametersInfo(uiAction, uiParam, pvParam, fWinIni);
}
typedef int (__stdcall *GetSystemMetricsForDpi_f)(int, UINT);
int GetSystemMetricsForDpi2(int a, UINT dpi)
{
auto pGetSystemMetricsForDpi = reinterpret_cast<GetSystemMetricsForDpi_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "GetSystemMetricsForDpi"));
return pGetSystemMetricsForDpi ? pGetSystemMetricsForDpi(a, dpi) : GetSystemMetrics(a);
}
QWindowsStylePrivate::QWindowsStylePrivate() = default;
qreal QWindowsStylePrivate::appDevicePixelRatio()
@ -268,27 +298,27 @@ int QWindowsStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, const
switch (pm) {
case QStyle::PM_DockWidgetFrameWidth:
return GetSystemMetricsForDpi(SM_CXFRAME, dpi);
return GetSystemMetricsForDpi2(SM_CXFRAME, dpi);
case QStyle::PM_TitleBarHeight: {
const int resizeBorderThickness =
GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
GetSystemMetricsForDpi2(SM_CXSIZEFRAME, dpi) + GetSystemMetricsForDpi2(SM_CXPADDEDBORDER, dpi);
if (widget && (widget->windowType() == Qt::Tool))
return GetSystemMetricsForDpi(SM_CYSMCAPTION, dpi) + resizeBorderThickness;
return GetSystemMetricsForDpi(SM_CYCAPTION, dpi) + resizeBorderThickness;
return GetSystemMetricsForDpi2(SM_CYSMCAPTION, dpi) + resizeBorderThickness;
return GetSystemMetricsForDpi2(SM_CYCAPTION, dpi) + resizeBorderThickness;
}
case QStyle::PM_ScrollBarExtent:
{
NONCLIENTMETRICS ncm;
ncm.cbSize = sizeof(NONCLIENTMETRICS);
if (SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0, dpi))
if (SystemParametersInfoForDpi2(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0, dpi))
return qMax(ncm.iScrollHeight, ncm.iScrollWidth);
}
break;
case QStyle::PM_MdiSubWindowFrameWidth:
return GetSystemMetricsForDpi(SM_CYFRAME, dpi);
return GetSystemMetricsForDpi2(SM_CYFRAME, dpi);
default:
break;