mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2024-10-30 07:47:52 +08:00
update to Qt 6.7.3
This commit is contained in:
parent
d8e4680eb6
commit
36dc9b47f0
@ -112,8 +112,10 @@ static GUID writableSpecialFolderId(QStandardPaths::StandardLocation type)
|
||||
FOLDERID_LocalAppData, // AppConfigLocation ("Local" path)
|
||||
FOLDERID_Public, // PublicShareLocation
|
||||
FOLDERID_Templates, // TemplatesLocation
|
||||
GUID(), // StateLocation
|
||||
GUID(), // GenericStateLocation
|
||||
};
|
||||
static_assert(sizeof(folderIds) / sizeof(folderIds[0]) == size_t(QStandardPaths::TemplatesLocation + 1));
|
||||
static_assert(sizeof(folderIds) / sizeof(folderIds[0]) == size_t(QStandardPaths::GenericStateLocation + 1));
|
||||
|
||||
// folders for low integrity processes
|
||||
static const GUID folderIds_li[] = {
|
||||
@ -137,6 +139,8 @@ static GUID writableSpecialFolderId(QStandardPaths::StandardLocation type)
|
||||
FOLDERID_LocalAppDataLow,// AppConfigLocation ("Local" path)
|
||||
FOLDERID_Public, // PublicShareLocation
|
||||
FOLDERID_Templates, // TemplatesLocation
|
||||
GUID(), // StateLocation
|
||||
GUID(), // GenericStateLocation
|
||||
};
|
||||
static_assert(sizeof(folderIds_li) == sizeof(folderIds));
|
||||
|
||||
@ -191,6 +195,23 @@ QString QStandardPaths::writableLocation(StandardLocation type)
|
||||
result = QDir::tempPath();
|
||||
break;
|
||||
|
||||
case StateLocation:
|
||||
result = sHGetKnownFolderPath(writableSpecialFolderId(AppLocalDataLocation));
|
||||
if (!result.isEmpty()) {
|
||||
appendTestMode(result);
|
||||
appendOrganizationAndApp(result);
|
||||
result += "/State"_L1;
|
||||
}
|
||||
break;
|
||||
|
||||
case GenericStateLocation:
|
||||
result = sHGetKnownFolderPath(writableSpecialFolderId(GenericDataLocation));
|
||||
if (!result.isEmpty()) {
|
||||
appendTestMode(result);
|
||||
result += "/State"_L1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
result = sHGetKnownFolderPath(writableSpecialFolderId(type));
|
||||
if (!result.isEmpty() && isConfigLocation(type)) {
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include "qcoreapplication.h"
|
||||
#include <private/qsystemlibrary_p.h>
|
||||
#include "qoperatingsystemversion.h"
|
||||
#include "qpair.h"
|
||||
#include "qset.h"
|
||||
#include "qsocketnotifier.h"
|
||||
#include "qvarlengtharray.h"
|
||||
@ -136,7 +135,7 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
|
||||
QSNDict *sn_vec[4] = { &d->sn_read, &d->sn_write, &d->sn_except, &d->sn_read };
|
||||
QSNDict *dict = sn_vec[type];
|
||||
|
||||
QSockNot *sn = dict ? dict->value(wp) : 0;
|
||||
QSockNot *sn = dict ? dict->value(qintptr(wp)) : 0;
|
||||
if (sn == nullptr) {
|
||||
d->postActivateSocketNotifiers();
|
||||
} else {
|
||||
@ -414,7 +413,7 @@ void QEventDispatcherWin32Private::sendTimerEvent(int timerId)
|
||||
}
|
||||
}
|
||||
|
||||
void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket, long event)
|
||||
void QEventDispatcherWin32Private::doWsaAsyncSelect(qintptr socket, long event)
|
||||
{
|
||||
Q_ASSERT(internalHwnd);
|
||||
// BoundsChecker may emit a warning for WSAAsyncSelect when event == 0
|
||||
@ -563,7 +562,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
|
||||
void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier)
|
||||
{
|
||||
Q_ASSERT(notifier);
|
||||
int sockfd = notifier->socket();
|
||||
qintptr sockfd = notifier->socket();
|
||||
int type = notifier->type();
|
||||
#ifndef QT_NO_DEBUG
|
||||
if (sockfd < 0) {
|
||||
@ -587,7 +586,7 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier)
|
||||
const char *t[] = { "Read", "Write", "Exception" };
|
||||
/* Variable "socket" below is a function pointer. */
|
||||
qWarning("QSocketNotifier: Multiple socket notifiers for "
|
||||
"same socket %d and type %s", sockfd, t[type]);
|
||||
"same socket %" PRIdQINTPTR " and type %s", sockfd, t[type]);
|
||||
}
|
||||
|
||||
QSockNot *sn = new QSockNot;
|
||||
@ -631,7 +630,7 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier)
|
||||
{
|
||||
Q_ASSERT(notifier);
|
||||
#ifndef QT_NO_DEBUG
|
||||
int sockfd = notifier->socket();
|
||||
qintptr sockfd = notifier->socket();
|
||||
if (sockfd < 0) {
|
||||
qWarning("QEventDispatcherWin32::unregisterSocketNotifier: invalid socket identifier");
|
||||
return;
|
||||
@ -648,7 +647,7 @@ void QEventDispatcherWin32::doUnregisterSocketNotifier(QSocketNotifier *notifier
|
||||
{
|
||||
Q_D(QEventDispatcherWin32);
|
||||
int type = notifier->type();
|
||||
int sockfd = notifier->socket();
|
||||
qintptr sockfd = notifier->socket();
|
||||
Q_ASSERT(sockfd >= 0);
|
||||
|
||||
QSFDict::iterator it = d->active_fd.find(sockfd);
|
||||
@ -911,3 +910,5 @@ HWND QEventDispatcherWin32::internalHwnd()
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#include "moc_qeventdispatcher_win_p.cpp"
|
||||
|
@ -51,21 +51,21 @@ bool qt_win_hasPackageIdentity()
|
||||
{
|
||||
#if defined(HAS_APPMODEL)
|
||||
|
||||
static const bool hasPackageIdentity = []() {
|
||||
UINT32 length = 0;
|
||||
switch (const auto result = myGetCurrentPackageFullName(&length, nullptr)) {
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
return true;
|
||||
case APPMODEL_ERROR_NO_PACKAGE:
|
||||
return false;
|
||||
default:
|
||||
qWarning("Failed to resolve package identity (error code %ld)", result);
|
||||
return false;
|
||||
}
|
||||
}();
|
||||
return hasPackageIdentity;
|
||||
static const bool hasPackageIdentity = []() {
|
||||
UINT32 length = 0;
|
||||
switch (const auto result = myGetCurrentPackageFullName(&length, nullptr)) {
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
return true;
|
||||
case APPMODEL_ERROR_NO_PACKAGE:
|
||||
return false;
|
||||
default:
|
||||
qWarning("Failed to resolve package identity (error code %ld)", result);
|
||||
return false;
|
||||
}
|
||||
}();
|
||||
return hasPackageIdentity;
|
||||
#else
|
||||
return false;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -15,15 +15,15 @@
|
||||
// We mean it.
|
||||
//
|
||||
|
||||
#include <qdeadlinetimer.h>
|
||||
#include <private/qglobal_p.h>
|
||||
#include <QtCore/qtsan_impl.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QtDummyFutex {
|
||||
constexpr inline bool futexAvailable() { return false; }
|
||||
template <typename Atomic>
|
||||
inline bool futexWait(Atomic &, typename Atomic::Type, int = 0)
|
||||
inline bool futexWait(Atomic &, typename Atomic::Type, QDeadlineTimer = {})
|
||||
{ Q_UNREACHABLE_RETURN(false); }
|
||||
template <typename Atomic> inline void futexWakeOne(Atomic &)
|
||||
{ Q_UNREACHABLE(); }
|
||||
@ -33,82 +33,16 @@ namespace QtDummyFutex {
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
|
||||
#if defined(Q_OS_DARWIN)
|
||||
# include "qfutex_mac_p.h"
|
||||
#elif defined(Q_OS_FREEBSD)
|
||||
# include "qfutex_freebsd_p.h"
|
||||
#elif defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
|
||||
// use Linux mutexes everywhere except for LSB builds
|
||||
# include <sys/syscall.h>
|
||||
# include <errno.h>
|
||||
# include <limits.h>
|
||||
# include <unistd.h>
|
||||
# include <asm/unistd.h>
|
||||
# include <linux/futex.h>
|
||||
# define QT_ALWAYS_USE_FUTEX
|
||||
|
||||
// if not defined in linux/futex.h
|
||||
# define FUTEX_PRIVATE_FLAG 128 // added in v2.6.22
|
||||
|
||||
// RISC-V does not supply __NR_futex
|
||||
# ifndef __NR_futex
|
||||
# define __NR_futex __NR_futex_time64
|
||||
# endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace QtLinuxFutex {
|
||||
constexpr inline bool futexAvailable() { return true; }
|
||||
inline int _q_futex(int *addr, int op, int val, quintptr val2 = 0,
|
||||
int *addr2 = nullptr, int val3 = 0) noexcept
|
||||
{
|
||||
QtTsan::futexRelease(addr, addr2);
|
||||
|
||||
// we use __NR_futex because some libcs (like Android's bionic) don't
|
||||
// provide SYS_futex etc.
|
||||
int result = syscall(__NR_futex, addr, op | FUTEX_PRIVATE_FLAG, val, val2, addr2, val3);
|
||||
|
||||
QtTsan::futexAcquire(addr, addr2);
|
||||
|
||||
return result;
|
||||
}
|
||||
template <typename T> int *addr(T *ptr)
|
||||
{
|
||||
int *int_addr = reinterpret_cast<int *>(ptr);
|
||||
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
|
||||
if (sizeof(T) > sizeof(int))
|
||||
int_addr++; //We want a pointer to the least significant half
|
||||
#endif
|
||||
return int_addr;
|
||||
}
|
||||
|
||||
template <typename Atomic>
|
||||
inline void futexWait(Atomic &futex, typename Atomic::Type expectedValue)
|
||||
{
|
||||
_q_futex(addr(&futex), FUTEX_WAIT, qintptr(expectedValue));
|
||||
}
|
||||
template <typename Atomic>
|
||||
inline bool futexWait(Atomic &futex, typename Atomic::Type expectedValue, qint64 nstimeout)
|
||||
{
|
||||
struct timespec ts;
|
||||
ts.tv_sec = nstimeout / 1000 / 1000 / 1000;
|
||||
ts.tv_nsec = nstimeout % (1000 * 1000 * 1000);
|
||||
int r = _q_futex(addr(&futex), FUTEX_WAIT, qintptr(expectedValue), quintptr(&ts));
|
||||
return r == 0 || errno != ETIMEDOUT;
|
||||
}
|
||||
template <typename Atomic> inline void futexWakeOne(Atomic &futex)
|
||||
{
|
||||
_q_futex(addr(&futex), FUTEX_WAKE, 1);
|
||||
}
|
||||
template <typename Atomic> inline void futexWakeAll(Atomic &futex)
|
||||
{
|
||||
_q_futex(addr(&futex), FUTEX_WAKE, INT_MAX);
|
||||
}
|
||||
template <typename Atomic> inline
|
||||
void futexWakeOp(Atomic &futex1, int wake1, int wake2, Atomic &futex2, quint32 op)
|
||||
{
|
||||
_q_futex(addr(&futex1), FUTEX_WAKE_OP, wake1, wake2, addr(&futex2), op);
|
||||
}
|
||||
}
|
||||
namespace QtFutex = QtLinuxFutex;
|
||||
QT_END_NAMESPACE
|
||||
# include "qfutex_linux_p.h"
|
||||
//#elif defined(Q_OS_WIN)
|
||||
//# include "qfutex_win_p.h"
|
||||
#else
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace QtFutex = QtDummyFutex;
|
||||
QT_END_NAMESPACE
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include "qmutex.h"
|
||||
#include <qdebug.h>
|
||||
#include "qatomic.h"
|
||||
#include "qelapsedtimer.h"
|
||||
#include "qfutex_p.h"
|
||||
#include "qthread.h"
|
||||
#include "qmutex_p.h"
|
||||
@ -673,12 +672,11 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
|
||||
*/
|
||||
bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXCEPT
|
||||
{
|
||||
qint64 remainingTime = deadlineTimer.remainingTimeNSecs();
|
||||
if (remainingTime == 0)
|
||||
if (deadlineTimer.hasExpired())
|
||||
return false;
|
||||
|
||||
if (futexAvailable()) {
|
||||
if (Q_UNLIKELY(remainingTime < 0)) { // deadlineTimer.isForever()
|
||||
if (Q_UNLIKELY(deadlineTimer.isForever())) {
|
||||
lockInternal();
|
||||
return true;
|
||||
}
|
||||
@ -689,8 +687,8 @@ bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXC
|
||||
if (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) == nullptr)
|
||||
return true;
|
||||
|
||||
Q_FOREVER {
|
||||
if (!futexWait(d_ptr, dummyFutexValue(), remainingTime))
|
||||
for (;;) {
|
||||
if (!futexWait(d_ptr, dummyFutexValue(), deadlineTimer))
|
||||
return false;
|
||||
|
||||
// We got woken up, so must try to acquire the mutex. We must set
|
||||
@ -699,9 +697,7 @@ bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXC
|
||||
if (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) == nullptr)
|
||||
return true;
|
||||
|
||||
// calculate the remaining time
|
||||
remainingTime = deadlineTimer.remainingTimeNSecs();
|
||||
if (remainingTime <= 0)
|
||||
if (deadlineTimer.hasExpired())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -713,7 +709,7 @@ bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXC
|
||||
continue;
|
||||
|
||||
if (copy == dummyLocked()) {
|
||||
if (remainingTime == 0)
|
||||
if (deadlineTimer.hasExpired())
|
||||
return false;
|
||||
// The mutex is locked but does not have a QMutexPrivate yet.
|
||||
// we need to allocate a QMutexPrivate
|
||||
@ -728,7 +724,7 @@ bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXC
|
||||
}
|
||||
|
||||
QMutexPrivate *d = static_cast<QMutexPrivate *>(copy);
|
||||
if (remainingTime == 0 && !d->possiblyUnlocked.loadRelaxed())
|
||||
if (deadlineTimer.hasExpired() && !d->possiblyUnlocked.loadRelaxed())
|
||||
return false;
|
||||
|
||||
// At this point we have a pointer to a QMutexPrivate. But the other thread
|
||||
@ -790,7 +786,6 @@ bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXC
|
||||
Q_ASSERT(d == d_ptr.loadRelaxed());
|
||||
return true;
|
||||
} else {
|
||||
Q_ASSERT(remainingTime >= 0);
|
||||
// timed out
|
||||
d->derefWaiters(1);
|
||||
//There may be a race in which the mutex is unlocked right after we timed out,
|
||||
@ -915,10 +910,10 @@ QT_END_NAMESPACE
|
||||
|
||||
#if defined(QT_ALWAYS_USE_FUTEX)
|
||||
// nothing
|
||||
#elif defined(Q_OS_MAC)
|
||||
#elif defined(Q_OS_DARWIN)
|
||||
# include "qmutex_mac.cpp"
|
||||
#elif defined(Q_OS_WIN)
|
||||
# include "qmutex_win.cpp"
|
||||
#else
|
||||
# include "qmutex_unix.cpp"
|
||||
#endif
|
||||
#endif
|
||||
|
@ -95,22 +95,47 @@ using namespace Qt::StringLiterals;
|
||||
|
||||
/*!
|
||||
\variable QRhiD3D11NativeHandles::dev
|
||||
|
||||
Points to a
|
||||
\l{https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nn-d3d11-id3d11device}{ID3D11Device}
|
||||
or left set to \nullptr if no existing device is to be imported.
|
||||
|
||||
\note When importing a device, both the device and the device context must be set to valid objects.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiD3D11NativeHandles::context
|
||||
|
||||
Points to a \l{https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nn-d3d11-id3d11devicecontext}{ID3D11DeviceContext}
|
||||
or left set to \nullptr if no existing device context is to be imported.
|
||||
|
||||
\note When importing a device, both the device and the device context must be set to valid objects.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiD3D11NativeHandles::featureLevel
|
||||
|
||||
Specifies the feature level passed to
|
||||
\l{https://learn.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-d3d11createdevice}{D3D11CreateDevice()}.
|
||||
Relevant only when QRhi creates the device, ignored when importing a device
|
||||
and device context. When not set, the default rules outlined in the D3D
|
||||
documentation apply.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiD3D11NativeHandles::adapterLuidLow
|
||||
|
||||
The low part of the local identifier (LUID) of the DXGI adapter to use.
|
||||
Relevant only when QRhi creates the device, ignored when importing a device
|
||||
and device context.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\variable QRhiD3D11NativeHandles::adapterLuidHigh
|
||||
|
||||
The high part of the local identifier (LUID) of the DXGI adapter to use.
|
||||
Relevant only when QRhi creates the device, ignored when importing a device
|
||||
and device context.
|
||||
*/
|
||||
|
||||
// help mingw with its ancient sdk headers
|
||||
@ -259,9 +284,7 @@ bool QRhiD3D11::create(QRhi::Flags flags)
|
||||
if (!activeAdapter && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
|
||||
activeAdapter = adapter;
|
||||
adapterLuid = desc.AdapterLuid;
|
||||
driverInfoStruct.deviceName = name.toUtf8();
|
||||
driverInfoStruct.deviceId = desc.DeviceId;
|
||||
driverInfoStruct.vendorId = desc.VendorId;
|
||||
QRhiD3D::fillDriverInfo(&driverInfoStruct, desc);
|
||||
qCDebug(QRHI_LOG_INFO, " using this adapter");
|
||||
} else {
|
||||
adapter->Release();
|
||||
@ -304,21 +327,24 @@ bool QRhiD3D11::create(QRhi::Flags flags)
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool supports11_1 = SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast<void **>(&context)));
|
||||
ctx->Release();
|
||||
if (!supports11_1) {
|
||||
qWarning("ID3D11DeviceContext1 not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test if creating a Shader Model 5.0 vertex shader works; we want to
|
||||
// fail already in create() if that's not the case.
|
||||
ID3D11VertexShader *testShader = nullptr;
|
||||
if (SUCCEEDED(dev->CreateVertexShader(g_testVertexShader, sizeof(g_testVertexShader), nullptr, &testShader))) {
|
||||
testShader->Release();
|
||||
} else {
|
||||
qWarning("D3D11 smoke test failed (failed to create vertex shader)");
|
||||
ctx->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool supports11_1 = SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast<void **>(&context)));
|
||||
ctx->Release();
|
||||
if (!supports11_1) {
|
||||
qWarning("ID3D11DeviceContext1 not supported");
|
||||
static const char *msg = "D3D11 smoke test: Failed to create vertex shader";
|
||||
if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
|
||||
qCDebug(QRHI_LOG_INFO, "%s", msg);
|
||||
else
|
||||
qWarning("%s", msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -328,11 +354,19 @@ bool QRhiD3D11::create(QRhi::Flags flags)
|
||||
// still not support this D3D_FEATURE_LEVEL_11_1 feature. (e.g.
|
||||
// because it only does 11_0)
|
||||
if (!features.ConstantBufferOffsetting) {
|
||||
qWarning("Constant buffer offsetting is not supported by the driver");
|
||||
static const char *msg = "D3D11 smoke test: Constant buffer offsetting is not supported by the driver";
|
||||
if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
|
||||
qCDebug(QRHI_LOG_INFO, "%s", msg);
|
||||
else
|
||||
qWarning("%s", msg);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
qWarning("Failed to query D3D11_FEATURE_D3D11_OPTIONS");
|
||||
static const char *msg = "D3D11 smoke test: Failed to query D3D11_FEATURE_D3D11_OPTIONS";
|
||||
if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
|
||||
qCDebug(QRHI_LOG_INFO, "%s", msg);
|
||||
else
|
||||
qWarning("%s", msg);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@ -342,12 +376,14 @@ bool QRhiD3D11::create(QRhi::Flags flags)
|
||||
if (SUCCEEDED(dev->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void **>(&dxgiDev)))) {
|
||||
IDXGIAdapter *adapter = nullptr;
|
||||
if (SUCCEEDED(dxgiDev->GetAdapter(&adapter))) {
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
adapter->GetDesc(&desc);
|
||||
adapterLuid = desc.AdapterLuid;
|
||||
driverInfoStruct.deviceName = QString::fromUtf16(reinterpret_cast<char16_t *>(desc.Description)).toUtf8();
|
||||
driverInfoStruct.deviceId = desc.DeviceId;
|
||||
driverInfoStruct.vendorId = desc.VendorId;
|
||||
IDXGIAdapter1 *adapter1 = nullptr;
|
||||
if (SUCCEEDED(adapter->QueryInterface(__uuidof(IDXGIAdapter1), reinterpret_cast<void **>(&adapter1)))) {
|
||||
DXGI_ADAPTER_DESC1 desc;
|
||||
adapter1->GetDesc1(&desc);
|
||||
adapterLuid = desc.AdapterLuid;
|
||||
QRhiD3D::fillDriverInfo(&driverInfoStruct, desc);
|
||||
adapter1->Release();
|
||||
}
|
||||
adapter->Release();
|
||||
}
|
||||
dxgiDev->Release();
|
||||
@ -358,11 +394,6 @@ bool QRhiD3D11::create(QRhi::Flags flags)
|
||||
if (FAILED(context->QueryInterface(__uuidof(ID3DUserDefinedAnnotation), reinterpret_cast<void **>(&annotations))))
|
||||
annotations = nullptr;
|
||||
|
||||
if (flags.testFlag(QRhi::EnableTimestamps)) {
|
||||
ofr.timestamps.prepare(2, this);
|
||||
// timestamp queries are optional so we can go on even if they failed
|
||||
}
|
||||
|
||||
deviceLost = false;
|
||||
|
||||
nativeHandlesStruct.dev = dev;
|
||||
@ -388,7 +419,16 @@ void QRhiD3D11::destroy()
|
||||
|
||||
clearShaderCache();
|
||||
|
||||
ofr.timestamps.destroy();
|
||||
if (ofr.tsDisjointQuery) {
|
||||
ofr.tsDisjointQuery->Release();
|
||||
ofr.tsDisjointQuery = nullptr;
|
||||
}
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (ofr.tsQueries[i]) {
|
||||
ofr.tsQueries[i]->Release();
|
||||
ofr.tsQueries[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (annotations) {
|
||||
annotations->Release();
|
||||
@ -592,6 +632,8 @@ bool QRhiD3D11::isFeatureSupported(QRhi::Feature feature) const
|
||||
return true;
|
||||
case QRhi::ThreeDimensionalTextureMipmaps:
|
||||
return true;
|
||||
case QRhi::MultiView:
|
||||
return false;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
return false;
|
||||
@ -1262,7 +1304,6 @@ const QRhiNativeHandles *QRhiD3D11::nativeHandles(QRhiCommandBuffer *cb)
|
||||
void QRhiD3D11::beginExternal(QRhiCommandBuffer *cb)
|
||||
{
|
||||
QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
|
||||
// no timestampSwapChain, in order to avoid timestamp mess
|
||||
executeCommandBuffer(cbD);
|
||||
cbD->resetCommands();
|
||||
}
|
||||
@ -1285,6 +1326,19 @@ double QRhiD3D11::lastCompletedGpuTime(QRhiCommandBuffer *cb)
|
||||
return cbD->lastGpuTime;
|
||||
}
|
||||
|
||||
static inline QD3D11RenderTargetData *rtData(QRhiRenderTarget *rt)
|
||||
{
|
||||
switch (rt->resourceType()) {
|
||||
case QRhiResource::SwapChainRenderTarget:
|
||||
return &QRHI_RES(QD3D11SwapChainRenderTarget, rt)->d;
|
||||
case QRhiResource::TextureRenderTarget:
|
||||
return &QRHI_RES(QD3D11TextureRenderTarget, rt)->d;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
QRhi::FrameOpResult QRhiD3D11::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
|
||||
{
|
||||
Q_UNUSED(flags);
|
||||
@ -1301,12 +1355,22 @@ QRhi::FrameOpResult QRhiD3D11::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginF
|
||||
|
||||
finishActiveReadbacks();
|
||||
|
||||
if (swapChainD->timestamps.active[currentFrameSlot]) {
|
||||
if (swapChainD->timestamps.active[swapChainD->currentTimestampPairIndex]) {
|
||||
double elapsedSec = 0;
|
||||
if (swapChainD->timestamps.tryQueryTimestamps(currentFrameSlot, context, &elapsedSec))
|
||||
if (swapChainD->timestamps.tryQueryTimestamps(swapChainD->currentTimestampPairIndex, context, &elapsedSec))
|
||||
swapChainD->cb.lastGpuTime = elapsedSec;
|
||||
}
|
||||
|
||||
ID3D11Query *tsStart = swapChainD->timestamps.query[swapChainD->currentTimestampPairIndex * 2];
|
||||
ID3D11Query *tsDisjoint = swapChainD->timestamps.disjointQuery[swapChainD->currentTimestampPairIndex];
|
||||
const bool recordTimestamps = tsStart && tsDisjoint && !swapChainD->timestamps.active[swapChainD->currentTimestampPairIndex];
|
||||
|
||||
QD3D11CommandBuffer::Command &cmd(swapChainD->cb.commands.get());
|
||||
cmd.cmd = QD3D11CommandBuffer::Command::BeginFrame;
|
||||
cmd.args.beginFrame.tsQuery = recordTimestamps ? tsStart : nullptr;
|
||||
cmd.args.beginFrame.tsDisjointQuery = recordTimestamps ? tsDisjoint : nullptr;
|
||||
cmd.args.beginFrame.swapchainData = rtData(&swapChainD->rt);
|
||||
|
||||
return QRhi::FrameOpSuccess;
|
||||
}
|
||||
|
||||
@ -1316,17 +1380,13 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
|
||||
Q_ASSERT(contextState.currentSwapChain = swapChainD);
|
||||
const int currentFrameSlot = swapChainD->currentFrameSlot;
|
||||
|
||||
ID3D11Query *tsDisjoint = swapChainD->timestamps.disjointQuery[currentFrameSlot];
|
||||
const int tsIdx = QD3D11SwapChain::BUFFER_COUNT * currentFrameSlot;
|
||||
ID3D11Query *tsStart = swapChainD->timestamps.query[tsIdx];
|
||||
ID3D11Query *tsEnd = swapChainD->timestamps.query[tsIdx + 1];
|
||||
const bool recordTimestamps = tsDisjoint && tsStart && tsEnd && !swapChainD->timestamps.active[currentFrameSlot];
|
||||
QD3D11CommandBuffer::Command &cmd(swapChainD->cb.commands.get());
|
||||
cmd.cmd = QD3D11CommandBuffer::Command::EndFrame;
|
||||
cmd.args.endFrame.tsQuery = nullptr; // done later manually, see below
|
||||
cmd.args.endFrame.tsDisjointQuery = nullptr;
|
||||
|
||||
// send all commands to the context
|
||||
if (recordTimestamps)
|
||||
executeCommandBuffer(&swapChainD->cb, swapChainD);
|
||||
else
|
||||
executeCommandBuffer(&swapChainD->cb);
|
||||
executeCommandBuffer(&swapChainD->cb);
|
||||
|
||||
if (swapChainD->sampleDesc.Count > 1) {
|
||||
context->ResolveSubresource(swapChainD->backBufferTex, 0,
|
||||
@ -1334,11 +1394,15 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
|
||||
swapChainD->colorFormat);
|
||||
}
|
||||
|
||||
// this is here because we want to include the time spent on the resolve as well
|
||||
// this is here because we want to include the time spent on the ResolveSubresource as well
|
||||
ID3D11Query *tsEnd = swapChainD->timestamps.query[swapChainD->currentTimestampPairIndex * 2 + 1];
|
||||
ID3D11Query *tsDisjoint = swapChainD->timestamps.disjointQuery[swapChainD->currentTimestampPairIndex];
|
||||
const bool recordTimestamps = tsEnd && tsDisjoint && !swapChainD->timestamps.active[swapChainD->currentTimestampPairIndex];
|
||||
if (recordTimestamps) {
|
||||
context->End(tsEnd);
|
||||
context->End(tsDisjoint);
|
||||
swapChainD->timestamps.active[currentFrameSlot] = true;
|
||||
swapChainD->timestamps.active[swapChainD->currentTimestampPairIndex] = true;
|
||||
swapChainD->currentTimestampPairIndex = (swapChainD->currentTimestampPairIndex + 1) % QD3D11SwapChainTimestamps::TIMESTAMP_PAIRS;
|
||||
}
|
||||
|
||||
if (!flags.testFlag(QRhi::SkipPresent)) {
|
||||
@ -1383,12 +1447,36 @@ QRhi::FrameOpResult QRhiD3D11::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi:
|
||||
ofr.cbWrapper.resetState();
|
||||
*cb = &ofr.cbWrapper;
|
||||
|
||||
if (ofr.timestamps.active[ofr.timestampIdx]) {
|
||||
double elapsedSec = 0;
|
||||
if (ofr.timestamps.tryQueryTimestamps(ofr.timestampIdx, context, &elapsedSec))
|
||||
ofr.cbWrapper.lastGpuTime = elapsedSec;
|
||||
if (rhiFlags.testFlag(QRhi::EnableTimestamps)) {
|
||||
D3D11_QUERY_DESC queryDesc = {};
|
||||
if (!ofr.tsDisjointQuery) {
|
||||
queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
|
||||
HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsDisjointQuery);
|
||||
if (FAILED(hr)) {
|
||||
qWarning("Failed to create timestamp disjoint query: %s",
|
||||
qPrintable(QSystemError::windowsComString(hr)));
|
||||
return QRhi::FrameOpError;
|
||||
}
|
||||
}
|
||||
queryDesc.Query = D3D11_QUERY_TIMESTAMP;
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (!ofr.tsQueries[i]) {
|
||||
HRESULT hr = dev->CreateQuery(&queryDesc, &ofr.tsQueries[i]);
|
||||
if (FAILED(hr)) {
|
||||
qWarning("Failed to create timestamp query: %s",
|
||||
qPrintable(QSystemError::windowsComString(hr)));
|
||||
return QRhi::FrameOpError;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QD3D11CommandBuffer::Command &cmd(ofr.cbWrapper.commands.get());
|
||||
cmd.cmd = QD3D11CommandBuffer::Command::BeginFrame;
|
||||
cmd.args.beginFrame.tsQuery = ofr.tsQueries[0] ? ofr.tsQueries[0] : nullptr;
|
||||
cmd.args.beginFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery : nullptr;
|
||||
cmd.args.beginFrame.swapchainData = nullptr;
|
||||
|
||||
return QRhi::FrameOpSuccess;
|
||||
}
|
||||
|
||||
@ -1397,25 +1485,39 @@ QRhi::FrameOpResult QRhiD3D11::endOffscreenFrame(QRhi::EndFrameFlags flags)
|
||||
Q_UNUSED(flags);
|
||||
ofr.active = false;
|
||||
|
||||
ID3D11Query *tsDisjoint = ofr.timestamps.disjointQuery[ofr.timestampIdx];
|
||||
ID3D11Query *tsStart = ofr.timestamps.query[ofr.timestampIdx * 2];
|
||||
ID3D11Query *tsEnd = ofr.timestamps.query[ofr.timestampIdx * 2 + 1];
|
||||
const bool recordTimestamps = tsDisjoint && tsStart && tsEnd && !ofr.timestamps.active[ofr.timestampIdx];
|
||||
if (recordTimestamps) {
|
||||
context->Begin(tsDisjoint);
|
||||
context->End(tsStart); // record timestamp; no Begin() for D3D11_QUERY_TIMESTAMP
|
||||
}
|
||||
QD3D11CommandBuffer::Command &cmd(ofr.cbWrapper.commands.get());
|
||||
cmd.cmd = QD3D11CommandBuffer::Command::EndFrame;
|
||||
cmd.args.endFrame.tsQuery = ofr.tsQueries[1] ? ofr.tsQueries[1] : nullptr;
|
||||
cmd.args.endFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery : nullptr;
|
||||
|
||||
executeCommandBuffer(&ofr.cbWrapper);
|
||||
context->Flush();
|
||||
|
||||
finishActiveReadbacks();
|
||||
|
||||
if (recordTimestamps) {
|
||||
context->End(tsEnd);
|
||||
context->End(tsDisjoint);
|
||||
ofr.timestamps.active[ofr.timestampIdx] = true;
|
||||
ofr.timestampIdx = (ofr.timestampIdx + 1) % 2;
|
||||
if (ofr.tsQueries[0]) {
|
||||
quint64 timestamps[2];
|
||||
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
|
||||
HRESULT hr;
|
||||
bool ok = true;
|
||||
do {
|
||||
hr = context->GetData(ofr.tsDisjointQuery, &dj, sizeof(dj), 0);
|
||||
} while (hr == S_FALSE);
|
||||
ok &= hr == S_OK;
|
||||
do {
|
||||
hr = context->GetData(ofr.tsQueries[1], ×tamps[1], sizeof(quint64), 0);
|
||||
} while (hr == S_FALSE);
|
||||
ok &= hr == S_OK;
|
||||
do {
|
||||
hr = context->GetData(ofr.tsQueries[0], ×tamps[0], sizeof(quint64), 0);
|
||||
} while (hr == S_FALSE);
|
||||
ok &= hr == S_OK;
|
||||
if (ok) {
|
||||
if (!dj.Disjoint && dj.Frequency) {
|
||||
const float elapsedMs = (timestamps[1] - timestamps[0]) / float(dj.Frequency) * 1000.0f;
|
||||
ofr.cbWrapper.lastGpuTime = elapsedMs / 1000.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QRhi::FrameOpSuccess;
|
||||
@ -1558,7 +1660,7 @@ QRhi::FrameOpResult QRhiD3D11::finish()
|
||||
} else {
|
||||
Q_ASSERT(contextState.currentSwapChain);
|
||||
Q_ASSERT(contextState.currentSwapChain->cb.recordingPass == QD3D11CommandBuffer::NoPass);
|
||||
executeCommandBuffer(&contextState.currentSwapChain->cb); // no timestampSwapChain, in order to avoid timestamp mess
|
||||
executeCommandBuffer(&contextState.currentSwapChain->cb);
|
||||
contextState.currentSwapChain->cb.resetCommands();
|
||||
}
|
||||
}
|
||||
@ -1933,19 +2035,6 @@ void QRhiD3D11::finishActiveReadbacks()
|
||||
f();
|
||||
}
|
||||
|
||||
static inline QD3D11RenderTargetData *rtData(QRhiRenderTarget *rt)
|
||||
{
|
||||
switch (rt->resourceType()) {
|
||||
case QRhiResource::SwapChainRenderTarget:
|
||||
return &QRHI_RES(QD3D11SwapChainRenderTarget, rt)->d;
|
||||
case QRhiResource::TextureRenderTarget:
|
||||
return &QRHI_RES(QD3D11TextureRenderTarget, rt)->d;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void QRhiD3D11::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
|
||||
{
|
||||
Q_ASSERT(QRHI_RES(QD3D11CommandBuffer, cb)->recordingPass == QD3D11CommandBuffer::NoPass);
|
||||
@ -2651,7 +2740,7 @@ void QRhiD3D11::resetShaderResources()
|
||||
currentShaderMask &= ~StageU##MaskBit; \
|
||||
}
|
||||
|
||||
void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain)
|
||||
void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD)
|
||||
{
|
||||
quint32 stencilRef = 0;
|
||||
float blendConstants[] = { 1, 1, 1, 1 };
|
||||
@ -2664,26 +2753,30 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
|
||||
};
|
||||
int currentShaderMask = 0xFF;
|
||||
|
||||
if (timestampSwapChain) {
|
||||
const int currentFrameSlot = timestampSwapChain->currentFrameSlot;
|
||||
ID3D11Query *tsDisjoint = timestampSwapChain->timestamps.disjointQuery[currentFrameSlot];
|
||||
const int tsIdx = QD3D11SwapChain::BUFFER_COUNT * currentFrameSlot;
|
||||
ID3D11Query *tsStart = timestampSwapChain->timestamps.query[tsIdx];
|
||||
if (tsDisjoint && tsStart && !timestampSwapChain->timestamps.active[currentFrameSlot]) {
|
||||
// The timestamps seem to include vsync time with Present(1), except
|
||||
// when running on a non-primary gpu. This is not ideal. So try working
|
||||
// it around by issuing a semi-fake OMSetRenderTargets early and
|
||||
// writing the first timestamp only afterwards.
|
||||
context->Begin(tsDisjoint);
|
||||
QD3D11RenderTargetData *rtD = rtData(×tampSwapChain->rt);
|
||||
context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv);
|
||||
context->End(tsStart); // just record a timestamp, no Begin needed
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
|
||||
const QD3D11CommandBuffer::Command &cmd(*it);
|
||||
switch (cmd.cmd) {
|
||||
case QD3D11CommandBuffer::Command::BeginFrame:
|
||||
if (cmd.args.beginFrame.tsDisjointQuery)
|
||||
context->Begin(cmd.args.beginFrame.tsDisjointQuery);
|
||||
if (cmd.args.beginFrame.tsQuery) {
|
||||
if (cmd.args.beginFrame.swapchainData) {
|
||||
// The timestamps seem to include vsync time with Present(1), except
|
||||
// when running on a non-primary gpu. This is not ideal. So try working
|
||||
// it around by issuing a semi-fake OMSetRenderTargets early and
|
||||
// writing the first timestamp only afterwards.
|
||||
QD3D11RenderTargetData *rtD = cmd.args.beginFrame.swapchainData;
|
||||
context->OMSetRenderTargets(UINT(rtD->colorAttCount), rtD->colorAttCount ? rtD->rtv : nullptr, rtD->dsv);
|
||||
}
|
||||
context->End(cmd.args.beginFrame.tsQuery); // no Begin() for D3D11_QUERY_TIMESTAMP
|
||||
}
|
||||
break;
|
||||
case QD3D11CommandBuffer::Command::EndFrame:
|
||||
if (cmd.args.endFrame.tsQuery)
|
||||
context->End(cmd.args.endFrame.tsQuery);
|
||||
if (cmd.args.endFrame.tsDisjointQuery)
|
||||
context->End(cmd.args.endFrame.tsDisjointQuery);
|
||||
break;
|
||||
case QD3D11CommandBuffer::Command::ResetShaderResources:
|
||||
resetShaderResources();
|
||||
break;
|
||||
@ -4702,14 +4795,13 @@ void QD3D11CommandBuffer::destroy()
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
bool QD3D11Timestamps::prepare(int pairCount, QRhiD3D11 *rhiD)
|
||||
bool QD3D11SwapChainTimestamps::prepare(QRhiD3D11 *rhiD)
|
||||
{
|
||||
// Creates the query objects if not yet done, but otherwise calling this
|
||||
// function is expected to be a no-op.
|
||||
|
||||
Q_ASSERT(pairCount <= MAX_TIMESTAMP_PAIRS);
|
||||
D3D11_QUERY_DESC queryDesc = {};
|
||||
for (int i = 0; i < pairCount; ++i) {
|
||||
for (int i = 0; i < TIMESTAMP_PAIRS; ++i) {
|
||||
if (!disjointQuery[i]) {
|
||||
queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
|
||||
HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &disjointQuery[i]);
|
||||
@ -4721,7 +4813,7 @@ bool QD3D11Timestamps::prepare(int pairCount, QRhiD3D11 *rhiD)
|
||||
}
|
||||
queryDesc.Query = D3D11_QUERY_TIMESTAMP;
|
||||
for (int j = 0; j < 2; ++j) {
|
||||
const int idx = pairCount * i + j;
|
||||
const int idx = 2 * i + j;
|
||||
if (!query[idx]) {
|
||||
HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &query[idx]);
|
||||
if (FAILED(hr)) {
|
||||
@ -4732,20 +4824,19 @@ bool QD3D11Timestamps::prepare(int pairCount, QRhiD3D11 *rhiD)
|
||||
}
|
||||
}
|
||||
}
|
||||
this->pairCount = pairCount;
|
||||
return true;
|
||||
}
|
||||
|
||||
void QD3D11Timestamps::destroy()
|
||||
void QD3D11SwapChainTimestamps::destroy()
|
||||
{
|
||||
for (int i = 0; i < MAX_TIMESTAMP_PAIRS; ++i) {
|
||||
for (int i = 0; i < TIMESTAMP_PAIRS; ++i) {
|
||||
active[i] = false;
|
||||
if (disjointQuery[i]) {
|
||||
disjointQuery[i]->Release();
|
||||
disjointQuery[i] = nullptr;
|
||||
}
|
||||
for (int j = 0; j < 2; ++j) {
|
||||
const int idx = MAX_TIMESTAMP_PAIRS * i + j;
|
||||
const int idx = TIMESTAMP_PAIRS * i + j;
|
||||
if (query[idx]) {
|
||||
query[idx]->Release();
|
||||
query[idx] = nullptr;
|
||||
@ -4754,26 +4845,21 @@ void QD3D11Timestamps::destroy()
|
||||
}
|
||||
}
|
||||
|
||||
bool QD3D11Timestamps::tryQueryTimestamps(int idx, ID3D11DeviceContext *context, double *elapsedSec)
|
||||
bool QD3D11SwapChainTimestamps::tryQueryTimestamps(int pairIndex, ID3D11DeviceContext *context, double *elapsedSec)
|
||||
{
|
||||
bool result = false;
|
||||
if (!active[idx])
|
||||
if (!active[pairIndex])
|
||||
return result;
|
||||
|
||||
ID3D11Query *tsDisjoint = disjointQuery[idx];
|
||||
const int tsIdx = pairCount * idx;
|
||||
ID3D11Query *tsStart = query[tsIdx];
|
||||
ID3D11Query *tsEnd = query[tsIdx + 1];
|
||||
ID3D11Query *tsDisjoint = disjointQuery[pairIndex];
|
||||
ID3D11Query *tsStart = query[pairIndex * 2];
|
||||
ID3D11Query *tsEnd = query[pairIndex * 2 + 1];
|
||||
quint64 timestamps[2];
|
||||
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
|
||||
|
||||
bool ok = true;
|
||||
ok &= context->GetData(tsDisjoint, &dj, sizeof(dj), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
|
||||
ok &= context->GetData(tsEnd, ×tamps[1], sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
|
||||
// this above is often not ready, not even in frame_where_recorded+2,
|
||||
// not clear why. so make the whole thing async and do not touch the
|
||||
// queries until they are finally all available in frame this+2 or
|
||||
// this+4 or ...
|
||||
ok &= context->GetData(tsStart, ×tamps[0], sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
|
||||
|
||||
if (ok) {
|
||||
@ -4782,16 +4868,14 @@ bool QD3D11Timestamps::tryQueryTimestamps(int idx, ID3D11DeviceContext *context,
|
||||
*elapsedSec = elapsedMs / 1000.0;
|
||||
result = true;
|
||||
}
|
||||
active[idx] = false;
|
||||
} // else leave active set, will retry in a subsequent beginFrame or similar
|
||||
active[pairIndex] = false;
|
||||
} // else leave active set, will retry in a subsequent beginFrame
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QD3D11SwapChain::QD3D11SwapChain(QRhiImplementation *rhi)
|
||||
: QRhiSwapChain(rhi),
|
||||
rt(rhi, this),
|
||||
cb(rhi)
|
||||
: QRhiSwapChain(rhi), rt(rhi, this), rtRight(rhi, this), cb(rhi)
|
||||
{
|
||||
backBufferTex = nullptr;
|
||||
backBufferRtv = nullptr;
|
||||
@ -4812,6 +4896,10 @@ void QD3D11SwapChain::releaseBuffers()
|
||||
backBufferRtv->Release();
|
||||
backBufferRtv = nullptr;
|
||||
}
|
||||
if (backBufferRtvRight) {
|
||||
backBufferRtvRight->Release();
|
||||
backBufferRtvRight = nullptr;
|
||||
}
|
||||
if (backBufferTex) {
|
||||
backBufferTex->Release();
|
||||
backBufferTex = nullptr;
|
||||
@ -4869,50 +4957,17 @@ QRhiRenderTarget *QD3D11SwapChain::currentFrameRenderTarget()
|
||||
return &rt;
|
||||
}
|
||||
|
||||
QRhiRenderTarget *QD3D11SwapChain::currentFrameRenderTarget(StereoTargetBuffer targetBuffer)
|
||||
{
|
||||
return targetBuffer == StereoTargetBuffer::LeftBuffer? &rt: &rtRight;
|
||||
}
|
||||
|
||||
QSize QD3D11SwapChain::surfacePixelSize()
|
||||
{
|
||||
Q_ASSERT(m_window);
|
||||
return m_window->size() * m_window->devicePixelRatio();
|
||||
}
|
||||
|
||||
static bool output6ForWindow(QWindow *w, IDXGIAdapter1 *adapter, IDXGIOutput6 **result)
|
||||
{
|
||||
bool ok = false;
|
||||
QRect wr = w->geometry();
|
||||
wr = QRect(wr.topLeft() * w->devicePixelRatio(), wr.size() * w->devicePixelRatio());
|
||||
const QPoint center = wr.center();
|
||||
IDXGIOutput *currentOutput = nullptr;
|
||||
IDXGIOutput *output = nullptr;
|
||||
for (UINT i = 0; adapter->EnumOutputs(i, &output) != DXGI_ERROR_NOT_FOUND; ++i) {
|
||||
DXGI_OUTPUT_DESC desc;
|
||||
output->GetDesc(&desc);
|
||||
const RECT r = desc.DesktopCoordinates;
|
||||
const QRect dr(QPoint(r.left, r.top), QPoint(r.right - 1, r.bottom - 1));
|
||||
if (dr.contains(center)) {
|
||||
currentOutput = output;
|
||||
break;
|
||||
} else {
|
||||
output->Release();
|
||||
}
|
||||
}
|
||||
if (currentOutput) {
|
||||
ok = SUCCEEDED(currentOutput->QueryInterface(__uuidof(IDXGIOutput6), reinterpret_cast<void **>(result)));
|
||||
currentOutput->Release();
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
static bool outputDesc1ForWindow(QWindow *w, IDXGIAdapter1 *adapter, DXGI_OUTPUT_DESC1 *result)
|
||||
{
|
||||
bool ok = false;
|
||||
IDXGIOutput6 *out6 = nullptr;
|
||||
if (output6ForWindow(w, adapter, &out6)) {
|
||||
ok = SUCCEEDED(out6->GetDesc1(result));
|
||||
out6->Release();
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool QD3D11SwapChain::isFormatSupported(Format f)
|
||||
{
|
||||
if (f == SDR)
|
||||
@ -4925,7 +4980,7 @@ bool QD3D11SwapChain::isFormatSupported(Format f)
|
||||
|
||||
QRHI_RES_RHI(QRhiD3D11);
|
||||
DXGI_OUTPUT_DESC1 desc1;
|
||||
if (outputDesc1ForWindow(m_window, rhiD->activeAdapter, &desc1)) {
|
||||
if (QRhiD3D::outputDesc1ForWindow(m_window, rhiD->activeAdapter, &desc1)) {
|
||||
if (desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020)
|
||||
return f == QRhiSwapChain::HDRExtendedSrgbLinear || f == QRhiSwapChain::HDR10;
|
||||
}
|
||||
@ -4936,14 +4991,16 @@ bool QD3D11SwapChain::isFormatSupported(Format f)
|
||||
QRhiSwapChainHdrInfo QD3D11SwapChain::hdrInfo()
|
||||
{
|
||||
QRhiSwapChainHdrInfo info = QRhiSwapChain::hdrInfo();
|
||||
// Must use m_window, not window, given this may be called before createOrResize().
|
||||
if (m_window) {
|
||||
QRHI_RES_RHI(QRhiD3D11);
|
||||
DXGI_OUTPUT_DESC1 hdrOutputDesc;
|
||||
if (outputDesc1ForWindow(m_window, rhiD->activeAdapter, &hdrOutputDesc)) {
|
||||
info.isHardCodedDefaults = false;
|
||||
if (QRhiD3D::outputDesc1ForWindow(m_window, rhiD->activeAdapter, &hdrOutputDesc)) {
|
||||
info.limitsType = QRhiSwapChainHdrInfo::LuminanceInNits;
|
||||
info.limits.luminanceInNits.minLuminance = hdrOutputDesc.MinLuminance;
|
||||
info.limits.luminanceInNits.maxLuminance = hdrOutputDesc.MaxLuminance;
|
||||
info.luminanceBehavior = QRhiSwapChainHdrInfo::SceneReferred; // 1.0 = 80 nits
|
||||
info.sdrWhiteLevel = QRhiD3D::sdrWhiteLevelInNits(hdrOutputDesc);
|
||||
}
|
||||
}
|
||||
return info;
|
||||
@ -5016,11 +5073,13 @@ bool QD3D11SwapChain::createOrResize()
|
||||
{
|
||||
return createOrResizeWin7();
|
||||
}
|
||||
|
||||
// Can be called multiple times due to window resizes - that is not the
|
||||
// same as a simple destroy+create (as with other resources). Just need to
|
||||
// resize the buffers then.
|
||||
|
||||
const bool needsRegistration = !window || window != m_window;
|
||||
const bool stereo = m_window->format().stereo();
|
||||
|
||||
// except if the window actually changes
|
||||
if (window && window != m_window)
|
||||
@ -5078,7 +5137,7 @@ bool QD3D11SwapChain::createOrResize()
|
||||
|
||||
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) {
|
||||
if (QRhiD3D::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) {
|
||||
@ -5120,6 +5179,7 @@ bool QD3D11SwapChain::createOrResize()
|
||||
desc.Flags = swapChainFlags;
|
||||
desc.Scaling = rhiD->useLegacySwapchainModel ? DXGI_SCALING_STRETCH : DXGI_SCALING_NONE;
|
||||
desc.SwapEffect = rhiD->useLegacySwapchainModel ? DXGI_SWAP_EFFECT_DISCARD : DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||
desc.Stereo = stereo;
|
||||
|
||||
if (dcompVisual) {
|
||||
// With DirectComposition setting AlphaMode to STRAIGHT fails the
|
||||
@ -5238,6 +5298,19 @@ bool QD3D11SwapChain::createOrResize()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stereo) {
|
||||
// Create a second render target view for the right eye
|
||||
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
|
||||
rtvDesc.Texture2DArray.FirstArraySlice = 1;
|
||||
rtvDesc.Texture2DArray.ArraySize = 1;
|
||||
hr = rhiD->dev->CreateRenderTargetView(backBufferTex, &rtvDesc, &backBufferRtvRight);
|
||||
if (FAILED(hr)) {
|
||||
qWarning("Failed to create rtv for swapchain backbuffer (right eye): %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) {
|
||||
@ -5276,8 +5349,20 @@ bool QD3D11SwapChain::createOrResize()
|
||||
rtD->d.colorAttCount = 1;
|
||||
rtD->d.dsAttCount = m_depthStencil ? 1 : 0;
|
||||
|
||||
if (stereo) {
|
||||
rtD = QRHI_RES(QD3D11SwapChainRenderTarget, &rtRight);
|
||||
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;
|
||||
rtD->d.rtv[0] = backBufferRtvRight;
|
||||
rtD->d.dsv = ds ? ds->dsv : nullptr;
|
||||
}
|
||||
|
||||
if (rhiD->rhiFlags.testFlag(QRhi::EnableTimestamps)) {
|
||||
timestamps.prepare(BUFFER_COUNT, rhiD);
|
||||
timestamps.prepare(rhiD);
|
||||
// timestamp queries are optional so we can go on even if they failed
|
||||
}
|
||||
|
||||
|
@ -356,6 +356,8 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
|
||||
|
||||
struct Command {
|
||||
enum Cmd {
|
||||
BeginFrame,
|
||||
EndFrame,
|
||||
ResetShaderResources,
|
||||
SetRenderTarget,
|
||||
Clear,
|
||||
@ -385,6 +387,15 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
|
||||
// QRhi*/QD3D11* references should be kept at minimum (so no
|
||||
// QRhiTexture/Buffer/etc. pointers).
|
||||
union Args {
|
||||
struct {
|
||||
ID3D11Query *tsQuery;
|
||||
ID3D11Query *tsDisjointQuery;
|
||||
QD3D11RenderTargetData *swapchainData;
|
||||
} beginFrame;
|
||||
struct {
|
||||
ID3D11Query *tsQuery;
|
||||
ID3D11Query *tsDisjointQuery;
|
||||
} endFrame;
|
||||
struct {
|
||||
QRhiRenderTarget *rt;
|
||||
} setRenderTarget;
|
||||
@ -556,17 +567,15 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
|
||||
}
|
||||
};
|
||||
|
||||
static const int QD3D11_SWAPCHAIN_BUFFER_COUNT = 2;
|
||||
|
||||
struct QD3D11Timestamps
|
||||
struct QD3D11SwapChainTimestamps
|
||||
{
|
||||
static const int MAX_TIMESTAMP_PAIRS = QD3D11_SWAPCHAIN_BUFFER_COUNT;
|
||||
bool active[MAX_TIMESTAMP_PAIRS] = {};
|
||||
ID3D11Query *disjointQuery[MAX_TIMESTAMP_PAIRS] = {};
|
||||
ID3D11Query *query[MAX_TIMESTAMP_PAIRS * 2] = {};
|
||||
int pairCount = 0;
|
||||
static const int TIMESTAMP_PAIRS = 2;
|
||||
|
||||
bool prepare(int pairCount, QRhiD3D11 *rhiD);
|
||||
bool active[TIMESTAMP_PAIRS] = {};
|
||||
ID3D11Query *disjointQuery[TIMESTAMP_PAIRS] = {};
|
||||
ID3D11Query *query[TIMESTAMP_PAIRS * 2] = {};
|
||||
|
||||
bool prepare(QRhiD3D11 *rhiD);
|
||||
void destroy();
|
||||
bool tryQueryTimestamps(int idx, ID3D11DeviceContext *context, double *elapsedSec);
|
||||
};
|
||||
@ -579,6 +588,7 @@ struct QD3D11SwapChain : public QRhiSwapChain
|
||||
|
||||
QRhiCommandBuffer *currentFrameCommandBuffer() override;
|
||||
QRhiRenderTarget *currentFrameRenderTarget() override;
|
||||
QRhiRenderTarget *currentFrameRenderTarget(StereoTargetBuffer targetBuffer) override;
|
||||
|
||||
QSize surfacePixelSize() override;
|
||||
bool isFormatSupported(Format f) override;
|
||||
@ -587,7 +597,7 @@ struct QD3D11SwapChain : public QRhiSwapChain
|
||||
QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
|
||||
bool createOrResize() override;
|
||||
bool createOrResizeWin7();
|
||||
|
||||
|
||||
void releaseBuffers();
|
||||
bool newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc,
|
||||
ID3D11Texture2D **tex, ID3D11RenderTargetView **rtv) const;
|
||||
@ -595,6 +605,7 @@ struct QD3D11SwapChain : public QRhiSwapChain
|
||||
QWindow *window = nullptr;
|
||||
QSize pixelSize;
|
||||
QD3D11SwapChainRenderTarget rt;
|
||||
QD3D11SwapChainRenderTarget rtRight;
|
||||
QD3D11CommandBuffer cb;
|
||||
DXGI_FORMAT colorFormat;
|
||||
DXGI_FORMAT srgbAdjustedColorFormat;
|
||||
@ -602,7 +613,8 @@ struct QD3D11SwapChain : public QRhiSwapChain
|
||||
UINT swapChainFlags = 0;
|
||||
ID3D11Texture2D *backBufferTex;
|
||||
ID3D11RenderTargetView *backBufferRtv;
|
||||
static const int BUFFER_COUNT = QD3D11_SWAPCHAIN_BUFFER_COUNT;
|
||||
ID3D11RenderTargetView *backBufferRtvRight = nullptr;
|
||||
static const int BUFFER_COUNT = 2;
|
||||
ID3D11Texture2D *msaaTex[BUFFER_COUNT];
|
||||
ID3D11RenderTargetView *msaaRtv[BUFFER_COUNT];
|
||||
DXGI_SAMPLE_DESC sampleDesc;
|
||||
@ -612,7 +624,8 @@ struct QD3D11SwapChain : public QRhiSwapChain
|
||||
UINT swapInterval = 1;
|
||||
IDCompositionTarget *dcompTarget = nullptr;
|
||||
IDCompositionVisual *dcompVisual = nullptr;
|
||||
QD3D11Timestamps timestamps;
|
||||
QD3D11SwapChainTimestamps timestamps;
|
||||
int currentTimestampPairIndex = 0;
|
||||
};
|
||||
|
||||
class QRhiD3D11 : public QRhiImplementation
|
||||
@ -737,7 +750,7 @@ public:
|
||||
const uint *dynOfsPairs, int dynOfsPairCount,
|
||||
bool offsetOnlyChange);
|
||||
void resetShaderResources();
|
||||
void executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain = nullptr);
|
||||
void executeCommandBuffer(QD3D11CommandBuffer *cbD);
|
||||
DXGI_SAMPLE_DESC effectiveSampleDesc(int sampleCount) const;
|
||||
void finishActiveReadbacks();
|
||||
void reportLiveObjects(ID3D11Device *device);
|
||||
@ -780,8 +793,8 @@ public:
|
||||
OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { }
|
||||
bool active = false;
|
||||
QD3D11CommandBuffer cbWrapper;
|
||||
QD3D11Timestamps timestamps;
|
||||
int timestampIdx = 0;
|
||||
ID3D11Query *tsQueries[2] = {};
|
||||
ID3D11Query *tsDisjointQuery = nullptr;
|
||||
} ofr;
|
||||
|
||||
struct TextureReadback {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -359,10 +359,10 @@ namespace {
|
||||
{
|
||||
}
|
||||
|
||||
inline void addKey(const void *key, const QByteArray &fontData)
|
||||
inline void addKey(const QByteArray &fontData)
|
||||
{
|
||||
Q_ASSERT(!m_fontDatas.contains(key));
|
||||
m_fontDatas.insert(key, fontData);
|
||||
if (!m_fontDatas.contains(fontData.data()))
|
||||
m_fontDatas.insert(fontData.data(), fontData);
|
||||
}
|
||||
|
||||
inline void removeKey(const void *key)
|
||||
@ -378,6 +378,11 @@ namespace {
|
||||
UINT32 fontFileReferenceKeySize,
|
||||
OUT IDWriteFontFileStream **fontFileStream) override;
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_fontDatas.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
ULONG m_referenceCount;
|
||||
QHash<const void *, QByteArray> m_fontDatas;
|
||||
@ -435,53 +440,63 @@ namespace {
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
class CustomFontFileLoader
|
||||
{
|
||||
public:
|
||||
CustomFontFileLoader(IDWriteFactory *factory)
|
||||
{
|
||||
m_directWriteFactory = factory;
|
||||
|
||||
if (m_directWriteFactory) {
|
||||
m_directWriteFactory->AddRef();
|
||||
|
||||
m_directWriteFontFileLoader = new DirectWriteFontFileLoader();
|
||||
m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader);
|
||||
}
|
||||
}
|
||||
|
||||
~CustomFontFileLoader()
|
||||
{
|
||||
if (m_directWriteFactory != nullptr && m_directWriteFontFileLoader != nullptr)
|
||||
m_directWriteFactory->UnregisterFontFileLoader(m_directWriteFontFileLoader);
|
||||
|
||||
if (m_directWriteFactory != nullptr)
|
||||
m_directWriteFactory->Release();
|
||||
}
|
||||
|
||||
void addKey(const void *key, const QByteArray &fontData)
|
||||
{
|
||||
if (m_directWriteFontFileLoader != nullptr)
|
||||
m_directWriteFontFileLoader->addKey(key, fontData);
|
||||
}
|
||||
|
||||
void removeKey(const void *key)
|
||||
{
|
||||
if (m_directWriteFontFileLoader != nullptr)
|
||||
m_directWriteFontFileLoader->removeKey(key);
|
||||
}
|
||||
|
||||
IDWriteFontFileLoader *loader() const
|
||||
{
|
||||
return m_directWriteFontFileLoader;
|
||||
}
|
||||
|
||||
private:
|
||||
IDWriteFactory *m_directWriteFactory = nullptr;
|
||||
DirectWriteFontFileLoader *m_directWriteFontFileLoader = nullptr;
|
||||
};
|
||||
} // Anonymous namespace
|
||||
|
||||
class QCustomFontFileLoader
|
||||
{
|
||||
public:
|
||||
QCustomFontFileLoader(IDWriteFactory *factory)
|
||||
{
|
||||
m_directWriteFactory = factory;
|
||||
|
||||
if (m_directWriteFactory) {
|
||||
m_directWriteFactory->AddRef();
|
||||
|
||||
m_directWriteFontFileLoader = new DirectWriteFontFileLoader();
|
||||
m_directWriteFactory->RegisterFontFileLoader(m_directWriteFontFileLoader);
|
||||
}
|
||||
}
|
||||
|
||||
~QCustomFontFileLoader()
|
||||
{
|
||||
clear();
|
||||
|
||||
if (m_directWriteFactory != nullptr && m_directWriteFontFileLoader != nullptr)
|
||||
m_directWriteFactory->UnregisterFontFileLoader(m_directWriteFontFileLoader);
|
||||
|
||||
if (m_directWriteFactory != nullptr)
|
||||
m_directWriteFactory->Release();
|
||||
}
|
||||
|
||||
void addKey(const QByteArray &fontData)
|
||||
{
|
||||
if (m_directWriteFontFileLoader != nullptr)
|
||||
m_directWriteFontFileLoader->addKey(fontData);
|
||||
}
|
||||
|
||||
void removeKey(const void *key)
|
||||
{
|
||||
if (m_directWriteFontFileLoader != nullptr)
|
||||
m_directWriteFontFileLoader->removeKey(key);
|
||||
}
|
||||
|
||||
IDWriteFontFileLoader *loader() const
|
||||
{
|
||||
return m_directWriteFontFileLoader;
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
if (m_directWriteFontFileLoader != nullptr)
|
||||
m_directWriteFontFileLoader->clear();
|
||||
}
|
||||
|
||||
private:
|
||||
IDWriteFactory *m_directWriteFactory = nullptr;
|
||||
DirectWriteFontFileLoader *m_directWriteFontFileLoader = nullptr;
|
||||
};
|
||||
|
||||
|
||||
#endif // directwrite && direct2d
|
||||
|
||||
|
||||
@ -550,8 +565,12 @@ void QWindowsFontDatabaseBase::createDirectWriteFactory(IDWriteFactory **factory
|
||||
IUnknown *result = nullptr;
|
||||
|
||||
# if QT_CONFIG(directwrite3)
|
||||
DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory3), &result);
|
||||
DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory5), &result);
|
||||
|
||||
if (result == nullptr)
|
||||
DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory3), &result);
|
||||
# endif
|
||||
|
||||
if (result == nullptr)
|
||||
DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory2), &result);
|
||||
|
||||
@ -700,28 +719,47 @@ QFont QWindowsFontDatabaseBase::systemDefaultFont()
|
||||
return systemFont;
|
||||
}
|
||||
|
||||
#if QT_CONFIG(directwrite) && QT_CONFIG(direct2d)
|
||||
IDWriteFontFace *QWindowsFontDatabaseBase::createDirectWriteFace(const QByteArray &fontData) const
|
||||
void QWindowsFontDatabaseBase::invalidate()
|
||||
{
|
||||
#if QT_CONFIG(directwrite)
|
||||
m_fontFileLoader.reset(nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if QT_CONFIG(directwrite) && QT_CONFIG(direct2d)
|
||||
IDWriteFontFace *QWindowsFontDatabaseBase::createDirectWriteFace(const QByteArray &fontData)
|
||||
{
|
||||
QList<IDWriteFontFace *> faces = createDirectWriteFaces(fontData, false);
|
||||
Q_ASSERT(faces.size() <= 1);
|
||||
|
||||
return faces.isEmpty() ? nullptr : faces.first();
|
||||
}
|
||||
|
||||
QList<IDWriteFontFace *> QWindowsFontDatabaseBase::createDirectWriteFaces(const QByteArray &fontData,
|
||||
bool queryVariations) const
|
||||
{
|
||||
QList<IDWriteFontFace *> ret;
|
||||
QSharedPointer<QWindowsFontEngineData> fontEngineData = data();
|
||||
if (fontEngineData->directWriteFactory == nullptr) {
|
||||
qCWarning(lcQpaFonts) << "DirectWrite factory not created in QWindowsFontDatabaseBase::createDirectWriteFace()";
|
||||
return nullptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
CustomFontFileLoader fontFileLoader(fontEngineData->directWriteFactory);
|
||||
fontFileLoader.addKey(this, fontData);
|
||||
if (m_fontFileLoader == nullptr)
|
||||
m_fontFileLoader.reset(new QCustomFontFileLoader(fontEngineData->directWriteFactory));
|
||||
|
||||
m_fontFileLoader->addKey(fontData);
|
||||
|
||||
IDWriteFontFile *fontFile = nullptr;
|
||||
const void *key = this;
|
||||
const void *key = fontData.data();
|
||||
|
||||
HRESULT hres = fontEngineData->directWriteFactory->CreateCustomFontFileReference(&key,
|
||||
sizeof(void *),
|
||||
fontFileLoader.loader(),
|
||||
m_fontFileLoader->loader(),
|
||||
&fontFile);
|
||||
if (FAILED(hres)) {
|
||||
qErrnoWarning(hres, "%s: CreateCustomFontFileReference failed", __FUNCTION__);
|
||||
return nullptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
BOOL isSupportedFontType;
|
||||
@ -731,25 +769,65 @@ IDWriteFontFace *QWindowsFontDatabaseBase::createDirectWriteFace(const QByteArra
|
||||
fontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, &numberOfFaces);
|
||||
if (!isSupportedFontType) {
|
||||
fontFile->Release();
|
||||
return nullptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if QT_CONFIG(directwrite3)
|
||||
IDWriteFactory5 *factory5 = nullptr;
|
||||
if (queryVariations && SUCCEEDED(fontEngineData->directWriteFactory->QueryInterface(__uuidof(IDWriteFactory5),
|
||||
reinterpret_cast<void **>(&factory5)))) {
|
||||
|
||||
IDWriteFontSetBuilder1 *builder;
|
||||
if (SUCCEEDED(factory5->CreateFontSetBuilder(&builder))) {
|
||||
if (SUCCEEDED(builder->AddFontFile(fontFile))) {
|
||||
IDWriteFontSet *fontSet;
|
||||
if (SUCCEEDED(builder->CreateFontSet(&fontSet))) {
|
||||
int count = fontSet->GetFontCount();
|
||||
qCDebug(lcQpaFonts) << "Found" << count << "variations in font file";
|
||||
for (int i = 0; i < count; ++i) {
|
||||
IDWriteFontFaceReference *ref;
|
||||
if (SUCCEEDED(fontSet->GetFontFaceReference(i, &ref))) {
|
||||
IDWriteFontFace3 *face;
|
||||
if (SUCCEEDED(ref->CreateFontFace(&face))) {
|
||||
ret.append(face);
|
||||
}
|
||||
ref->Release();
|
||||
}
|
||||
}
|
||||
fontSet->Release();
|
||||
}
|
||||
}
|
||||
|
||||
builder->Release();
|
||||
}
|
||||
|
||||
factory5->Release();
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(queryVariations);
|
||||
#endif
|
||||
|
||||
// ### Currently no support for .ttc, but we could easily return a list here.
|
||||
IDWriteFontFace *directWriteFontFace = nullptr;
|
||||
hres = fontEngineData->directWriteFactory->CreateFontFace(fontFaceType,
|
||||
1,
|
||||
&fontFile,
|
||||
0,
|
||||
DWRITE_FONT_SIMULATIONS_NONE,
|
||||
&directWriteFontFace);
|
||||
if (FAILED(hres)) {
|
||||
qErrnoWarning(hres, "%s: CreateFontFace failed", __FUNCTION__);
|
||||
fontFile->Release();
|
||||
return nullptr;
|
||||
if (ret.isEmpty()) {
|
||||
IDWriteFontFace *directWriteFontFace = nullptr;
|
||||
hres = fontEngineData->directWriteFactory->CreateFontFace(fontFaceType,
|
||||
1,
|
||||
&fontFile,
|
||||
0,
|
||||
DWRITE_FONT_SIMULATIONS_NONE,
|
||||
&directWriteFontFace);
|
||||
if (FAILED(hres)) {
|
||||
qErrnoWarning(hres, "%s: CreateFontFace failed", __FUNCTION__);
|
||||
fontFile->Release();
|
||||
return ret;
|
||||
} else {
|
||||
ret.append(directWriteFontFace);
|
||||
}
|
||||
}
|
||||
|
||||
fontFile->Release();
|
||||
return directWriteFontFace;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif // directwrite && direct2d
|
||||
|
||||
@ -769,7 +847,10 @@ QFontEngine *QWindowsFontDatabaseBase::fontEngine(const QByteArray &fontData, qr
|
||||
if (fontEngineData->directWriteFactory == nullptr)
|
||||
return nullptr;
|
||||
|
||||
IDWriteFontFace *directWriteFontFace = createDirectWriteFace(fontData);
|
||||
IDWriteFontFace * directWriteFontFace = createDirectWriteFace(fontData);
|
||||
if (directWriteFontFace == nullptr)
|
||||
return nullptr;
|
||||
|
||||
fontEngine = new QWindowsFontEngineDirectWrite(directWriteFontFace,
|
||||
pixelSize,
|
||||
fontEngineData);
|
||||
|
@ -46,10 +46,13 @@
|
||||
#include <QtCore/quuid.h>
|
||||
#include <QtCore/private/qsystemlibrary_p.h>
|
||||
#include <QtCore/private/qwinregistry_p.h>
|
||||
#include <QtCore/private/qfactorycacheregistration_p.h>
|
||||
#if QT_CONFIG(cpp_winrt)
|
||||
# include <QtCore/private/qfactorycacheregistration_p.h>
|
||||
#endif
|
||||
#include <QtCore/private/qsystemerror_p.h>
|
||||
|
||||
#include <QtGui/private/qwindowsguieventdispatcher_p.h>
|
||||
#include <QtGui/private/qwindowsthemecache_p.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@ -58,6 +61,8 @@
|
||||
#include <wtsapi32.h>
|
||||
#include <shellscalingapi.h>
|
||||
|
||||
#include "vxkex.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
@ -276,6 +281,8 @@ QWindowsContext::~QWindowsContext()
|
||||
if (d->m_powerDummyWindow)
|
||||
DestroyWindow(d->m_powerDummyWindow);
|
||||
|
||||
d->m_screenManager.destroyWindow();
|
||||
|
||||
unregisterWindowClasses();
|
||||
if (d->m_oleInitializeResult == S_OK || d->m_oleInitializeResult == S_FALSE) {
|
||||
#ifdef QT_USE_FACTORY_CACHE_REGISTRATION
|
||||
@ -445,11 +452,25 @@ void QWindowsContext::setDetectAltGrModifier(bool a)
|
||||
return QtWindows::DpiAwareness::System;
|
||||
if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE))
|
||||
return QtWindows::DpiAwareness::Unaware;
|
||||
|
||||
return QtWindows::DpiAwareness::Invalid;
|
||||
}
|
||||
else
|
||||
{
|
||||
// IsValidDpiAwarenessContext() will handle the NULL pointer case.
|
||||
if (!vxkex::IsValidDpiAwarenessContext(context))
|
||||
return QtWindows::DpiAwareness::Invalid;
|
||||
if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED))
|
||||
return QtWindows::DpiAwareness::Unaware_GdiScaled;
|
||||
if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
|
||||
return QtWindows::DpiAwareness::PerMonitorVersion2;
|
||||
if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE))
|
||||
return QtWindows::DpiAwareness::PerMonitor;
|
||||
if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))
|
||||
return QtWindows::DpiAwareness::System;
|
||||
if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE))
|
||||
return QtWindows::DpiAwareness::Unaware;
|
||||
}
|
||||
|
||||
return QtWindows::DpiAwareness::Unaware; // Windows 7
|
||||
return QtWindows::DpiAwareness::Invalid;
|
||||
}
|
||||
|
||||
QtWindows::DpiAwareness QWindowsContext::windowDpiAwareness(HWND hwnd)
|
||||
@ -457,31 +478,26 @@ QtWindows::DpiAwareness QWindowsContext::windowDpiAwareness(HWND hwnd)
|
||||
if (!hwnd)
|
||||
return QtWindows::DpiAwareness::Invalid;
|
||||
|
||||
if (QWindowsContext::user32dll.getWindowDpiAwarenessContext)
|
||||
{
|
||||
const auto context = QWindowsContext::user32dll.getWindowDpiAwarenessContext(hwnd);
|
||||
return dpiAwarenessContextToQtDpiAwareness(context);
|
||||
}
|
||||
const auto context = QWindowsContext::user32dll.getWindowDpiAwarenessContext ?
|
||||
QWindowsContext::user32dll.getWindowDpiAwarenessContext(hwnd) :
|
||||
vxkex::GetWindowDpiAwarenessContext(hwnd);
|
||||
|
||||
return dpiAwarenessContextToQtDpiAwareness(DPI_AWARENESS_CONTEXT_UNAWARE);
|
||||
return dpiAwarenessContextToQtDpiAwareness(context);
|
||||
}
|
||||
|
||||
QtWindows::DpiAwareness QWindowsContext::processDpiAwareness()
|
||||
{
|
||||
if (QWindowsContext::user32dll.getThreadDpiAwarenessContext)
|
||||
{
|
||||
// Although we have GetDpiAwarenessContextForProcess(), however,
|
||||
// it's only available on Win10 1903+, which is a little higher
|
||||
// than Qt's minimum supported version (1809), so we can't use it.
|
||||
// Luckily, MS docs said GetThreadDpiAwarenessContext() will also
|
||||
// return the default DPI_AWARENESS_CONTEXT for the process if
|
||||
// SetThreadDpiAwarenessContext() was never called. So we can use
|
||||
// it as an equivalent.
|
||||
const auto context = QWindowsContext::user32dll.getThreadDpiAwarenessContext();
|
||||
return dpiAwarenessContextToQtDpiAwareness(context);
|
||||
}
|
||||
|
||||
return dpiAwarenessContextToQtDpiAwareness(DPI_AWARENESS_CONTEXT_UNAWARE);
|
||||
// Although we have GetDpiAwarenessContextForProcess(), however,
|
||||
// it's only available on Win10 1903+, which is a little higher
|
||||
// than Qt's minimum supported version (1809), so we can't use it.
|
||||
// Luckily, MS docs said GetThreadDpiAwarenessContext() will also
|
||||
// return the default DPI_AWARENESS_CONTEXT for the process if
|
||||
// SetThreadDpiAwarenessContext() was never called. So we can use
|
||||
// it as an equivalent.
|
||||
const DPI_AWARENESS_CONTEXT context = QWindowsContext::user32dll.getThreadDpiAwarenessContext ?
|
||||
QWindowsContext::user32dll.getThreadDpiAwarenessContext() :
|
||||
vxkex::GetThreadDpiAwarenessContext();
|
||||
return dpiAwarenessContextToQtDpiAwareness(context);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline DPI_AWARENESS_CONTEXT
|
||||
@ -541,28 +557,32 @@ bool QWindowsContext::setProcessDpiAwareness(QtWindows::DpiAwareness dpiAwarenes
|
||||
return true;
|
||||
const auto context = qtDpiAwarenessToDpiAwarenessContext(dpiAwareness);
|
||||
|
||||
if (QWindowsContext::user32dll.isValidDpiAwarenessContext && QWindowsContext::user32dll.setProcessDpiAwarenessContext)
|
||||
{
|
||||
if (!QWindowsContext::user32dll.isValidDpiAwarenessContext(context)) {
|
||||
qCWarning(lcQpaWindow) << dpiAwareness << "is not supported by current system.";
|
||||
return false;
|
||||
}
|
||||
if (!QWindowsContext::user32dll.setProcessDpiAwarenessContext(context)) {
|
||||
qCWarning(lcQpaWindow).noquote().nospace()
|
||||
<< "SetProcessDpiAwarenessContext() failed: "
|
||||
<< QSystemError::windowsString()
|
||||
<< "\nQt's default DPI awareness context is "
|
||||
<< "DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2. If you know what you "
|
||||
<< "are doing, you can overwrite this default using qt.conf "
|
||||
<< "(https://doc.qt.io/qt-6/highdpi.html#configuring-windows).";
|
||||
return false;
|
||||
}
|
||||
QWindowsContextPrivate::m_v2DpiAware
|
||||
= processDpiAwareness() == QtWindows::DpiAwareness::PerMonitorVersion2;
|
||||
return true;
|
||||
BOOL bResultIsValid = QWindowsContext::user32dll.isValidDpiAwarenessContext ?
|
||||
QWindowsContext::user32dll.isValidDpiAwarenessContext(context) :
|
||||
vxkex::IsValidDpiAwarenessContext(context);
|
||||
|
||||
if (!bResultIsValid) {
|
||||
qCWarning(lcQpaWindow) << dpiAwareness << "is not supported by current system.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return false; // Windows 7
|
||||
BOOL bResultSet = QWindowsContext::user32dll.setProcessDpiAwarenessContext ?
|
||||
QWindowsContext::user32dll.setProcessDpiAwarenessContext(context) :
|
||||
vxkex::SetProcessDpiAwarenessContext(context);
|
||||
|
||||
if (!bResultSet) {
|
||||
qCWarning(lcQpaWindow).noquote().nospace()
|
||||
<< "SetProcessDpiAwarenessContext() failed: "
|
||||
<< QSystemError::windowsString()
|
||||
<< "\nQt's default DPI awareness context is "
|
||||
<< "DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2. If you know what you "
|
||||
<< "are doing, you can overwrite this default using qt.conf "
|
||||
<< "(https://doc.qt.io/qt-6/highdpi.html#configuring-windows).";
|
||||
return false;
|
||||
}
|
||||
QWindowsContextPrivate::m_v2DpiAware
|
||||
= processDpiAwareness() == QtWindows::DpiAwareness::PerMonitorVersion2;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QWindowsContext::isDarkMode()
|
||||
@ -585,9 +605,9 @@ bool QWindowsContext::useRTLExtensions() const
|
||||
return d->m_keyMapper.useRTLExtensions();
|
||||
}
|
||||
|
||||
QList<int> QWindowsContext::possibleKeys(const QKeyEvent *e) const
|
||||
QPlatformKeyMapper *QWindowsContext::keyMapper() const
|
||||
{
|
||||
return d->m_keyMapper.possibleKeys(e);
|
||||
return &d->m_keyMapper;
|
||||
}
|
||||
|
||||
QWindowsContext::HandleBaseWindowHash &QWindowsContext::windows()
|
||||
@ -994,7 +1014,7 @@ bool QWindowsContext::systemParametersInfo(unsigned action, unsigned param, void
|
||||
{
|
||||
const BOOL result = (QWindowsContext::user32dll.systemParametersInfoForDpi != nullptr && dpi != 0)
|
||||
? QWindowsContext::user32dll.systemParametersInfoForDpi(action, param, out, 0, dpi)
|
||||
: SystemParametersInfo(action, param, out, 0);
|
||||
: vxkex::SystemParametersInfoForDpi(action, param, out, 0, dpi);
|
||||
return result == TRUE;
|
||||
}
|
||||
|
||||
@ -1080,8 +1100,11 @@ static inline bool isInputMessage(UINT m)
|
||||
static bool enableNonClientDpiScaling(HWND hwnd)
|
||||
{
|
||||
bool result = false;
|
||||
if (QWindowsContext::user32dll.enableNonClientDpiScaling && QWindowsContext::windowDpiAwareness(hwnd) == QtWindows::DpiAwareness::PerMonitor) {
|
||||
result = QWindowsContext::user32dll.enableNonClientDpiScaling(hwnd) != FALSE;
|
||||
if (QWindowsContext::windowDpiAwareness(hwnd) == QtWindows::DpiAwareness::PerMonitor) {
|
||||
result = QWindowsContext::user32dll.enableNonClientDpiScaling ?
|
||||
(QWindowsContext::user32dll.enableNonClientDpiScaling(hwnd) != FALSE) :
|
||||
(vxkex::EnableNonClientDpiScaling(hwnd) != FALSE);
|
||||
|
||||
if (!result) {
|
||||
const DWORD errorCode = GetLastError();
|
||||
qErrnoWarning(int(errorCode), "EnableNonClientDpiScaling() failed for HWND %p (%lu)",
|
||||
@ -1267,7 +1290,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();
|
||||
@ -1379,6 +1402,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());
|
||||
@ -1517,7 +1541,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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1547,7 +1571,7 @@ bool QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg)
|
||||
}
|
||||
|
||||
QWindowSystemInterface::handleContextMenuEvent(window, mouseTriggered, pos, globalPos,
|
||||
QWindowsKeyMapper::queryKeyboardModifiers());
|
||||
keyMapper()->queryKeyboardModifiers());
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@ -1568,7 +1592,7 @@ void QWindowsContext::handleExitSizeMove(QWindow *window)
|
||||
const Qt::MouseButtons appButtons = QGuiApplication::mouseButtons();
|
||||
if (currentButtons == appButtons)
|
||||
return;
|
||||
const Qt::KeyboardModifiers keyboardModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
|
||||
const Qt::KeyboardModifiers keyboardModifiers = keyMapper()->queryKeyboardModifiers();
|
||||
const QPoint globalPos = QWindowsCursor::mousePosition();
|
||||
const QPlatformWindow *platWin = window->handle();
|
||||
const QPoint localPos = platWin->mapFromGlobal(globalPos);
|
||||
|
@ -34,6 +34,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen)
|
||||
class QWindow;
|
||||
class QPlatformScreen;
|
||||
class QPlatformWindow;
|
||||
class QPlatformKeyMapper;
|
||||
class QWindowsMenuBar;
|
||||
class QWindowsScreenManager;
|
||||
class QWindowsTabletSupport;
|
||||
@ -217,7 +218,7 @@ public:
|
||||
unsigned systemInfo() const;
|
||||
|
||||
bool useRTLExtensions() const;
|
||||
QList<int> possibleKeys(const QKeyEvent *e) const;
|
||||
QPlatformKeyMapper *keyMapper() const;
|
||||
|
||||
HandleBaseWindowHash &windows();
|
||||
|
||||
|
@ -28,9 +28,13 @@
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <QtCore/qbuffer.h>
|
||||
#include <QtCore/qpoint.h>
|
||||
#include <QtCore/qpointer.h>
|
||||
#include <QtCore/private/qcomobject_p.h>
|
||||
|
||||
#include <shlobj.h>
|
||||
|
||||
#include "vxkex.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
@ -167,7 +171,7 @@ static Qt::MouseButtons lastButtons = Qt::NoButton;
|
||||
\internal
|
||||
*/
|
||||
|
||||
class QWindowsOleDropSource : public QWindowsComBase<IDropSource>
|
||||
class QWindowsOleDropSource : public QComObject<IDropSource>
|
||||
{
|
||||
public:
|
||||
enum Mode {
|
||||
@ -526,7 +530,8 @@ QWindowsOleDropTarget::DragLeave()
|
||||
|
||||
qCDebug(lcQpaMime) << __FUNCTION__ << ' ' << m_window;
|
||||
|
||||
lastModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
|
||||
const auto *keyMapper = QWindowsContext::instance()->keyMapper();
|
||||
lastModifiers = keyMapper->queryKeyboardModifiers();
|
||||
lastButtons = QWindowsMouseHandler::queryMouseButtons();
|
||||
|
||||
QWindowSystemInterface::handleDrag(m_window, nullptr, QPoint(), Qt::IgnoreAction,
|
||||
@ -611,7 +616,6 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState,
|
||||
*/
|
||||
|
||||
bool QWindowsDrag::m_canceled = false;
|
||||
bool QWindowsDrag::m_dragging = false;
|
||||
|
||||
QWindowsDrag::QWindowsDrag() = default;
|
||||
|
||||
@ -671,7 +675,11 @@ static HRESULT startDoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource,
|
||||
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
|
||||
|
||||
POINTER_INFO pointerInfo{};
|
||||
if (!QWindowsContext::user32dll.getPointerInfo || !QWindowsContext::user32dll.getPointerInfo(pointerId, &pointerInfo))
|
||||
BOOL bResultPointerInfo = QWindowsContext::user32dll.getPointerInfo ?
|
||||
QWindowsContext::user32dll.getPointerInfo(pointerId, &pointerInfo) :
|
||||
vxkex::GetPointerInfo(pointerId, &pointerInfo);
|
||||
|
||||
if (!bResultPointerInfo)
|
||||
return E_FAIL;
|
||||
|
||||
if (pointerInfo.pointerFlags & POINTER_FLAG_PRIMARY) {
|
||||
@ -739,10 +747,7 @@ Qt::DropAction QWindowsDrag::drag(QDrag *drag)
|
||||
const DWORD allowedEffects = translateToWinDragEffects(possibleActions);
|
||||
qCDebug(lcQpaMime) << '>' << __FUNCTION__ << "possible Actions=0x"
|
||||
<< Qt::hex << int(possibleActions) << "effects=0x" << allowedEffects << Qt::dec;
|
||||
// Indicate message handlers we are in DoDragDrop() event loop.
|
||||
QWindowsDrag::m_dragging = true;
|
||||
const HRESULT r = startDoDragDrop(dropDataObject, windowDropSource, allowedEffects, &resultEffect);
|
||||
QWindowsDrag::m_dragging = false;
|
||||
const DWORD reportedPerformedEffect = dropDataObject->reportedPerformedEffect();
|
||||
if (r == DRAGDROP_S_DROP) {
|
||||
if (reportedPerformedEffect == DROPEFFECT_MOVE && resultEffect != DROPEFFECT_MOVE) {
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include <QtCore/private/qdebug_p.h>
|
||||
#include <QtCore/private/qtools_p.h>
|
||||
|
||||
#include "vxkex.h"
|
||||
|
||||
#if defined(WM_APPCOMMAND)
|
||||
# ifndef FAPPCOMMAND_MOUSE
|
||||
# define FAPPCOMMAND_MOUSE 0x8000
|
||||
@ -88,9 +90,17 @@ QWindowsKeyMapper::~QWindowsKeyMapper()= default;
|
||||
#define VK_OEM_3 0xC0
|
||||
#endif
|
||||
|
||||
// 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 };
|
||||
// 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;
|
||||
}
|
||||
|
||||
// Key recorder ------------------------------------------------------------------------[ start ] --
|
||||
struct KeyRecord {
|
||||
@ -532,33 +542,6 @@ 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
|
||||
|
||||
/**
|
||||
@ -656,7 +639,7 @@ void QWindowsKeyMapper::updateKeyMap(const MSG &msg)
|
||||
{
|
||||
unsigned char kbdBuffer[256]; // Will hold the complete keyboard state
|
||||
GetKeyboardState(kbdBuffer);
|
||||
const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask;
|
||||
const quint32 scancode = getScancode(msg);
|
||||
updatePossibleKeyCodes(kbdBuffer, scancode, quint32(msg.wParam));
|
||||
}
|
||||
|
||||
@ -751,28 +734,18 @@ static inline QString messageKeyText(const MSG &msg)
|
||||
|
||||
[[nodiscard]] static inline int getTitleBarHeight(const HWND hwnd)
|
||||
{
|
||||
if (QWindowsContext::user32dll.getDpiForWindow && QWindowsContext::user32dll.getSystemMetricsForDpi)
|
||||
{
|
||||
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
|
||||
const int captionHeight = QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYCAPTION, dpi);
|
||||
if (IsZoomed(hwnd))
|
||||
return captionHeight;
|
||||
// The frame height should also be taken into account if the window
|
||||
// is not maximized.
|
||||
const int frameHeight = QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYSIZEFRAME, dpi)
|
||||
+ QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
||||
return captionHeight + frameHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int captionHeight = GetSystemMetrics(SM_CYCAPTION);
|
||||
if (IsZoomed(hwnd))
|
||||
return captionHeight;
|
||||
// The frame height should also be taken into account if the window
|
||||
// is not maximized.
|
||||
const int frameHeight = GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
|
||||
return captionHeight + frameHeight;
|
||||
}
|
||||
const BOOL bNewAPI = (QWindowsContext::user32dll.getSystemMetricsForDpi != nullptr);
|
||||
const UINT dpi = bNewAPI ? QWindowsContext::user32dll.getDpiForWindow(hwnd) : vxkex::GetDpiForWindow(hwnd);
|
||||
const int captionHeight = bNewAPI ? QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYCAPTION, dpi) : vxkex::GetSystemMetricsForDpi(SM_CYCAPTION, dpi);
|
||||
if (IsZoomed(hwnd))
|
||||
return captionHeight;
|
||||
// The frame height should also be taken into account if the window
|
||||
// is not maximized.
|
||||
const int frameHeight = bNewAPI ?
|
||||
(QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYSIZEFRAME, dpi) + QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi))
|
||||
: (vxkex::GetSystemMetricsForDpi(SM_CYSIZEFRAME, dpi) + vxkex::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi));
|
||||
|
||||
return captionHeight + frameHeight;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool isSystemMenuOffsetNeeded(const Qt::WindowFlags flags)
|
||||
@ -955,7 +928,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
|
||||
m_seenAltGr = true;
|
||||
const UINT msgType = msg.message;
|
||||
|
||||
const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask;
|
||||
const quint32 scancode = getScancode(msg);
|
||||
auto vk_key = quint32(msg.wParam);
|
||||
quint32 nModifiers = 0;
|
||||
|
||||
@ -1352,7 +1325,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
|
||||
return result;
|
||||
}
|
||||
|
||||
Qt::KeyboardModifiers QWindowsKeyMapper::queryKeyboardModifiers()
|
||||
Qt::KeyboardModifiers QWindowsKeyMapper::queryKeyboardModifiers() const
|
||||
{
|
||||
Qt::KeyboardModifiers modifiers = Qt::NoModifier;
|
||||
if (GetKeyState(VK_SHIFT) < 0)
|
||||
@ -1366,9 +1339,9 @@ Qt::KeyboardModifiers QWindowsKeyMapper::queryKeyboardModifiers()
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const
|
||||
QList<QKeyCombination> QWindowsKeyMapper::possibleKeyCombinations(const QKeyEvent *e) const
|
||||
{
|
||||
QList<int> result;
|
||||
QList<QKeyCombination> result;
|
||||
|
||||
|
||||
const quint32 nativeVirtualKey = e->nativeVirtualKey();
|
||||
@ -1382,31 +1355,34 @@ QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const
|
||||
quint32 baseKey = kbItem.qtKey[0];
|
||||
Qt::KeyboardModifiers keyMods = e->modifiers();
|
||||
if (baseKey == Qt::Key_Return && (e->nativeModifiers() & ExtendedKey)) {
|
||||
result << (Qt::Key_Enter | keyMods).toCombined();
|
||||
result << (Qt::Key_Enter | keyMods);
|
||||
return result;
|
||||
}
|
||||
result << int(baseKey) + int(keyMods); // The base key is _always_ valid, of course
|
||||
|
||||
// The base key is _always_ valid, of course
|
||||
result << QKeyCombination::fromCombined(int(baseKey) + int(keyMods));
|
||||
|
||||
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 int matchedKey = int(key) + int(missingMods);
|
||||
const auto it =
|
||||
std::find_if(result.begin(), result.end(),
|
||||
[key] (int k) { return (k & ~Qt::KeyboardModifierMask) == key; });
|
||||
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;
|
||||
});
|
||||
// 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 > Qt::KeyboardModifiers(*it & Qt::KeyboardModifierMask))
|
||||
else if (missingMods > it->keyboardModifiers())
|
||||
*it = matchedKey;
|
||||
}
|
||||
}
|
||||
qCDebug(lcQpaEvents) << __FUNCTION__ << e << "nativeVirtualKey="
|
||||
<< Qt::showbase << Qt::hex << e->nativeVirtualKey() << Qt::dec << Qt::noshowbase
|
||||
<< e->modifiers() << kbItem << "\n returns" << formatKeys(result);
|
||||
<< e->modifiers() << kbItem << "\n returns" << result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,8 @@
|
||||
|
||||
#include <windowsx.h>
|
||||
|
||||
#include "vxkex.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
enum {
|
||||
@ -48,7 +50,11 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
||||
*result = 0;
|
||||
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
|
||||
|
||||
if (!QWindowsContext::user32dll.getPointerType(pointerId, &m_pointerType)) {
|
||||
BOOL bResultPt = QWindowsContext::user32dll.getPointerType ?
|
||||
QWindowsContext::user32dll.getPointerType(pointerId, &m_pointerType) :
|
||||
vxkex::GetPointerType(pointerId, &m_pointerType);
|
||||
|
||||
if (!bResultPt) {
|
||||
qWarning() << "GetPointerType() failed:" << qt_error_string();
|
||||
return false;
|
||||
}
|
||||
@ -62,12 +68,21 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
||||
}
|
||||
case QT_PT_TOUCH: {
|
||||
quint32 pointerCount = 0;
|
||||
if (!QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, nullptr)) {
|
||||
BOOL bResultPointerTouchInfo = QWindowsContext::user32dll.getPointerFrameTouchInfo ?
|
||||
QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, nullptr) :
|
||||
vxkex::GetPointerFrameTouchInfo(pointerId, &pointerCount, nullptr);
|
||||
|
||||
if (!bResultPointerTouchInfo) {
|
||||
qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
|
||||
return false;
|
||||
}
|
||||
QVarLengthArray<POINTER_TOUCH_INFO, 10> touchInfo(pointerCount);
|
||||
if (!QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data())) {
|
||||
|
||||
bResultPointerTouchInfo = QWindowsContext::user32dll.getPointerFrameTouchInfo ?
|
||||
QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data()) :
|
||||
vxkex::GetPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data());
|
||||
|
||||
if (!bResultPointerTouchInfo) {
|
||||
qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
|
||||
return false;
|
||||
}
|
||||
@ -80,10 +95,12 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
||||
// dispatch any skipped frames if event compression is disabled by the app
|
||||
if (historyCount > 1 && !QCoreApplication::testAttribute(Qt::AA_CompressHighFrequencyEvents)) {
|
||||
touchInfo.resize(pointerCount * historyCount);
|
||||
if (!QWindowsContext::user32dll.getPointerFrameTouchInfoHistory(pointerId,
|
||||
&historyCount,
|
||||
&pointerCount,
|
||||
touchInfo.data())) {
|
||||
|
||||
BOOL bResultTouchHistory = QWindowsContext::user32dll.getPointerFrameTouchInfoHistory ?
|
||||
QWindowsContext::user32dll.getPointerFrameTouchInfoHistory(pointerId, &historyCount, &pointerCount, touchInfo.data()) :
|
||||
vxkex::GetPointerFrameTouchInfoHistory(pointerId, &historyCount, &pointerCount, touchInfo.data());
|
||||
|
||||
if (!bResultTouchHistory) {
|
||||
qWarning() << "GetPointerFrameTouchInfoHistory() failed:" << qt_error_string();
|
||||
return false;
|
||||
}
|
||||
@ -101,7 +118,11 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
||||
}
|
||||
case QT_PT_PEN: {
|
||||
POINTER_PEN_INFO penInfo;
|
||||
if (!QWindowsContext::user32dll.getPointerPenInfo(pointerId, &penInfo)) {
|
||||
|
||||
BOOL bResultPenInfo = QWindowsContext::user32dll.getPointerPenInfo ?
|
||||
QWindowsContext::user32dll.getPointerPenInfo(pointerId, &penInfo) : vxkex::GetPointerPenInfo(pointerId, &penInfo);
|
||||
|
||||
if (!bResultPenInfo) {
|
||||
qWarning() << "GetPointerPenInfo() failed:" << qt_error_string();
|
||||
return false;
|
||||
}
|
||||
@ -113,7 +134,11 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
||||
|| !QCoreApplication::testAttribute(Qt::AA_CompressTabletEvents))) {
|
||||
QVarLengthArray<POINTER_PEN_INFO, 10> penInfoHistory(historyCount);
|
||||
|
||||
if (!QWindowsContext::user32dll.getPointerPenInfoHistory(pointerId, &historyCount, penInfoHistory.data())) {
|
||||
BOOL bResultPenInfoHistory = QWindowsContext::user32dll.getPointerPenInfoHistory ?
|
||||
QWindowsContext::user32dll.getPointerPenInfoHistory(pointerId, &historyCount, penInfoHistory.data()) :
|
||||
vxkex::GetPointerPenInfoHistory(pointerId, &historyCount, penInfoHistory.data());
|
||||
|
||||
if (!bResultPenInfoHistory) {
|
||||
qWarning() << "GetPointerPenInfoHistory() failed:" << qt_error_string();
|
||||
return false;
|
||||
}
|
||||
@ -428,8 +453,9 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
|
||||
return false;
|
||||
|
||||
if (msg.message == WM_POINTERCAPTURECHANGED) {
|
||||
const auto *keyMapper = QWindowsContext::instance()->keyMapper();
|
||||
QWindowSystemInterface::handleTouchCancelEvent(window, m_touchDevice.data(),
|
||||
QWindowsKeyMapper::queryKeyboardModifiers());
|
||||
keyMapper->queryKeyboardModifiers());
|
||||
m_lastTouchPoints.clear();
|
||||
return true;
|
||||
}
|
||||
@ -519,7 +545,10 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
|
||||
inputIds.insert(touchPoint.id);
|
||||
|
||||
// Avoid getting repeated messages for this frame if there are multiple pointerIds
|
||||
QWindowsContext::user32dll.skipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
|
||||
if (QWindowsContext::user32dll.skipPointerFrameMessages)
|
||||
QWindowsContext::user32dll.skipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
|
||||
else
|
||||
vxkex::SkipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
|
||||
}
|
||||
|
||||
// Some devices send touches for each finger in a different message/frame, instead of consolidating
|
||||
@ -539,8 +568,9 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
|
||||
if (allStates == QEventPoint::State::Released)
|
||||
m_touchInputIDToTouchPointID.clear();
|
||||
|
||||
const auto *keyMapper = QWindowsContext::instance()->keyMapper();
|
||||
QWindowSystemInterface::handleTouchEvent(window, m_touchDevice.data(), touchPoints,
|
||||
QWindowsKeyMapper::queryKeyboardModifiers());
|
||||
keyMapper->queryKeyboardModifiers());
|
||||
return false; // Allow mouse messages to be generated.
|
||||
}
|
||||
|
||||
@ -565,7 +595,12 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
|
||||
auto *penInfo = static_cast<POINTER_PEN_INFO *>(vPenInfo);
|
||||
|
||||
RECT pRect, dRect;
|
||||
if (!QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect))
|
||||
|
||||
BOOL bResultDeviceRects = QWindowsContext::user32dll.getPointerDeviceRects ?
|
||||
QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect) :
|
||||
vxkex::GetPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect);
|
||||
|
||||
if (!bResultDeviceRects)
|
||||
return false;
|
||||
|
||||
const auto systemId = (qint64)penInfo->pointerInfo.sourceDevice;
|
||||
@ -673,7 +708,8 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
|
||||
wumPlatformWindow->applyCursor();
|
||||
}
|
||||
}
|
||||
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
|
||||
const auto *keyMapper = QWindowsContext::instance()->keyMapper();
|
||||
const Qt::KeyboardModifiers keyModifiers = keyMapper->queryKeyboardModifiers();
|
||||
|
||||
QWindowSystemInterface::handleTabletEvent(target, device.data(),
|
||||
localPos, hiResGlobalPos, mouseButtons,
|
||||
@ -762,7 +798,8 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
|
||||
: QWindowsGeometryHint::mapFromGlobal(targetHwnd, globalPos);
|
||||
}
|
||||
|
||||
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
|
||||
const auto *keyMapper = QWindowsContext::instance()->keyMapper();
|
||||
const Qt::KeyboardModifiers keyModifiers = keyMapper->queryKeyboardModifiers();
|
||||
QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
|
||||
|
||||
if (et == QtWindows::MouseWheelEvent)
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include <setupapi.h>
|
||||
#include <shellscalingapi.h>
|
||||
|
||||
#include "vxkex.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
@ -43,12 +45,18 @@ static inline QDpi deviceDPI(HDC hdc)
|
||||
|
||||
static inline QDpi monitorDPI(HMONITOR hMonitor)
|
||||
{
|
||||
if (QWindowsContext::shcoredll.isValid()) {
|
||||
UINT dpiX;
|
||||
UINT dpiY;
|
||||
if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY)))
|
||||
return QDpi(dpiX, dpiY);
|
||||
}
|
||||
UINT dpiX;
|
||||
UINT dpiY;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (QWindowsContext::shcoredll.isValid())
|
||||
hr = QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
|
||||
else
|
||||
hr = vxkex::GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
return QDpi(dpiX, dpiY);
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
@ -579,51 +587,58 @@ QRect QWindowsScreen::virtualGeometry(const QPlatformScreen *screen) // cf QScre
|
||||
bool QWindowsScreen::setOrientationPreference(Qt::ScreenOrientation o)
|
||||
{
|
||||
bool result = false;
|
||||
if (QWindowsContext::user32dll.setDisplayAutoRotationPreferences) {
|
||||
ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
||||
switch (o) {
|
||||
case Qt::PrimaryOrientation:
|
||||
break;
|
||||
case Qt::PortraitOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_PORTRAIT;
|
||||
break;
|
||||
case Qt::LandscapeOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE;
|
||||
break;
|
||||
case Qt::InvertedPortraitOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED;
|
||||
break;
|
||||
case Qt::InvertedLandscapeOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED;
|
||||
break;
|
||||
}
|
||||
result = QWindowsContext::user32dll.setDisplayAutoRotationPreferences(orientationPreference);
|
||||
ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
||||
switch (o) {
|
||||
case Qt::PrimaryOrientation:
|
||||
break;
|
||||
case Qt::PortraitOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_PORTRAIT;
|
||||
break;
|
||||
case Qt::LandscapeOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE;
|
||||
break;
|
||||
case Qt::InvertedPortraitOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED;
|
||||
break;
|
||||
case Qt::InvertedLandscapeOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED;
|
||||
break;
|
||||
}
|
||||
if (QWindowsContext::user32dll.setDisplayAutoRotationPreferences)
|
||||
result = QWindowsContext::user32dll.setDisplayAutoRotationPreferences(orientationPreference);
|
||||
else
|
||||
result = vxkex::SetDisplayAutoRotationPreferences(orientationPreference);
|
||||
return result;
|
||||
}
|
||||
|
||||
Qt::ScreenOrientation QWindowsScreen::orientationPreference()
|
||||
{
|
||||
Qt::ScreenOrientation result = Qt::PrimaryOrientation;
|
||||
if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences) {
|
||||
DWORD orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
||||
if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences(&orientationPreference)) {
|
||||
switch (orientationPreference) {
|
||||
case ORIENTATION_PREFERENCE_NONE:
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_LANDSCAPE:
|
||||
result = Qt::LandscapeOrientation;
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_PORTRAIT:
|
||||
result = Qt::PortraitOrientation;
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED:
|
||||
result = Qt::InvertedLandscapeOrientation;
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED:
|
||||
result = Qt::InvertedPortraitOrientation;
|
||||
break;
|
||||
}
|
||||
ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
||||
|
||||
BOOL bResult = TRUE;
|
||||
|
||||
if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences)
|
||||
bResult = QWindowsContext::user32dll.getDisplayAutoRotationPreferences((DWORD *)&orientationPreference);
|
||||
else
|
||||
bResult = vxkex::GetDisplayAutoRotationPreferences(&orientationPreference);
|
||||
|
||||
if (bResult) {
|
||||
switch (orientationPreference) {
|
||||
case ORIENTATION_PREFERENCE_NONE:
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_LANDSCAPE:
|
||||
result = Qt::LandscapeOrientation;
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_PORTRAIT:
|
||||
result = Qt::PortraitOrientation;
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED:
|
||||
result = Qt::InvertedLandscapeOrientation;
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED:
|
||||
result = Qt::InvertedPortraitOrientation;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -704,11 +719,15 @@ void QWindowsScreenManager::initialize()
|
||||
handleScreenChanges();
|
||||
}
|
||||
|
||||
QWindowsScreenManager::~QWindowsScreenManager()
|
||||
void QWindowsScreenManager::destroyWindow()
|
||||
{
|
||||
qCDebug(lcQpaScreen) << "Destroying display change observer" << m_displayChangeObserver;
|
||||
DestroyWindow(m_displayChangeObserver);
|
||||
m_displayChangeObserver = nullptr;
|
||||
}
|
||||
|
||||
QWindowsScreenManager::~QWindowsScreenManager() = default;
|
||||
|
||||
bool QWindowsScreenManager::isSingleScreen()
|
||||
{
|
||||
return QWindowsContext::instance()->screenManager().screens().size() < 2;
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "qwindowsmenu.h"
|
||||
#include "qwindowsdialoghelpers.h"
|
||||
#include "qwindowscontext.h"
|
||||
#include "qwindowsiconengine.h"
|
||||
#include "qwindowsintegration.h"
|
||||
#if QT_CONFIG(systemtrayicon)
|
||||
# include "qwindowssystemtrayicon.h"
|
||||
@ -27,6 +28,7 @@
|
||||
#include <QtCore/qthread.h>
|
||||
#include <QtCore/qmutex.h>
|
||||
#include <QtCore/qwaitcondition.h>
|
||||
#include <QtCore/qoperatingsystemversion.h>
|
||||
#include <QtGui/qcolor.h>
|
||||
#include <QtGui/qpalette.h>
|
||||
#include <QtGui/qguiapplication.h>
|
||||
@ -42,7 +44,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <VersionHelpers.h>
|
||||
#include "vxkex.h"
|
||||
|
||||
#if QT_CONFIG(cpp_winrt)
|
||||
# include <QtCore/private/qt_winrtbase_p.h>
|
||||
@ -81,11 +83,11 @@ static inline QColor mixColors(const QColor &c1, const QColor &c2)
|
||||
(c1.blue() + c2.blue()) / 2};
|
||||
}
|
||||
|
||||
static inline QColor getSysColor(int index)
|
||||
{
|
||||
COLORREF cr = GetSysColor(index);
|
||||
return QColor(GetRValue(cr), GetGValue(cr), GetBValue(cr));
|
||||
}
|
||||
enum AccentColorLevel {
|
||||
AccentColorDarkest,
|
||||
AccentColorNormal,
|
||||
AccentColorLightest
|
||||
};
|
||||
|
||||
#if QT_CONFIG(cpp_winrt)
|
||||
static constexpr QColor getSysColor(winrt::Windows::UI::Color &&color)
|
||||
@ -94,6 +96,54 @@ static constexpr QColor getSysColor(winrt::Windows::UI::Color &&color)
|
||||
}
|
||||
#endif
|
||||
|
||||
[[maybe_unused]] [[nodiscard]] static inline QColor qt_accentColor(AccentColorLevel level)
|
||||
{
|
||||
QColor accent;
|
||||
QColor accentLight;
|
||||
QColor accentDarkest;
|
||||
|
||||
#if QT_CONFIG(cpp_winrt)
|
||||
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10)
|
||||
{
|
||||
using namespace winrt::Windows::UI::ViewManagement;
|
||||
const auto settings = UISettings();
|
||||
accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
|
||||
accentLight = getSysColor(settings.GetColorValue(UIColorType::AccentLight1));
|
||||
accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!accent.isValid())
|
||||
{
|
||||
const QWinRegistryKey registry(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\DWM)");
|
||||
if (!registry.isValid())
|
||||
return {};
|
||||
const QVariant value = registry.value(L"AccentColor");
|
||||
if (!value.isValid())
|
||||
return {};
|
||||
// The retrieved value is in the #AABBGGRR format, we need to
|
||||
// convert it to the #AARRGGBB format which Qt expects.
|
||||
const QColor abgr = QColor::fromRgba(qvariant_cast<DWORD>(value));
|
||||
if (!abgr.isValid())
|
||||
return {};
|
||||
accent = QColor::fromRgb(abgr.blue(), abgr.green(), abgr.red(), abgr.alpha());
|
||||
accentLight = accent.lighter(120);
|
||||
accentDarkest = accent.darker(120 * 120 * 120);
|
||||
}
|
||||
|
||||
if (level == AccentColorDarkest)
|
||||
return accentDarkest;
|
||||
else if (level == AccentColorLightest)
|
||||
return accentLight;
|
||||
return accent;
|
||||
}
|
||||
|
||||
static inline QColor getSysColor(int index)
|
||||
{
|
||||
COLORREF cr = GetSysColor(index);
|
||||
return QColor(GetRValue(cr), GetGValue(cr), GetBValue(cr));
|
||||
}
|
||||
|
||||
// QTBUG-48823/Windows 10: SHGetFileInfo() (as called by item views on file system
|
||||
// models has been observed to trigger a WM_PAINT on the mainwindow. Suppress the
|
||||
// behavior by running it in a thread.
|
||||
@ -223,44 +273,17 @@ static QColor placeHolderColor(QColor textColor)
|
||||
return textColor;
|
||||
}
|
||||
|
||||
[[maybe_unused]] [[nodiscard]] static inline QColor qt_accentColor()
|
||||
{
|
||||
const QWinRegistryKey registry(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\DWM)");
|
||||
if (!registry.isValid())
|
||||
return {};
|
||||
const QVariant value = registry.value(L"AccentColor");
|
||||
if (!value.isValid())
|
||||
return {};
|
||||
// The retrieved value is in the #AABBGGRR format, we need to
|
||||
// convert it to the #AARRGGBB format which Qt expects.
|
||||
const QColor abgr = QColor::fromRgba(qvariant_cast<DWORD>(value));
|
||||
if (!abgr.isValid())
|
||||
return {};
|
||||
return QColor::fromRgb(abgr.blue(), abgr.green(), abgr.red(), abgr.alpha());
|
||||
}
|
||||
|
||||
/*
|
||||
This is used when the theme is light mode, and when the theme is dark but the
|
||||
application doesn't support dark mode. In the latter case, we need to check.
|
||||
*/
|
||||
static void populateLightSystemBasePalette(QPalette &result)
|
||||
{
|
||||
QColor background = getSysColor(COLOR_BTNFACE);
|
||||
QColor textColor = getSysColor(COLOR_WINDOWTEXT);
|
||||
QColor accent = qt_accentColor();
|
||||
QColor accentDarkest = accent.darker(120 * 120 * 120);
|
||||
const QColor background = getSysColor(COLOR_BTNFACE);
|
||||
const QColor textColor = getSysColor(COLOR_WINDOWTEXT);
|
||||
|
||||
#if QT_CONFIG(cpp_winrt)
|
||||
if (IsWindows10OrGreater())
|
||||
{
|
||||
// respect the Windows 11 accent color
|
||||
using namespace winrt::Windows::UI::ViewManagement;
|
||||
const auto settings = UISettings();
|
||||
|
||||
accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
|
||||
accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
|
||||
}
|
||||
#endif
|
||||
const QColor accent = qt_accentColor(AccentColorNormal);
|
||||
const QColor accentDarkest = qt_accentColor(AccentColorDarkest);
|
||||
|
||||
const QColor linkColor = accent;
|
||||
const QColor btnFace = background;
|
||||
@ -298,7 +321,7 @@ static void populateDarkSystemBasePalette(QPalette &result)
|
||||
{
|
||||
QColor foreground = Qt::white;
|
||||
QColor background = QColor(0x1E, 0x1E, 0x1E);
|
||||
QColor accent = qt_accentColor();
|
||||
QColor accent = qt_accentColor(AccentColorNormal);
|
||||
QColor accentDark = accent.darker(120);
|
||||
QColor accentDarker = accentDark.darker(120);
|
||||
QColor accentDarkest = accentDarker.darker(120);
|
||||
@ -307,7 +330,7 @@ static void populateDarkSystemBasePalette(QPalette &result)
|
||||
QColor accentLightest = accentLighter.lighter(120);
|
||||
|
||||
#if QT_CONFIG(cpp_winrt)
|
||||
if (IsWindows10OrGreater())
|
||||
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10)
|
||||
{
|
||||
using namespace winrt::Windows::UI::ViewManagement;
|
||||
const auto settings = UISettings();
|
||||
@ -472,7 +495,10 @@ static inline QStringList iconThemeSearchPaths()
|
||||
|
||||
static inline QStringList styleNames()
|
||||
{
|
||||
return { QStringLiteral("WindowsVista"), QStringLiteral("Windows") };
|
||||
QStringList styles = { QStringLiteral("WindowsVista"), QStringLiteral("Windows") };
|
||||
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows11)
|
||||
styles.prepend(QStringLiteral("Windows11"));
|
||||
return styles;
|
||||
}
|
||||
|
||||
static inline int uiEffects()
|
||||
@ -537,6 +563,8 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const
|
||||
|
||||
Qt::ColorScheme QWindowsTheme::colorScheme() const
|
||||
{
|
||||
if (queryHighContrast())
|
||||
return Qt::ColorScheme::Unknown;
|
||||
return QWindowsContext::isDarkMode() ? Qt::ColorScheme::Dark : Qt::ColorScheme::Light;
|
||||
}
|
||||
|
||||
@ -559,24 +587,10 @@ void QWindowsTheme::refreshPalettes()
|
||||
m_palettes[MenuPalette] = new QPalette(menuPalette(*m_palettes[SystemPalette], light));
|
||||
m_palettes[MenuBarPalette] = menuBarPalette(*m_palettes[MenuPalette], light);
|
||||
if (!light) {
|
||||
QColor accent = qt_accentColor();
|
||||
QColor accentLight = accent.lighter(120);
|
||||
QColor accentDarkest = accent.darker(120 * 120 * 120);
|
||||
|
||||
#if QT_CONFIG(cpp_winrt)
|
||||
if (IsWindows10OrGreater())
|
||||
{
|
||||
using namespace winrt::Windows::UI::ViewManagement;
|
||||
const auto settings = UISettings();
|
||||
accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
|
||||
accentLight = getSysColor(settings.GetColorValue(UIColorType::AccentLight1));
|
||||
accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
|
||||
}
|
||||
#endif
|
||||
m_palettes[CheckBoxPalette] = new QPalette(*m_palettes[SystemPalette]);
|
||||
m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Base, accent);
|
||||
m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Button, accentLight);
|
||||
m_palettes[CheckBoxPalette]->setColor(QPalette::Inactive, QPalette::Base, accentDarkest);
|
||||
m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Base, qt_accentColor(AccentColorNormal));
|
||||
m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Button, qt_accentColor(AccentColorLightest));
|
||||
m_palettes[CheckBoxPalette]->setColor(QPalette::Inactive, QPalette::Base, qt_accentColor(AccentColorDarkest));
|
||||
m_palettes[RadioButtonPalette] = new QPalette(*m_palettes[CheckBoxPalette]);
|
||||
}
|
||||
}
|
||||
@ -586,15 +600,15 @@ QPalette QWindowsTheme::systemPalette(Qt::ColorScheme colorScheme)
|
||||
QPalette result = standardPalette();
|
||||
|
||||
switch (colorScheme) {
|
||||
case Qt::ColorScheme::Light:
|
||||
populateLightSystemBasePalette(result);
|
||||
break;
|
||||
case Qt::ColorScheme::Dark:
|
||||
populateDarkSystemBasePalette(result);
|
||||
break;
|
||||
default:
|
||||
qFatal("Unknown color scheme");
|
||||
break;
|
||||
case Qt::ColorScheme::Light:
|
||||
populateLightSystemBasePalette(result);
|
||||
break;
|
||||
case Qt::ColorScheme::Dark:
|
||||
populateDarkSystemBasePalette(result);
|
||||
break;
|
||||
default:
|
||||
qFatal("Unknown color scheme");
|
||||
break;
|
||||
}
|
||||
|
||||
if (result.window() != result.base()) {
|
||||
@ -675,14 +689,11 @@ void QWindowsTheme::refreshFonts()
|
||||
fixedFont.setStyleHint(QFont::TypeWriter);
|
||||
|
||||
LOGFONT lfIconTitleFont;
|
||||
QFont iconTitleFont;
|
||||
if (QWindowsContext::user32dll.systemParametersInfoForDpi) {
|
||||
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);
|
||||
}
|
||||
else
|
||||
vxkex::SystemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
|
||||
const QFont iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont, dpi);
|
||||
|
||||
m_fonts[SystemFont] = new QFont(QWindowsFontDatabase::systemDefaultFont());
|
||||
m_fonts[MenuFont] = new QFont(menuFont);
|
||||
@ -856,15 +867,18 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz
|
||||
}
|
||||
|
||||
if (stockId != SIID_INVALID) {
|
||||
QPixmap pixmap;
|
||||
SHSTOCKICONINFO iconInfo;
|
||||
memset(&iconInfo, 0, sizeof(iconInfo));
|
||||
iconInfo.cbSize = sizeof(iconInfo);
|
||||
stockFlags |= (pixmapSize.width() > 16 ? SHGFI_LARGEICON : SHGFI_SMALLICON);
|
||||
if (SHGetStockIconInfo(stockId, SHGFI_ICON | stockFlags, &iconInfo) == S_OK) {
|
||||
pixmap = qt_pixmapFromWinHICON(iconInfo.hIcon);
|
||||
DestroyIcon(iconInfo.hIcon);
|
||||
return pixmap;
|
||||
stockFlags |= SHGSI_ICONLOCATION;
|
||||
if (SHGetStockIconInfo(stockId, stockFlags, &iconInfo) == S_OK) {
|
||||
const auto iconSize = pixmapSize.width();
|
||||
HICON icon;
|
||||
if (SHDefExtractIcon(iconInfo.szPath, iconInfo.iIcon, 0, &icon, nullptr, iconSize) == S_OK) {
|
||||
QPixmap pixmap = qt_pixmapFromWinHICON(icon);
|
||||
DestroyIcon(icon);
|
||||
return pixmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1088,6 +1102,11 @@ QIcon QWindowsTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOpt
|
||||
return QIcon(new QWindowsFileIconEngine(fileInfo, iconOptions));
|
||||
}
|
||||
|
||||
QIconEngine *QWindowsTheme::createIconEngine(const QString &iconName) const
|
||||
{
|
||||
return new QWindowsIconEngine(iconName);
|
||||
}
|
||||
|
||||
static inline bool doUseNativeMenus()
|
||||
{
|
||||
const unsigned options = QWindowsIntegration::instance()->options();
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <QtGui/qwindow.h>
|
||||
#include <QtGui/qregion.h>
|
||||
#include <QtGui/qopenglcontext.h>
|
||||
#include <QtGui/private/qwindowsthemecache_p.h>
|
||||
#include <private/qwindow_p.h> // QWINDOWSIZE_MAX
|
||||
#include <private/qguiapplication_p.h>
|
||||
#include <private/qhighdpiscaling_p.h>
|
||||
@ -43,6 +44,8 @@
|
||||
|
||||
#include <shellscalingapi.h>
|
||||
|
||||
#include "vxkex.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
using QWindowCreationContextPtr = QSharedPointer<QWindowCreationContext>;
|
||||
@ -526,8 +529,8 @@ static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::Windo
|
||||
return QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi)
|
||||
+ QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
||||
}
|
||||
|
||||
return GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
|
||||
else
|
||||
return vxkex::GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + vxkex::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -537,16 +540,22 @@ static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::Windo
|
||||
|
||||
static QMargins invisibleMargins(QPoint screenPoint)
|
||||
{
|
||||
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10) {
|
||||
POINT pt = {screenPoint.x(), screenPoint.y()};
|
||||
if (HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
|
||||
if (QWindowsContext::shcoredll.isValid()) {
|
||||
UINT dpiX;
|
||||
UINT dpiY;
|
||||
if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY))) {
|
||||
const int gap = getResizeBorderThickness(dpiX);
|
||||
return QMargins(gap, 0, gap, gap);
|
||||
}
|
||||
POINT pt = {screenPoint.x(), screenPoint.y()};
|
||||
if (HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
|
||||
if (QWindowsContext::shcoredll.isValid()) {
|
||||
UINT dpiX;
|
||||
UINT dpiY;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10)
|
||||
hr = QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
|
||||
else
|
||||
hr = vxkex::GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
const int gap = getResizeBorderThickness(dpiX);
|
||||
return QMargins(gap, 0, gap, gap);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -555,12 +564,10 @@ static QMargins invisibleMargins(QPoint screenPoint)
|
||||
|
||||
[[nodiscard]] static inline QMargins invisibleMargins(const HWND hwnd)
|
||||
{
|
||||
if (QWindowsContext::user32dll.getDpiForWindow) {
|
||||
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
|
||||
const int gap = getResizeBorderThickness(dpi);
|
||||
return QMargins(gap, 0, gap, gap);
|
||||
}
|
||||
return QMargins();
|
||||
const UINT dpi = (QWindowsContext::user32dll.getDpiForWindow) ? QWindowsContext::user32dll.getDpiForWindow(hwnd) : vxkex::GetDpiForWindow(hwnd);
|
||||
|
||||
const int gap = getResizeBorderThickness(dpi);
|
||||
return QMargins(gap, 0, gap, gap);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -848,6 +855,10 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
|
||||
// NOTE: WS_EX_TRANSPARENT flag can make mouse inputs fall through a layered window
|
||||
if (flagsIn & Qt::WindowTransparentForInput)
|
||||
exStyle |= WS_EX_LAYERED | WS_EX_TRANSPARENT;
|
||||
|
||||
// Currently only compatible with D3D surfaces, use it with care.
|
||||
if (qEnvironmentVariableIntValue("QT_QPA_DISABLE_REDIRECTION_SURFACE"))
|
||||
exStyle |= WS_EX_NOREDIRECTIONBITMAP;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1074,10 +1085,17 @@ QMargins QWindowsGeometryHint::frame(const QWindow *w, DWORD style, DWORD exStyl
|
||||
return {};
|
||||
RECT rect = {0,0,0,0};
|
||||
style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
|
||||
if (QWindowsContext::user32dll.adjustWindowRectExForDpi &&
|
||||
QWindowsContext::user32dll.adjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi))) == FALSE) {
|
||||
qErrnoWarning("%s: AdjustWindowRectExForDpi failed", __FUNCTION__);
|
||||
if (QWindowsContext::user32dll.adjustWindowRectExForDpi)
|
||||
{
|
||||
if (QWindowsContext::user32dll.adjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi))) == FALSE)
|
||||
qErrnoWarning("%s: AdjustWindowRectExForDpi failed", __FUNCTION__);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vxkex::AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi))) == FALSE)
|
||||
qErrnoWarning("%s: vxkex::AdjustWindowRectExForDpi failed", __FUNCTION__);
|
||||
}
|
||||
|
||||
const QMargins result(qAbs(rect.left), qAbs(rect.top),
|
||||
qAbs(rect.right), qAbs(rect.bottom));
|
||||
qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << " style="
|
||||
@ -1364,6 +1382,8 @@ QWindowsForeignWindow::QWindowsForeignWindow(QWindow *window, HWND hwnd)
|
||||
, m_hwnd(hwnd)
|
||||
, m_topLevelStyle(0)
|
||||
{
|
||||
if (QPlatformWindow::parent())
|
||||
setParent(QPlatformWindow::parent());
|
||||
}
|
||||
|
||||
void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow)
|
||||
@ -1539,6 +1559,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
|
||||
QWindowsWindow::~QWindowsWindow()
|
||||
{
|
||||
setFlag(WithinDestroy);
|
||||
QWindowsThemeCache::clearThemeCache(m_data.hwnd);
|
||||
if (testFlag(TouchRegistered))
|
||||
UnregisterTouchWindow(m_data.hwnd);
|
||||
destroyWindow();
|
||||
@ -1568,7 +1589,7 @@ void QWindowsWindow::initialize()
|
||||
}
|
||||
}
|
||||
QWindowsWindow::setSavedDpi(QWindowsContext::user32dll.getDpiForWindow ?
|
||||
QWindowsContext::user32dll.getDpiForWindow(handle()) : 96);
|
||||
QWindowsContext::user32dll.getDpiForWindow(handle()) : vxkex::GetDpiForWindow(handle()));
|
||||
}
|
||||
|
||||
QSurfaceFormat QWindowsWindow::format() const
|
||||
@ -2018,6 +2039,9 @@ void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||
const UINT dpi = HIWORD(wParam);
|
||||
const qreal scale = dpiRelativeScale(dpi);
|
||||
setSavedDpi(dpi);
|
||||
|
||||
QWindowsThemeCache::clearThemeCache(hwnd);
|
||||
|
||||
// Send screen change first, so that the new screen is set during any following resize
|
||||
checkForScreenChanged(QWindowsWindow::FromDpiChange);
|
||||
|
||||
@ -2060,20 +2084,17 @@ void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||
|
||||
void QWindowsWindow::handleDpiChangedAfterParent(HWND hwnd)
|
||||
{
|
||||
if (QWindowsContext::user32dll.getDpiForWindow)
|
||||
{
|
||||
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
|
||||
const qreal scale = dpiRelativeScale(dpi);
|
||||
setSavedDpi(dpi);
|
||||
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow ? QWindowsContext::user32dll.getDpiForWindow(hwnd) : vxkex::GetDpiForWindow(hwnd);
|
||||
const qreal scale = dpiRelativeScale(dpi);
|
||||
setSavedDpi(dpi);
|
||||
|
||||
checkForScreenChanged(QWindowsWindow::FromDpiChange);
|
||||
checkForScreenChanged(QWindowsWindow::FromDpiChange);
|
||||
|
||||
// Child windows do not get WM_GETDPISCALEDSIZE messages to inform
|
||||
// Windows about the new size, so we need to manually scale them.
|
||||
QRect currentGeometry = geometry();
|
||||
QRect scaledGeometry = QRect(currentGeometry.topLeft() * scale, currentGeometry.size() * scale);
|
||||
setGeometry(scaledGeometry);
|
||||
}
|
||||
// Child windows do not get WM_GETDPISCALEDSIZE messages to inform
|
||||
// Windows about the new size, so we need to manually scale them.
|
||||
QRect currentGeometry = geometry();
|
||||
QRect scaledGeometry = QRect(currentGeometry.topLeft() * scale, currentGeometry.size() * scale);
|
||||
setGeometry(scaledGeometry);
|
||||
}
|
||||
|
||||
static QRect normalFrameGeometry(HWND hwnd)
|
||||
@ -2485,6 +2506,11 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
|
||||
GetWindowPlacement(m_data.hwnd, &windowPlacement);
|
||||
const RECT geometry = RECTfromQRect(m_data.restoreGeometry);
|
||||
windowPlacement.rcNormalPosition = geometry;
|
||||
// Even if the window is hidden, windowPlacement's showCmd is not SW_HIDE, so change it
|
||||
// manually to avoid unhiding a hidden window with the subsequent call to
|
||||
// SetWindowPlacement().
|
||||
if (!isVisible())
|
||||
windowPlacement.showCmd = SW_HIDE;
|
||||
SetWindowPlacement(m_data.hwnd, &windowPlacement);
|
||||
}
|
||||
// QTBUG-17548: We send expose events when receiving WM_Paint, but for
|
||||
|
430
qtbase/src/plugins/platforms/windows/vxkex.h
Normal file
430
qtbase/src/plugins/platforms/windows/vxkex.h
Normal file
@ -0,0 +1,430 @@
|
||||
#pragma once
|
||||
|
||||
#include <shtypes.h>
|
||||
#include <winuser.h>
|
||||
#include <windef.h>
|
||||
#include <shellscalingapi.h>
|
||||
|
||||
#define MDT_MAXIMUM_DPI 3
|
||||
|
||||
namespace vxkex {
|
||||
|
||||
static INT GetSystemMetricsForDpi(
|
||||
IN INT Index,
|
||||
IN UINT Dpi)
|
||||
{
|
||||
INT Value;
|
||||
|
||||
Value = GetSystemMetrics(Index);
|
||||
|
||||
switch (Index) {
|
||||
case SM_CXVSCROLL:
|
||||
case SM_CYHSCROLL:
|
||||
case SM_CYCAPTION:
|
||||
case SM_CYVTHUMB:
|
||||
case SM_CXHTHUMB:
|
||||
case SM_CXICON:
|
||||
case SM_CYICON:
|
||||
case SM_CXCURSOR:
|
||||
case SM_CYCURSOR:
|
||||
case SM_CYMENU:
|
||||
case SM_CYVSCROLL:
|
||||
case SM_CXHSCROLL:
|
||||
case SM_CXMIN:
|
||||
case SM_CXMINTRACK:
|
||||
case SM_CYMIN:
|
||||
case SM_CYMINTRACK:
|
||||
case SM_CXSIZE:
|
||||
case SM_CXFRAME:
|
||||
case SM_CYFRAME:
|
||||
case SM_CXICONSPACING:
|
||||
case SM_CYICONSPACING:
|
||||
case SM_CXSMICON:
|
||||
case SM_CYSMICON:
|
||||
case SM_CYSMCAPTION:
|
||||
case SM_CXSMSIZE:
|
||||
case SM_CYSMSIZE:
|
||||
case SM_CXMENUSIZE:
|
||||
case SM_CYMENUSIZE:
|
||||
case SM_CXMENUCHECK:
|
||||
case SM_CYMENUCHECK:
|
||||
// These are pixel values that have to be scaled according to DPI.
|
||||
Value *= Dpi;
|
||||
Value /= USER_DEFAULT_SCREEN_DPI;
|
||||
break;
|
||||
}
|
||||
|
||||
return Value;
|
||||
}
|
||||
|
||||
static BOOL SystemParametersInfoForDpi(
|
||||
IN UINT Action,
|
||||
IN UINT Parameter,
|
||||
IN OUT PVOID Data,
|
||||
IN UINT WinIni,
|
||||
IN UINT Dpi)
|
||||
{
|
||||
switch (Action) {
|
||||
case SPI_GETICONTITLELOGFONT:
|
||||
return SystemParametersInfo(Action, Parameter, Data, 0);
|
||||
case SPI_GETICONMETRICS:
|
||||
{
|
||||
BOOL Success;
|
||||
PICONMETRICS IconMetrics;
|
||||
|
||||
Success = SystemParametersInfo(Action, Parameter, Data, 0);
|
||||
|
||||
if (Success) {
|
||||
IconMetrics = (PICONMETRICS) Data;
|
||||
|
||||
IconMetrics->iHorzSpacing *= Dpi;
|
||||
IconMetrics->iVertSpacing *= Dpi;
|
||||
IconMetrics->iHorzSpacing /= USER_DEFAULT_SCREEN_DPI;
|
||||
IconMetrics->iVertSpacing /= USER_DEFAULT_SCREEN_DPI;
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
case SPI_GETNONCLIENTMETRICS:
|
||||
{
|
||||
BOOL Success;
|
||||
PNONCLIENTMETRICS NonClientMetrics;
|
||||
|
||||
Success = SystemParametersInfo(Action, Parameter, Data, 0);
|
||||
|
||||
if (Success) {
|
||||
NonClientMetrics = (PNONCLIENTMETRICS) Data;
|
||||
|
||||
NonClientMetrics->iBorderWidth *= Dpi;
|
||||
NonClientMetrics->iScrollWidth *= Dpi;
|
||||
NonClientMetrics->iScrollHeight *= Dpi;
|
||||
NonClientMetrics->iCaptionWidth *= Dpi;
|
||||
NonClientMetrics->iCaptionHeight *= Dpi;
|
||||
NonClientMetrics->iSmCaptionWidth *= Dpi;
|
||||
NonClientMetrics->iSmCaptionHeight *= Dpi;
|
||||
NonClientMetrics->iMenuWidth *= Dpi;
|
||||
NonClientMetrics->iMenuHeight *= Dpi;
|
||||
NonClientMetrics->iPaddedBorderWidth *= Dpi;
|
||||
|
||||
NonClientMetrics->iBorderWidth /= USER_DEFAULT_SCREEN_DPI;
|
||||
NonClientMetrics->iScrollWidth /= USER_DEFAULT_SCREEN_DPI;
|
||||
NonClientMetrics->iScrollHeight /= USER_DEFAULT_SCREEN_DPI;
|
||||
NonClientMetrics->iCaptionWidth /= USER_DEFAULT_SCREEN_DPI;
|
||||
NonClientMetrics->iCaptionHeight /= USER_DEFAULT_SCREEN_DPI;
|
||||
NonClientMetrics->iSmCaptionWidth /= USER_DEFAULT_SCREEN_DPI;
|
||||
NonClientMetrics->iSmCaptionHeight /= USER_DEFAULT_SCREEN_DPI;
|
||||
NonClientMetrics->iMenuWidth /= USER_DEFAULT_SCREEN_DPI;
|
||||
NonClientMetrics->iMenuHeight /= USER_DEFAULT_SCREEN_DPI;
|
||||
NonClientMetrics->iPaddedBorderWidth /= USER_DEFAULT_SCREEN_DPI;
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
default:
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT GetScaleFactorForMonitor(
|
||||
IN HMONITOR Monitor,
|
||||
OUT DEVICE_SCALE_FACTOR *ScaleFactor)
|
||||
{
|
||||
HDC DeviceContext;
|
||||
ULONG LogPixelsX;
|
||||
|
||||
DeviceContext = GetDC(NULL);
|
||||
if (!DeviceContext) {
|
||||
*ScaleFactor = SCALE_100_PERCENT;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
LogPixelsX = GetDeviceCaps(DeviceContext, LOGPIXELSX);
|
||||
ReleaseDC(NULL, DeviceContext);
|
||||
|
||||
*ScaleFactor = (DEVICE_SCALE_FACTOR) (9600 / LogPixelsX);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT GetDpiForMonitor(
|
||||
IN HMONITOR Monitor,
|
||||
IN MONITOR_DPI_TYPE DpiType,
|
||||
OUT UINT * DpiX,
|
||||
OUT UINT * DpiY)
|
||||
{
|
||||
HDC DeviceContext;
|
||||
|
||||
if (DpiType >= MDT_MAXIMUM_DPI) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (!DpiX || !DpiY) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (!IsProcessDPIAware()) {
|
||||
*DpiX = USER_DEFAULT_SCREEN_DPI;
|
||||
*DpiY = USER_DEFAULT_SCREEN_DPI;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
DeviceContext = GetDC(NULL);
|
||||
if (!DeviceContext) {
|
||||
*DpiX = USER_DEFAULT_SCREEN_DPI;
|
||||
*DpiY = USER_DEFAULT_SCREEN_DPI;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*DpiX = GetDeviceCaps(DeviceContext, LOGPIXELSX);
|
||||
*DpiY = GetDeviceCaps(DeviceContext, LOGPIXELSY);
|
||||
|
||||
if (DpiType == MDT_EFFECTIVE_DPI) {
|
||||
DEVICE_SCALE_FACTOR ScaleFactor;
|
||||
|
||||
// We have to multiply the DPI values by the scaling factor.
|
||||
vxkex::GetScaleFactorForMonitor(Monitor, &ScaleFactor);
|
||||
|
||||
*DpiX *= ScaleFactor;
|
||||
*DpiY *= ScaleFactor;
|
||||
*DpiX /= 100;
|
||||
*DpiY /= 100;
|
||||
}
|
||||
|
||||
ReleaseDC(NULL, DeviceContext);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static UINT GetDpiForSystem(
|
||||
VOID)
|
||||
{
|
||||
HDC DeviceContext;
|
||||
ULONG LogPixelsX;
|
||||
|
||||
if (!IsProcessDPIAware()) {
|
||||
return 96;
|
||||
}
|
||||
|
||||
DeviceContext = GetDC(NULL);
|
||||
if (!DeviceContext) {
|
||||
return 96;
|
||||
}
|
||||
|
||||
LogPixelsX = GetDeviceCaps(DeviceContext, LOGPIXELSX);
|
||||
ReleaseDC(NULL, DeviceContext);
|
||||
|
||||
return LogPixelsX;
|
||||
}
|
||||
|
||||
static UINT GetDpiForWindow(
|
||||
IN HWND Window)
|
||||
{
|
||||
if (!IsWindow(Window)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return vxkex::GetDpiForSystem();
|
||||
}
|
||||
|
||||
static BOOL AdjustWindowRectExForDpi(
|
||||
IN OUT LPRECT Rect,
|
||||
IN ULONG WindowStyle,
|
||||
IN BOOL HasMenu,
|
||||
IN ULONG WindowExStyle,
|
||||
IN ULONG Dpi)
|
||||
{
|
||||
// I'm not sure how to implement this function properly.
|
||||
// If it turns out to be important, I'll have to do some testing
|
||||
// on a Win10 VM.
|
||||
|
||||
return AdjustWindowRectEx(
|
||||
Rect,
|
||||
WindowStyle,
|
||||
HasMenu,
|
||||
WindowExStyle);
|
||||
}
|
||||
|
||||
static BOOL SetDisplayAutoRotationPreferences(
|
||||
IN ORIENTATION_PREFERENCE Orientation)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL GetDisplayAutoRotationPreferences(
|
||||
OUT ORIENTATION_PREFERENCE * Orientation)
|
||||
{
|
||||
*Orientation = ORIENTATION_PREFERENCE_NONE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// scaling.c
|
||||
|
||||
static BOOL SetProcessDpiAwarenessContext(
|
||||
IN DPI_AWARENESS_CONTEXT DpiContext)
|
||||
{
|
||||
switch ((ULONG_PTR)DpiContext) {
|
||||
case (ULONG_PTR)DPI_AWARENESS_CONTEXT_UNAWARE:
|
||||
//NOTHING;
|
||||
break;
|
||||
case (ULONG_PTR)DPI_AWARENESS_CONTEXT_SYSTEM_AWARE:
|
||||
case (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE:
|
||||
case (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2:
|
||||
SetProcessDPIAware();
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL AreDpiAwarenessContextsEqual(
|
||||
IN DPI_AWARENESS_CONTEXT Value1,
|
||||
IN DPI_AWARENESS_CONTEXT Value2)
|
||||
{
|
||||
return (Value1 == Value2);
|
||||
}
|
||||
|
||||
static BOOL IsValidDpiAwarenessContext(
|
||||
IN DPI_AWARENESS_CONTEXT Value)
|
||||
{
|
||||
switch ((ULONG_PTR)Value) {
|
||||
case (ULONG_PTR)DPI_AWARENESS_CONTEXT_UNAWARE:
|
||||
case (ULONG_PTR)DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED:
|
||||
case (ULONG_PTR)DPI_AWARENESS_CONTEXT_SYSTEM_AWARE:
|
||||
case (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE:
|
||||
case (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL EnableNonClientDpiScaling(
|
||||
IN HWND Window)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static DPI_AWARENESS_CONTEXT GetThreadDpiAwarenessContext(
|
||||
VOID)
|
||||
{
|
||||
if (IsProcessDPIAware()) {
|
||||
return DPI_AWARENESS_CONTEXT_SYSTEM_AWARE;
|
||||
} else {
|
||||
return DPI_AWARENESS_CONTEXT_UNAWARE;
|
||||
}
|
||||
}
|
||||
|
||||
static DPI_AWARENESS_CONTEXT GetWindowDpiAwarenessContext(
|
||||
IN HWND Window)
|
||||
{
|
||||
ULONG WindowThreadId;
|
||||
ULONG WindowProcessId;
|
||||
|
||||
WindowThreadId = GetWindowThreadProcessId(Window, &WindowProcessId);
|
||||
if (!WindowThreadId) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// looks like there's a bug in vxkex, here should be == instead of =
|
||||
// and if is always true
|
||||
// anyway I don't want to deal with Windows kernel mode structures here
|
||||
|
||||
if (1) { //if (WindowProcessId = (ULONG) NtCurrentTeb()->ClientId.UniqueProcess) {
|
||||
return vxkex::GetThreadDpiAwarenessContext();
|
||||
}
|
||||
|
||||
return DPI_AWARENESS_CONTEXT_UNAWARE;
|
||||
}
|
||||
|
||||
// pointer.c
|
||||
|
||||
static BOOL GetPointerType(
|
||||
IN UINT32 PointerId,
|
||||
OUT POINTER_INPUT_TYPE *PointerType)
|
||||
{
|
||||
*PointerType = PT_MOUSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL GetPointerFrameTouchInfo(
|
||||
IN UINT32 PointerId,
|
||||
IN OUT UINT32 *PointerCount,
|
||||
OUT LPVOID TouchInfo)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL GetPointerFrameTouchInfoHistory(
|
||||
IN UINT32 PointerId,
|
||||
IN OUT UINT32 *EntriesCount,
|
||||
IN OUT UINT32 *PointerCount,
|
||||
OUT LPVOID TouchInfo)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL GetPointerPenInfo(
|
||||
IN UINT32 PointerId,
|
||||
OUT LPVOID PenInfo)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL GetPointerPenInfoHistory(
|
||||
IN UINT32 PointerId,
|
||||
IN OUT UINT32 *EntriesCount,
|
||||
OUT LPVOID PenInfo)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL SkipPointerFrameMessages(
|
||||
IN UINT32 PointerId)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL GetPointerDeviceRects(
|
||||
IN HANDLE Device,
|
||||
OUT LPRECT PointerDeviceRect,
|
||||
OUT LPRECT DisplayRect)
|
||||
{
|
||||
PointerDeviceRect->top = 0;
|
||||
PointerDeviceRect->left = 0;
|
||||
PointerDeviceRect->bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
||||
PointerDeviceRect->right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
||||
|
||||
DisplayRect->top = 0;
|
||||
DisplayRect->left = 0;
|
||||
DisplayRect->bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
||||
DisplayRect->right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL GetPointerInfo(
|
||||
IN DWORD PointerId,
|
||||
OUT POINTER_INFO *PointerInfo)
|
||||
{
|
||||
PointerInfo->pointerType = PT_MOUSE;
|
||||
PointerInfo->pointerId = PointerId;
|
||||
PointerInfo->frameId = 0;
|
||||
PointerInfo->pointerFlags = POINTER_FLAG_NONE;
|
||||
PointerInfo->sourceDevice = NULL;
|
||||
PointerInfo->hwndTarget = NULL;
|
||||
GetCursorPos(&PointerInfo->ptPixelLocation);
|
||||
GetCursorPos(&PointerInfo->ptHimetricLocation);
|
||||
GetCursorPos(&PointerInfo->ptPixelLocationRaw);
|
||||
GetCursorPos(&PointerInfo->ptHimetricLocationRaw);
|
||||
PointerInfo->dwTime = 0;
|
||||
PointerInfo->historyCount = 1;
|
||||
PointerInfo->InputData = 0;
|
||||
PointerInfo->dwKeyStates = 0;
|
||||
PointerInfo->PerformanceCount = 0;
|
||||
PointerInfo->ButtonChangeType = POINTER_CHANGE_NONE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} // namespace vxkex
|
2365
qtbase/src/widgets/styles/qwindowsstyle.cpp
Normal file
2365
qtbase/src/widgets/styles/qwindowsstyle.cpp
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user