mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2024-10-30 15:57: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_LocalAppData, // AppConfigLocation ("Local" path)
|
||||||
FOLDERID_Public, // PublicShareLocation
|
FOLDERID_Public, // PublicShareLocation
|
||||||
FOLDERID_Templates, // TemplatesLocation
|
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
|
// folders for low integrity processes
|
||||||
static const GUID folderIds_li[] = {
|
static const GUID folderIds_li[] = {
|
||||||
@ -137,6 +139,8 @@ static GUID writableSpecialFolderId(QStandardPaths::StandardLocation type)
|
|||||||
FOLDERID_LocalAppDataLow,// AppConfigLocation ("Local" path)
|
FOLDERID_LocalAppDataLow,// AppConfigLocation ("Local" path)
|
||||||
FOLDERID_Public, // PublicShareLocation
|
FOLDERID_Public, // PublicShareLocation
|
||||||
FOLDERID_Templates, // TemplatesLocation
|
FOLDERID_Templates, // TemplatesLocation
|
||||||
|
GUID(), // StateLocation
|
||||||
|
GUID(), // GenericStateLocation
|
||||||
};
|
};
|
||||||
static_assert(sizeof(folderIds_li) == sizeof(folderIds));
|
static_assert(sizeof(folderIds_li) == sizeof(folderIds));
|
||||||
|
|
||||||
@ -191,6 +195,23 @@ QString QStandardPaths::writableLocation(StandardLocation type)
|
|||||||
result = QDir::tempPath();
|
result = QDir::tempPath();
|
||||||
break;
|
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:
|
default:
|
||||||
result = sHGetKnownFolderPath(writableSpecialFolderId(type));
|
result = sHGetKnownFolderPath(writableSpecialFolderId(type));
|
||||||
if (!result.isEmpty() && isConfigLocation(type)) {
|
if (!result.isEmpty() && isConfigLocation(type)) {
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include "qcoreapplication.h"
|
#include "qcoreapplication.h"
|
||||||
#include <private/qsystemlibrary_p.h>
|
#include <private/qsystemlibrary_p.h>
|
||||||
#include "qoperatingsystemversion.h"
|
#include "qoperatingsystemversion.h"
|
||||||
#include "qpair.h"
|
|
||||||
#include "qset.h"
|
#include "qset.h"
|
||||||
#include "qsocketnotifier.h"
|
#include "qsocketnotifier.h"
|
||||||
#include "qvarlengtharray.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 *sn_vec[4] = { &d->sn_read, &d->sn_write, &d->sn_except, &d->sn_read };
|
||||||
QSNDict *dict = sn_vec[type];
|
QSNDict *dict = sn_vec[type];
|
||||||
|
|
||||||
QSockNot *sn = dict ? dict->value(wp) : 0;
|
QSockNot *sn = dict ? dict->value(qintptr(wp)) : 0;
|
||||||
if (sn == nullptr) {
|
if (sn == nullptr) {
|
||||||
d->postActivateSocketNotifiers();
|
d->postActivateSocketNotifiers();
|
||||||
} else {
|
} 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);
|
Q_ASSERT(internalHwnd);
|
||||||
// BoundsChecker may emit a warning for WSAAsyncSelect when event == 0
|
// 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)
|
void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier)
|
||||||
{
|
{
|
||||||
Q_ASSERT(notifier);
|
Q_ASSERT(notifier);
|
||||||
int sockfd = notifier->socket();
|
qintptr sockfd = notifier->socket();
|
||||||
int type = notifier->type();
|
int type = notifier->type();
|
||||||
#ifndef QT_NO_DEBUG
|
#ifndef QT_NO_DEBUG
|
||||||
if (sockfd < 0) {
|
if (sockfd < 0) {
|
||||||
@ -587,7 +586,7 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier)
|
|||||||
const char *t[] = { "Read", "Write", "Exception" };
|
const char *t[] = { "Read", "Write", "Exception" };
|
||||||
/* Variable "socket" below is a function pointer. */
|
/* Variable "socket" below is a function pointer. */
|
||||||
qWarning("QSocketNotifier: Multiple socket notifiers for "
|
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;
|
QSockNot *sn = new QSockNot;
|
||||||
@ -631,7 +630,7 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier)
|
|||||||
{
|
{
|
||||||
Q_ASSERT(notifier);
|
Q_ASSERT(notifier);
|
||||||
#ifndef QT_NO_DEBUG
|
#ifndef QT_NO_DEBUG
|
||||||
int sockfd = notifier->socket();
|
qintptr sockfd = notifier->socket();
|
||||||
if (sockfd < 0) {
|
if (sockfd < 0) {
|
||||||
qWarning("QEventDispatcherWin32::unregisterSocketNotifier: invalid socket identifier");
|
qWarning("QEventDispatcherWin32::unregisterSocketNotifier: invalid socket identifier");
|
||||||
return;
|
return;
|
||||||
@ -648,7 +647,7 @@ void QEventDispatcherWin32::doUnregisterSocketNotifier(QSocketNotifier *notifier
|
|||||||
{
|
{
|
||||||
Q_D(QEventDispatcherWin32);
|
Q_D(QEventDispatcherWin32);
|
||||||
int type = notifier->type();
|
int type = notifier->type();
|
||||||
int sockfd = notifier->socket();
|
qintptr sockfd = notifier->socket();
|
||||||
Q_ASSERT(sockfd >= 0);
|
Q_ASSERT(sockfd >= 0);
|
||||||
|
|
||||||
QSFDict::iterator it = d->active_fd.find(sockfd);
|
QSFDict::iterator it = d->active_fd.find(sockfd);
|
||||||
@ -911,3 +910,5 @@ HWND QEventDispatcherWin32::internalHwnd()
|
|||||||
}
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
#include "moc_qeventdispatcher_win_p.cpp"
|
||||||
|
@ -51,21 +51,21 @@ bool qt_win_hasPackageIdentity()
|
|||||||
{
|
{
|
||||||
#if defined(HAS_APPMODEL)
|
#if defined(HAS_APPMODEL)
|
||||||
|
|
||||||
static const bool hasPackageIdentity = []() {
|
static const bool hasPackageIdentity = []() {
|
||||||
UINT32 length = 0;
|
UINT32 length = 0;
|
||||||
switch (const auto result = myGetCurrentPackageFullName(&length, nullptr)) {
|
switch (const auto result = myGetCurrentPackageFullName(&length, nullptr)) {
|
||||||
case ERROR_INSUFFICIENT_BUFFER:
|
case ERROR_INSUFFICIENT_BUFFER:
|
||||||
return true;
|
return true;
|
||||||
case APPMODEL_ERROR_NO_PACKAGE:
|
case APPMODEL_ERROR_NO_PACKAGE:
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
qWarning("Failed to resolve package identity (error code %ld)", result);
|
qWarning("Failed to resolve package identity (error code %ld)", result);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
return hasPackageIdentity;
|
return hasPackageIdentity;
|
||||||
#else
|
#else
|
||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,15 +15,15 @@
|
|||||||
// We mean it.
|
// We mean it.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <qdeadlinetimer.h>
|
||||||
#include <private/qglobal_p.h>
|
#include <private/qglobal_p.h>
|
||||||
#include <QtCore/qtsan_impl.h>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
namespace QtDummyFutex {
|
namespace QtDummyFutex {
|
||||||
constexpr inline bool futexAvailable() { return false; }
|
constexpr inline bool futexAvailable() { return false; }
|
||||||
template <typename Atomic>
|
template <typename Atomic>
|
||||||
inline bool futexWait(Atomic &, typename Atomic::Type, int = 0)
|
inline bool futexWait(Atomic &, typename Atomic::Type, QDeadlineTimer = {})
|
||||||
{ Q_UNREACHABLE_RETURN(false); }
|
{ Q_UNREACHABLE_RETURN(false); }
|
||||||
template <typename Atomic> inline void futexWakeOne(Atomic &)
|
template <typename Atomic> inline void futexWakeOne(Atomic &)
|
||||||
{ Q_UNREACHABLE(); }
|
{ Q_UNREACHABLE(); }
|
||||||
@ -33,82 +33,16 @@ namespace QtDummyFutex {
|
|||||||
|
|
||||||
QT_END_NAMESPACE
|
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
|
// use Linux mutexes everywhere except for LSB builds
|
||||||
# include <sys/syscall.h>
|
# include "qfutex_linux_p.h"
|
||||||
# include <errno.h>
|
//#elif defined(Q_OS_WIN)
|
||||||
# include <limits.h>
|
//# include "qfutex_win_p.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
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
namespace QtFutex = QtDummyFutex;
|
namespace QtFutex = QtDummyFutex;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
#include "qmutex.h"
|
#include "qmutex.h"
|
||||||
#include <qdebug.h>
|
#include <qdebug.h>
|
||||||
#include "qatomic.h"
|
#include "qatomic.h"
|
||||||
#include "qelapsedtimer.h"
|
|
||||||
#include "qfutex_p.h"
|
#include "qfutex_p.h"
|
||||||
#include "qthread.h"
|
#include "qthread.h"
|
||||||
#include "qmutex_p.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
|
bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXCEPT
|
||||||
{
|
{
|
||||||
qint64 remainingTime = deadlineTimer.remainingTimeNSecs();
|
if (deadlineTimer.hasExpired())
|
||||||
if (remainingTime == 0)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (futexAvailable()) {
|
if (futexAvailable()) {
|
||||||
if (Q_UNLIKELY(remainingTime < 0)) { // deadlineTimer.isForever()
|
if (Q_UNLIKELY(deadlineTimer.isForever())) {
|
||||||
lockInternal();
|
lockInternal();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -689,8 +687,8 @@ bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXC
|
|||||||
if (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) == nullptr)
|
if (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) == nullptr)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
Q_FOREVER {
|
for (;;) {
|
||||||
if (!futexWait(d_ptr, dummyFutexValue(), remainingTime))
|
if (!futexWait(d_ptr, dummyFutexValue(), deadlineTimer))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// We got woken up, so must try to acquire the mutex. We must set
|
// 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)
|
if (d_ptr.fetchAndStoreAcquire(dummyFutexValue()) == nullptr)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// calculate the remaining time
|
if (deadlineTimer.hasExpired())
|
||||||
remainingTime = deadlineTimer.remainingTimeNSecs();
|
|
||||||
if (remainingTime <= 0)
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -713,7 +709,7 @@ bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXC
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (copy == dummyLocked()) {
|
if (copy == dummyLocked()) {
|
||||||
if (remainingTime == 0)
|
if (deadlineTimer.hasExpired())
|
||||||
return false;
|
return false;
|
||||||
// The mutex is locked but does not have a QMutexPrivate yet.
|
// The mutex is locked but does not have a QMutexPrivate yet.
|
||||||
// we need to allocate a QMutexPrivate
|
// 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);
|
QMutexPrivate *d = static_cast<QMutexPrivate *>(copy);
|
||||||
if (remainingTime == 0 && !d->possiblyUnlocked.loadRelaxed())
|
if (deadlineTimer.hasExpired() && !d->possiblyUnlocked.loadRelaxed())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// At this point we have a pointer to a QMutexPrivate. But the other thread
|
// 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());
|
Q_ASSERT(d == d_ptr.loadRelaxed());
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
Q_ASSERT(remainingTime >= 0);
|
|
||||||
// timed out
|
// timed out
|
||||||
d->derefWaiters(1);
|
d->derefWaiters(1);
|
||||||
//There may be a race in which the mutex is unlocked right after we timed out,
|
//There may be a race in which the mutex is unlocked right after we timed out,
|
||||||
@ -915,7 +910,7 @@ QT_END_NAMESPACE
|
|||||||
|
|
||||||
#if defined(QT_ALWAYS_USE_FUTEX)
|
#if defined(QT_ALWAYS_USE_FUTEX)
|
||||||
// nothing
|
// nothing
|
||||||
#elif defined(Q_OS_MAC)
|
#elif defined(Q_OS_DARWIN)
|
||||||
# include "qmutex_mac.cpp"
|
# include "qmutex_mac.cpp"
|
||||||
#elif defined(Q_OS_WIN)
|
#elif defined(Q_OS_WIN)
|
||||||
# include "qmutex_win.cpp"
|
# include "qmutex_win.cpp"
|
||||||
|
@ -95,22 +95,47 @@ using namespace Qt::StringLiterals;
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
\variable QRhiD3D11NativeHandles::dev
|
\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
|
\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
|
\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
|
\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
|
\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
|
// help mingw with its ancient sdk headers
|
||||||
@ -259,9 +284,7 @@ bool QRhiD3D11::create(QRhi::Flags flags)
|
|||||||
if (!activeAdapter && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
|
if (!activeAdapter && (requestedAdapterIndex < 0 || requestedAdapterIndex == adapterIndex)) {
|
||||||
activeAdapter = adapter;
|
activeAdapter = adapter;
|
||||||
adapterLuid = desc.AdapterLuid;
|
adapterLuid = desc.AdapterLuid;
|
||||||
driverInfoStruct.deviceName = name.toUtf8();
|
QRhiD3D::fillDriverInfo(&driverInfoStruct, desc);
|
||||||
driverInfoStruct.deviceId = desc.DeviceId;
|
|
||||||
driverInfoStruct.vendorId = desc.VendorId;
|
|
||||||
qCDebug(QRHI_LOG_INFO, " using this adapter");
|
qCDebug(QRHI_LOG_INFO, " using this adapter");
|
||||||
} else {
|
} else {
|
||||||
adapter->Release();
|
adapter->Release();
|
||||||
@ -304,21 +327,24 @@ bool QRhiD3D11::create(QRhi::Flags flags)
|
|||||||
return false;
|
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
|
// Test if creating a Shader Model 5.0 vertex shader works; we want to
|
||||||
// fail already in create() if that's not the case.
|
// fail already in create() if that's not the case.
|
||||||
ID3D11VertexShader *testShader = nullptr;
|
ID3D11VertexShader *testShader = nullptr;
|
||||||
if (SUCCEEDED(dev->CreateVertexShader(g_testVertexShader, sizeof(g_testVertexShader), nullptr, &testShader))) {
|
if (SUCCEEDED(dev->CreateVertexShader(g_testVertexShader, sizeof(g_testVertexShader), nullptr, &testShader))) {
|
||||||
testShader->Release();
|
testShader->Release();
|
||||||
} else {
|
} else {
|
||||||
qWarning("D3D11 smoke test failed (failed to create vertex shader)");
|
static const char *msg = "D3D11 smoke test: Failed to create vertex shader";
|
||||||
ctx->Release();
|
if (flags.testFlag(QRhi::SuppressSmokeTestWarnings))
|
||||||
return false;
|
qCDebug(QRHI_LOG_INFO, "%s", msg);
|
||||||
}
|
else
|
||||||
|
qWarning("%s", msg);
|
||||||
const bool supports11_1 = SUCCEEDED(ctx->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast<void **>(&context)));
|
|
||||||
ctx->Release();
|
|
||||||
if (!supports11_1) {
|
|
||||||
qWarning("ID3D11DeviceContext1 not supported");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,11 +354,19 @@ bool QRhiD3D11::create(QRhi::Flags flags)
|
|||||||
// still not support this D3D_FEATURE_LEVEL_11_1 feature. (e.g.
|
// still not support this D3D_FEATURE_LEVEL_11_1 feature. (e.g.
|
||||||
// because it only does 11_0)
|
// because it only does 11_0)
|
||||||
if (!features.ConstantBufferOffsetting) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} 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;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -342,12 +376,14 @@ bool QRhiD3D11::create(QRhi::Flags flags)
|
|||||||
if (SUCCEEDED(dev->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void **>(&dxgiDev)))) {
|
if (SUCCEEDED(dev->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void **>(&dxgiDev)))) {
|
||||||
IDXGIAdapter *adapter = nullptr;
|
IDXGIAdapter *adapter = nullptr;
|
||||||
if (SUCCEEDED(dxgiDev->GetAdapter(&adapter))) {
|
if (SUCCEEDED(dxgiDev->GetAdapter(&adapter))) {
|
||||||
DXGI_ADAPTER_DESC desc;
|
IDXGIAdapter1 *adapter1 = nullptr;
|
||||||
adapter->GetDesc(&desc);
|
if (SUCCEEDED(adapter->QueryInterface(__uuidof(IDXGIAdapter1), reinterpret_cast<void **>(&adapter1)))) {
|
||||||
adapterLuid = desc.AdapterLuid;
|
DXGI_ADAPTER_DESC1 desc;
|
||||||
driverInfoStruct.deviceName = QString::fromUtf16(reinterpret_cast<char16_t *>(desc.Description)).toUtf8();
|
adapter1->GetDesc1(&desc);
|
||||||
driverInfoStruct.deviceId = desc.DeviceId;
|
adapterLuid = desc.AdapterLuid;
|
||||||
driverInfoStruct.vendorId = desc.VendorId;
|
QRhiD3D::fillDriverInfo(&driverInfoStruct, desc);
|
||||||
|
adapter1->Release();
|
||||||
|
}
|
||||||
adapter->Release();
|
adapter->Release();
|
||||||
}
|
}
|
||||||
dxgiDev->Release();
|
dxgiDev->Release();
|
||||||
@ -358,11 +394,6 @@ bool QRhiD3D11::create(QRhi::Flags flags)
|
|||||||
if (FAILED(context->QueryInterface(__uuidof(ID3DUserDefinedAnnotation), reinterpret_cast<void **>(&annotations))))
|
if (FAILED(context->QueryInterface(__uuidof(ID3DUserDefinedAnnotation), reinterpret_cast<void **>(&annotations))))
|
||||||
annotations = nullptr;
|
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;
|
deviceLost = false;
|
||||||
|
|
||||||
nativeHandlesStruct.dev = dev;
|
nativeHandlesStruct.dev = dev;
|
||||||
@ -388,7 +419,16 @@ void QRhiD3D11::destroy()
|
|||||||
|
|
||||||
clearShaderCache();
|
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) {
|
if (annotations) {
|
||||||
annotations->Release();
|
annotations->Release();
|
||||||
@ -592,6 +632,8 @@ bool QRhiD3D11::isFeatureSupported(QRhi::Feature feature) const
|
|||||||
return true;
|
return true;
|
||||||
case QRhi::ThreeDimensionalTextureMipmaps:
|
case QRhi::ThreeDimensionalTextureMipmaps:
|
||||||
return true;
|
return true;
|
||||||
|
case QRhi::MultiView:
|
||||||
|
return false;
|
||||||
default:
|
default:
|
||||||
Q_UNREACHABLE();
|
Q_UNREACHABLE();
|
||||||
return false;
|
return false;
|
||||||
@ -1262,7 +1304,6 @@ const QRhiNativeHandles *QRhiD3D11::nativeHandles(QRhiCommandBuffer *cb)
|
|||||||
void QRhiD3D11::beginExternal(QRhiCommandBuffer *cb)
|
void QRhiD3D11::beginExternal(QRhiCommandBuffer *cb)
|
||||||
{
|
{
|
||||||
QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
|
QD3D11CommandBuffer *cbD = QRHI_RES(QD3D11CommandBuffer, cb);
|
||||||
// no timestampSwapChain, in order to avoid timestamp mess
|
|
||||||
executeCommandBuffer(cbD);
|
executeCommandBuffer(cbD);
|
||||||
cbD->resetCommands();
|
cbD->resetCommands();
|
||||||
}
|
}
|
||||||
@ -1285,6 +1326,19 @@ double QRhiD3D11::lastCompletedGpuTime(QRhiCommandBuffer *cb)
|
|||||||
return cbD->lastGpuTime;
|
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)
|
QRhi::FrameOpResult QRhiD3D11::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginFrameFlags flags)
|
||||||
{
|
{
|
||||||
Q_UNUSED(flags);
|
Q_UNUSED(flags);
|
||||||
@ -1301,12 +1355,22 @@ QRhi::FrameOpResult QRhiD3D11::beginFrame(QRhiSwapChain *swapChain, QRhi::BeginF
|
|||||||
|
|
||||||
finishActiveReadbacks();
|
finishActiveReadbacks();
|
||||||
|
|
||||||
if (swapChainD->timestamps.active[currentFrameSlot]) {
|
if (swapChainD->timestamps.active[swapChainD->currentTimestampPairIndex]) {
|
||||||
double elapsedSec = 0;
|
double elapsedSec = 0;
|
||||||
if (swapChainD->timestamps.tryQueryTimestamps(currentFrameSlot, context, &elapsedSec))
|
if (swapChainD->timestamps.tryQueryTimestamps(swapChainD->currentTimestampPairIndex, context, &elapsedSec))
|
||||||
swapChainD->cb.lastGpuTime = 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;
|
return QRhi::FrameOpSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1316,17 +1380,13 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
|
|||||||
Q_ASSERT(contextState.currentSwapChain = swapChainD);
|
Q_ASSERT(contextState.currentSwapChain = swapChainD);
|
||||||
const int currentFrameSlot = swapChainD->currentFrameSlot;
|
const int currentFrameSlot = swapChainD->currentFrameSlot;
|
||||||
|
|
||||||
ID3D11Query *tsDisjoint = swapChainD->timestamps.disjointQuery[currentFrameSlot];
|
QD3D11CommandBuffer::Command &cmd(swapChainD->cb.commands.get());
|
||||||
const int tsIdx = QD3D11SwapChain::BUFFER_COUNT * currentFrameSlot;
|
cmd.cmd = QD3D11CommandBuffer::Command::EndFrame;
|
||||||
ID3D11Query *tsStart = swapChainD->timestamps.query[tsIdx];
|
cmd.args.endFrame.tsQuery = nullptr; // done later manually, see below
|
||||||
ID3D11Query *tsEnd = swapChainD->timestamps.query[tsIdx + 1];
|
cmd.args.endFrame.tsDisjointQuery = nullptr;
|
||||||
const bool recordTimestamps = tsDisjoint && tsStart && tsEnd && !swapChainD->timestamps.active[currentFrameSlot];
|
|
||||||
|
|
||||||
// send all commands to the context
|
// send all commands to the context
|
||||||
if (recordTimestamps)
|
executeCommandBuffer(&swapChainD->cb);
|
||||||
executeCommandBuffer(&swapChainD->cb, swapChainD);
|
|
||||||
else
|
|
||||||
executeCommandBuffer(&swapChainD->cb);
|
|
||||||
|
|
||||||
if (swapChainD->sampleDesc.Count > 1) {
|
if (swapChainD->sampleDesc.Count > 1) {
|
||||||
context->ResolveSubresource(swapChainD->backBufferTex, 0,
|
context->ResolveSubresource(swapChainD->backBufferTex, 0,
|
||||||
@ -1334,11 +1394,15 @@ QRhi::FrameOpResult QRhiD3D11::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
|
|||||||
swapChainD->colorFormat);
|
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) {
|
if (recordTimestamps) {
|
||||||
context->End(tsEnd);
|
context->End(tsEnd);
|
||||||
context->End(tsDisjoint);
|
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)) {
|
if (!flags.testFlag(QRhi::SkipPresent)) {
|
||||||
@ -1383,12 +1447,36 @@ QRhi::FrameOpResult QRhiD3D11::beginOffscreenFrame(QRhiCommandBuffer **cb, QRhi:
|
|||||||
ofr.cbWrapper.resetState();
|
ofr.cbWrapper.resetState();
|
||||||
*cb = &ofr.cbWrapper;
|
*cb = &ofr.cbWrapper;
|
||||||
|
|
||||||
if (ofr.timestamps.active[ofr.timestampIdx]) {
|
if (rhiFlags.testFlag(QRhi::EnableTimestamps)) {
|
||||||
double elapsedSec = 0;
|
D3D11_QUERY_DESC queryDesc = {};
|
||||||
if (ofr.timestamps.tryQueryTimestamps(ofr.timestampIdx, context, &elapsedSec))
|
if (!ofr.tsDisjointQuery) {
|
||||||
ofr.cbWrapper.lastGpuTime = elapsedSec;
|
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;
|
return QRhi::FrameOpSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1397,25 +1485,39 @@ QRhi::FrameOpResult QRhiD3D11::endOffscreenFrame(QRhi::EndFrameFlags flags)
|
|||||||
Q_UNUSED(flags);
|
Q_UNUSED(flags);
|
||||||
ofr.active = false;
|
ofr.active = false;
|
||||||
|
|
||||||
ID3D11Query *tsDisjoint = ofr.timestamps.disjointQuery[ofr.timestampIdx];
|
QD3D11CommandBuffer::Command &cmd(ofr.cbWrapper.commands.get());
|
||||||
ID3D11Query *tsStart = ofr.timestamps.query[ofr.timestampIdx * 2];
|
cmd.cmd = QD3D11CommandBuffer::Command::EndFrame;
|
||||||
ID3D11Query *tsEnd = ofr.timestamps.query[ofr.timestampIdx * 2 + 1];
|
cmd.args.endFrame.tsQuery = ofr.tsQueries[1] ? ofr.tsQueries[1] : nullptr;
|
||||||
const bool recordTimestamps = tsDisjoint && tsStart && tsEnd && !ofr.timestamps.active[ofr.timestampIdx];
|
cmd.args.endFrame.tsDisjointQuery = ofr.tsDisjointQuery ? ofr.tsDisjointQuery : nullptr;
|
||||||
if (recordTimestamps) {
|
|
||||||
context->Begin(tsDisjoint);
|
|
||||||
context->End(tsStart); // record timestamp; no Begin() for D3D11_QUERY_TIMESTAMP
|
|
||||||
}
|
|
||||||
|
|
||||||
executeCommandBuffer(&ofr.cbWrapper);
|
executeCommandBuffer(&ofr.cbWrapper);
|
||||||
context->Flush();
|
context->Flush();
|
||||||
|
|
||||||
finishActiveReadbacks();
|
finishActiveReadbacks();
|
||||||
|
|
||||||
if (recordTimestamps) {
|
if (ofr.tsQueries[0]) {
|
||||||
context->End(tsEnd);
|
quint64 timestamps[2];
|
||||||
context->End(tsDisjoint);
|
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
|
||||||
ofr.timestamps.active[ofr.timestampIdx] = true;
|
HRESULT hr;
|
||||||
ofr.timestampIdx = (ofr.timestampIdx + 1) % 2;
|
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;
|
return QRhi::FrameOpSuccess;
|
||||||
@ -1558,7 +1660,7 @@ QRhi::FrameOpResult QRhiD3D11::finish()
|
|||||||
} else {
|
} else {
|
||||||
Q_ASSERT(contextState.currentSwapChain);
|
Q_ASSERT(contextState.currentSwapChain);
|
||||||
Q_ASSERT(contextState.currentSwapChain->cb.recordingPass == QD3D11CommandBuffer::NoPass);
|
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();
|
contextState.currentSwapChain->cb.resetCommands();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1933,19 +2035,6 @@ void QRhiD3D11::finishActiveReadbacks()
|
|||||||
f();
|
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)
|
void QRhiD3D11::resourceUpdate(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resourceUpdates)
|
||||||
{
|
{
|
||||||
Q_ASSERT(QRHI_RES(QD3D11CommandBuffer, cb)->recordingPass == QD3D11CommandBuffer::NoPass);
|
Q_ASSERT(QRHI_RES(QD3D11CommandBuffer, cb)->recordingPass == QD3D11CommandBuffer::NoPass);
|
||||||
@ -2651,7 +2740,7 @@ void QRhiD3D11::resetShaderResources()
|
|||||||
currentShaderMask &= ~StageU##MaskBit; \
|
currentShaderMask &= ~StageU##MaskBit; \
|
||||||
}
|
}
|
||||||
|
|
||||||
void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain)
|
void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD)
|
||||||
{
|
{
|
||||||
quint32 stencilRef = 0;
|
quint32 stencilRef = 0;
|
||||||
float blendConstants[] = { 1, 1, 1, 1 };
|
float blendConstants[] = { 1, 1, 1, 1 };
|
||||||
@ -2664,26 +2753,30 @@ void QRhiD3D11::executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *
|
|||||||
};
|
};
|
||||||
int currentShaderMask = 0xFF;
|
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) {
|
for (auto it = cbD->commands.cbegin(), end = cbD->commands.cend(); it != end; ++it) {
|
||||||
const QD3D11CommandBuffer::Command &cmd(*it);
|
const QD3D11CommandBuffer::Command &cmd(*it);
|
||||||
switch (cmd.cmd) {
|
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:
|
case QD3D11CommandBuffer::Command::ResetShaderResources:
|
||||||
resetShaderResources();
|
resetShaderResources();
|
||||||
break;
|
break;
|
||||||
@ -4702,14 +4795,13 @@ void QD3D11CommandBuffer::destroy()
|
|||||||
// nothing to do here
|
// 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
|
// Creates the query objects if not yet done, but otherwise calling this
|
||||||
// function is expected to be a no-op.
|
// function is expected to be a no-op.
|
||||||
|
|
||||||
Q_ASSERT(pairCount <= MAX_TIMESTAMP_PAIRS);
|
|
||||||
D3D11_QUERY_DESC queryDesc = {};
|
D3D11_QUERY_DESC queryDesc = {};
|
||||||
for (int i = 0; i < pairCount; ++i) {
|
for (int i = 0; i < TIMESTAMP_PAIRS; ++i) {
|
||||||
if (!disjointQuery[i]) {
|
if (!disjointQuery[i]) {
|
||||||
queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
|
queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT;
|
||||||
HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &disjointQuery[i]);
|
HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &disjointQuery[i]);
|
||||||
@ -4721,7 +4813,7 @@ bool QD3D11Timestamps::prepare(int pairCount, QRhiD3D11 *rhiD)
|
|||||||
}
|
}
|
||||||
queryDesc.Query = D3D11_QUERY_TIMESTAMP;
|
queryDesc.Query = D3D11_QUERY_TIMESTAMP;
|
||||||
for (int j = 0; j < 2; ++j) {
|
for (int j = 0; j < 2; ++j) {
|
||||||
const int idx = pairCount * i + j;
|
const int idx = 2 * i + j;
|
||||||
if (!query[idx]) {
|
if (!query[idx]) {
|
||||||
HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &query[idx]);
|
HRESULT hr = rhiD->dev->CreateQuery(&queryDesc, &query[idx]);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
@ -4732,20 +4824,19 @@ bool QD3D11Timestamps::prepare(int pairCount, QRhiD3D11 *rhiD)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->pairCount = pairCount;
|
|
||||||
return true;
|
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;
|
active[i] = false;
|
||||||
if (disjointQuery[i]) {
|
if (disjointQuery[i]) {
|
||||||
disjointQuery[i]->Release();
|
disjointQuery[i]->Release();
|
||||||
disjointQuery[i] = nullptr;
|
disjointQuery[i] = nullptr;
|
||||||
}
|
}
|
||||||
for (int j = 0; j < 2; ++j) {
|
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]) {
|
if (query[idx]) {
|
||||||
query[idx]->Release();
|
query[idx]->Release();
|
||||||
query[idx] = nullptr;
|
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;
|
bool result = false;
|
||||||
if (!active[idx])
|
if (!active[pairIndex])
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
ID3D11Query *tsDisjoint = disjointQuery[idx];
|
ID3D11Query *tsDisjoint = disjointQuery[pairIndex];
|
||||||
const int tsIdx = pairCount * idx;
|
ID3D11Query *tsStart = query[pairIndex * 2];
|
||||||
ID3D11Query *tsStart = query[tsIdx];
|
ID3D11Query *tsEnd = query[pairIndex * 2 + 1];
|
||||||
ID3D11Query *tsEnd = query[tsIdx + 1];
|
|
||||||
quint64 timestamps[2];
|
quint64 timestamps[2];
|
||||||
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
|
D3D11_QUERY_DATA_TIMESTAMP_DISJOINT dj;
|
||||||
|
|
||||||
bool ok = true;
|
bool ok = true;
|
||||||
ok &= context->GetData(tsDisjoint, &dj, sizeof(dj), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
|
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;
|
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;
|
ok &= context->GetData(tsStart, ×tamps[0], sizeof(quint64), D3D11_ASYNC_GETDATA_DONOTFLUSH) == S_OK;
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
@ -4782,16 +4868,14 @@ bool QD3D11Timestamps::tryQueryTimestamps(int idx, ID3D11DeviceContext *context,
|
|||||||
*elapsedSec = elapsedMs / 1000.0;
|
*elapsedSec = elapsedMs / 1000.0;
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
active[idx] = false;
|
active[pairIndex] = false;
|
||||||
} // else leave active set, will retry in a subsequent beginFrame or similar
|
} // else leave active set, will retry in a subsequent beginFrame
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
QD3D11SwapChain::QD3D11SwapChain(QRhiImplementation *rhi)
|
QD3D11SwapChain::QD3D11SwapChain(QRhiImplementation *rhi)
|
||||||
: QRhiSwapChain(rhi),
|
: QRhiSwapChain(rhi), rt(rhi, this), rtRight(rhi, this), cb(rhi)
|
||||||
rt(rhi, this),
|
|
||||||
cb(rhi)
|
|
||||||
{
|
{
|
||||||
backBufferTex = nullptr;
|
backBufferTex = nullptr;
|
||||||
backBufferRtv = nullptr;
|
backBufferRtv = nullptr;
|
||||||
@ -4812,6 +4896,10 @@ void QD3D11SwapChain::releaseBuffers()
|
|||||||
backBufferRtv->Release();
|
backBufferRtv->Release();
|
||||||
backBufferRtv = nullptr;
|
backBufferRtv = nullptr;
|
||||||
}
|
}
|
||||||
|
if (backBufferRtvRight) {
|
||||||
|
backBufferRtvRight->Release();
|
||||||
|
backBufferRtvRight = nullptr;
|
||||||
|
}
|
||||||
if (backBufferTex) {
|
if (backBufferTex) {
|
||||||
backBufferTex->Release();
|
backBufferTex->Release();
|
||||||
backBufferTex = nullptr;
|
backBufferTex = nullptr;
|
||||||
@ -4869,50 +4957,17 @@ QRhiRenderTarget *QD3D11SwapChain::currentFrameRenderTarget()
|
|||||||
return &rt;
|
return &rt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRhiRenderTarget *QD3D11SwapChain::currentFrameRenderTarget(StereoTargetBuffer targetBuffer)
|
||||||
|
{
|
||||||
|
return targetBuffer == StereoTargetBuffer::LeftBuffer? &rt: &rtRight;
|
||||||
|
}
|
||||||
|
|
||||||
QSize QD3D11SwapChain::surfacePixelSize()
|
QSize QD3D11SwapChain::surfacePixelSize()
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_window);
|
Q_ASSERT(m_window);
|
||||||
return m_window->size() * m_window->devicePixelRatio();
|
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)
|
bool QD3D11SwapChain::isFormatSupported(Format f)
|
||||||
{
|
{
|
||||||
if (f == SDR)
|
if (f == SDR)
|
||||||
@ -4925,7 +4980,7 @@ bool QD3D11SwapChain::isFormatSupported(Format f)
|
|||||||
|
|
||||||
QRHI_RES_RHI(QRhiD3D11);
|
QRHI_RES_RHI(QRhiD3D11);
|
||||||
DXGI_OUTPUT_DESC1 desc1;
|
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)
|
if (desc1.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020)
|
||||||
return f == QRhiSwapChain::HDRExtendedSrgbLinear || f == QRhiSwapChain::HDR10;
|
return f == QRhiSwapChain::HDRExtendedSrgbLinear || f == QRhiSwapChain::HDR10;
|
||||||
}
|
}
|
||||||
@ -4936,14 +4991,16 @@ bool QD3D11SwapChain::isFormatSupported(Format f)
|
|||||||
QRhiSwapChainHdrInfo QD3D11SwapChain::hdrInfo()
|
QRhiSwapChainHdrInfo QD3D11SwapChain::hdrInfo()
|
||||||
{
|
{
|
||||||
QRhiSwapChainHdrInfo info = QRhiSwapChain::hdrInfo();
|
QRhiSwapChainHdrInfo info = QRhiSwapChain::hdrInfo();
|
||||||
|
// Must use m_window, not window, given this may be called before createOrResize().
|
||||||
if (m_window) {
|
if (m_window) {
|
||||||
QRHI_RES_RHI(QRhiD3D11);
|
QRHI_RES_RHI(QRhiD3D11);
|
||||||
DXGI_OUTPUT_DESC1 hdrOutputDesc;
|
DXGI_OUTPUT_DESC1 hdrOutputDesc;
|
||||||
if (outputDesc1ForWindow(m_window, rhiD->activeAdapter, &hdrOutputDesc)) {
|
if (QRhiD3D::outputDesc1ForWindow(m_window, rhiD->activeAdapter, &hdrOutputDesc)) {
|
||||||
info.isHardCodedDefaults = false;
|
|
||||||
info.limitsType = QRhiSwapChainHdrInfo::LuminanceInNits;
|
info.limitsType = QRhiSwapChainHdrInfo::LuminanceInNits;
|
||||||
info.limits.luminanceInNits.minLuminance = hdrOutputDesc.MinLuminance;
|
info.limits.luminanceInNits.minLuminance = hdrOutputDesc.MinLuminance;
|
||||||
info.limits.luminanceInNits.maxLuminance = hdrOutputDesc.MaxLuminance;
|
info.limits.luminanceInNits.maxLuminance = hdrOutputDesc.MaxLuminance;
|
||||||
|
info.luminanceBehavior = QRhiSwapChainHdrInfo::SceneReferred; // 1.0 = 80 nits
|
||||||
|
info.sdrWhiteLevel = QRhiD3D::sdrWhiteLevelInNits(hdrOutputDesc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return info;
|
return info;
|
||||||
@ -5016,11 +5073,13 @@ bool QD3D11SwapChain::createOrResize()
|
|||||||
{
|
{
|
||||||
return createOrResizeWin7();
|
return createOrResizeWin7();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can be called multiple times due to window resizes - that is not the
|
// Can be called multiple times due to window resizes - that is not the
|
||||||
// same as a simple destroy+create (as with other resources). Just need to
|
// same as a simple destroy+create (as with other resources). Just need to
|
||||||
// resize the buffers then.
|
// resize the buffers then.
|
||||||
|
|
||||||
const bool needsRegistration = !window || window != m_window;
|
const bool needsRegistration = !window || window != m_window;
|
||||||
|
const bool stereo = m_window->format().stereo();
|
||||||
|
|
||||||
// except if the window actually changes
|
// except if the window actually changes
|
||||||
if (window && window != m_window)
|
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_COLOR_SPACE_TYPE hdrColorSpace = DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; // SDR
|
||||||
DXGI_OUTPUT_DESC1 hdrOutputDesc;
|
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
|
// https://docs.microsoft.com/en-us/windows/win32/direct3darticles/high-dynamic-range
|
||||||
if (hdrOutputDesc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) {
|
if (hdrOutputDesc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020) {
|
||||||
switch (m_format) {
|
switch (m_format) {
|
||||||
@ -5120,6 +5179,7 @@ bool QD3D11SwapChain::createOrResize()
|
|||||||
desc.Flags = swapChainFlags;
|
desc.Flags = swapChainFlags;
|
||||||
desc.Scaling = rhiD->useLegacySwapchainModel ? DXGI_SCALING_STRETCH : DXGI_SCALING_NONE;
|
desc.Scaling = rhiD->useLegacySwapchainModel ? DXGI_SCALING_STRETCH : DXGI_SCALING_NONE;
|
||||||
desc.SwapEffect = rhiD->useLegacySwapchainModel ? DXGI_SWAP_EFFECT_DISCARD : DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
desc.SwapEffect = rhiD->useLegacySwapchainModel ? DXGI_SWAP_EFFECT_DISCARD : DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
||||||
|
desc.Stereo = stereo;
|
||||||
|
|
||||||
if (dcompVisual) {
|
if (dcompVisual) {
|
||||||
// With DirectComposition setting AlphaMode to STRAIGHT fails the
|
// With DirectComposition setting AlphaMode to STRAIGHT fails the
|
||||||
@ -5238,6 +5298,19 @@ bool QD3D11SwapChain::createOrResize()
|
|||||||
return false;
|
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.
|
// Try to reduce stalls by having a dedicated MSAA texture per swapchain buffer.
|
||||||
for (int i = 0; i < BUFFER_COUNT; ++i) {
|
for (int i = 0; i < BUFFER_COUNT; ++i) {
|
||||||
if (sampleDesc.Count > 1) {
|
if (sampleDesc.Count > 1) {
|
||||||
@ -5276,8 +5349,20 @@ bool QD3D11SwapChain::createOrResize()
|
|||||||
rtD->d.colorAttCount = 1;
|
rtD->d.colorAttCount = 1;
|
||||||
rtD->d.dsAttCount = m_depthStencil ? 1 : 0;
|
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)) {
|
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
|
// timestamp queries are optional so we can go on even if they failed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,6 +356,8 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
|
|||||||
|
|
||||||
struct Command {
|
struct Command {
|
||||||
enum Cmd {
|
enum Cmd {
|
||||||
|
BeginFrame,
|
||||||
|
EndFrame,
|
||||||
ResetShaderResources,
|
ResetShaderResources,
|
||||||
SetRenderTarget,
|
SetRenderTarget,
|
||||||
Clear,
|
Clear,
|
||||||
@ -385,6 +387,15 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
|
|||||||
// QRhi*/QD3D11* references should be kept at minimum (so no
|
// QRhi*/QD3D11* references should be kept at minimum (so no
|
||||||
// QRhiTexture/Buffer/etc. pointers).
|
// QRhiTexture/Buffer/etc. pointers).
|
||||||
union Args {
|
union Args {
|
||||||
|
struct {
|
||||||
|
ID3D11Query *tsQuery;
|
||||||
|
ID3D11Query *tsDisjointQuery;
|
||||||
|
QD3D11RenderTargetData *swapchainData;
|
||||||
|
} beginFrame;
|
||||||
|
struct {
|
||||||
|
ID3D11Query *tsQuery;
|
||||||
|
ID3D11Query *tsDisjointQuery;
|
||||||
|
} endFrame;
|
||||||
struct {
|
struct {
|
||||||
QRhiRenderTarget *rt;
|
QRhiRenderTarget *rt;
|
||||||
} setRenderTarget;
|
} setRenderTarget;
|
||||||
@ -556,17 +567,15 @@ struct QD3D11CommandBuffer : public QRhiCommandBuffer
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int QD3D11_SWAPCHAIN_BUFFER_COUNT = 2;
|
struct QD3D11SwapChainTimestamps
|
||||||
|
|
||||||
struct QD3D11Timestamps
|
|
||||||
{
|
{
|
||||||
static const int MAX_TIMESTAMP_PAIRS = QD3D11_SWAPCHAIN_BUFFER_COUNT;
|
static const int TIMESTAMP_PAIRS = 2;
|
||||||
bool active[MAX_TIMESTAMP_PAIRS] = {};
|
|
||||||
ID3D11Query *disjointQuery[MAX_TIMESTAMP_PAIRS] = {};
|
|
||||||
ID3D11Query *query[MAX_TIMESTAMP_PAIRS * 2] = {};
|
|
||||||
int pairCount = 0;
|
|
||||||
|
|
||||||
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();
|
void destroy();
|
||||||
bool tryQueryTimestamps(int idx, ID3D11DeviceContext *context, double *elapsedSec);
|
bool tryQueryTimestamps(int idx, ID3D11DeviceContext *context, double *elapsedSec);
|
||||||
};
|
};
|
||||||
@ -579,6 +588,7 @@ struct QD3D11SwapChain : public QRhiSwapChain
|
|||||||
|
|
||||||
QRhiCommandBuffer *currentFrameCommandBuffer() override;
|
QRhiCommandBuffer *currentFrameCommandBuffer() override;
|
||||||
QRhiRenderTarget *currentFrameRenderTarget() override;
|
QRhiRenderTarget *currentFrameRenderTarget() override;
|
||||||
|
QRhiRenderTarget *currentFrameRenderTarget(StereoTargetBuffer targetBuffer) override;
|
||||||
|
|
||||||
QSize surfacePixelSize() override;
|
QSize surfacePixelSize() override;
|
||||||
bool isFormatSupported(Format f) override;
|
bool isFormatSupported(Format f) override;
|
||||||
@ -595,6 +605,7 @@ struct QD3D11SwapChain : public QRhiSwapChain
|
|||||||
QWindow *window = nullptr;
|
QWindow *window = nullptr;
|
||||||
QSize pixelSize;
|
QSize pixelSize;
|
||||||
QD3D11SwapChainRenderTarget rt;
|
QD3D11SwapChainRenderTarget rt;
|
||||||
|
QD3D11SwapChainRenderTarget rtRight;
|
||||||
QD3D11CommandBuffer cb;
|
QD3D11CommandBuffer cb;
|
||||||
DXGI_FORMAT colorFormat;
|
DXGI_FORMAT colorFormat;
|
||||||
DXGI_FORMAT srgbAdjustedColorFormat;
|
DXGI_FORMAT srgbAdjustedColorFormat;
|
||||||
@ -602,7 +613,8 @@ struct QD3D11SwapChain : public QRhiSwapChain
|
|||||||
UINT swapChainFlags = 0;
|
UINT swapChainFlags = 0;
|
||||||
ID3D11Texture2D *backBufferTex;
|
ID3D11Texture2D *backBufferTex;
|
||||||
ID3D11RenderTargetView *backBufferRtv;
|
ID3D11RenderTargetView *backBufferRtv;
|
||||||
static const int BUFFER_COUNT = QD3D11_SWAPCHAIN_BUFFER_COUNT;
|
ID3D11RenderTargetView *backBufferRtvRight = nullptr;
|
||||||
|
static const int BUFFER_COUNT = 2;
|
||||||
ID3D11Texture2D *msaaTex[BUFFER_COUNT];
|
ID3D11Texture2D *msaaTex[BUFFER_COUNT];
|
||||||
ID3D11RenderTargetView *msaaRtv[BUFFER_COUNT];
|
ID3D11RenderTargetView *msaaRtv[BUFFER_COUNT];
|
||||||
DXGI_SAMPLE_DESC sampleDesc;
|
DXGI_SAMPLE_DESC sampleDesc;
|
||||||
@ -612,7 +624,8 @@ struct QD3D11SwapChain : public QRhiSwapChain
|
|||||||
UINT swapInterval = 1;
|
UINT swapInterval = 1;
|
||||||
IDCompositionTarget *dcompTarget = nullptr;
|
IDCompositionTarget *dcompTarget = nullptr;
|
||||||
IDCompositionVisual *dcompVisual = nullptr;
|
IDCompositionVisual *dcompVisual = nullptr;
|
||||||
QD3D11Timestamps timestamps;
|
QD3D11SwapChainTimestamps timestamps;
|
||||||
|
int currentTimestampPairIndex = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QRhiD3D11 : public QRhiImplementation
|
class QRhiD3D11 : public QRhiImplementation
|
||||||
@ -737,7 +750,7 @@ public:
|
|||||||
const uint *dynOfsPairs, int dynOfsPairCount,
|
const uint *dynOfsPairs, int dynOfsPairCount,
|
||||||
bool offsetOnlyChange);
|
bool offsetOnlyChange);
|
||||||
void resetShaderResources();
|
void resetShaderResources();
|
||||||
void executeCommandBuffer(QD3D11CommandBuffer *cbD, QD3D11SwapChain *timestampSwapChain = nullptr);
|
void executeCommandBuffer(QD3D11CommandBuffer *cbD);
|
||||||
DXGI_SAMPLE_DESC effectiveSampleDesc(int sampleCount) const;
|
DXGI_SAMPLE_DESC effectiveSampleDesc(int sampleCount) const;
|
||||||
void finishActiveReadbacks();
|
void finishActiveReadbacks();
|
||||||
void reportLiveObjects(ID3D11Device *device);
|
void reportLiveObjects(ID3D11Device *device);
|
||||||
@ -780,8 +793,8 @@ public:
|
|||||||
OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { }
|
OffscreenFrame(QRhiImplementation *rhi) : cbWrapper(rhi) { }
|
||||||
bool active = false;
|
bool active = false;
|
||||||
QD3D11CommandBuffer cbWrapper;
|
QD3D11CommandBuffer cbWrapper;
|
||||||
QD3D11Timestamps timestamps;
|
ID3D11Query *tsQueries[2] = {};
|
||||||
int timestampIdx = 0;
|
ID3D11Query *tsDisjointQuery = nullptr;
|
||||||
} ofr;
|
} ofr;
|
||||||
|
|
||||||
struct TextureReadback {
|
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));
|
if (!m_fontDatas.contains(fontData.data()))
|
||||||
m_fontDatas.insert(key, fontData);
|
m_fontDatas.insert(fontData.data(), fontData);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void removeKey(const void *key)
|
inline void removeKey(const void *key)
|
||||||
@ -378,6 +378,11 @@ namespace {
|
|||||||
UINT32 fontFileReferenceKeySize,
|
UINT32 fontFileReferenceKeySize,
|
||||||
OUT IDWriteFontFileStream **fontFileStream) override;
|
OUT IDWriteFontFileStream **fontFileStream) override;
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
m_fontDatas.clear();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ULONG m_referenceCount;
|
ULONG m_referenceCount;
|
||||||
QHash<const void *, QByteArray> m_fontDatas;
|
QHash<const void *, QByteArray> m_fontDatas;
|
||||||
@ -435,53 +440,63 @@ namespace {
|
|||||||
return S_OK;
|
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
|
} // 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
|
#endif // directwrite && direct2d
|
||||||
|
|
||||||
|
|
||||||
@ -550,8 +565,12 @@ void QWindowsFontDatabaseBase::createDirectWriteFactory(IDWriteFactory **factory
|
|||||||
IUnknown *result = nullptr;
|
IUnknown *result = nullptr;
|
||||||
|
|
||||||
# if QT_CONFIG(directwrite3)
|
# 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
|
# endif
|
||||||
|
|
||||||
if (result == nullptr)
|
if (result == nullptr)
|
||||||
DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory2), &result);
|
DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory2), &result);
|
||||||
|
|
||||||
@ -700,28 +719,47 @@ QFont QWindowsFontDatabaseBase::systemDefaultFont()
|
|||||||
return systemFont;
|
return systemFont;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if QT_CONFIG(directwrite) && QT_CONFIG(direct2d)
|
void QWindowsFontDatabaseBase::invalidate()
|
||||||
IDWriteFontFace *QWindowsFontDatabaseBase::createDirectWriteFace(const QByteArray &fontData) const
|
|
||||||
{
|
{
|
||||||
|
#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();
|
QSharedPointer<QWindowsFontEngineData> fontEngineData = data();
|
||||||
if (fontEngineData->directWriteFactory == nullptr) {
|
if (fontEngineData->directWriteFactory == nullptr) {
|
||||||
qCWarning(lcQpaFonts) << "DirectWrite factory not created in QWindowsFontDatabaseBase::createDirectWriteFace()";
|
qCWarning(lcQpaFonts) << "DirectWrite factory not created in QWindowsFontDatabaseBase::createDirectWriteFace()";
|
||||||
return nullptr;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomFontFileLoader fontFileLoader(fontEngineData->directWriteFactory);
|
if (m_fontFileLoader == nullptr)
|
||||||
fontFileLoader.addKey(this, fontData);
|
m_fontFileLoader.reset(new QCustomFontFileLoader(fontEngineData->directWriteFactory));
|
||||||
|
|
||||||
|
m_fontFileLoader->addKey(fontData);
|
||||||
|
|
||||||
IDWriteFontFile *fontFile = nullptr;
|
IDWriteFontFile *fontFile = nullptr;
|
||||||
const void *key = this;
|
const void *key = fontData.data();
|
||||||
|
|
||||||
HRESULT hres = fontEngineData->directWriteFactory->CreateCustomFontFileReference(&key,
|
HRESULT hres = fontEngineData->directWriteFactory->CreateCustomFontFileReference(&key,
|
||||||
sizeof(void *),
|
sizeof(void *),
|
||||||
fontFileLoader.loader(),
|
m_fontFileLoader->loader(),
|
||||||
&fontFile);
|
&fontFile);
|
||||||
if (FAILED(hres)) {
|
if (FAILED(hres)) {
|
||||||
qErrnoWarning(hres, "%s: CreateCustomFontFileReference failed", __FUNCTION__);
|
qErrnoWarning(hres, "%s: CreateCustomFontFileReference failed", __FUNCTION__);
|
||||||
return nullptr;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL isSupportedFontType;
|
BOOL isSupportedFontType;
|
||||||
@ -731,25 +769,65 @@ IDWriteFontFace *QWindowsFontDatabaseBase::createDirectWriteFace(const QByteArra
|
|||||||
fontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, &numberOfFaces);
|
fontFile->Analyze(&isSupportedFontType, &fontFileType, &fontFaceType, &numberOfFaces);
|
||||||
if (!isSupportedFontType) {
|
if (!isSupportedFontType) {
|
||||||
fontFile->Release();
|
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.
|
// ### Currently no support for .ttc, but we could easily return a list here.
|
||||||
IDWriteFontFace *directWriteFontFace = nullptr;
|
if (ret.isEmpty()) {
|
||||||
hres = fontEngineData->directWriteFactory->CreateFontFace(fontFaceType,
|
IDWriteFontFace *directWriteFontFace = nullptr;
|
||||||
1,
|
hres = fontEngineData->directWriteFactory->CreateFontFace(fontFaceType,
|
||||||
&fontFile,
|
1,
|
||||||
0,
|
&fontFile,
|
||||||
DWRITE_FONT_SIMULATIONS_NONE,
|
0,
|
||||||
&directWriteFontFace);
|
DWRITE_FONT_SIMULATIONS_NONE,
|
||||||
if (FAILED(hres)) {
|
&directWriteFontFace);
|
||||||
qErrnoWarning(hres, "%s: CreateFontFace failed", __FUNCTION__);
|
if (FAILED(hres)) {
|
||||||
fontFile->Release();
|
qErrnoWarning(hres, "%s: CreateFontFace failed", __FUNCTION__);
|
||||||
return nullptr;
|
fontFile->Release();
|
||||||
|
return ret;
|
||||||
|
} else {
|
||||||
|
ret.append(directWriteFontFace);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fontFile->Release();
|
fontFile->Release();
|
||||||
return directWriteFontFace;
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
#endif // directwrite && direct2d
|
#endif // directwrite && direct2d
|
||||||
|
|
||||||
@ -769,7 +847,10 @@ QFontEngine *QWindowsFontDatabaseBase::fontEngine(const QByteArray &fontData, qr
|
|||||||
if (fontEngineData->directWriteFactory == nullptr)
|
if (fontEngineData->directWriteFactory == nullptr)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
IDWriteFontFace *directWriteFontFace = createDirectWriteFace(fontData);
|
IDWriteFontFace * directWriteFontFace = createDirectWriteFace(fontData);
|
||||||
|
if (directWriteFontFace == nullptr)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
fontEngine = new QWindowsFontEngineDirectWrite(directWriteFontFace,
|
fontEngine = new QWindowsFontEngineDirectWrite(directWriteFontFace,
|
||||||
pixelSize,
|
pixelSize,
|
||||||
fontEngineData);
|
fontEngineData);
|
||||||
|
@ -46,10 +46,13 @@
|
|||||||
#include <QtCore/quuid.h>
|
#include <QtCore/quuid.h>
|
||||||
#include <QtCore/private/qsystemlibrary_p.h>
|
#include <QtCore/private/qsystemlibrary_p.h>
|
||||||
#include <QtCore/private/qwinregistry_p.h>
|
#include <QtCore/private/qwinregistry_p.h>
|
||||||
#include <QtCore/private/qfactorycacheregistration_p.h>
|
#if QT_CONFIG(cpp_winrt)
|
||||||
|
# include <QtCore/private/qfactorycacheregistration_p.h>
|
||||||
|
#endif
|
||||||
#include <QtCore/private/qsystemerror_p.h>
|
#include <QtCore/private/qsystemerror_p.h>
|
||||||
|
|
||||||
#include <QtGui/private/qwindowsguieventdispatcher_p.h>
|
#include <QtGui/private/qwindowsguieventdispatcher_p.h>
|
||||||
|
#include <QtGui/private/qwindowsthemecache_p.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -58,6 +61,8 @@
|
|||||||
#include <wtsapi32.h>
|
#include <wtsapi32.h>
|
||||||
#include <shellscalingapi.h>
|
#include <shellscalingapi.h>
|
||||||
|
|
||||||
|
#include "vxkex.h"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace Qt::StringLiterals;
|
using namespace Qt::StringLiterals;
|
||||||
@ -276,6 +281,8 @@ QWindowsContext::~QWindowsContext()
|
|||||||
if (d->m_powerDummyWindow)
|
if (d->m_powerDummyWindow)
|
||||||
DestroyWindow(d->m_powerDummyWindow);
|
DestroyWindow(d->m_powerDummyWindow);
|
||||||
|
|
||||||
|
d->m_screenManager.destroyWindow();
|
||||||
|
|
||||||
unregisterWindowClasses();
|
unregisterWindowClasses();
|
||||||
if (d->m_oleInitializeResult == S_OK || d->m_oleInitializeResult == S_FALSE) {
|
if (d->m_oleInitializeResult == S_OK || d->m_oleInitializeResult == S_FALSE) {
|
||||||
#ifdef QT_USE_FACTORY_CACHE_REGISTRATION
|
#ifdef QT_USE_FACTORY_CACHE_REGISTRATION
|
||||||
@ -445,11 +452,25 @@ void QWindowsContext::setDetectAltGrModifier(bool a)
|
|||||||
return QtWindows::DpiAwareness::System;
|
return QtWindows::DpiAwareness::System;
|
||||||
if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE))
|
if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE))
|
||||||
return QtWindows::DpiAwareness::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)
|
QtWindows::DpiAwareness QWindowsContext::windowDpiAwareness(HWND hwnd)
|
||||||
@ -457,31 +478,26 @@ QtWindows::DpiAwareness QWindowsContext::windowDpiAwareness(HWND hwnd)
|
|||||||
if (!hwnd)
|
if (!hwnd)
|
||||||
return QtWindows::DpiAwareness::Invalid;
|
return QtWindows::DpiAwareness::Invalid;
|
||||||
|
|
||||||
if (QWindowsContext::user32dll.getWindowDpiAwarenessContext)
|
const auto context = QWindowsContext::user32dll.getWindowDpiAwarenessContext ?
|
||||||
{
|
QWindowsContext::user32dll.getWindowDpiAwarenessContext(hwnd) :
|
||||||
const auto context = QWindowsContext::user32dll.getWindowDpiAwarenessContext(hwnd);
|
vxkex::GetWindowDpiAwarenessContext(hwnd);
|
||||||
return dpiAwarenessContextToQtDpiAwareness(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dpiAwarenessContextToQtDpiAwareness(DPI_AWARENESS_CONTEXT_UNAWARE);
|
return dpiAwarenessContextToQtDpiAwareness(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
QtWindows::DpiAwareness QWindowsContext::processDpiAwareness()
|
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
|
||||||
// Although we have GetDpiAwarenessContextForProcess(), however,
|
// than Qt's minimum supported version (1809), so we can't use it.
|
||||||
// it's only available on Win10 1903+, which is a little higher
|
// Luckily, MS docs said GetThreadDpiAwarenessContext() will also
|
||||||
// than Qt's minimum supported version (1809), so we can't use it.
|
// return the default DPI_AWARENESS_CONTEXT for the process if
|
||||||
// Luckily, MS docs said GetThreadDpiAwarenessContext() will also
|
// SetThreadDpiAwarenessContext() was never called. So we can use
|
||||||
// return the default DPI_AWARENESS_CONTEXT for the process if
|
// it as an equivalent.
|
||||||
// SetThreadDpiAwarenessContext() was never called. So we can use
|
const DPI_AWARENESS_CONTEXT context = QWindowsContext::user32dll.getThreadDpiAwarenessContext ?
|
||||||
// it as an equivalent.
|
QWindowsContext::user32dll.getThreadDpiAwarenessContext() :
|
||||||
const auto context = QWindowsContext::user32dll.getThreadDpiAwarenessContext();
|
vxkex::GetThreadDpiAwarenessContext();
|
||||||
return dpiAwarenessContextToQtDpiAwareness(context);
|
return dpiAwarenessContextToQtDpiAwareness(context);
|
||||||
}
|
|
||||||
|
|
||||||
return dpiAwarenessContextToQtDpiAwareness(DPI_AWARENESS_CONTEXT_UNAWARE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] static inline DPI_AWARENESS_CONTEXT
|
[[nodiscard]] static inline DPI_AWARENESS_CONTEXT
|
||||||
@ -541,28 +557,32 @@ bool QWindowsContext::setProcessDpiAwareness(QtWindows::DpiAwareness dpiAwarenes
|
|||||||
return true;
|
return true;
|
||||||
const auto context = qtDpiAwarenessToDpiAwarenessContext(dpiAwareness);
|
const auto context = qtDpiAwarenessToDpiAwarenessContext(dpiAwareness);
|
||||||
|
|
||||||
if (QWindowsContext::user32dll.isValidDpiAwarenessContext && QWindowsContext::user32dll.setProcessDpiAwarenessContext)
|
BOOL bResultIsValid = QWindowsContext::user32dll.isValidDpiAwarenessContext ?
|
||||||
{
|
QWindowsContext::user32dll.isValidDpiAwarenessContext(context) :
|
||||||
if (!QWindowsContext::user32dll.isValidDpiAwarenessContext(context)) {
|
vxkex::IsValidDpiAwarenessContext(context);
|
||||||
qCWarning(lcQpaWindow) << dpiAwareness << "is not supported by current system.";
|
|
||||||
return false;
|
if (!bResultIsValid) {
|
||||||
}
|
qCWarning(lcQpaWindow) << dpiAwareness << "is not supported by current system.";
|
||||||
if (!QWindowsContext::user32dll.setProcessDpiAwarenessContext(context)) {
|
return false;
|
||||||
qCWarning(lcQpaWindow).noquote().nospace()
|
|
||||||
<< "SetProcessDpiAwarenessContext() failed: "
|
|
||||||
<< QSystemError::windowsString()
|
|
||||||
<< "\nQt's default DPI awareness context is "
|
|
||||||
<< "DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2. If you know what you "
|
|
||||||
<< "are doing, you can overwrite this default using qt.conf "
|
|
||||||
<< "(https://doc.qt.io/qt-6/highdpi.html#configuring-windows).";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
QWindowsContextPrivate::m_v2DpiAware
|
|
||||||
= processDpiAwareness() == QtWindows::DpiAwareness::PerMonitorVersion2;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false; // Windows 7
|
BOOL 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()
|
bool QWindowsContext::isDarkMode()
|
||||||
@ -585,9 +605,9 @@ bool QWindowsContext::useRTLExtensions() const
|
|||||||
return d->m_keyMapper.useRTLExtensions();
|
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()
|
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)
|
const BOOL result = (QWindowsContext::user32dll.systemParametersInfoForDpi != nullptr && dpi != 0)
|
||||||
? QWindowsContext::user32dll.systemParametersInfoForDpi(action, param, out, 0, dpi)
|
? QWindowsContext::user32dll.systemParametersInfoForDpi(action, param, out, 0, dpi)
|
||||||
: SystemParametersInfo(action, param, out, 0);
|
: vxkex::SystemParametersInfoForDpi(action, param, out, 0, dpi);
|
||||||
return result == TRUE;
|
return result == TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1080,8 +1100,11 @@ static inline bool isInputMessage(UINT m)
|
|||||||
static bool enableNonClientDpiScaling(HWND hwnd)
|
static bool enableNonClientDpiScaling(HWND hwnd)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if (QWindowsContext::user32dll.enableNonClientDpiScaling && QWindowsContext::windowDpiAwareness(hwnd) == QtWindows::DpiAwareness::PerMonitor) {
|
if (QWindowsContext::windowDpiAwareness(hwnd) == QtWindows::DpiAwareness::PerMonitor) {
|
||||||
result = QWindowsContext::user32dll.enableNonClientDpiScaling(hwnd) != FALSE;
|
result = QWindowsContext::user32dll.enableNonClientDpiScaling ?
|
||||||
|
(QWindowsContext::user32dll.enableNonClientDpiScaling(hwnd) != FALSE) :
|
||||||
|
(vxkex::EnableNonClientDpiScaling(hwnd) != FALSE);
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
const DWORD errorCode = GetLastError();
|
const DWORD errorCode = GetLastError();
|
||||||
qErrnoWarning(int(errorCode), "EnableNonClientDpiScaling() failed for HWND %p (%lu)",
|
qErrnoWarning(int(errorCode), "EnableNonClientDpiScaling() failed for HWND %p (%lu)",
|
||||||
@ -1267,7 +1290,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
|
|||||||
if (wParam == DBT_DEVNODES_CHANGED)
|
if (wParam == DBT_DEVNODES_CHANGED)
|
||||||
initTouch();
|
initTouch();
|
||||||
break;
|
break;
|
||||||
case QtWindows::KeyboardLayoutChangeEvent:
|
case QtWindows::InputLanguageChangeEvent:
|
||||||
if (QWindowsInputContext *wic = windowsInputContext())
|
if (QWindowsInputContext *wic = windowsInputContext())
|
||||||
wic->handleInputLanguageChanged(wParam, lParam);
|
wic->handleInputLanguageChanged(wParam, lParam);
|
||||||
Q_FALLTHROUGH();
|
Q_FALLTHROUGH();
|
||||||
@ -1379,6 +1402,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
|
|||||||
QWindowSystemInterface::handleCloseEvent(platformWindow->window());
|
QWindowSystemInterface::handleCloseEvent(platformWindow->window());
|
||||||
return true;
|
return true;
|
||||||
case QtWindows::ThemeChanged: {
|
case QtWindows::ThemeChanged: {
|
||||||
|
QWindowsThemeCache::clearThemeCache(platformWindow->handle());
|
||||||
// Switch from Aero to Classic changes margins.
|
// Switch from Aero to Classic changes margins.
|
||||||
if (QWindowsTheme *theme = QWindowsTheme::instance())
|
if (QWindowsTheme *theme = QWindowsTheme::instance())
|
||||||
theme->windowsThemeChanged(platformWindow->window());
|
theme->windowsThemeChanged(platformWindow->window());
|
||||||
@ -1517,7 +1541,7 @@ void QWindowsContext::handleFocusEvent(QtWindows::WindowsEventType et,
|
|||||||
}
|
}
|
||||||
if (nextActiveWindow != d->m_lastActiveWindow) {
|
if (nextActiveWindow != d->m_lastActiveWindow) {
|
||||||
d->m_lastActiveWindow = nextActiveWindow;
|
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,
|
QWindowSystemInterface::handleContextMenuEvent(window, mouseTriggered, pos, globalPos,
|
||||||
QWindowsKeyMapper::queryKeyboardModifiers());
|
keyMapper()->queryKeyboardModifiers());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -1568,7 +1592,7 @@ void QWindowsContext::handleExitSizeMove(QWindow *window)
|
|||||||
const Qt::MouseButtons appButtons = QGuiApplication::mouseButtons();
|
const Qt::MouseButtons appButtons = QGuiApplication::mouseButtons();
|
||||||
if (currentButtons == appButtons)
|
if (currentButtons == appButtons)
|
||||||
return;
|
return;
|
||||||
const Qt::KeyboardModifiers keyboardModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
|
const Qt::KeyboardModifiers keyboardModifiers = keyMapper()->queryKeyboardModifiers();
|
||||||
const QPoint globalPos = QWindowsCursor::mousePosition();
|
const QPoint globalPos = QWindowsCursor::mousePosition();
|
||||||
const QPlatformWindow *platWin = window->handle();
|
const QPlatformWindow *platWin = window->handle();
|
||||||
const QPoint localPos = platWin->mapFromGlobal(globalPos);
|
const QPoint localPos = platWin->mapFromGlobal(globalPos);
|
||||||
|
@ -34,6 +34,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen)
|
|||||||
class QWindow;
|
class QWindow;
|
||||||
class QPlatformScreen;
|
class QPlatformScreen;
|
||||||
class QPlatformWindow;
|
class QPlatformWindow;
|
||||||
|
class QPlatformKeyMapper;
|
||||||
class QWindowsMenuBar;
|
class QWindowsMenuBar;
|
||||||
class QWindowsScreenManager;
|
class QWindowsScreenManager;
|
||||||
class QWindowsTabletSupport;
|
class QWindowsTabletSupport;
|
||||||
@ -217,7 +218,7 @@ public:
|
|||||||
unsigned systemInfo() const;
|
unsigned systemInfo() const;
|
||||||
|
|
||||||
bool useRTLExtensions() const;
|
bool useRTLExtensions() const;
|
||||||
QList<int> possibleKeys(const QKeyEvent *e) const;
|
QPlatformKeyMapper *keyMapper() const;
|
||||||
|
|
||||||
HandleBaseWindowHash &windows();
|
HandleBaseWindowHash &windows();
|
||||||
|
|
||||||
|
@ -28,9 +28,13 @@
|
|||||||
#include <QtCore/qdebug.h>
|
#include <QtCore/qdebug.h>
|
||||||
#include <QtCore/qbuffer.h>
|
#include <QtCore/qbuffer.h>
|
||||||
#include <QtCore/qpoint.h>
|
#include <QtCore/qpoint.h>
|
||||||
|
#include <QtCore/qpointer.h>
|
||||||
|
#include <QtCore/private/qcomobject_p.h>
|
||||||
|
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
|
|
||||||
|
#include "vxkex.h"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -167,7 +171,7 @@ static Qt::MouseButtons lastButtons = Qt::NoButton;
|
|||||||
\internal
|
\internal
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class QWindowsOleDropSource : public QWindowsComBase<IDropSource>
|
class QWindowsOleDropSource : public QComObject<IDropSource>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Mode {
|
enum Mode {
|
||||||
@ -526,7 +530,8 @@ QWindowsOleDropTarget::DragLeave()
|
|||||||
|
|
||||||
qCDebug(lcQpaMime) << __FUNCTION__ << ' ' << m_window;
|
qCDebug(lcQpaMime) << __FUNCTION__ << ' ' << m_window;
|
||||||
|
|
||||||
lastModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
|
const auto *keyMapper = QWindowsContext::instance()->keyMapper();
|
||||||
|
lastModifiers = keyMapper->queryKeyboardModifiers();
|
||||||
lastButtons = QWindowsMouseHandler::queryMouseButtons();
|
lastButtons = QWindowsMouseHandler::queryMouseButtons();
|
||||||
|
|
||||||
QWindowSystemInterface::handleDrag(m_window, nullptr, QPoint(), Qt::IgnoreAction,
|
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_canceled = false;
|
||||||
bool QWindowsDrag::m_dragging = false;
|
|
||||||
|
|
||||||
QWindowsDrag::QWindowsDrag() = default;
|
QWindowsDrag::QWindowsDrag() = default;
|
||||||
|
|
||||||
@ -671,7 +675,11 @@ static HRESULT startDoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource,
|
|||||||
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
|
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
|
||||||
|
|
||||||
POINTER_INFO pointerInfo{};
|
POINTER_INFO pointerInfo{};
|
||||||
if (!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;
|
return E_FAIL;
|
||||||
|
|
||||||
if (pointerInfo.pointerFlags & POINTER_FLAG_PRIMARY) {
|
if (pointerInfo.pointerFlags & POINTER_FLAG_PRIMARY) {
|
||||||
@ -739,10 +747,7 @@ Qt::DropAction QWindowsDrag::drag(QDrag *drag)
|
|||||||
const DWORD allowedEffects = translateToWinDragEffects(possibleActions);
|
const DWORD allowedEffects = translateToWinDragEffects(possibleActions);
|
||||||
qCDebug(lcQpaMime) << '>' << __FUNCTION__ << "possible Actions=0x"
|
qCDebug(lcQpaMime) << '>' << __FUNCTION__ << "possible Actions=0x"
|
||||||
<< Qt::hex << int(possibleActions) << "effects=0x" << allowedEffects << Qt::dec;
|
<< 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);
|
const HRESULT r = startDoDragDrop(dropDataObject, windowDropSource, allowedEffects, &resultEffect);
|
||||||
QWindowsDrag::m_dragging = false;
|
|
||||||
const DWORD reportedPerformedEffect = dropDataObject->reportedPerformedEffect();
|
const DWORD reportedPerformedEffect = dropDataObject->reportedPerformedEffect();
|
||||||
if (r == DRAGDROP_S_DROP) {
|
if (r == DRAGDROP_S_DROP) {
|
||||||
if (reportedPerformedEffect == DROPEFFECT_MOVE && resultEffect != DROPEFFECT_MOVE) {
|
if (reportedPerformedEffect == DROPEFFECT_MOVE && resultEffect != DROPEFFECT_MOVE) {
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
#include <QtCore/private/qdebug_p.h>
|
#include <QtCore/private/qdebug_p.h>
|
||||||
#include <QtCore/private/qtools_p.h>
|
#include <QtCore/private/qtools_p.h>
|
||||||
|
|
||||||
|
#include "vxkex.h"
|
||||||
|
|
||||||
#if defined(WM_APPCOMMAND)
|
#if defined(WM_APPCOMMAND)
|
||||||
# ifndef FAPPCOMMAND_MOUSE
|
# ifndef FAPPCOMMAND_MOUSE
|
||||||
# define FAPPCOMMAND_MOUSE 0x8000
|
# define FAPPCOMMAND_MOUSE 0x8000
|
||||||
@ -88,9 +90,17 @@ QWindowsKeyMapper::~QWindowsKeyMapper()= default;
|
|||||||
#define VK_OEM_3 0xC0
|
#define VK_OEM_3 0xC0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// We not only need the scancode itself but also the extended bit of key messages. Thus we need
|
// Get scancode from the given message
|
||||||
// the additional bit when masking the scancode.
|
static constexpr quint32 getScancode(const MSG &msg)
|
||||||
enum { scancodeBitmask = 0x1ff };
|
{
|
||||||
|
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 ] --
|
// Key recorder ------------------------------------------------------------------------[ start ] --
|
||||||
struct KeyRecord {
|
struct KeyRecord {
|
||||||
@ -532,33 +542,6 @@ QDebug operator<<(QDebug d, const KeyboardLayoutItem &k)
|
|||||||
d << ')';
|
d << ')';
|
||||||
return 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
|
#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
|
unsigned char kbdBuffer[256]; // Will hold the complete keyboard state
|
||||||
GetKeyboardState(kbdBuffer);
|
GetKeyboardState(kbdBuffer);
|
||||||
const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask;
|
const quint32 scancode = getScancode(msg);
|
||||||
updatePossibleKeyCodes(kbdBuffer, scancode, quint32(msg.wParam));
|
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)
|
[[nodiscard]] static inline int getTitleBarHeight(const HWND hwnd)
|
||||||
{
|
{
|
||||||
if (QWindowsContext::user32dll.getDpiForWindow && QWindowsContext::user32dll.getSystemMetricsForDpi)
|
const BOOL bNewAPI = (QWindowsContext::user32dll.getSystemMetricsForDpi != nullptr);
|
||||||
{
|
const UINT dpi = bNewAPI ? QWindowsContext::user32dll.getDpiForWindow(hwnd) : vxkex::GetDpiForWindow(hwnd);
|
||||||
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
|
const int captionHeight = bNewAPI ? QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYCAPTION, dpi) : vxkex::GetSystemMetricsForDpi(SM_CYCAPTION, dpi);
|
||||||
const int captionHeight = QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYCAPTION, dpi);
|
if (IsZoomed(hwnd))
|
||||||
if (IsZoomed(hwnd))
|
return captionHeight;
|
||||||
return captionHeight;
|
// The frame height should also be taken into account if the window
|
||||||
// The frame height should also be taken into account if the window
|
// is not maximized.
|
||||||
// is not maximized.
|
const int frameHeight = bNewAPI ?
|
||||||
const int frameHeight = QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYSIZEFRAME, dpi)
|
(QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYSIZEFRAME, dpi) + QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi))
|
||||||
+ QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
: (vxkex::GetSystemMetricsForDpi(SM_CYSIZEFRAME, dpi) + vxkex::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi));
|
||||||
return captionHeight + frameHeight;
|
|
||||||
}
|
return captionHeight + frameHeight;
|
||||||
else
|
|
||||||
{
|
|
||||||
const int captionHeight = GetSystemMetrics(SM_CYCAPTION);
|
|
||||||
if (IsZoomed(hwnd))
|
|
||||||
return captionHeight;
|
|
||||||
// The frame height should also be taken into account if the window
|
|
||||||
// is not maximized.
|
|
||||||
const int frameHeight = GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
|
|
||||||
return captionHeight + frameHeight;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] static inline bool isSystemMenuOffsetNeeded(const Qt::WindowFlags flags)
|
[[nodiscard]] static inline bool isSystemMenuOffsetNeeded(const Qt::WindowFlags flags)
|
||||||
@ -955,7 +928,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
|
|||||||
m_seenAltGr = true;
|
m_seenAltGr = true;
|
||||||
const UINT msgType = msg.message;
|
const UINT msgType = msg.message;
|
||||||
|
|
||||||
const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask;
|
const quint32 scancode = getScancode(msg);
|
||||||
auto vk_key = quint32(msg.wParam);
|
auto vk_key = quint32(msg.wParam);
|
||||||
quint32 nModifiers = 0;
|
quint32 nModifiers = 0;
|
||||||
|
|
||||||
@ -1352,7 +1325,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::KeyboardModifiers QWindowsKeyMapper::queryKeyboardModifiers()
|
Qt::KeyboardModifiers QWindowsKeyMapper::queryKeyboardModifiers() const
|
||||||
{
|
{
|
||||||
Qt::KeyboardModifiers modifiers = Qt::NoModifier;
|
Qt::KeyboardModifiers modifiers = Qt::NoModifier;
|
||||||
if (GetKeyState(VK_SHIFT) < 0)
|
if (GetKeyState(VK_SHIFT) < 0)
|
||||||
@ -1366,9 +1339,9 @@ Qt::KeyboardModifiers QWindowsKeyMapper::queryKeyboardModifiers()
|
|||||||
return modifiers;
|
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();
|
const quint32 nativeVirtualKey = e->nativeVirtualKey();
|
||||||
@ -1382,31 +1355,34 @@ QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const
|
|||||||
quint32 baseKey = kbItem.qtKey[0];
|
quint32 baseKey = kbItem.qtKey[0];
|
||||||
Qt::KeyboardModifiers keyMods = e->modifiers();
|
Qt::KeyboardModifiers keyMods = e->modifiers();
|
||||||
if (baseKey == Qt::Key_Return && (e->nativeModifiers() & ExtendedKey)) {
|
if (baseKey == Qt::Key_Return && (e->nativeModifiers() & ExtendedKey)) {
|
||||||
result << (Qt::Key_Enter | keyMods).toCombined();
|
result << (Qt::Key_Enter | keyMods);
|
||||||
return result;
|
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) {
|
for (size_t i = 1; i < NumMods; ++i) {
|
||||||
Qt::KeyboardModifiers neededMods = ModsTbl[i];
|
Qt::KeyboardModifiers neededMods = ModsTbl[i];
|
||||||
quint32 key = kbItem.qtKey[i];
|
quint32 key = kbItem.qtKey[i];
|
||||||
if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) {
|
if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) {
|
||||||
const Qt::KeyboardModifiers missingMods = keyMods & ~neededMods;
|
const Qt::KeyboardModifiers missingMods = keyMods & ~neededMods;
|
||||||
const int matchedKey = int(key) + int(missingMods);
|
const auto matchedKey = QKeyCombination::fromCombined(int(key) + int(missingMods));
|
||||||
const auto it =
|
const auto it = std::find_if(result.begin(), result.end(),
|
||||||
std::find_if(result.begin(), result.end(),
|
[key](auto keyCombination) {
|
||||||
[key] (int k) { return (k & ~Qt::KeyboardModifierMask) == key; });
|
return keyCombination.key() == key;
|
||||||
|
});
|
||||||
// QTBUG-67200: Use the match with the least modifiers (prefer
|
// QTBUG-67200: Use the match with the least modifiers (prefer
|
||||||
// Shift+9 over Alt + Shift + 9) resulting in more missing modifiers.
|
// Shift+9 over Alt + Shift + 9) resulting in more missing modifiers.
|
||||||
if (it == result.end())
|
if (it == result.end())
|
||||||
result << matchedKey;
|
result << matchedKey;
|
||||||
else if (missingMods > Qt::KeyboardModifiers(*it & Qt::KeyboardModifierMask))
|
else if (missingMods > it->keyboardModifiers())
|
||||||
*it = matchedKey;
|
*it = matchedKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qCDebug(lcQpaEvents) << __FUNCTION__ << e << "nativeVirtualKey="
|
qCDebug(lcQpaEvents) << __FUNCTION__ << e << "nativeVirtualKey="
|
||||||
<< Qt::showbase << Qt::hex << e->nativeVirtualKey() << Qt::dec << Qt::noshowbase
|
<< 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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
|
|
||||||
|
#include "vxkex.h"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -48,7 +50,11 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
|||||||
*result = 0;
|
*result = 0;
|
||||||
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
|
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
|
||||||
|
|
||||||
if (!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();
|
qWarning() << "GetPointerType() failed:" << qt_error_string();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -62,12 +68,21 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
|||||||
}
|
}
|
||||||
case QT_PT_TOUCH: {
|
case QT_PT_TOUCH: {
|
||||||
quint32 pointerCount = 0;
|
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();
|
qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
QVarLengthArray<POINTER_TOUCH_INFO, 10> touchInfo(pointerCount);
|
QVarLengthArray<POINTER_TOUCH_INFO, 10> touchInfo(pointerCount);
|
||||||
if (!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();
|
qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
|
||||||
return false;
|
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
|
// dispatch any skipped frames if event compression is disabled by the app
|
||||||
if (historyCount > 1 && !QCoreApplication::testAttribute(Qt::AA_CompressHighFrequencyEvents)) {
|
if (historyCount > 1 && !QCoreApplication::testAttribute(Qt::AA_CompressHighFrequencyEvents)) {
|
||||||
touchInfo.resize(pointerCount * historyCount);
|
touchInfo.resize(pointerCount * historyCount);
|
||||||
if (!QWindowsContext::user32dll.getPointerFrameTouchInfoHistory(pointerId,
|
|
||||||
&historyCount,
|
BOOL bResultTouchHistory = QWindowsContext::user32dll.getPointerFrameTouchInfoHistory ?
|
||||||
&pointerCount,
|
QWindowsContext::user32dll.getPointerFrameTouchInfoHistory(pointerId, &historyCount, &pointerCount, touchInfo.data()) :
|
||||||
touchInfo.data())) {
|
vxkex::GetPointerFrameTouchInfoHistory(pointerId, &historyCount, &pointerCount, touchInfo.data());
|
||||||
|
|
||||||
|
if (!bResultTouchHistory) {
|
||||||
qWarning() << "GetPointerFrameTouchInfoHistory() failed:" << qt_error_string();
|
qWarning() << "GetPointerFrameTouchInfoHistory() failed:" << qt_error_string();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -101,7 +118,11 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
|||||||
}
|
}
|
||||||
case QT_PT_PEN: {
|
case QT_PT_PEN: {
|
||||||
POINTER_PEN_INFO penInfo;
|
POINTER_PEN_INFO penInfo;
|
||||||
if (!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();
|
qWarning() << "GetPointerPenInfo() failed:" << qt_error_string();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -113,7 +134,11 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
|||||||
|| !QCoreApplication::testAttribute(Qt::AA_CompressTabletEvents))) {
|
|| !QCoreApplication::testAttribute(Qt::AA_CompressTabletEvents))) {
|
||||||
QVarLengthArray<POINTER_PEN_INFO, 10> penInfoHistory(historyCount);
|
QVarLengthArray<POINTER_PEN_INFO, 10> penInfoHistory(historyCount);
|
||||||
|
|
||||||
if (!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();
|
qWarning() << "GetPointerPenInfoHistory() failed:" << qt_error_string();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -428,8 +453,9 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (msg.message == WM_POINTERCAPTURECHANGED) {
|
if (msg.message == WM_POINTERCAPTURECHANGED) {
|
||||||
|
const auto *keyMapper = QWindowsContext::instance()->keyMapper();
|
||||||
QWindowSystemInterface::handleTouchCancelEvent(window, m_touchDevice.data(),
|
QWindowSystemInterface::handleTouchCancelEvent(window, m_touchDevice.data(),
|
||||||
QWindowsKeyMapper::queryKeyboardModifiers());
|
keyMapper->queryKeyboardModifiers());
|
||||||
m_lastTouchPoints.clear();
|
m_lastTouchPoints.clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -519,7 +545,10 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
|
|||||||
inputIds.insert(touchPoint.id);
|
inputIds.insert(touchPoint.id);
|
||||||
|
|
||||||
// Avoid getting repeated messages for this frame if there are multiple pointerIds
|
// Avoid getting repeated messages for this frame if there are multiple pointerIds
|
||||||
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
|
// 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)
|
if (allStates == QEventPoint::State::Released)
|
||||||
m_touchInputIDToTouchPointID.clear();
|
m_touchInputIDToTouchPointID.clear();
|
||||||
|
|
||||||
|
const auto *keyMapper = QWindowsContext::instance()->keyMapper();
|
||||||
QWindowSystemInterface::handleTouchEvent(window, m_touchDevice.data(), touchPoints,
|
QWindowSystemInterface::handleTouchEvent(window, m_touchDevice.data(), touchPoints,
|
||||||
QWindowsKeyMapper::queryKeyboardModifiers());
|
keyMapper->queryKeyboardModifiers());
|
||||||
return false; // Allow mouse messages to be generated.
|
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);
|
auto *penInfo = static_cast<POINTER_PEN_INFO *>(vPenInfo);
|
||||||
|
|
||||||
RECT pRect, dRect;
|
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;
|
return false;
|
||||||
|
|
||||||
const auto systemId = (qint64)penInfo->pointerInfo.sourceDevice;
|
const auto systemId = (qint64)penInfo->pointerInfo.sourceDevice;
|
||||||
@ -673,7 +708,8 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
|
|||||||
wumPlatformWindow->applyCursor();
|
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(),
|
QWindowSystemInterface::handleTabletEvent(target, device.data(),
|
||||||
localPos, hiResGlobalPos, mouseButtons,
|
localPos, hiResGlobalPos, mouseButtons,
|
||||||
@ -762,7 +798,8 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
|
|||||||
: QWindowsGeometryHint::mapFromGlobal(targetHwnd, globalPos);
|
: 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);
|
QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
|
||||||
|
|
||||||
if (et == QtWindows::MouseWheelEvent)
|
if (et == QtWindows::MouseWheelEvent)
|
||||||
|
@ -32,6 +32,8 @@
|
|||||||
#include <setupapi.h>
|
#include <setupapi.h>
|
||||||
#include <shellscalingapi.h>
|
#include <shellscalingapi.h>
|
||||||
|
|
||||||
|
#include "vxkex.h"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using namespace Qt::StringLiterals;
|
using namespace Qt::StringLiterals;
|
||||||
@ -43,12 +45,18 @@ static inline QDpi deviceDPI(HDC hdc)
|
|||||||
|
|
||||||
static inline QDpi monitorDPI(HMONITOR hMonitor)
|
static inline QDpi monitorDPI(HMONITOR hMonitor)
|
||||||
{
|
{
|
||||||
if (QWindowsContext::shcoredll.isValid()) {
|
UINT dpiX;
|
||||||
UINT dpiX;
|
UINT dpiY;
|
||||||
UINT dpiY;
|
|
||||||
if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY)))
|
HRESULT hr = S_OK;
|
||||||
return QDpi(dpiX, dpiY);
|
|
||||||
}
|
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};
|
return {0, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -579,51 +587,58 @@ QRect QWindowsScreen::virtualGeometry(const QPlatformScreen *screen) // cf QScre
|
|||||||
bool QWindowsScreen::setOrientationPreference(Qt::ScreenOrientation o)
|
bool QWindowsScreen::setOrientationPreference(Qt::ScreenOrientation o)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if (QWindowsContext::user32dll.setDisplayAutoRotationPreferences) {
|
ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
||||||
ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
switch (o) {
|
||||||
switch (o) {
|
case Qt::PrimaryOrientation:
|
||||||
case Qt::PrimaryOrientation:
|
break;
|
||||||
break;
|
case Qt::PortraitOrientation:
|
||||||
case Qt::PortraitOrientation:
|
orientationPreference = ORIENTATION_PREFERENCE_PORTRAIT;
|
||||||
orientationPreference = ORIENTATION_PREFERENCE_PORTRAIT;
|
break;
|
||||||
break;
|
case Qt::LandscapeOrientation:
|
||||||
case Qt::LandscapeOrientation:
|
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE;
|
||||||
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE;
|
break;
|
||||||
break;
|
case Qt::InvertedPortraitOrientation:
|
||||||
case Qt::InvertedPortraitOrientation:
|
orientationPreference = ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED;
|
||||||
orientationPreference = ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED;
|
break;
|
||||||
break;
|
case Qt::InvertedLandscapeOrientation:
|
||||||
case Qt::InvertedLandscapeOrientation:
|
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED;
|
||||||
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED;
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
result = QWindowsContext::user32dll.setDisplayAutoRotationPreferences(orientationPreference);
|
|
||||||
}
|
}
|
||||||
|
if (QWindowsContext::user32dll.setDisplayAutoRotationPreferences)
|
||||||
|
result = QWindowsContext::user32dll.setDisplayAutoRotationPreferences(orientationPreference);
|
||||||
|
else
|
||||||
|
result = vxkex::SetDisplayAutoRotationPreferences(orientationPreference);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::ScreenOrientation QWindowsScreen::orientationPreference()
|
Qt::ScreenOrientation QWindowsScreen::orientationPreference()
|
||||||
{
|
{
|
||||||
Qt::ScreenOrientation result = Qt::PrimaryOrientation;
|
Qt::ScreenOrientation result = Qt::PrimaryOrientation;
|
||||||
if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences) {
|
ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
||||||
DWORD orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
|
||||||
if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences(&orientationPreference)) {
|
BOOL bResult = TRUE;
|
||||||
switch (orientationPreference) {
|
|
||||||
case ORIENTATION_PREFERENCE_NONE:
|
if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences)
|
||||||
break;
|
bResult = QWindowsContext::user32dll.getDisplayAutoRotationPreferences((DWORD *)&orientationPreference);
|
||||||
case ORIENTATION_PREFERENCE_LANDSCAPE:
|
else
|
||||||
result = Qt::LandscapeOrientation;
|
bResult = vxkex::GetDisplayAutoRotationPreferences(&orientationPreference);
|
||||||
break;
|
|
||||||
case ORIENTATION_PREFERENCE_PORTRAIT:
|
if (bResult) {
|
||||||
result = Qt::PortraitOrientation;
|
switch (orientationPreference) {
|
||||||
break;
|
case ORIENTATION_PREFERENCE_NONE:
|
||||||
case ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED:
|
break;
|
||||||
result = Qt::InvertedLandscapeOrientation;
|
case ORIENTATION_PREFERENCE_LANDSCAPE:
|
||||||
break;
|
result = Qt::LandscapeOrientation;
|
||||||
case ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED:
|
break;
|
||||||
result = Qt::InvertedPortraitOrientation;
|
case ORIENTATION_PREFERENCE_PORTRAIT:
|
||||||
break;
|
result = Qt::PortraitOrientation;
|
||||||
}
|
break;
|
||||||
|
case ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED:
|
||||||
|
result = Qt::InvertedLandscapeOrientation;
|
||||||
|
break;
|
||||||
|
case ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED:
|
||||||
|
result = Qt::InvertedPortraitOrientation;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -704,11 +719,15 @@ void QWindowsScreenManager::initialize()
|
|||||||
handleScreenChanges();
|
handleScreenChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
QWindowsScreenManager::~QWindowsScreenManager()
|
void QWindowsScreenManager::destroyWindow()
|
||||||
{
|
{
|
||||||
|
qCDebug(lcQpaScreen) << "Destroying display change observer" << m_displayChangeObserver;
|
||||||
DestroyWindow(m_displayChangeObserver);
|
DestroyWindow(m_displayChangeObserver);
|
||||||
|
m_displayChangeObserver = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QWindowsScreenManager::~QWindowsScreenManager() = default;
|
||||||
|
|
||||||
bool QWindowsScreenManager::isSingleScreen()
|
bool QWindowsScreenManager::isSingleScreen()
|
||||||
{
|
{
|
||||||
return QWindowsContext::instance()->screenManager().screens().size() < 2;
|
return QWindowsContext::instance()->screenManager().screens().size() < 2;
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include "qwindowsmenu.h"
|
#include "qwindowsmenu.h"
|
||||||
#include "qwindowsdialoghelpers.h"
|
#include "qwindowsdialoghelpers.h"
|
||||||
#include "qwindowscontext.h"
|
#include "qwindowscontext.h"
|
||||||
|
#include "qwindowsiconengine.h"
|
||||||
#include "qwindowsintegration.h"
|
#include "qwindowsintegration.h"
|
||||||
#if QT_CONFIG(systemtrayicon)
|
#if QT_CONFIG(systemtrayicon)
|
||||||
# include "qwindowssystemtrayicon.h"
|
# include "qwindowssystemtrayicon.h"
|
||||||
@ -27,6 +28,7 @@
|
|||||||
#include <QtCore/qthread.h>
|
#include <QtCore/qthread.h>
|
||||||
#include <QtCore/qmutex.h>
|
#include <QtCore/qmutex.h>
|
||||||
#include <QtCore/qwaitcondition.h>
|
#include <QtCore/qwaitcondition.h>
|
||||||
|
#include <QtCore/qoperatingsystemversion.h>
|
||||||
#include <QtGui/qcolor.h>
|
#include <QtGui/qcolor.h>
|
||||||
#include <QtGui/qpalette.h>
|
#include <QtGui/qpalette.h>
|
||||||
#include <QtGui/qguiapplication.h>
|
#include <QtGui/qguiapplication.h>
|
||||||
@ -42,7 +44,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <VersionHelpers.h>
|
#include "vxkex.h"
|
||||||
|
|
||||||
#if QT_CONFIG(cpp_winrt)
|
#if QT_CONFIG(cpp_winrt)
|
||||||
# include <QtCore/private/qt_winrtbase_p.h>
|
# include <QtCore/private/qt_winrtbase_p.h>
|
||||||
@ -81,11 +83,11 @@ static inline QColor mixColors(const QColor &c1, const QColor &c2)
|
|||||||
(c1.blue() + c2.blue()) / 2};
|
(c1.blue() + c2.blue()) / 2};
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline QColor getSysColor(int index)
|
enum AccentColorLevel {
|
||||||
{
|
AccentColorDarkest,
|
||||||
COLORREF cr = GetSysColor(index);
|
AccentColorNormal,
|
||||||
return QColor(GetRValue(cr), GetGValue(cr), GetBValue(cr));
|
AccentColorLightest
|
||||||
}
|
};
|
||||||
|
|
||||||
#if QT_CONFIG(cpp_winrt)
|
#if QT_CONFIG(cpp_winrt)
|
||||||
static constexpr QColor getSysColor(winrt::Windows::UI::Color &&color)
|
static constexpr QColor getSysColor(winrt::Windows::UI::Color &&color)
|
||||||
@ -94,6 +96,54 @@ static constexpr QColor getSysColor(winrt::Windows::UI::Color &&color)
|
|||||||
}
|
}
|
||||||
#endif
|
#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
|
// 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
|
// models has been observed to trigger a WM_PAINT on the mainwindow. Suppress the
|
||||||
// behavior by running it in a thread.
|
// behavior by running it in a thread.
|
||||||
@ -223,44 +273,17 @@ static QColor placeHolderColor(QColor textColor)
|
|||||||
return 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
|
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.
|
application doesn't support dark mode. In the latter case, we need to check.
|
||||||
*/
|
*/
|
||||||
static void populateLightSystemBasePalette(QPalette &result)
|
static void populateLightSystemBasePalette(QPalette &result)
|
||||||
{
|
{
|
||||||
QColor background = getSysColor(COLOR_BTNFACE);
|
const QColor background = getSysColor(COLOR_BTNFACE);
|
||||||
QColor textColor = getSysColor(COLOR_WINDOWTEXT);
|
const QColor textColor = getSysColor(COLOR_WINDOWTEXT);
|
||||||
QColor accent = qt_accentColor();
|
|
||||||
QColor accentDarkest = accent.darker(120 * 120 * 120);
|
|
||||||
|
|
||||||
#if QT_CONFIG(cpp_winrt)
|
const QColor accent = qt_accentColor(AccentColorNormal);
|
||||||
if (IsWindows10OrGreater())
|
const QColor accentDarkest = qt_accentColor(AccentColorDarkest);
|
||||||
{
|
|
||||||
// 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 linkColor = accent;
|
const QColor linkColor = accent;
|
||||||
const QColor btnFace = background;
|
const QColor btnFace = background;
|
||||||
@ -298,7 +321,7 @@ static void populateDarkSystemBasePalette(QPalette &result)
|
|||||||
{
|
{
|
||||||
QColor foreground = Qt::white;
|
QColor foreground = Qt::white;
|
||||||
QColor background = QColor(0x1E, 0x1E, 0x1E);
|
QColor background = QColor(0x1E, 0x1E, 0x1E);
|
||||||
QColor accent = qt_accentColor();
|
QColor accent = qt_accentColor(AccentColorNormal);
|
||||||
QColor accentDark = accent.darker(120);
|
QColor accentDark = accent.darker(120);
|
||||||
QColor accentDarker = accentDark.darker(120);
|
QColor accentDarker = accentDark.darker(120);
|
||||||
QColor accentDarkest = accentDarker.darker(120);
|
QColor accentDarkest = accentDarker.darker(120);
|
||||||
@ -307,7 +330,7 @@ static void populateDarkSystemBasePalette(QPalette &result)
|
|||||||
QColor accentLightest = accentLighter.lighter(120);
|
QColor accentLightest = accentLighter.lighter(120);
|
||||||
|
|
||||||
#if QT_CONFIG(cpp_winrt)
|
#if QT_CONFIG(cpp_winrt)
|
||||||
if (IsWindows10OrGreater())
|
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10)
|
||||||
{
|
{
|
||||||
using namespace winrt::Windows::UI::ViewManagement;
|
using namespace winrt::Windows::UI::ViewManagement;
|
||||||
const auto settings = UISettings();
|
const auto settings = UISettings();
|
||||||
@ -472,7 +495,10 @@ static inline QStringList iconThemeSearchPaths()
|
|||||||
|
|
||||||
static inline QStringList styleNames()
|
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()
|
static inline int uiEffects()
|
||||||
@ -537,6 +563,8 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const
|
|||||||
|
|
||||||
Qt::ColorScheme QWindowsTheme::colorScheme() const
|
Qt::ColorScheme QWindowsTheme::colorScheme() const
|
||||||
{
|
{
|
||||||
|
if (queryHighContrast())
|
||||||
|
return Qt::ColorScheme::Unknown;
|
||||||
return QWindowsContext::isDarkMode() ? Qt::ColorScheme::Dark : Qt::ColorScheme::Light;
|
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[MenuPalette] = new QPalette(menuPalette(*m_palettes[SystemPalette], light));
|
||||||
m_palettes[MenuBarPalette] = menuBarPalette(*m_palettes[MenuPalette], light);
|
m_palettes[MenuBarPalette] = menuBarPalette(*m_palettes[MenuPalette], light);
|
||||||
if (!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] = new QPalette(*m_palettes[SystemPalette]);
|
||||||
m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Base, accent);
|
m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Base, qt_accentColor(AccentColorNormal));
|
||||||
m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Button, accentLight);
|
m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Button, qt_accentColor(AccentColorLightest));
|
||||||
m_palettes[CheckBoxPalette]->setColor(QPalette::Inactive, QPalette::Base, accentDarkest);
|
m_palettes[CheckBoxPalette]->setColor(QPalette::Inactive, QPalette::Base, qt_accentColor(AccentColorDarkest));
|
||||||
m_palettes[RadioButtonPalette] = new QPalette(*m_palettes[CheckBoxPalette]);
|
m_palettes[RadioButtonPalette] = new QPalette(*m_palettes[CheckBoxPalette]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -586,15 +600,15 @@ QPalette QWindowsTheme::systemPalette(Qt::ColorScheme colorScheme)
|
|||||||
QPalette result = standardPalette();
|
QPalette result = standardPalette();
|
||||||
|
|
||||||
switch (colorScheme) {
|
switch (colorScheme) {
|
||||||
case Qt::ColorScheme::Light:
|
case Qt::ColorScheme::Light:
|
||||||
populateLightSystemBasePalette(result);
|
populateLightSystemBasePalette(result);
|
||||||
break;
|
break;
|
||||||
case Qt::ColorScheme::Dark:
|
case Qt::ColorScheme::Dark:
|
||||||
populateDarkSystemBasePalette(result);
|
populateDarkSystemBasePalette(result);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
qFatal("Unknown color scheme");
|
qFatal("Unknown color scheme");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.window() != result.base()) {
|
if (result.window() != result.base()) {
|
||||||
@ -675,14 +689,11 @@ void QWindowsTheme::refreshFonts()
|
|||||||
fixedFont.setStyleHint(QFont::TypeWriter);
|
fixedFont.setStyleHint(QFont::TypeWriter);
|
||||||
|
|
||||||
LOGFONT lfIconTitleFont;
|
LOGFONT lfIconTitleFont;
|
||||||
QFont iconTitleFont;
|
if (QWindowsContext::user32dll.systemParametersInfoForDpi)
|
||||||
if (QWindowsContext::user32dll.systemParametersInfoForDpi) {
|
|
||||||
QWindowsContext::user32dll.systemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
|
QWindowsContext::user32dll.systemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
|
||||||
iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont, dpi);
|
else
|
||||||
} else {
|
vxkex::SystemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
|
||||||
SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
|
const QFont iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont, dpi);
|
||||||
iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_fonts[SystemFont] = new QFont(QWindowsFontDatabase::systemDefaultFont());
|
m_fonts[SystemFont] = new QFont(QWindowsFontDatabase::systemDefaultFont());
|
||||||
m_fonts[MenuFont] = new QFont(menuFont);
|
m_fonts[MenuFont] = new QFont(menuFont);
|
||||||
@ -856,15 +867,18 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (stockId != SIID_INVALID) {
|
if (stockId != SIID_INVALID) {
|
||||||
QPixmap pixmap;
|
|
||||||
SHSTOCKICONINFO iconInfo;
|
SHSTOCKICONINFO iconInfo;
|
||||||
memset(&iconInfo, 0, sizeof(iconInfo));
|
memset(&iconInfo, 0, sizeof(iconInfo));
|
||||||
iconInfo.cbSize = sizeof(iconInfo);
|
iconInfo.cbSize = sizeof(iconInfo);
|
||||||
stockFlags |= (pixmapSize.width() > 16 ? SHGFI_LARGEICON : SHGFI_SMALLICON);
|
stockFlags |= SHGSI_ICONLOCATION;
|
||||||
if (SHGetStockIconInfo(stockId, SHGFI_ICON | stockFlags, &iconInfo) == S_OK) {
|
if (SHGetStockIconInfo(stockId, stockFlags, &iconInfo) == S_OK) {
|
||||||
pixmap = qt_pixmapFromWinHICON(iconInfo.hIcon);
|
const auto iconSize = pixmapSize.width();
|
||||||
DestroyIcon(iconInfo.hIcon);
|
HICON icon;
|
||||||
return pixmap;
|
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));
|
return QIcon(new QWindowsFileIconEngine(fileInfo, iconOptions));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QIconEngine *QWindowsTheme::createIconEngine(const QString &iconName) const
|
||||||
|
{
|
||||||
|
return new QWindowsIconEngine(iconName);
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool doUseNativeMenus()
|
static inline bool doUseNativeMenus()
|
||||||
{
|
{
|
||||||
const unsigned options = QWindowsIntegration::instance()->options();
|
const unsigned options = QWindowsIntegration::instance()->options();
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <QtGui/qwindow.h>
|
#include <QtGui/qwindow.h>
|
||||||
#include <QtGui/qregion.h>
|
#include <QtGui/qregion.h>
|
||||||
#include <QtGui/qopenglcontext.h>
|
#include <QtGui/qopenglcontext.h>
|
||||||
|
#include <QtGui/private/qwindowsthemecache_p.h>
|
||||||
#include <private/qwindow_p.h> // QWINDOWSIZE_MAX
|
#include <private/qwindow_p.h> // QWINDOWSIZE_MAX
|
||||||
#include <private/qguiapplication_p.h>
|
#include <private/qguiapplication_p.h>
|
||||||
#include <private/qhighdpiscaling_p.h>
|
#include <private/qhighdpiscaling_p.h>
|
||||||
@ -43,6 +44,8 @@
|
|||||||
|
|
||||||
#include <shellscalingapi.h>
|
#include <shellscalingapi.h>
|
||||||
|
|
||||||
|
#include "vxkex.h"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
using QWindowCreationContextPtr = QSharedPointer<QWindowCreationContext>;
|
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)
|
return QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi)
|
||||||
+ QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
+ QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
return GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
|
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)
|
static QMargins invisibleMargins(QPoint screenPoint)
|
||||||
{
|
{
|
||||||
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10) {
|
POINT pt = {screenPoint.x(), screenPoint.y()};
|
||||||
POINT pt = {screenPoint.x(), screenPoint.y()};
|
if (HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
|
||||||
if (HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
|
if (QWindowsContext::shcoredll.isValid()) {
|
||||||
if (QWindowsContext::shcoredll.isValid()) {
|
UINT dpiX;
|
||||||
UINT dpiX;
|
UINT dpiY;
|
||||||
UINT dpiY;
|
|
||||||
if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY))) {
|
HRESULT hr = S_OK;
|
||||||
const int gap = getResizeBorderThickness(dpiX);
|
|
||||||
return QMargins(gap, 0, gap, gap);
|
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)
|
[[nodiscard]] static inline QMargins invisibleMargins(const HWND hwnd)
|
||||||
{
|
{
|
||||||
if (QWindowsContext::user32dll.getDpiForWindow) {
|
const UINT dpi = (QWindowsContext::user32dll.getDpiForWindow) ? QWindowsContext::user32dll.getDpiForWindow(hwnd) : vxkex::GetDpiForWindow(hwnd);
|
||||||
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
|
|
||||||
const int gap = getResizeBorderThickness(dpi);
|
const int gap = getResizeBorderThickness(dpi);
|
||||||
return QMargins(gap, 0, gap, gap);
|
return QMargins(gap, 0, gap, gap);
|
||||||
}
|
|
||||||
return QMargins();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -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
|
// NOTE: WS_EX_TRANSPARENT flag can make mouse inputs fall through a layered window
|
||||||
if (flagsIn & Qt::WindowTransparentForInput)
|
if (flagsIn & Qt::WindowTransparentForInput)
|
||||||
exStyle |= WS_EX_LAYERED | WS_EX_TRANSPARENT;
|
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 {};
|
return {};
|
||||||
RECT rect = {0,0,0,0};
|
RECT rect = {0,0,0,0};
|
||||||
style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
|
style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
|
||||||
if (QWindowsContext::user32dll.adjustWindowRectExForDpi &&
|
if (QWindowsContext::user32dll.adjustWindowRectExForDpi)
|
||||||
QWindowsContext::user32dll.adjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi))) == FALSE) {
|
{
|
||||||
qErrnoWarning("%s: AdjustWindowRectExForDpi failed", __FUNCTION__);
|
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),
|
const QMargins result(qAbs(rect.left), qAbs(rect.top),
|
||||||
qAbs(rect.right), qAbs(rect.bottom));
|
qAbs(rect.right), qAbs(rect.bottom));
|
||||||
qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << " style="
|
qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << " style="
|
||||||
@ -1364,6 +1382,8 @@ QWindowsForeignWindow::QWindowsForeignWindow(QWindow *window, HWND hwnd)
|
|||||||
, m_hwnd(hwnd)
|
, m_hwnd(hwnd)
|
||||||
, m_topLevelStyle(0)
|
, m_topLevelStyle(0)
|
||||||
{
|
{
|
||||||
|
if (QPlatformWindow::parent())
|
||||||
|
setParent(QPlatformWindow::parent());
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow)
|
void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow)
|
||||||
@ -1539,6 +1559,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
|
|||||||
QWindowsWindow::~QWindowsWindow()
|
QWindowsWindow::~QWindowsWindow()
|
||||||
{
|
{
|
||||||
setFlag(WithinDestroy);
|
setFlag(WithinDestroy);
|
||||||
|
QWindowsThemeCache::clearThemeCache(m_data.hwnd);
|
||||||
if (testFlag(TouchRegistered))
|
if (testFlag(TouchRegistered))
|
||||||
UnregisterTouchWindow(m_data.hwnd);
|
UnregisterTouchWindow(m_data.hwnd);
|
||||||
destroyWindow();
|
destroyWindow();
|
||||||
@ -1568,7 +1589,7 @@ void QWindowsWindow::initialize()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
QWindowsWindow::setSavedDpi(QWindowsContext::user32dll.getDpiForWindow ?
|
QWindowsWindow::setSavedDpi(QWindowsContext::user32dll.getDpiForWindow ?
|
||||||
QWindowsContext::user32dll.getDpiForWindow(handle()) : 96);
|
QWindowsContext::user32dll.getDpiForWindow(handle()) : vxkex::GetDpiForWindow(handle()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QSurfaceFormat QWindowsWindow::format() const
|
QSurfaceFormat QWindowsWindow::format() const
|
||||||
@ -2018,6 +2039,9 @@ void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|||||||
const UINT dpi = HIWORD(wParam);
|
const UINT dpi = HIWORD(wParam);
|
||||||
const qreal scale = dpiRelativeScale(dpi);
|
const qreal scale = dpiRelativeScale(dpi);
|
||||||
setSavedDpi(dpi);
|
setSavedDpi(dpi);
|
||||||
|
|
||||||
|
QWindowsThemeCache::clearThemeCache(hwnd);
|
||||||
|
|
||||||
// Send screen change first, so that the new screen is set during any following resize
|
// Send screen change first, so that the new screen is set during any following resize
|
||||||
checkForScreenChanged(QWindowsWindow::FromDpiChange);
|
checkForScreenChanged(QWindowsWindow::FromDpiChange);
|
||||||
|
|
||||||
@ -2060,20 +2084,17 @@ void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
|||||||
|
|
||||||
void QWindowsWindow::handleDpiChangedAfterParent(HWND hwnd)
|
void QWindowsWindow::handleDpiChangedAfterParent(HWND hwnd)
|
||||||
{
|
{
|
||||||
if (QWindowsContext::user32dll.getDpiForWindow)
|
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow ? QWindowsContext::user32dll.getDpiForWindow(hwnd) : vxkex::GetDpiForWindow(hwnd);
|
||||||
{
|
const qreal scale = dpiRelativeScale(dpi);
|
||||||
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
|
setSavedDpi(dpi);
|
||||||
const qreal scale = dpiRelativeScale(dpi);
|
|
||||||
setSavedDpi(dpi);
|
|
||||||
|
|
||||||
checkForScreenChanged(QWindowsWindow::FromDpiChange);
|
checkForScreenChanged(QWindowsWindow::FromDpiChange);
|
||||||
|
|
||||||
// Child windows do not get WM_GETDPISCALEDSIZE messages to inform
|
// Child windows do not get WM_GETDPISCALEDSIZE messages to inform
|
||||||
// Windows about the new size, so we need to manually scale them.
|
// Windows about the new size, so we need to manually scale them.
|
||||||
QRect currentGeometry = geometry();
|
QRect currentGeometry = geometry();
|
||||||
QRect scaledGeometry = QRect(currentGeometry.topLeft() * scale, currentGeometry.size() * scale);
|
QRect scaledGeometry = QRect(currentGeometry.topLeft() * scale, currentGeometry.size() * scale);
|
||||||
setGeometry(scaledGeometry);
|
setGeometry(scaledGeometry);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static QRect normalFrameGeometry(HWND hwnd)
|
static QRect normalFrameGeometry(HWND hwnd)
|
||||||
@ -2485,6 +2506,11 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
|
|||||||
GetWindowPlacement(m_data.hwnd, &windowPlacement);
|
GetWindowPlacement(m_data.hwnd, &windowPlacement);
|
||||||
const RECT geometry = RECTfromQRect(m_data.restoreGeometry);
|
const RECT geometry = RECTfromQRect(m_data.restoreGeometry);
|
||||||
windowPlacement.rcNormalPosition = geometry;
|
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);
|
SetWindowPlacement(m_data.hwnd, &windowPlacement);
|
||||||
}
|
}
|
||||||
// QTBUG-17548: We send expose events when receiving WM_Paint, but for
|
// 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