mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2024-11-26 14:17:05 +08:00
qt 6.5.3 win7 compatibility with fallbacks to newer behaviour on later windows, qrhi3d11 not tested
This commit is contained in:
parent
7018d9e6c8
commit
a948a5cdf9
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <qt_windows.h>
|
#include <qt_windows.h>
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
|
#include <VersionHelpers.h>
|
||||||
#include <intshcut.h>
|
#include <intshcut.h>
|
||||||
#include <qvarlengtharray.h>
|
#include <qvarlengtharray.h>
|
||||||
|
|
||||||
@ -60,19 +61,25 @@ static inline void appendTestMode(QString &path)
|
|||||||
|
|
||||||
static bool isProcessLowIntegrity()
|
static bool isProcessLowIntegrity()
|
||||||
{
|
{
|
||||||
|
if (!IsWindows8OrGreater())
|
||||||
|
return false;
|
||||||
|
|
||||||
// same as GetCurrentProcessToken()
|
// same as GetCurrentProcessToken()
|
||||||
const auto process_token = HANDLE(quintptr(-4));
|
const auto process_token = HANDLE(quintptr(-4));
|
||||||
|
|
||||||
QVarLengthArray<char,256> token_info_buf(256);
|
QVarLengthArray<char,256> token_info_buf(256);
|
||||||
auto* token_info = reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_info_buf.data());
|
auto* token_info = reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_info_buf.data());
|
||||||
DWORD token_info_length = token_info_buf.size();
|
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
|
// grow buffer and retry GetTokenInformation
|
||||||
token_info_buf.resize(token_info_length);
|
token_info_buf.resize(token_info_length);
|
||||||
token_info = reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_info_buf.data());
|
token_info = reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_info_buf.data());
|
||||||
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))
|
||||||
return false; // assume "normal" process
|
return false; // assume "normal" process
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
// The GetSidSubAuthorityCount return-code is undefined on failure, so
|
// The GetSidSubAuthorityCount return-code is undefined on failure, so
|
||||||
// there's no point in checking before dereferencing
|
// there's no point in checking before dereferencing
|
||||||
|
@ -354,10 +354,15 @@ void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t)
|
|||||||
ok = t->fastTimerId;
|
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
|
// 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)
|
if (!ok)
|
||||||
ok = SetTimer(internalHwnd, t->timerId, interval, nullptr);
|
ok = SetTimer(internalHwnd, t->timerId, interval, nullptr);
|
||||||
|
|
||||||
|
@ -43,10 +43,17 @@ QComHelper::~QComHelper()
|
|||||||
*/
|
*/
|
||||||
bool qt_win_hasPackageIdentity()
|
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)
|
#if defined(HAS_APPMODEL)
|
||||||
|
|
||||||
static const bool hasPackageIdentity = []() {
|
static const bool hasPackageIdentity = []() {
|
||||||
UINT32 length = 0;
|
UINT32 length = 0;
|
||||||
switch (const auto result = GetCurrentPackageFullName(&length, nullptr)) {
|
switch (const auto result = myGetCurrentPackageFullName(&length, nullptr)) {
|
||||||
case ERROR_INSUFFICIENT_BUFFER:
|
case ERROR_INSUFFICIENT_BUFFER:
|
||||||
return true;
|
return true;
|
||||||
case APPMODEL_ERROR_NO_PACKAGE:
|
case APPMODEL_ERROR_NO_PACKAGE:
|
||||||
@ -60,6 +67,9 @@ bool qt_win_hasPackageIdentity()
|
|||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -107,39 +107,6 @@ namespace QtLinuxFutex {
|
|||||||
}
|
}
|
||||||
namespace QtFutex = QtLinuxFutex;
|
namespace QtFutex = QtLinuxFutex;
|
||||||
QT_END_NAMESPACE
|
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
|
#else
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
@ -869,6 +869,8 @@ QT_END_NAMESPACE
|
|||||||
// nothing
|
// nothing
|
||||||
#elif defined(Q_OS_MAC)
|
#elif defined(Q_OS_MAC)
|
||||||
# include "qmutex_mac.cpp"
|
# include "qmutex_mac.cpp"
|
||||||
|
#elif defined(Q_OS_WIN)
|
||||||
|
# include "qmutex_win.cpp"
|
||||||
#else
|
#else
|
||||||
# include "qmutex_unix.cpp"
|
# include "qmutex_unix.cpp"
|
||||||
#endif
|
#endif
|
||||||
|
@ -91,6 +91,8 @@ public:
|
|||||||
bool wakeup;
|
bool wakeup;
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
pthread_cond_t cond;
|
pthread_cond_t cond;
|
||||||
|
#elif defined(Q_OS_WIN)
|
||||||
|
Qt::HANDLE event;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
30
src/corelib/thread/qmutex_win.cpp
Normal file
30
src/corelib/thread/qmutex_win.cpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// Copyright (C) 2016 The Qt Company Ltd.
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
#include "qmutex.h"
|
||||||
|
#include <qatomic.h>
|
||||||
|
#include "qmutex_p.h"
|
||||||
|
#include <qt_windows.h>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
QMutexPrivate::QMutexPrivate()
|
||||||
|
{
|
||||||
|
event = CreateEvent(0, FALSE, FALSE, 0);
|
||||||
|
|
||||||
|
if (!event)
|
||||||
|
qWarning("QMutexPrivate::QMutexPrivate: Cannot create event");
|
||||||
|
}
|
||||||
|
|
||||||
|
QMutexPrivate::~QMutexPrivate()
|
||||||
|
{ CloseHandle(event); }
|
||||||
|
|
||||||
|
bool QMutexPrivate::wait(int timeout)
|
||||||
|
{
|
||||||
|
return (WaitForSingleObjectEx(event, timeout < 0 ? INFINITE : timeout, FALSE) == WAIT_OBJECT_0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QMutexPrivate::wakeUp() noexcept
|
||||||
|
{ SetEvent(event); }
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
#include <d3dcompiler.h>
|
#include <d3dcompiler.h>
|
||||||
|
|
||||||
|
#include <VersionHelpers.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace Qt::StringLiterals;
|
using namespace Qt::StringLiterals;
|
||||||
@ -131,13 +133,22 @@ inline Int aligned(Int v, Int byteAlign)
|
|||||||
|
|
||||||
static IDXGIFactory1 *createDXGIFactory2()
|
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;
|
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)) {
|
if (FAILED(hr)) {
|
||||||
qWarning("CreateDXGIFactory2() failed to create DXGI factory: %s",
|
qWarning("CreateDXGIFactory2() failed to create DXGI factory: %s",
|
||||||
qPrintable(QSystemError::windowsComString(hr)));
|
qPrintable(QSystemError::windowsComString(hr)));
|
||||||
result = nullptr;
|
result = nullptr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4914,6 +4925,15 @@ static const DXGI_FORMAT DEFAULT_SRGB_FORMAT = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
|
|||||||
|
|
||||||
bool QD3D11SwapChain::createOrResize()
|
bool QD3D11SwapChain::createOrResize()
|
||||||
{
|
{
|
||||||
|
if (IsWindows10OrGreater())
|
||||||
|
{
|
||||||
|
// continue
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return createOrResizeWin7();
|
||||||
|
}
|
||||||
|
|
||||||
// Can be called multiple times due to window resizes - that is not the
|
// 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
|
// same as a simple destroy+create (as with other resources). Just need to
|
||||||
// resize the buffers then.
|
// resize the buffers then.
|
||||||
@ -5203,6 +5223,295 @@ bool QD3D11SwapChain::createOrResize()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QD3D11SwapChain::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.
|
||||||
|
|
||||||
|
const bool needsRegistration = !window || window != m_window;
|
||||||
|
|
||||||
|
// except if the window actually changes
|
||||||
|
if (window && window != m_window)
|
||||||
|
destroy();
|
||||||
|
|
||||||
|
window = m_window;
|
||||||
|
m_currentPixelSize = surfacePixelSize();
|
||||||
|
pixelSize = m_currentPixelSize;
|
||||||
|
|
||||||
|
if (pixelSize.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QRHI_RES_RHI(QRhiD3D11);
|
||||||
|
bool useFlipModel = rhiD->supportsFlipSwapchain;
|
||||||
|
|
||||||
|
// Take a shortcut for alpha: whatever the platform plugin does to enable
|
||||||
|
// transparency for our QWindow will be sufficient on the legacy (DISCARD)
|
||||||
|
// path. For FLIP_* we'd need to use DirectComposition (create a
|
||||||
|
// IDCompositionDevice/Target/Visual), avoid that for now. (this though
|
||||||
|
// means HDR and semi-transparent windows cannot be combined)
|
||||||
|
if (m_flags.testFlag(SurfaceHasPreMulAlpha) || m_flags.testFlag(SurfaceHasNonPreMulAlpha)) {
|
||||||
|
useFlipModel = false;
|
||||||
|
if (window->requestedFormat().alphaBufferSize() <= 0)
|
||||||
|
qWarning("Swapchain says surface has alpha but the window has no alphaBufferSize set. "
|
||||||
|
"This may lead to problems.");
|
||||||
|
}
|
||||||
|
|
||||||
|
swapInterval = m_flags.testFlag(QRhiSwapChain::NoVSync) ? 0 : 1;
|
||||||
|
swapChainFlags = 0;
|
||||||
|
|
||||||
|
// A non-flip swapchain can do Present(0) as expected without
|
||||||
|
// ALLOW_TEARING, and ALLOW_TEARING is not compatible with it at all so the
|
||||||
|
// flag must not be set then. Whereas for flip we should use it, if
|
||||||
|
// supported, to get better results for 'unthrottled' presentation.
|
||||||
|
if (swapInterval == 0 && useFlipModel && rhiD->supportsAllowTearing)
|
||||||
|
swapChainFlags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING;
|
||||||
|
|
||||||
|
if (!swapChain) {
|
||||||
|
HWND hwnd = reinterpret_cast<HWND>(window->winId());
|
||||||
|
sampleDesc = rhiD->effectiveSampleCount(m_sampleCount);
|
||||||
|
colorFormat = DEFAULT_FORMAT;
|
||||||
|
srgbAdjustedColorFormat = m_flags.testFlag(sRGB) ? DEFAULT_SRGB_FORMAT : DEFAULT_FORMAT;
|
||||||
|
|
||||||
|
HRESULT hr;
|
||||||
|
if (useFlipModel) {
|
||||||
|
DXGI_COLOR_SPACE_TYPE hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; // SDR
|
||||||
|
DXGI_OUTPUT_DESC1 hdrOutputDesc;
|
||||||
|
if (outputDesc1ForWindow(m_window, rhiD->activeAdapter, &hdrOutputDesc) && m_format != SDR) {
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/direct3darticles/high-dynamic-range
|
||||||
|
if (hdrOutputDesc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) {
|
||||||
|
switch (m_format) {
|
||||||
|
case HDRExtendedSrgbLinear:
|
||||||
|
colorFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||||
|
hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P709;
|
||||||
|
srgbAdjustedColorFormat = colorFormat;
|
||||||
|
break;
|
||||||
|
case HDR10:
|
||||||
|
colorFormat = DXGI_FORMAT_R10G10B10A2_UNORM;
|
||||||
|
hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020;
|
||||||
|
srgbAdjustedColorFormat = colorFormat;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// This happens also when Use HDR is set to Off in the Windows
|
||||||
|
// Display settings. Show a helpful warning, but continue with the
|
||||||
|
// default non-HDR format.
|
||||||
|
qWarning("The output associated with the window is not HDR capable "
|
||||||
|
"(or Use HDR is Off in the Display Settings), ignoring HDR format request");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We use a FLIP model swapchain which implies a buffer count of 2
|
||||||
|
// (as opposed to the old DISCARD with back buffer count == 1).
|
||||||
|
// This makes no difference for the rest of the stuff except that
|
||||||
|
// automatic MSAA is unsupported and needs to be implemented via a
|
||||||
|
// custom multisample render target and an explicit resolve.
|
||||||
|
|
||||||
|
DXGI_SWAP_CHAIN_DESC1 desc;
|
||||||
|
memset(&desc, 0, sizeof(desc));
|
||||||
|
desc.Width = UINT(pixelSize.width());
|
||||||
|
desc.Height = UINT(pixelSize.height());
|
||||||
|
desc.Format = colorFormat;
|
||||||
|
desc.SampleDesc.Count = 1;
|
||||||
|
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||||
|
desc.BufferCount = BUFFER_COUNT;
|
||||||
|
|
||||||
|
// Normally we'd want FLIP_DISCARD, but that comes with the default
|
||||||
|
// SCALING_STRETCH, as SCALING_NONE is documented to be only
|
||||||
|
// available for FLIP_SEQUENTIAl. The problem with stretch is that
|
||||||
|
// Qt Quick and similar apps typically running in resizable windows
|
||||||
|
// will not like how that looks in practice: the content will
|
||||||
|
// appear to be "jumping" around during a window resize. So choose
|
||||||
|
// sequential/none by default.
|
||||||
|
if (rhiD->forceFlipDiscard) {
|
||||||
|
desc.Scaling = DXGI_SCALING_STRETCH;
|
||||||
|
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||||
|
} else {
|
||||||
|
desc.Scaling = DXGI_SCALING_NONE;
|
||||||
|
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do not bother with AlphaMode, if won't work unless we go through
|
||||||
|
// DirectComposition. Instead, we just take the other (DISCARD)
|
||||||
|
// path for now when alpha is requested.
|
||||||
|
desc.Flags = swapChainFlags;
|
||||||
|
|
||||||
|
IDXGIFactory2 *fac = static_cast<IDXGIFactory2 *>(rhiD->dxgiFactory);
|
||||||
|
IDXGISwapChain1 *sc1;
|
||||||
|
hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc, nullptr, nullptr, &sc1);
|
||||||
|
|
||||||
|
// If failed and we tried a HDR format, then try with SDR. This
|
||||||
|
// matches other backends, such as Vulkan where if the format is
|
||||||
|
// not supported, the default one is used instead.
|
||||||
|
if (FAILED(hr) && m_format != SDR) {
|
||||||
|
colorFormat = DEFAULT_FORMAT;
|
||||||
|
desc.Format = DEFAULT_FORMAT;
|
||||||
|
hr = fac->CreateSwapChainForHwnd(rhiD->dev, hwnd, &desc, nullptr, nullptr, &sc1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr)) {
|
||||||
|
swapChain = sc1;
|
||||||
|
if (m_format != SDR) {
|
||||||
|
IDXGISwapChain3 *sc3 = nullptr;
|
||||||
|
if (SUCCEEDED(sc1->QueryInterface(__uuidof(IDXGISwapChain3), reinterpret_cast<void **>(&sc3)))) {
|
||||||
|
hr = sc3->SetColorSpace1(hdrColorSpace);
|
||||||
|
if (FAILED(hr))
|
||||||
|
qWarning("Failed to set color space on swapchain: %s",
|
||||||
|
qPrintable(QSystemError::windowsComString(hr)));
|
||||||
|
sc3->Release();
|
||||||
|
} else {
|
||||||
|
qWarning("IDXGISwapChain3 not available, HDR swapchain will not work as expected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Fallback: use DISCARD mode. Regardless, keep on using our manual
|
||||||
|
// resolve for symmetry with the FLIP_* code path when MSAA is
|
||||||
|
// requested. This has no HDR support.
|
||||||
|
|
||||||
|
DXGI_SWAP_CHAIN_DESC desc;
|
||||||
|
memset(&desc, 0, sizeof(desc));
|
||||||
|
desc.BufferDesc.Width = UINT(pixelSize.width());
|
||||||
|
desc.BufferDesc.Height = UINT(pixelSize.height());
|
||||||
|
desc.BufferDesc.RefreshRate.Numerator = 60;
|
||||||
|
desc.BufferDesc.RefreshRate.Denominator = 1;
|
||||||
|
desc.BufferDesc.Format = colorFormat;
|
||||||
|
desc.SampleDesc.Count = 1;
|
||||||
|
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||||
|
desc.BufferCount = 1;
|
||||||
|
desc.OutputWindow = hwnd;
|
||||||
|
desc.Windowed = true;
|
||||||
|
desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
||||||
|
desc.Flags = swapChainFlags;
|
||||||
|
|
||||||
|
hr = rhiD->dxgiFactory->CreateSwapChain(rhiD->dev, &desc, &swapChain);
|
||||||
|
}
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
qWarning("Failed to create D3D11 swapchain: %s",
|
||||||
|
qPrintable(QSystemError::windowsComString(hr)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
rhiD->dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_WINDOW_CHANGES);
|
||||||
|
} else {
|
||||||
|
releaseBuffers();
|
||||||
|
const UINT count = useFlipModel ? BUFFER_COUNT : 1;
|
||||||
|
HRESULT hr = swapChain->ResizeBuffers(count, UINT(pixelSize.width()), UINT(pixelSize.height()),
|
||||||
|
colorFormat, swapChainFlags);
|
||||||
|
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) {
|
||||||
|
qWarning("Device loss detected in ResizeBuffers()");
|
||||||
|
rhiD->deviceLost = true;
|
||||||
|
return false;
|
||||||
|
} else if (FAILED(hr)) {
|
||||||
|
qWarning("Failed to resize D3D11 swapchain: %s",
|
||||||
|
qPrintable(QSystemError::windowsComString(hr)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This looks odd (for FLIP_*, esp. compared with backends for Vulkan
|
||||||
|
// & co.) but the backbuffer is always at index 0, with magic underneath.
|
||||||
|
// Some explanation from
|
||||||
|
// https://docs.microsoft.com/en-us/windows/win32/direct3ddxgi/dxgi-1-4-improvements
|
||||||
|
//
|
||||||
|
// "In Direct3D 11, applications could call GetBuffer( 0, … ) only once.
|
||||||
|
// Every call to Present implicitly changed the resource identity of the
|
||||||
|
// returned interface. Direct3D 12 no longer supports that implicit
|
||||||
|
// resource identity change, due to the CPU overhead required and the
|
||||||
|
// flexible resource descriptor design. As a result, the application must
|
||||||
|
// manually call GetBuffer for every each buffer created with the
|
||||||
|
// swapchain."
|
||||||
|
|
||||||
|
// So just query index 0 once (per resize) and be done with it.
|
||||||
|
HRESULT hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void **>(&backBufferTex));
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
qWarning("Failed to query swapchain backbuffer: %s",
|
||||||
|
qPrintable(QSystemError::windowsComString(hr)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
|
||||||
|
rtvDesc.Format = srgbAdjustedColorFormat;
|
||||||
|
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||||
|
hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtv);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
qWarning("Failed to create rtv for swapchain backbuffer: %s",
|
||||||
|
qPrintable(QSystemError::windowsComString(hr)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to reduce stalls by having a dedicated MSAA texture per swapchain buffer.
|
||||||
|
for (int i = 0; i < BUFFER_COUNT; ++i) {
|
||||||
|
if (sampleDesc.Count > 1) {
|
||||||
|
if (!newColorBuffer(pixelSize, srgbAdjustedColorFormat, sampleDesc, &msaaTex[i], &msaaRtv[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_depthStencil && m_depthStencil->sampleCount() != m_sampleCount) {
|
||||||
|
qWarning("Depth-stencil buffer's sampleCount (%d) does not match color buffers' sample count (%d). Expect problems.",
|
||||||
|
m_depthStencil->sampleCount(), m_sampleCount);
|
||||||
|
}
|
||||||
|
if (m_depthStencil && m_depthStencil->pixelSize() != pixelSize) {
|
||||||
|
if (m_depthStencil->flags().testFlag(QRhiRenderBuffer::UsedWithSwapChainOnly)) {
|
||||||
|
m_depthStencil->setPixelSize(pixelSize);
|
||||||
|
if (!m_depthStencil->create())
|
||||||
|
qWarning("Failed to rebuild swapchain's associated depth-stencil buffer for size %dx%d",
|
||||||
|
pixelSize.width(), pixelSize.height());
|
||||||
|
} else {
|
||||||
|
qWarning("Depth-stencil buffer's size (%dx%d) does not match the surface size (%dx%d). Expect problems.",
|
||||||
|
m_depthStencil->pixelSize().width(), m_depthStencil->pixelSize().height(),
|
||||||
|
pixelSize.width(), pixelSize.height());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currentFrameSlot = 0;
|
||||||
|
frameCount = 0;
|
||||||
|
ds = m_depthStencil ? QRHI_RES(QD3D11RenderBuffer, m_depthStencil) : nullptr;
|
||||||
|
|
||||||
|
rt.setRenderPassDescriptor(m_renderPassDesc); // for the public getter in QRhiRenderTarget
|
||||||
|
QD3D11SwapChainRenderTarget *rtD = QRHI_RES(QD3D11SwapChainRenderTarget, &rt);
|
||||||
|
rtD->d.rp = QRHI_RES(QD3D11RenderPassDescriptor, m_renderPassDesc);
|
||||||
|
rtD->d.pixelSize = pixelSize;
|
||||||
|
rtD->d.dpr = float(window->devicePixelRatio());
|
||||||
|
rtD->d.sampleCount = int(sampleDesc.Count);
|
||||||
|
rtD->d.colorAttCount = 1;
|
||||||
|
rtD->d.dsAttCount = m_depthStencil ? 1 : 0;
|
||||||
|
|
||||||
|
if (rhiD->hasGpuFrameTimeCallback()) {
|
||||||
|
D3D11_QUERY_DESC queryDesc = {};
|
||||||
|
for (int i = 0; i < BUFFER_COUNT; ++i) {
|
||||||
|
if (!timestampDisjointQuery[i]) {
|
||||||
|
queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
|
||||||
|
hr = rhiD->dev->CreateQuery(&queryDesc, ×tampDisjointQuery[i]);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
qWarning("Failed to create timestamp disjoint query: %s",
|
||||||
|
qPrintable(QSystemError::windowsComString(hr)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
queryDesc.Query = D3D11_QUERY_TIMESTAMP;
|
||||||
|
for (int j = 0; j < 2; ++j) {
|
||||||
|
const int idx = BUFFER_COUNT * i + j; // one pair per buffer (frame)
|
||||||
|
if (!timestampQuery[idx]) {
|
||||||
|
hr = rhiD->dev->CreateQuery(&queryDesc, ×tampQuery[idx]);
|
||||||
|
if (FAILED(hr)) {
|
||||||
|
qWarning("Failed to create timestamp query: %s",
|
||||||
|
qPrintable(QSystemError::windowsComString(hr)));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// timestamp queries are optional so we can go on even if they failed
|
||||||
|
}
|
||||||
|
|
||||||
|
if (needsRegistration)
|
||||||
|
rhiD->registerResource(this);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void QRhiD3D11::DeviceCurse::initResources()
|
void QRhiD3D11::DeviceCurse::initResources()
|
||||||
{
|
{
|
||||||
framesLeft = framesToActivate;
|
framesLeft = framesToActivate;
|
||||||
|
@ -569,6 +569,8 @@ struct QD3D11SwapChain : public QRhiSwapChain
|
|||||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
|
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
|
||||||
bool createOrResize() override;
|
bool createOrResize() override;
|
||||||
|
|
||||||
|
bool createOrResizeWin7();
|
||||||
|
|
||||||
void releaseBuffers();
|
void releaseBuffers();
|
||||||
bool newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc,
|
bool newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc,
|
||||||
ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv) const;
|
ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv) const;
|
||||||
@ -740,6 +742,8 @@ public:
|
|||||||
IDXGIFactory1 *dxgiFactory = nullptr;
|
IDXGIFactory1 *dxgiFactory = nullptr;
|
||||||
IDCompositionDevice *dcompDevice = nullptr;
|
IDCompositionDevice *dcompDevice = nullptr;
|
||||||
bool supportsAllowTearing = false;
|
bool supportsAllowTearing = false;
|
||||||
|
bool supportsFlipSwapchain = false; // win7
|
||||||
|
bool forceFlipDiscard = false; // win7
|
||||||
bool deviceLost = false;
|
bool deviceLost = false;
|
||||||
QRhiD3D11NativeHandles nativeHandlesStruct;
|
QRhiD3D11NativeHandles nativeHandlesStruct;
|
||||||
QRhiDriverInfo driverInfoStruct;
|
QRhiDriverInfo driverInfoStruct;
|
||||||
|
@ -685,7 +685,16 @@ QFont QWindowsFontDatabaseBase::systemDefaultFont()
|
|||||||
// Qt 6: Obtain default GUI font (typically "Segoe UI, 9pt", see QTBUG-58610)
|
// Qt 6: Obtain default GUI font (typically "Segoe UI, 9pt", see QTBUG-58610)
|
||||||
NONCLIENTMETRICS ncm = {};
|
NONCLIENTMETRICS ncm = {};
|
||||||
ncm.cbSize = sizeof(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);
|
const QFont systemFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMessageFont);
|
||||||
qCDebug(lcQpaFonts) << __FUNCTION__ << systemFont;
|
qCDebug(lcQpaFonts) << __FUNCTION__ << systemFont;
|
||||||
return systemFont;
|
return systemFont;
|
||||||
|
@ -58,25 +58,52 @@ public:
|
|||||||
} // namespace ABI
|
} // namespace ABI
|
||||||
#endif // HAS_UI_VIEW_SETTINGS
|
#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
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
// Return tablet mode, note: Does not work for GetDesktopWindow().
|
// Return tablet mode, note: Does not work for GetDesktopWindow().
|
||||||
bool qt_windowsIsTabletMode(HWND hwnd)
|
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;
|
bool result = false;
|
||||||
|
|
||||||
const wchar_t uiViewSettingsId[] = L"Windows.UI.ViewManagement.UIViewSettings";
|
const wchar_t uiViewSettingsId[] = L"Windows.UI.ViewManagement.UIViewSettings";
|
||||||
HSTRING_HEADER uiViewSettingsIdRefHeader;
|
HSTRING_HEADER uiViewSettingsIdRefHeader;
|
||||||
HSTRING uiViewSettingsIdHs = nullptr;
|
HSTRING uiViewSettingsIdHs = nullptr;
|
||||||
const auto uiViewSettingsIdLen = UINT32(sizeof(uiViewSettingsId) / sizeof(uiViewSettingsId[0]) - 1);
|
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;
|
return false;
|
||||||
|
|
||||||
IUIViewSettingsInterop *uiViewSettingsInterop = nullptr;
|
IUIViewSettingsInterop *uiViewSettingsInterop = nullptr;
|
||||||
// __uuidof(IUIViewSettingsInterop);
|
// __uuidof(IUIViewSettingsInterop);
|
||||||
const GUID uiViewSettingsInteropRefId = {0x3694dbf9, 0x8f68, 0x44be,{0x8f, 0xf5, 0x19, 0x5c, 0x98, 0xed, 0xe8, 0xa6}};
|
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));
|
reinterpret_cast<void **>(&uiViewSettingsInterop));
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return false;
|
return false;
|
||||||
@ -95,6 +122,9 @@ bool qt_windowsIsTabletMode(HWND hwnd)
|
|||||||
}
|
}
|
||||||
uiViewSettingsInterop->Release();
|
uiViewSettingsInterop->Release();
|
||||||
return result;
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
@ -44,6 +44,7 @@
|
|||||||
#include <QtCore/qsysinfo.h>
|
#include <QtCore/qsysinfo.h>
|
||||||
#include <QtCore/qscopedpointer.h>
|
#include <QtCore/qscopedpointer.h>
|
||||||
#include <QtCore/quuid.h>
|
#include <QtCore/quuid.h>
|
||||||
|
#include <QtCore/private/qsystemlibrary_p.h>
|
||||||
#include <QtCore/private/qwinregistry_p.h>
|
#include <QtCore/private/qwinregistry_p.h>
|
||||||
#include <QtCore/private/qfactorycacheregistration_p.h>
|
#include <QtCore/private/qfactorycacheregistration_p.h>
|
||||||
#include <QtCore/private/qsystemerror_p.h>
|
#include <QtCore/private/qsystemerror_p.h>
|
||||||
@ -120,15 +121,17 @@ static inline bool sessionManagerInteractionBlocked() { return false; }
|
|||||||
|
|
||||||
static inline int windowDpiAwareness(HWND hwnd)
|
static inline int windowDpiAwareness(HWND hwnd)
|
||||||
{
|
{
|
||||||
return static_cast<int>(GetAwarenessFromDpiAwarenessContext(GetWindowDpiAwarenessContext(hwnd)));
|
return QWindowsContext::user32dll.getWindowDpiAwarenessContext && QWindowsContext::user32dll.getAwarenessFromDpiAwarenessContext
|
||||||
|
? QWindowsContext::user32dll.getAwarenessFromDpiAwarenessContext(QWindowsContext::user32dll.getWindowDpiAwarenessContext(hwnd))
|
||||||
|
: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: This only works within WM_NCCREATE
|
// Note: This only works within WM_NCCREATE
|
||||||
static bool enableNonClientDpiScaling(HWND hwnd)
|
static bool enableNonClientDpiScaling(HWND hwnd)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if (windowDpiAwareness(hwnd) == 2) {
|
if (QWindowsContext::user32dll.enableNonClientDpiScaling && windowDpiAwareness(hwnd) == 2) {
|
||||||
result = EnableNonClientDpiScaling(hwnd) != FALSE;
|
result = QWindowsContext::user32dll.enableNonClientDpiScaling(hwnd) != FALSE;
|
||||||
if (!result) {
|
if (!result) {
|
||||||
const DWORD errorCode = GetLastError();
|
const DWORD errorCode = GetLastError();
|
||||||
qErrnoWarning(int(errorCode), "EnableNonClientDpiScaling() failed for HWND %p (%lu)",
|
qErrnoWarning(int(errorCode), "EnableNonClientDpiScaling() failed for HWND %p (%lu)",
|
||||||
@ -138,6 +141,77 @@ static bool enableNonClientDpiScaling(HWND hwnd)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\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");
|
||||||
|
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)) {
|
||||||
|
adjustWindowRectEx = (AdjustWindowRectEx)library.resolve("AdjustWindowRectEx");
|
||||||
|
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;
|
QWindowsContext *QWindowsContext::m_instance = nullptr;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -181,6 +255,9 @@ bool QWindowsContextPrivate::m_v2DpiAware = false;
|
|||||||
QWindowsContextPrivate::QWindowsContextPrivate()
|
QWindowsContextPrivate::QWindowsContextPrivate()
|
||||||
: m_oleInitializeResult(OleInitialize(nullptr))
|
: m_oleInitializeResult(OleInitialize(nullptr))
|
||||||
{
|
{
|
||||||
|
QWindowsContext::user32dll.init();
|
||||||
|
QWindowsContext::shcoredll.init();
|
||||||
|
|
||||||
if (m_pointerHandler.touchDevice() || m_mouseHandler.touchDevice())
|
if (m_pointerHandler.touchDevice() || m_mouseHandler.touchDevice())
|
||||||
m_systemInfo |= QWindowsContext::SI_SupportsTouch;
|
m_systemInfo |= QWindowsContext::SI_SupportsTouch;
|
||||||
m_displayContext = GetDC(nullptr);
|
m_displayContext = GetDC(nullptr);
|
||||||
@ -299,6 +376,12 @@ bool QWindowsContext::initPointer(unsigned integrationOptions)
|
|||||||
if (integrationOptions & QWindowsIntegration::DontUseWMPointer)
|
if (integrationOptions & QWindowsIntegration::DontUseWMPointer)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!QWindowsContext::user32dll.supportsPointerApi())
|
||||||
|
return false;
|
||||||
|
|
||||||
d->m_systemInfo |= QWindowsContext::SI_SupportsPointer;
|
d->m_systemInfo |= QWindowsContext::SI_SupportsPointer;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -369,7 +452,8 @@ void QWindowsContext::setDetectAltGrModifier(bool a)
|
|||||||
int QWindowsContext::processDpiAwareness()
|
int QWindowsContext::processDpiAwareness()
|
||||||
{
|
{
|
||||||
PROCESS_DPI_AWARENESS result;
|
PROCESS_DPI_AWARENESS result;
|
||||||
if (SUCCEEDED(GetProcessDpiAwareness(nullptr, &result))) {
|
if (QWindowsContext::shcoredll.getProcessDpiAwareness
|
||||||
|
&& SUCCEEDED(QWindowsContext::shcoredll.getProcessDpiAwareness(nullptr, &result))) {
|
||||||
return static_cast<int>(result);
|
return static_cast<int>(result);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
@ -381,23 +465,34 @@ void QWindowsContext::setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiA
|
|||||||
if (processDpiAwareness() == int(dpiAwareness))
|
if (processDpiAwareness() == int(dpiAwareness))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const HRESULT hr = SetProcessDpiAwareness(static_cast<PROCESS_DPI_AWARENESS>(dpiAwareness));
|
if (QWindowsContext::shcoredll.isValid()) {
|
||||||
|
const HRESULT hr = QWindowsContext::shcoredll.setProcessDpiAwareness(static_cast<PROCESS_DPI_AWARENESS>(dpiAwareness));
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
qCWarning(lcQpaWindow).noquote().nospace() << "SetProcessDpiAwareness("
|
qCWarning(lcQpaWindow).noquote().nospace() << "SetProcessDpiAwareness("
|
||||||
<< dpiAwareness << ") failed: " << QSystemError::windowsComString(hr) << ", using "
|
<< dpiAwareness << ") failed: " << QSystemError::windowsComString(hr) << ", using "
|
||||||
<< QWindowsContext::processDpiAwareness() << "\nQt's fallback DPI awareness is "
|
<< QWindowsContext::processDpiAwareness() << "\nQt's fallback DPI awareness is "
|
||||||
<< "PROCESS_DPI_AWARENESS. If you know what you are doing consider an override in qt.conf";
|
<< "PROCESS_DPI_AWARENESS. If you know what you are doing consider an override in qt.conf";
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (dpiAwareness != QtWindows::ProcessDpiUnaware && QWindowsContext::user32dll.setProcessDPIAware) {
|
||||||
|
if (!QWindowsContext::user32dll.setProcessDPIAware())
|
||||||
|
qErrnoWarning("SetProcessDPIAware() failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QWindowsContext::setProcessDpiV2Awareness()
|
bool QWindowsContext::setProcessDpiV2Awareness()
|
||||||
{
|
{
|
||||||
qCDebug(lcQpaWindow) << __FUNCTION__;
|
qCDebug(lcQpaWindow) << __FUNCTION__;
|
||||||
auto dpiContext = GetThreadDpiAwarenessContext();
|
if (QWindowsContext::user32dll.getThreadDpiAwarenessContext) {
|
||||||
if (AreDpiAwarenessContextsEqual(dpiContext, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
|
auto dpiContext = QWindowsContext::user32dll.getThreadDpiAwarenessContext();
|
||||||
|
if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual &&
|
||||||
|
QWindowsContext::user32dll.areDpiAwarenessContextsEqual(dpiContext, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const BOOL ok = SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
if (QWindowsContext::user32dll.setProcessDpiAwarenessContext) {
|
||||||
|
const BOOL ok = QWindowsContext::user32dll.setProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
const DWORD dwError = GetLastError();
|
const DWORD dwError = GetLastError();
|
||||||
qCWarning(lcQpaWindow).noquote().nospace()
|
qCWarning(lcQpaWindow).noquote().nospace()
|
||||||
@ -409,7 +504,11 @@ bool QWindowsContext::setProcessDpiV2Awareness()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
QWindowsContextPrivate::m_v2DpiAware = true;
|
QWindowsContextPrivate::m_v2DpiAware = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QWindowsContext::isDarkMode()
|
bool QWindowsContext::isDarkMode()
|
||||||
@ -837,8 +936,8 @@ void QWindowsContext::forceNcCalcSize(HWND hwnd)
|
|||||||
bool QWindowsContext::systemParametersInfo(unsigned action, unsigned param, void *out,
|
bool QWindowsContext::systemParametersInfo(unsigned action, unsigned param, void *out,
|
||||||
unsigned dpi)
|
unsigned dpi)
|
||||||
{
|
{
|
||||||
const BOOL result = dpi != 0
|
const BOOL result = QWindowsContext::user32dll.systemParametersInfoForDpi != nullptr && dpi != 0
|
||||||
? SystemParametersInfoForDpi(action, param, out, 0, dpi)
|
? QWindowsContext::user32dll.systemParametersInfoForDpi(action, param, out, 0, dpi)
|
||||||
: SystemParametersInfo(action, param, out, 0);
|
: SystemParametersInfo(action, param, out, 0);
|
||||||
return result == TRUE;
|
return result == TRUE;
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#define STRICT_TYPED_ITEMIDS
|
#define STRICT_TYPED_ITEMIDS
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
|
#include <shellscalingapi.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
@ -44,6 +45,94 @@ class QPoint;
|
|||||||
class QKeyEvent;
|
class QKeyEvent;
|
||||||
class QPointingDevice;
|
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 *AdjustWindowRectEx)(LPRECT,DWORD,BOOL,DWORD);
|
||||||
|
typedef BOOL (WINAPI *AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
|
||||||
|
typedef BOOL (WINAPI *EnableNonClientDpiScaling)(HWND);
|
||||||
|
typedef int (WINAPI *GetWindowDpiAwarenessContext)(HWND);
|
||||||
|
typedef int (WINAPI *GetAwarenessFromDpiAwarenessContext)(int);
|
||||||
|
typedef BOOL (WINAPI *SystemParametersInfoForDpi)(UINT, UINT, PVOID, UINT, UINT);
|
||||||
|
typedef int (WINAPI *GetDpiForWindow)(HWND);
|
||||||
|
typedef BOOL (WINAPI *GetSystemMetricsForDpi)(INT, UINT);
|
||||||
|
typedef BOOL (WINAPI *AreDpiAwarenessContextsEqual)(int, HANDLE);
|
||||||
|
typedef int (WINAPI *GetThreadDpiAwarenessContext)();
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
AdjustWindowRectEx adjustWindowRectEx = 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
|
class QWindowsContext
|
||||||
{
|
{
|
||||||
Q_DISABLE_COPY_MOVE(QWindowsContext)
|
Q_DISABLE_COPY_MOVE(QWindowsContext)
|
||||||
@ -137,6 +226,9 @@ public:
|
|||||||
QWindowsScreenManager &screenManager();
|
QWindowsScreenManager &screenManager();
|
||||||
QWindowsTabletSupport *tabletSupport() const;
|
QWindowsTabletSupport *tabletSupport() const;
|
||||||
|
|
||||||
|
static QWindowsUser32DLL user32dll;
|
||||||
|
static QWindowsShcoreDLL shcoredll;
|
||||||
|
|
||||||
bool asyncExpose() const;
|
bool asyncExpose() const;
|
||||||
void setAsyncExpose(bool value);
|
void setAsyncExpose(bool value);
|
||||||
|
|
||||||
|
@ -670,7 +670,7 @@ static HRESULT startDoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource,
|
|||||||
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
|
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
|
||||||
|
|
||||||
POINTER_INFO pointerInfo{};
|
POINTER_INFO pointerInfo{};
|
||||||
if (!GetPointerInfo(pointerId, &pointerInfo))
|
if (!QWindowsContext::user32dll.getPointerInfo || !QWindowsContext::user32dll.getPointerInfo(pointerId, &pointerInfo))
|
||||||
return E_FAIL;
|
return E_FAIL;
|
||||||
|
|
||||||
if (pointerInfo.pointerFlags & POINTER_FLAG_PRIMARY) {
|
if (pointerInfo.pointerFlags & POINTER_FLAG_PRIMARY) {
|
||||||
|
@ -751,15 +751,28 @@ static inline QString messageKeyText(const MSG &msg)
|
|||||||
|
|
||||||
[[nodiscard]] static inline int getTitleBarHeight(const HWND hwnd)
|
[[nodiscard]] static inline int getTitleBarHeight(const HWND hwnd)
|
||||||
{
|
{
|
||||||
const UINT dpi = GetDpiForWindow(hwnd);
|
if (QWindowsContext::user32dll.getDpiForWindow && QWindowsContext::user32dll.getSystemMetricsForDpi)
|
||||||
const int captionHeight = GetSystemMetricsForDpi(SM_CYCAPTION, dpi);
|
{
|
||||||
|
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
|
||||||
|
const int captionHeight = QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYCAPTION, dpi);
|
||||||
if (IsZoomed(hwnd))
|
if (IsZoomed(hwnd))
|
||||||
return captionHeight;
|
return captionHeight;
|
||||||
// The frame height should also be taken into account if the window
|
// The frame height should also be taken into account if the window
|
||||||
// is not maximized.
|
// is not maximized.
|
||||||
const int frameHeight = GetSystemMetricsForDpi(SM_CYSIZEFRAME, dpi)
|
const int frameHeight = QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYSIZEFRAME, dpi)
|
||||||
+ GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
+ QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
||||||
return captionHeight + frameHeight;
|
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)
|
[[nodiscard]] static inline bool isSystemMenuOffsetNeeded(const Qt::WindowFlags flags)
|
||||||
|
@ -48,7 +48,7 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
|||||||
*result = 0;
|
*result = 0;
|
||||||
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
|
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();
|
qWarning() << "GetPointerType() failed:" << qt_error_string();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -62,12 +62,12 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
|||||||
}
|
}
|
||||||
case QT_PT_TOUCH: {
|
case QT_PT_TOUCH: {
|
||||||
quint32 pointerCount = 0;
|
quint32 pointerCount = 0;
|
||||||
if (!GetPointerFrameTouchInfo(pointerId, &pointerCount, nullptr)) {
|
if (!QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, nullptr)) {
|
||||||
qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
|
qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
QVarLengthArray<POINTER_TOUCH_INFO, 10> touchInfo(pointerCount);
|
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();
|
qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
|
||||||
return false;
|
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
|
// dispatch any skipped frames if event compression is disabled by the app
|
||||||
if (historyCount > 1 && !QCoreApplication::testAttribute(Qt::AA_CompressHighFrequencyEvents)) {
|
if (historyCount > 1 && !QCoreApplication::testAttribute(Qt::AA_CompressHighFrequencyEvents)) {
|
||||||
touchInfo.resize(pointerCount * historyCount);
|
touchInfo.resize(pointerCount * historyCount);
|
||||||
if (!GetPointerFrameTouchInfoHistory(pointerId,
|
if (!QWindowsContext::user32dll.getPointerFrameTouchInfoHistory(pointerId,
|
||||||
&historyCount,
|
&historyCount,
|
||||||
&pointerCount,
|
&pointerCount,
|
||||||
touchInfo.data())) {
|
touchInfo.data())) {
|
||||||
@ -101,7 +101,7 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
|||||||
}
|
}
|
||||||
case QT_PT_PEN: {
|
case QT_PT_PEN: {
|
||||||
POINTER_PEN_INFO penInfo;
|
POINTER_PEN_INFO penInfo;
|
||||||
if (!GetPointerPenInfo(pointerId, &penInfo)) {
|
if (!QWindowsContext::user32dll.getPointerPenInfo(pointerId, &penInfo)) {
|
||||||
qWarning() << "GetPointerPenInfo() failed:" << qt_error_string();
|
qWarning() << "GetPointerPenInfo() failed:" << qt_error_string();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -113,7 +113,7 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
|||||||
|| !QCoreApplication::testAttribute(Qt::AA_CompressTabletEvents))) {
|
|| !QCoreApplication::testAttribute(Qt::AA_CompressTabletEvents))) {
|
||||||
QVarLengthArray<POINTER_PEN_INFO, 10> penInfoHistory(historyCount);
|
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();
|
qWarning() << "GetPointerPenInfoHistory() failed:" << qt_error_string();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -441,8 +441,6 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
|
|||||||
if (id != -1)
|
if (id != -1)
|
||||||
m_lastTouchPoints.remove(id);
|
m_lastTouchPoints.remove(id);
|
||||||
}
|
}
|
||||||
// Send LeaveEvent to reset hover when the last finger leaves the touch screen (QTBUG-62912)
|
|
||||||
QWindowSystemInterface::handleEnterLeaveEvent(nullptr, window);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only handle down/up/update, ignore others like WM_POINTERENTER, WM_POINTERLEAVE, etc.
|
// Only handle down/up/update, ignore others like WM_POINTERENTER, WM_POINTERLEAVE, etc.
|
||||||
@ -519,7 +517,7 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
|
|||||||
inputIds.insert(touchPoint.id);
|
inputIds.insert(touchPoint.id);
|
||||||
|
|
||||||
// Avoid getting repeated messages for this frame if there are multiple pointerIds
|
// 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
|
// Some devices send touches for each finger in a different message/frame, instead of consolidating
|
||||||
@ -565,7 +563,7 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
|
|||||||
auto *penInfo = static_cast<POINTER_PEN_INFO *>(vPenInfo);
|
auto *penInfo = static_cast<POINTER_PEN_INFO *>(vPenInfo);
|
||||||
|
|
||||||
RECT pRect, dRect;
|
RECT pRect, dRect;
|
||||||
if (!GetPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect))
|
if (!QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const auto systemId = (qint64)penInfo->pointerInfo.sourceDevice;
|
const auto systemId = (qint64)penInfo->pointerInfo.sourceDevice;
|
||||||
|
@ -42,10 +42,12 @@ static inline QDpi deviceDPI(HDC hdc)
|
|||||||
|
|
||||||
static inline QDpi monitorDPI(HMONITOR hMonitor)
|
static inline QDpi monitorDPI(HMONITOR hMonitor)
|
||||||
{
|
{
|
||||||
|
if (QWindowsContext::shcoredll.isValid()) {
|
||||||
UINT dpiX;
|
UINT dpiX;
|
||||||
UINT dpiY;
|
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 QDpi(dpiX, dpiY);
|
||||||
|
}
|
||||||
return {0, 0};
|
return {0, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -564,6 +566,7 @@ QRect QWindowsScreen::virtualGeometry(const QPlatformScreen *screen) // cf QScre
|
|||||||
bool QWindowsScreen::setOrientationPreference(Qt::ScreenOrientation o)
|
bool QWindowsScreen::setOrientationPreference(Qt::ScreenOrientation o)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
if (QWindowsContext::user32dll.setDisplayAutoRotationPreferences) {
|
||||||
ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case Qt::PrimaryOrientation:
|
case Qt::PrimaryOrientation:
|
||||||
@ -581,15 +584,17 @@ bool QWindowsScreen::setOrientationPreference(Qt::ScreenOrientation o)
|
|||||||
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED;
|
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
result = SetDisplayAutoRotationPreferences(orientationPreference);
|
result = QWindowsContext::user32dll.setDisplayAutoRotationPreferences(orientationPreference);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::ScreenOrientation QWindowsScreen::orientationPreference()
|
Qt::ScreenOrientation QWindowsScreen::orientationPreference()
|
||||||
{
|
{
|
||||||
Qt::ScreenOrientation result = Qt::PrimaryOrientation;
|
Qt::ScreenOrientation result = Qt::PrimaryOrientation;
|
||||||
ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences) {
|
||||||
if (GetDisplayAutoRotationPreferences(&orientationPreference)) {
|
DWORD orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
||||||
|
if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences(&orientationPreference)) {
|
||||||
switch (orientationPreference) {
|
switch (orientationPreference) {
|
||||||
case ORIENTATION_PREFERENCE_NONE:
|
case ORIENTATION_PREFERENCE_NONE:
|
||||||
break;
|
break;
|
||||||
@ -607,6 +612,7 @@ Qt::ScreenOrientation QWindowsScreen::orientationPreference()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,8 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <VersionHelpers.h>
|
||||||
|
|
||||||
#if QT_CONFIG(cpp_winrt)
|
#if QT_CONFIG(cpp_winrt)
|
||||||
# include <QtCore/private/qt_winrtbase_p.h>
|
# include <QtCore/private/qt_winrtbase_p.h>
|
||||||
|
|
||||||
@ -232,11 +234,15 @@ static void populateLightSystemBasePalette(QPalette &result)
|
|||||||
QColor accent = getSysColor(COLOR_HIGHLIGHT);
|
QColor accent = getSysColor(COLOR_HIGHLIGHT);
|
||||||
|
|
||||||
#if QT_CONFIG(cpp_winrt)
|
#if QT_CONFIG(cpp_winrt)
|
||||||
|
|
||||||
|
if (IsWindows10OrGreater())
|
||||||
|
{
|
||||||
// respect the Windows 11 accent color
|
// respect the Windows 11 accent color
|
||||||
using namespace winrt::Windows::UI::ViewManagement;
|
using namespace winrt::Windows::UI::ViewManagement;
|
||||||
const auto settings = UISettings();
|
const auto settings = UISettings();
|
||||||
|
|
||||||
accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
|
accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const QColor btnFace = background;
|
const QColor btnFace = background;
|
||||||
@ -271,41 +277,45 @@ static void populateLightSystemBasePalette(QPalette &result)
|
|||||||
|
|
||||||
static void populateDarkSystemBasePalette(QPalette &result)
|
static void populateDarkSystemBasePalette(QPalette &result)
|
||||||
{
|
{
|
||||||
|
QColor foreground = Qt::white;
|
||||||
|
QColor background = QColor(0x1E, 0x1E, 0x1E);
|
||||||
|
QColor accent = QColor(0x00, 0x55, 0xff);
|
||||||
|
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);
|
||||||
|
QColor linkColor = Qt::blue;
|
||||||
|
|
||||||
#if QT_CONFIG(cpp_winrt)
|
#if QT_CONFIG(cpp_winrt)
|
||||||
|
|
||||||
|
if (IsWindows10OrGreater())
|
||||||
|
{
|
||||||
using namespace winrt::Windows::UI::ViewManagement;
|
using namespace winrt::Windows::UI::ViewManagement;
|
||||||
const auto settings = UISettings();
|
const auto settings = UISettings();
|
||||||
|
|
||||||
// We have to craft a palette from these colors. The settings.UIElementColor(UIElementType) API
|
// 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
|
// 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.
|
// 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));
|
foreground = getSysColor(settings.GetColorValue(UIColorType::Foreground));
|
||||||
const QColor background = [&settings]() -> QColor {
|
background = [&settings]() -> QColor {
|
||||||
auto systemBackground = getSysColor(settings.GetColorValue(UIColorType::Background));
|
auto systemBackground = getSysColor(settings.GetColorValue(UIColorType::Background));
|
||||||
if (systemBackground == Qt::black)
|
if (systemBackground == Qt::black)
|
||||||
systemBackground = QColor(0x1E, 0x1E, 0x1E);
|
systemBackground = QColor(0x1E, 0x1E, 0x1E);
|
||||||
return systemBackground;
|
return systemBackground;
|
||||||
}();
|
}();
|
||||||
|
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));
|
||||||
|
linkColor = accent;
|
||||||
|
}
|
||||||
|
|
||||||
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));
|
|
||||||
const QColor linkColor = accent;
|
|
||||||
#else
|
|
||||||
const QColor foreground = Qt::white;
|
|
||||||
const QColor background = QColor(0x1E, 0x1E, 0x1E);
|
|
||||||
const QColor accent = QColor(0x00, 0x55, 0xff);
|
|
||||||
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);
|
|
||||||
const QColor linkColor = Qt::blue;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const QColor buttonColor = background.lighter(200);
|
const QColor buttonColor = background.lighter(200);
|
||||||
|
|
||||||
result.setColor(QPalette::All, QPalette::WindowText, foreground);
|
result.setColor(QPalette::All, QPalette::WindowText, foreground);
|
||||||
@ -532,6 +542,8 @@ void QWindowsTheme::refreshPalettes()
|
|||||||
m_palettes[MenuBarPalette] = menuBarPalette(*m_palettes[MenuPalette], light);
|
m_palettes[MenuBarPalette] = menuBarPalette(*m_palettes[MenuPalette], light);
|
||||||
if (!light) {
|
if (!light) {
|
||||||
#if QT_CONFIG(cpp_winrt)
|
#if QT_CONFIG(cpp_winrt)
|
||||||
|
if (IsWindows10OrGreater())
|
||||||
|
{
|
||||||
using namespace winrt::Windows::UI::ViewManagement;
|
using namespace winrt::Windows::UI::ViewManagement;
|
||||||
const auto settings = UISettings();
|
const auto settings = UISettings();
|
||||||
const QColor accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
|
const QColor accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
|
||||||
@ -541,6 +553,18 @@ void QWindowsTheme::refreshPalettes()
|
|||||||
m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Base, accent);
|
m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Base, accent);
|
||||||
m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Button, accentLight);
|
m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Button, accentLight);
|
||||||
m_palettes[CheckBoxPalette]->setColor(QPalette::Inactive, QPalette::Base, accentDarkest);
|
m_palettes[CheckBoxPalette]->setColor(QPalette::Inactive, QPalette::Base, accentDarkest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_palettes[ButtonPalette] = new QPalette(*m_palettes[SystemPalette]);
|
||||||
|
m_palettes[ButtonPalette]->setColor(QPalette::Button, QColor(0x666666u));
|
||||||
|
const QColor checkBoxBlue(0x0078d7u);
|
||||||
|
m_palettes[CheckBoxPalette] = new QPalette(*m_palettes[SystemPalette]);
|
||||||
|
m_palettes[CheckBoxPalette]->setColor(QPalette::Base, checkBoxBlue);
|
||||||
|
m_palettes[CheckBoxPalette]->setColor(QPalette::Button, checkBoxBlue);
|
||||||
|
m_palettes[CheckBoxPalette]->setColor(QPalette::ButtonText, Qt::white);
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
m_palettes[ButtonPalette] = new QPalette(*m_palettes[SystemPalette]);
|
m_palettes[ButtonPalette] = new QPalette(*m_palettes[SystemPalette]);
|
||||||
m_palettes[ButtonPalette]->setColor(QPalette::Button, QColor(0x666666u));
|
m_palettes[ButtonPalette]->setColor(QPalette::Button, QColor(0x666666u));
|
||||||
@ -645,8 +669,14 @@ void QWindowsTheme::refreshFonts()
|
|||||||
fixedFont.setStyleHint(QFont::TypeWriter);
|
fixedFont.setStyleHint(QFont::TypeWriter);
|
||||||
|
|
||||||
LOGFONT lfIconTitleFont;
|
LOGFONT lfIconTitleFont;
|
||||||
SystemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
|
QFont iconTitleFont;
|
||||||
const QFont iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont, dpi);
|
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[SystemFont] = new QFont(QWindowsFontDatabase::systemDefaultFont());
|
||||||
m_fonts[MenuFont] = new QFont(menuFont);
|
m_fonts[MenuFont] = new QFont(menuFont);
|
||||||
|
@ -523,11 +523,14 @@ static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::Windo
|
|||||||
|
|
||||||
[[nodiscard]] static inline int getResizeBorderThickness(const UINT dpi)
|
[[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
|
// 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, but since it will always be enabled and can't be programtically
|
||||||
// disabled from Windows 8, we are safe to go.
|
// disabled from Windows 8, we are safe to go.
|
||||||
return GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi)
|
return QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi)
|
||||||
+ GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
+ QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -537,23 +540,30 @@ static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::Windo
|
|||||||
|
|
||||||
static QMargins invisibleMargins(QPoint screenPoint)
|
static QMargins invisibleMargins(QPoint screenPoint)
|
||||||
{
|
{
|
||||||
|
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10) {
|
||||||
POINT pt = {screenPoint.x(), screenPoint.y()};
|
POINT pt = {screenPoint.x(), screenPoint.y()};
|
||||||
if (HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
|
if (HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
|
||||||
|
if (QWindowsContext::shcoredll.isValid()) {
|
||||||
UINT dpiX;
|
UINT dpiX;
|
||||||
UINT dpiY;
|
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);
|
const int gap = getResizeBorderThickness(dpiX);
|
||||||
return QMargins(gap, 0, gap, gap);
|
return QMargins(gap, 0, gap, gap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return QMargins();
|
return QMargins();
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] static inline QMargins invisibleMargins(const HWND hwnd)
|
[[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);
|
const int gap = getResizeBorderThickness(dpi);
|
||||||
return QMargins(gap, 0, gap, gap);
|
return QMargins(gap, 0, gap, gap);
|
||||||
|
}
|
||||||
|
return QMargins();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -1038,7 +1048,8 @@ QMargins QWindowsGeometryHint::frameOnPrimaryScreen(const QWindow *w, DWORD styl
|
|||||||
return {};
|
return {};
|
||||||
RECT rect = {0,0,0,0};
|
RECT rect = {0,0,0,0};
|
||||||
style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
|
style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
|
||||||
if (AdjustWindowRectEx(&rect, style, FALSE, exStyle) == FALSE)
|
if (QWindowsContext::user32dll.adjustWindowRectEx &&
|
||||||
|
QWindowsContext::user32dll.adjustWindowRectEx(&rect, style, FALSE, exStyle) == FALSE)
|
||||||
qErrnoWarning("%s: AdjustWindowRectEx failed", __FUNCTION__);
|
qErrnoWarning("%s: AdjustWindowRectEx failed", __FUNCTION__);
|
||||||
const QMargins result(qAbs(rect.left), qAbs(rect.top),
|
const QMargins result(qAbs(rect.left), qAbs(rect.top),
|
||||||
qAbs(rect.right), qAbs(rect.bottom));
|
qAbs(rect.right), qAbs(rect.bottom));
|
||||||
@ -1062,7 +1073,8 @@ QMargins QWindowsGeometryHint::frame(const QWindow *w, DWORD style, DWORD exStyl
|
|||||||
return {};
|
return {};
|
||||||
RECT rect = {0,0,0,0};
|
RECT rect = {0,0,0,0};
|
||||||
style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
|
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__);
|
qErrnoWarning("%s: AdjustWindowRectExForDpi failed", __FUNCTION__);
|
||||||
}
|
}
|
||||||
const QMargins result(qAbs(rect.left), qAbs(rect.top),
|
const QMargins result(qAbs(rect.left), qAbs(rect.top),
|
||||||
@ -1556,7 +1568,8 @@ void QWindowsWindow::initialize()
|
|||||||
QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(w, obtainedGeometry);
|
QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(w, obtainedGeometry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QWindowsWindow::setSavedDpi(GetDpiForWindow(handle()));
|
QWindowsWindow::setSavedDpi(QWindowsContext::user32dll.getDpiForWindow ?
|
||||||
|
QWindowsContext::user32dll.getDpiForWindow(handle()) : 96);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSurfaceFormat QWindowsWindow::format() const
|
QSurfaceFormat QWindowsWindow::format() const
|
||||||
@ -2003,15 +2016,14 @@ void QWindowsWindow::handleDpiScaledSize(WPARAM wParam, LPARAM lParam, LRESULT *
|
|||||||
|
|
||||||
void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
const UINT dpi = HIWORD(wParam);
|
if (QWindowsContext::user32dll.getDpiForWindow) {
|
||||||
const qreal scale = dpiRelativeScale(dpi);
|
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
|
||||||
|
const qreal scale = qreal(dpi) / qreal(savedDpi());
|
||||||
setSavedDpi(dpi);
|
setSavedDpi(dpi);
|
||||||
|
|
||||||
// Send screen change first, so that the new screen is set during any following resize
|
// Send screen change first, so that the new screen is set during any following resize
|
||||||
checkForScreenChanged(QWindowsWindow::FromDpiChange);
|
checkForScreenChanged(QWindowsWindow::FromDpiChange);
|
||||||
|
|
||||||
if (!IsZoomed(hwnd))
|
|
||||||
m_data.restoreGeometry.setSize(m_data.restoreGeometry.size() * scale);
|
|
||||||
|
|
||||||
// We get WM_DPICHANGED in one of two situations:
|
// We get WM_DPICHANGED in one of two situations:
|
||||||
//
|
//
|
||||||
// 1. The DPI change is a "spontaneous" DPI change as a result of e.g.
|
// 1. The DPI change is a "spontaneous" DPI change as a result of e.g.
|
||||||
@ -2044,11 +2056,13 @@ void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|||||||
// Re-apply mask now that we have a new DPI, which have resulted in
|
// Re-apply mask now that we have a new DPI, which have resulted in
|
||||||
// a new scale factor.
|
// a new scale factor.
|
||||||
setMask(QHighDpi::toNativeLocalRegion(window()->mask(), window()));
|
setMask(QHighDpi::toNativeLocalRegion(window()->mask(), window()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWindowsWindow::handleDpiChangedAfterParent(HWND hwnd)
|
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);
|
const qreal scale = dpiRelativeScale(dpi);
|
||||||
setSavedDpi(dpi);
|
setSavedDpi(dpi);
|
||||||
|
|
||||||
@ -2059,6 +2073,7 @@ void QWindowsWindow::handleDpiChangedAfterParent(HWND hwnd)
|
|||||||
QRect currentGeometry = geometry();
|
QRect currentGeometry = geometry();
|
||||||
QRect scaledGeometry = QRect(currentGeometry.topLeft() * scale, currentGeometry.size() * scale);
|
QRect scaledGeometry = QRect(currentGeometry.topLeft() * scale, currentGeometry.size() * scale);
|
||||||
setGeometry(scaledGeometry);
|
setGeometry(scaledGeometry);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static QRect normalFrameGeometry(HWND hwnd)
|
static QRect normalFrameGeometry(HWND hwnd)
|
||||||
|
Loading…
Reference in New Issue
Block a user