mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-07-06 01:05:23 +08:00
update to Qt 6.7.3
This commit is contained in:
@ -46,10 +46,13 @@
|
||||
#include <QtCore/quuid.h>
|
||||
#include <QtCore/private/qsystemlibrary_p.h>
|
||||
#include <QtCore/private/qwinregistry_p.h>
|
||||
#include <QtCore/private/qfactorycacheregistration_p.h>
|
||||
#if QT_CONFIG(cpp_winrt)
|
||||
# include <QtCore/private/qfactorycacheregistration_p.h>
|
||||
#endif
|
||||
#include <QtCore/private/qsystemerror_p.h>
|
||||
|
||||
#include <QtGui/private/qwindowsguieventdispatcher_p.h>
|
||||
#include <QtGui/private/qwindowsthemecache_p.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@ -58,6 +61,8 @@
|
||||
#include <wtsapi32.h>
|
||||
#include <shellscalingapi.h>
|
||||
|
||||
#include "vxkex.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
@ -276,6 +281,8 @@ QWindowsContext::~QWindowsContext()
|
||||
if (d->m_powerDummyWindow)
|
||||
DestroyWindow(d->m_powerDummyWindow);
|
||||
|
||||
d->m_screenManager.destroyWindow();
|
||||
|
||||
unregisterWindowClasses();
|
||||
if (d->m_oleInitializeResult == S_OK || d->m_oleInitializeResult == S_FALSE) {
|
||||
#ifdef QT_USE_FACTORY_CACHE_REGISTRATION
|
||||
@ -445,11 +452,25 @@ void QWindowsContext::setDetectAltGrModifier(bool a)
|
||||
return QtWindows::DpiAwareness::System;
|
||||
if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE))
|
||||
return QtWindows::DpiAwareness::Unaware;
|
||||
|
||||
return QtWindows::DpiAwareness::Invalid;
|
||||
}
|
||||
else
|
||||
{
|
||||
// IsValidDpiAwarenessContext() will handle the NULL pointer case.
|
||||
if (!vxkex::IsValidDpiAwarenessContext(context))
|
||||
return QtWindows::DpiAwareness::Invalid;
|
||||
if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED))
|
||||
return QtWindows::DpiAwareness::Unaware_GdiScaled;
|
||||
if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
|
||||
return QtWindows::DpiAwareness::PerMonitorVersion2;
|
||||
if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE))
|
||||
return QtWindows::DpiAwareness::PerMonitor;
|
||||
if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))
|
||||
return QtWindows::DpiAwareness::System;
|
||||
if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE))
|
||||
return QtWindows::DpiAwareness::Unaware;
|
||||
}
|
||||
|
||||
return QtWindows::DpiAwareness::Unaware; // Windows 7
|
||||
return QtWindows::DpiAwareness::Invalid;
|
||||
}
|
||||
|
||||
QtWindows::DpiAwareness QWindowsContext::windowDpiAwareness(HWND hwnd)
|
||||
@ -457,31 +478,26 @@ QtWindows::DpiAwareness QWindowsContext::windowDpiAwareness(HWND hwnd)
|
||||
if (!hwnd)
|
||||
return QtWindows::DpiAwareness::Invalid;
|
||||
|
||||
if (QWindowsContext::user32dll.getWindowDpiAwarenessContext)
|
||||
{
|
||||
const auto context = QWindowsContext::user32dll.getWindowDpiAwarenessContext(hwnd);
|
||||
return dpiAwarenessContextToQtDpiAwareness(context);
|
||||
}
|
||||
const auto context = QWindowsContext::user32dll.getWindowDpiAwarenessContext ?
|
||||
QWindowsContext::user32dll.getWindowDpiAwarenessContext(hwnd) :
|
||||
vxkex::GetWindowDpiAwarenessContext(hwnd);
|
||||
|
||||
return dpiAwarenessContextToQtDpiAwareness(DPI_AWARENESS_CONTEXT_UNAWARE);
|
||||
return dpiAwarenessContextToQtDpiAwareness(context);
|
||||
}
|
||||
|
||||
QtWindows::DpiAwareness QWindowsContext::processDpiAwareness()
|
||||
{
|
||||
if (QWindowsContext::user32dll.getThreadDpiAwarenessContext)
|
||||
{
|
||||
// Although we have GetDpiAwarenessContextForProcess(), however,
|
||||
// it's only available on Win10 1903+, which is a little higher
|
||||
// than Qt's minimum supported version (1809), so we can't use it.
|
||||
// Luckily, MS docs said GetThreadDpiAwarenessContext() will also
|
||||
// return the default DPI_AWARENESS_CONTEXT for the process if
|
||||
// SetThreadDpiAwarenessContext() was never called. So we can use
|
||||
// it as an equivalent.
|
||||
const auto context = QWindowsContext::user32dll.getThreadDpiAwarenessContext();
|
||||
return dpiAwarenessContextToQtDpiAwareness(context);
|
||||
}
|
||||
|
||||
return dpiAwarenessContextToQtDpiAwareness(DPI_AWARENESS_CONTEXT_UNAWARE);
|
||||
// Although we have GetDpiAwarenessContextForProcess(), however,
|
||||
// it's only available on Win10 1903+, which is a little higher
|
||||
// than Qt's minimum supported version (1809), so we can't use it.
|
||||
// Luckily, MS docs said GetThreadDpiAwarenessContext() will also
|
||||
// return the default DPI_AWARENESS_CONTEXT for the process if
|
||||
// SetThreadDpiAwarenessContext() was never called. So we can use
|
||||
// it as an equivalent.
|
||||
const DPI_AWARENESS_CONTEXT context = QWindowsContext::user32dll.getThreadDpiAwarenessContext ?
|
||||
QWindowsContext::user32dll.getThreadDpiAwarenessContext() :
|
||||
vxkex::GetThreadDpiAwarenessContext();
|
||||
return dpiAwarenessContextToQtDpiAwareness(context);
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline DPI_AWARENESS_CONTEXT
|
||||
@ -541,28 +557,32 @@ bool QWindowsContext::setProcessDpiAwareness(QtWindows::DpiAwareness dpiAwarenes
|
||||
return true;
|
||||
const auto context = qtDpiAwarenessToDpiAwarenessContext(dpiAwareness);
|
||||
|
||||
if (QWindowsContext::user32dll.isValidDpiAwarenessContext && QWindowsContext::user32dll.setProcessDpiAwarenessContext)
|
||||
{
|
||||
if (!QWindowsContext::user32dll.isValidDpiAwarenessContext(context)) {
|
||||
qCWarning(lcQpaWindow) << dpiAwareness << "is not supported by current system.";
|
||||
return false;
|
||||
}
|
||||
if (!QWindowsContext::user32dll.setProcessDpiAwarenessContext(context)) {
|
||||
qCWarning(lcQpaWindow).noquote().nospace()
|
||||
<< "SetProcessDpiAwarenessContext() failed: "
|
||||
<< QSystemError::windowsString()
|
||||
<< "\nQt's default DPI awareness context is "
|
||||
<< "DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2. If you know what you "
|
||||
<< "are doing, you can overwrite this default using qt.conf "
|
||||
<< "(https://doc.qt.io/qt-6/highdpi.html#configuring-windows).";
|
||||
return false;
|
||||
}
|
||||
QWindowsContextPrivate::m_v2DpiAware
|
||||
= processDpiAwareness() == QtWindows::DpiAwareness::PerMonitorVersion2;
|
||||
return true;
|
||||
BOOL bResultIsValid = QWindowsContext::user32dll.isValidDpiAwarenessContext ?
|
||||
QWindowsContext::user32dll.isValidDpiAwarenessContext(context) :
|
||||
vxkex::IsValidDpiAwarenessContext(context);
|
||||
|
||||
if (!bResultIsValid) {
|
||||
qCWarning(lcQpaWindow) << dpiAwareness << "is not supported by current system.";
|
||||
return false;
|
||||
}
|
||||
|
||||
return false; // Windows 7
|
||||
BOOL bResultSet = QWindowsContext::user32dll.setProcessDpiAwarenessContext ?
|
||||
QWindowsContext::user32dll.setProcessDpiAwarenessContext(context) :
|
||||
vxkex::SetProcessDpiAwarenessContext(context);
|
||||
|
||||
if (!bResultSet) {
|
||||
qCWarning(lcQpaWindow).noquote().nospace()
|
||||
<< "SetProcessDpiAwarenessContext() failed: "
|
||||
<< QSystemError::windowsString()
|
||||
<< "\nQt's default DPI awareness context is "
|
||||
<< "DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2. If you know what you "
|
||||
<< "are doing, you can overwrite this default using qt.conf "
|
||||
<< "(https://doc.qt.io/qt-6/highdpi.html#configuring-windows).";
|
||||
return false;
|
||||
}
|
||||
QWindowsContextPrivate::m_v2DpiAware
|
||||
= processDpiAwareness() == QtWindows::DpiAwareness::PerMonitorVersion2;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QWindowsContext::isDarkMode()
|
||||
@ -585,9 +605,9 @@ bool QWindowsContext::useRTLExtensions() const
|
||||
return d->m_keyMapper.useRTLExtensions();
|
||||
}
|
||||
|
||||
QList<int> QWindowsContext::possibleKeys(const QKeyEvent *e) const
|
||||
QPlatformKeyMapper *QWindowsContext::keyMapper() const
|
||||
{
|
||||
return d->m_keyMapper.possibleKeys(e);
|
||||
return &d->m_keyMapper;
|
||||
}
|
||||
|
||||
QWindowsContext::HandleBaseWindowHash &QWindowsContext::windows()
|
||||
@ -994,7 +1014,7 @@ bool QWindowsContext::systemParametersInfo(unsigned action, unsigned param, void
|
||||
{
|
||||
const BOOL result = (QWindowsContext::user32dll.systemParametersInfoForDpi != nullptr && dpi != 0)
|
||||
? QWindowsContext::user32dll.systemParametersInfoForDpi(action, param, out, 0, dpi)
|
||||
: SystemParametersInfo(action, param, out, 0);
|
||||
: vxkex::SystemParametersInfoForDpi(action, param, out, 0, dpi);
|
||||
return result == TRUE;
|
||||
}
|
||||
|
||||
@ -1080,8 +1100,11 @@ static inline bool isInputMessage(UINT m)
|
||||
static bool enableNonClientDpiScaling(HWND hwnd)
|
||||
{
|
||||
bool result = false;
|
||||
if (QWindowsContext::user32dll.enableNonClientDpiScaling && QWindowsContext::windowDpiAwareness(hwnd) == QtWindows::DpiAwareness::PerMonitor) {
|
||||
result = QWindowsContext::user32dll.enableNonClientDpiScaling(hwnd) != FALSE;
|
||||
if (QWindowsContext::windowDpiAwareness(hwnd) == QtWindows::DpiAwareness::PerMonitor) {
|
||||
result = QWindowsContext::user32dll.enableNonClientDpiScaling ?
|
||||
(QWindowsContext::user32dll.enableNonClientDpiScaling(hwnd) != FALSE) :
|
||||
(vxkex::EnableNonClientDpiScaling(hwnd) != FALSE);
|
||||
|
||||
if (!result) {
|
||||
const DWORD errorCode = GetLastError();
|
||||
qErrnoWarning(int(errorCode), "EnableNonClientDpiScaling() failed for HWND %p (%lu)",
|
||||
@ -1267,7 +1290,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
|
||||
if (wParam == DBT_DEVNODES_CHANGED)
|
||||
initTouch();
|
||||
break;
|
||||
case QtWindows::KeyboardLayoutChangeEvent:
|
||||
case QtWindows::InputLanguageChangeEvent:
|
||||
if (QWindowsInputContext *wic = windowsInputContext())
|
||||
wic->handleInputLanguageChanged(wParam, lParam);
|
||||
Q_FALLTHROUGH();
|
||||
@ -1379,6 +1402,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
|
||||
QWindowSystemInterface::handleCloseEvent(platformWindow->window());
|
||||
return true;
|
||||
case QtWindows::ThemeChanged: {
|
||||
QWindowsThemeCache::clearThemeCache(platformWindow->handle());
|
||||
// Switch from Aero to Classic changes margins.
|
||||
if (QWindowsTheme *theme = QWindowsTheme::instance())
|
||||
theme->windowsThemeChanged(platformWindow->window());
|
||||
@ -1517,7 +1541,7 @@ void QWindowsContext::handleFocusEvent(QtWindows::WindowsEventType et,
|
||||
}
|
||||
if (nextActiveWindow != d->m_lastActiveWindow) {
|
||||
d->m_lastActiveWindow = nextActiveWindow;
|
||||
QWindowSystemInterface::handleWindowActivated(nextActiveWindow, Qt::ActiveWindowFocusReason);
|
||||
QWindowSystemInterface::handleFocusWindowChanged(nextActiveWindow, Qt::ActiveWindowFocusReason);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1547,7 +1571,7 @@ bool QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg)
|
||||
}
|
||||
|
||||
QWindowSystemInterface::handleContextMenuEvent(window, mouseTriggered, pos, globalPos,
|
||||
QWindowsKeyMapper::queryKeyboardModifiers());
|
||||
keyMapper()->queryKeyboardModifiers());
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@ -1568,7 +1592,7 @@ void QWindowsContext::handleExitSizeMove(QWindow *window)
|
||||
const Qt::MouseButtons appButtons = QGuiApplication::mouseButtons();
|
||||
if (currentButtons == appButtons)
|
||||
return;
|
||||
const Qt::KeyboardModifiers keyboardModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
|
||||
const Qt::KeyboardModifiers keyboardModifiers = keyMapper()->queryKeyboardModifiers();
|
||||
const QPoint globalPos = QWindowsCursor::mousePosition();
|
||||
const QPlatformWindow *platWin = window->handle();
|
||||
const QPoint localPos = platWin->mapFromGlobal(globalPos);
|
||||
|
@ -34,6 +34,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen)
|
||||
class QWindow;
|
||||
class QPlatformScreen;
|
||||
class QPlatformWindow;
|
||||
class QPlatformKeyMapper;
|
||||
class QWindowsMenuBar;
|
||||
class QWindowsScreenManager;
|
||||
class QWindowsTabletSupport;
|
||||
@ -217,7 +218,7 @@ public:
|
||||
unsigned systemInfo() const;
|
||||
|
||||
bool useRTLExtensions() const;
|
||||
QList<int> possibleKeys(const QKeyEvent *e) const;
|
||||
QPlatformKeyMapper *keyMapper() const;
|
||||
|
||||
HandleBaseWindowHash &windows();
|
||||
|
||||
|
@ -28,9 +28,13 @@
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <QtCore/qbuffer.h>
|
||||
#include <QtCore/qpoint.h>
|
||||
#include <QtCore/qpointer.h>
|
||||
#include <QtCore/private/qcomobject_p.h>
|
||||
|
||||
#include <shlobj.h>
|
||||
|
||||
#include "vxkex.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
@ -167,7 +171,7 @@ static Qt::MouseButtons lastButtons = Qt::NoButton;
|
||||
\internal
|
||||
*/
|
||||
|
||||
class QWindowsOleDropSource : public QWindowsComBase<IDropSource>
|
||||
class QWindowsOleDropSource : public QComObject<IDropSource>
|
||||
{
|
||||
public:
|
||||
enum Mode {
|
||||
@ -526,7 +530,8 @@ QWindowsOleDropTarget::DragLeave()
|
||||
|
||||
qCDebug(lcQpaMime) << __FUNCTION__ << ' ' << m_window;
|
||||
|
||||
lastModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
|
||||
const auto *keyMapper = QWindowsContext::instance()->keyMapper();
|
||||
lastModifiers = keyMapper->queryKeyboardModifiers();
|
||||
lastButtons = QWindowsMouseHandler::queryMouseButtons();
|
||||
|
||||
QWindowSystemInterface::handleDrag(m_window, nullptr, QPoint(), Qt::IgnoreAction,
|
||||
@ -611,7 +616,6 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState,
|
||||
*/
|
||||
|
||||
bool QWindowsDrag::m_canceled = false;
|
||||
bool QWindowsDrag::m_dragging = false;
|
||||
|
||||
QWindowsDrag::QWindowsDrag() = default;
|
||||
|
||||
@ -671,7 +675,11 @@ static HRESULT startDoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource,
|
||||
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
|
||||
|
||||
POINTER_INFO pointerInfo{};
|
||||
if (!QWindowsContext::user32dll.getPointerInfo || !QWindowsContext::user32dll.getPointerInfo(pointerId, &pointerInfo))
|
||||
BOOL bResultPointerInfo = QWindowsContext::user32dll.getPointerInfo ?
|
||||
QWindowsContext::user32dll.getPointerInfo(pointerId, &pointerInfo) :
|
||||
vxkex::GetPointerInfo(pointerId, &pointerInfo);
|
||||
|
||||
if (!bResultPointerInfo)
|
||||
return E_FAIL;
|
||||
|
||||
if (pointerInfo.pointerFlags & POINTER_FLAG_PRIMARY) {
|
||||
@ -739,10 +747,7 @@ Qt::DropAction QWindowsDrag::drag(QDrag *drag)
|
||||
const DWORD allowedEffects = translateToWinDragEffects(possibleActions);
|
||||
qCDebug(lcQpaMime) << '>' << __FUNCTION__ << "possible Actions=0x"
|
||||
<< Qt::hex << int(possibleActions) << "effects=0x" << allowedEffects << Qt::dec;
|
||||
// Indicate message handlers we are in DoDragDrop() event loop.
|
||||
QWindowsDrag::m_dragging = true;
|
||||
const HRESULT r = startDoDragDrop(dropDataObject, windowDropSource, allowedEffects, &resultEffect);
|
||||
QWindowsDrag::m_dragging = false;
|
||||
const DWORD reportedPerformedEffect = dropDataObject->reportedPerformedEffect();
|
||||
if (r == DRAGDROP_S_DROP) {
|
||||
if (reportedPerformedEffect == DROPEFFECT_MOVE && resultEffect != DROPEFFECT_MOVE) {
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include <QtCore/private/qdebug_p.h>
|
||||
#include <QtCore/private/qtools_p.h>
|
||||
|
||||
#include "vxkex.h"
|
||||
|
||||
#if defined(WM_APPCOMMAND)
|
||||
# ifndef FAPPCOMMAND_MOUSE
|
||||
# define FAPPCOMMAND_MOUSE 0x8000
|
||||
@ -88,9 +90,17 @@ QWindowsKeyMapper::~QWindowsKeyMapper()= default;
|
||||
#define VK_OEM_3 0xC0
|
||||
#endif
|
||||
|
||||
// We not only need the scancode itself but also the extended bit of key messages. Thus we need
|
||||
// the additional bit when masking the scancode.
|
||||
enum { scancodeBitmask = 0x1ff };
|
||||
// Get scancode from the given message
|
||||
static constexpr quint32 getScancode(const MSG &msg)
|
||||
{
|
||||
const auto keyFlags = HIWORD(msg.lParam);
|
||||
quint32 scancode = LOBYTE(keyFlags);
|
||||
// if extended-key flag is on, the scan code consists of a sequence of two bytes,
|
||||
// where the first byte has a value of 0xe0.
|
||||
if ((keyFlags & KF_EXTENDED) != 0)
|
||||
scancode |= 0xE000;
|
||||
return scancode;
|
||||
}
|
||||
|
||||
// Key recorder ------------------------------------------------------------------------[ start ] --
|
||||
struct KeyRecord {
|
||||
@ -532,33 +542,6 @@ QDebug operator<<(QDebug d, const KeyboardLayoutItem &k)
|
||||
d << ')';
|
||||
return d;
|
||||
}
|
||||
|
||||
// Helpers to format a list of int as Qt key sequence
|
||||
class formatKeys
|
||||
{
|
||||
public:
|
||||
explicit formatKeys(const QList<int> &keys) : m_keys(keys) {}
|
||||
|
||||
private:
|
||||
friend QDebug operator<<(QDebug d, const formatKeys &keys);
|
||||
const QList<int> &m_keys;
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug d, const formatKeys &k)
|
||||
{
|
||||
QDebugStateSaver saver(d);
|
||||
d.nospace();
|
||||
d << '(';
|
||||
for (int i =0, size = k.m_keys.size(); i < size; ++i) {
|
||||
if (i)
|
||||
d << ", ";
|
||||
d << QKeySequence(k.m_keys.at(i));
|
||||
}
|
||||
d << ')';
|
||||
return d;
|
||||
}
|
||||
#else // !QT_NO_DEBUG_STREAM
|
||||
static int formatKeys(const QList<int> &) { return 0; }
|
||||
#endif // QT_NO_DEBUG_STREAM
|
||||
|
||||
/**
|
||||
@ -656,7 +639,7 @@ void QWindowsKeyMapper::updateKeyMap(const MSG &msg)
|
||||
{
|
||||
unsigned char kbdBuffer[256]; // Will hold the complete keyboard state
|
||||
GetKeyboardState(kbdBuffer);
|
||||
const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask;
|
||||
const quint32 scancode = getScancode(msg);
|
||||
updatePossibleKeyCodes(kbdBuffer, scancode, quint32(msg.wParam));
|
||||
}
|
||||
|
||||
@ -751,28 +734,18 @@ static inline QString messageKeyText(const MSG &msg)
|
||||
|
||||
[[nodiscard]] static inline int getTitleBarHeight(const HWND hwnd)
|
||||
{
|
||||
if (QWindowsContext::user32dll.getDpiForWindow && QWindowsContext::user32dll.getSystemMetricsForDpi)
|
||||
{
|
||||
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
|
||||
const int captionHeight = QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYCAPTION, dpi);
|
||||
if (IsZoomed(hwnd))
|
||||
return captionHeight;
|
||||
// The frame height should also be taken into account if the window
|
||||
// is not maximized.
|
||||
const int frameHeight = QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYSIZEFRAME, dpi)
|
||||
+ QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
||||
return captionHeight + frameHeight;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int captionHeight = GetSystemMetrics(SM_CYCAPTION);
|
||||
if (IsZoomed(hwnd))
|
||||
return captionHeight;
|
||||
// The frame height should also be taken into account if the window
|
||||
// is not maximized.
|
||||
const int frameHeight = GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
|
||||
return captionHeight + frameHeight;
|
||||
}
|
||||
const BOOL bNewAPI = (QWindowsContext::user32dll.getSystemMetricsForDpi != nullptr);
|
||||
const UINT dpi = bNewAPI ? QWindowsContext::user32dll.getDpiForWindow(hwnd) : vxkex::GetDpiForWindow(hwnd);
|
||||
const int captionHeight = bNewAPI ? QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYCAPTION, dpi) : vxkex::GetSystemMetricsForDpi(SM_CYCAPTION, dpi);
|
||||
if (IsZoomed(hwnd))
|
||||
return captionHeight;
|
||||
// The frame height should also be taken into account if the window
|
||||
// is not maximized.
|
||||
const int frameHeight = bNewAPI ?
|
||||
(QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYSIZEFRAME, dpi) + QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi))
|
||||
: (vxkex::GetSystemMetricsForDpi(SM_CYSIZEFRAME, dpi) + vxkex::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi));
|
||||
|
||||
return captionHeight + frameHeight;
|
||||
}
|
||||
|
||||
[[nodiscard]] static inline bool isSystemMenuOffsetNeeded(const Qt::WindowFlags flags)
|
||||
@ -955,7 +928,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
|
||||
m_seenAltGr = true;
|
||||
const UINT msgType = msg.message;
|
||||
|
||||
const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask;
|
||||
const quint32 scancode = getScancode(msg);
|
||||
auto vk_key = quint32(msg.wParam);
|
||||
quint32 nModifiers = 0;
|
||||
|
||||
@ -1352,7 +1325,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
|
||||
return result;
|
||||
}
|
||||
|
||||
Qt::KeyboardModifiers QWindowsKeyMapper::queryKeyboardModifiers()
|
||||
Qt::KeyboardModifiers QWindowsKeyMapper::queryKeyboardModifiers() const
|
||||
{
|
||||
Qt::KeyboardModifiers modifiers = Qt::NoModifier;
|
||||
if (GetKeyState(VK_SHIFT) < 0)
|
||||
@ -1366,9 +1339,9 @@ Qt::KeyboardModifiers QWindowsKeyMapper::queryKeyboardModifiers()
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const
|
||||
QList<QKeyCombination> QWindowsKeyMapper::possibleKeyCombinations(const QKeyEvent *e) const
|
||||
{
|
||||
QList<int> result;
|
||||
QList<QKeyCombination> result;
|
||||
|
||||
|
||||
const quint32 nativeVirtualKey = e->nativeVirtualKey();
|
||||
@ -1382,31 +1355,34 @@ QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const
|
||||
quint32 baseKey = kbItem.qtKey[0];
|
||||
Qt::KeyboardModifiers keyMods = e->modifiers();
|
||||
if (baseKey == Qt::Key_Return && (e->nativeModifiers() & ExtendedKey)) {
|
||||
result << (Qt::Key_Enter | keyMods).toCombined();
|
||||
result << (Qt::Key_Enter | keyMods);
|
||||
return result;
|
||||
}
|
||||
result << int(baseKey) + int(keyMods); // The base key is _always_ valid, of course
|
||||
|
||||
// The base key is _always_ valid, of course
|
||||
result << QKeyCombination::fromCombined(int(baseKey) + int(keyMods));
|
||||
|
||||
for (size_t i = 1; i < NumMods; ++i) {
|
||||
Qt::KeyboardModifiers neededMods = ModsTbl[i];
|
||||
quint32 key = kbItem.qtKey[i];
|
||||
if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) {
|
||||
const Qt::KeyboardModifiers missingMods = keyMods & ~neededMods;
|
||||
const int matchedKey = int(key) + int(missingMods);
|
||||
const auto it =
|
||||
std::find_if(result.begin(), result.end(),
|
||||
[key] (int k) { return (k & ~Qt::KeyboardModifierMask) == key; });
|
||||
const auto matchedKey = QKeyCombination::fromCombined(int(key) + int(missingMods));
|
||||
const auto it = std::find_if(result.begin(), result.end(),
|
||||
[key](auto keyCombination) {
|
||||
return keyCombination.key() == key;
|
||||
});
|
||||
// QTBUG-67200: Use the match with the least modifiers (prefer
|
||||
// Shift+9 over Alt + Shift + 9) resulting in more missing modifiers.
|
||||
if (it == result.end())
|
||||
result << matchedKey;
|
||||
else if (missingMods > Qt::KeyboardModifiers(*it & Qt::KeyboardModifierMask))
|
||||
else if (missingMods > it->keyboardModifiers())
|
||||
*it = matchedKey;
|
||||
}
|
||||
}
|
||||
qCDebug(lcQpaEvents) << __FUNCTION__ << e << "nativeVirtualKey="
|
||||
<< Qt::showbase << Qt::hex << e->nativeVirtualKey() << Qt::dec << Qt::noshowbase
|
||||
<< e->modifiers() << kbItem << "\n returns" << formatKeys(result);
|
||||
<< e->modifiers() << kbItem << "\n returns" << result;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,8 @@
|
||||
|
||||
#include <windowsx.h>
|
||||
|
||||
#include "vxkex.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
enum {
|
||||
@ -48,7 +50,11 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
||||
*result = 0;
|
||||
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
|
||||
|
||||
if (!QWindowsContext::user32dll.getPointerType(pointerId, &m_pointerType)) {
|
||||
BOOL bResultPt = QWindowsContext::user32dll.getPointerType ?
|
||||
QWindowsContext::user32dll.getPointerType(pointerId, &m_pointerType) :
|
||||
vxkex::GetPointerType(pointerId, &m_pointerType);
|
||||
|
||||
if (!bResultPt) {
|
||||
qWarning() << "GetPointerType() failed:" << qt_error_string();
|
||||
return false;
|
||||
}
|
||||
@ -62,12 +68,21 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
||||
}
|
||||
case QT_PT_TOUCH: {
|
||||
quint32 pointerCount = 0;
|
||||
if (!QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, nullptr)) {
|
||||
BOOL bResultPointerTouchInfo = QWindowsContext::user32dll.getPointerFrameTouchInfo ?
|
||||
QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, nullptr) :
|
||||
vxkex::GetPointerFrameTouchInfo(pointerId, &pointerCount, nullptr);
|
||||
|
||||
if (!bResultPointerTouchInfo) {
|
||||
qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
|
||||
return false;
|
||||
}
|
||||
QVarLengthArray<POINTER_TOUCH_INFO, 10> touchInfo(pointerCount);
|
||||
if (!QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data())) {
|
||||
|
||||
bResultPointerTouchInfo = QWindowsContext::user32dll.getPointerFrameTouchInfo ?
|
||||
QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data()) :
|
||||
vxkex::GetPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data());
|
||||
|
||||
if (!bResultPointerTouchInfo) {
|
||||
qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
|
||||
return false;
|
||||
}
|
||||
@ -80,10 +95,12 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
||||
// dispatch any skipped frames if event compression is disabled by the app
|
||||
if (historyCount > 1 && !QCoreApplication::testAttribute(Qt::AA_CompressHighFrequencyEvents)) {
|
||||
touchInfo.resize(pointerCount * historyCount);
|
||||
if (!QWindowsContext::user32dll.getPointerFrameTouchInfoHistory(pointerId,
|
||||
&historyCount,
|
||||
&pointerCount,
|
||||
touchInfo.data())) {
|
||||
|
||||
BOOL bResultTouchHistory = QWindowsContext::user32dll.getPointerFrameTouchInfoHistory ?
|
||||
QWindowsContext::user32dll.getPointerFrameTouchInfoHistory(pointerId, &historyCount, &pointerCount, touchInfo.data()) :
|
||||
vxkex::GetPointerFrameTouchInfoHistory(pointerId, &historyCount, &pointerCount, touchInfo.data());
|
||||
|
||||
if (!bResultTouchHistory) {
|
||||
qWarning() << "GetPointerFrameTouchInfoHistory() failed:" << qt_error_string();
|
||||
return false;
|
||||
}
|
||||
@ -101,7 +118,11 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
||||
}
|
||||
case QT_PT_PEN: {
|
||||
POINTER_PEN_INFO penInfo;
|
||||
if (!QWindowsContext::user32dll.getPointerPenInfo(pointerId, &penInfo)) {
|
||||
|
||||
BOOL bResultPenInfo = QWindowsContext::user32dll.getPointerPenInfo ?
|
||||
QWindowsContext::user32dll.getPointerPenInfo(pointerId, &penInfo) : vxkex::GetPointerPenInfo(pointerId, &penInfo);
|
||||
|
||||
if (!bResultPenInfo) {
|
||||
qWarning() << "GetPointerPenInfo() failed:" << qt_error_string();
|
||||
return false;
|
||||
}
|
||||
@ -113,7 +134,11 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|
||||
|| !QCoreApplication::testAttribute(Qt::AA_CompressTabletEvents))) {
|
||||
QVarLengthArray<POINTER_PEN_INFO, 10> penInfoHistory(historyCount);
|
||||
|
||||
if (!QWindowsContext::user32dll.getPointerPenInfoHistory(pointerId, &historyCount, penInfoHistory.data())) {
|
||||
BOOL bResultPenInfoHistory = QWindowsContext::user32dll.getPointerPenInfoHistory ?
|
||||
QWindowsContext::user32dll.getPointerPenInfoHistory(pointerId, &historyCount, penInfoHistory.data()) :
|
||||
vxkex::GetPointerPenInfoHistory(pointerId, &historyCount, penInfoHistory.data());
|
||||
|
||||
if (!bResultPenInfoHistory) {
|
||||
qWarning() << "GetPointerPenInfoHistory() failed:" << qt_error_string();
|
||||
return false;
|
||||
}
|
||||
@ -428,8 +453,9 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
|
||||
return false;
|
||||
|
||||
if (msg.message == WM_POINTERCAPTURECHANGED) {
|
||||
const auto *keyMapper = QWindowsContext::instance()->keyMapper();
|
||||
QWindowSystemInterface::handleTouchCancelEvent(window, m_touchDevice.data(),
|
||||
QWindowsKeyMapper::queryKeyboardModifiers());
|
||||
keyMapper->queryKeyboardModifiers());
|
||||
m_lastTouchPoints.clear();
|
||||
return true;
|
||||
}
|
||||
@ -519,7 +545,10 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
|
||||
inputIds.insert(touchPoint.id);
|
||||
|
||||
// Avoid getting repeated messages for this frame if there are multiple pointerIds
|
||||
QWindowsContext::user32dll.skipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
|
||||
if (QWindowsContext::user32dll.skipPointerFrameMessages)
|
||||
QWindowsContext::user32dll.skipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
|
||||
else
|
||||
vxkex::SkipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
|
||||
}
|
||||
|
||||
// Some devices send touches for each finger in a different message/frame, instead of consolidating
|
||||
@ -539,8 +568,9 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
|
||||
if (allStates == QEventPoint::State::Released)
|
||||
m_touchInputIDToTouchPointID.clear();
|
||||
|
||||
const auto *keyMapper = QWindowsContext::instance()->keyMapper();
|
||||
QWindowSystemInterface::handleTouchEvent(window, m_touchDevice.data(), touchPoints,
|
||||
QWindowsKeyMapper::queryKeyboardModifiers());
|
||||
keyMapper->queryKeyboardModifiers());
|
||||
return false; // Allow mouse messages to be generated.
|
||||
}
|
||||
|
||||
@ -565,7 +595,12 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
|
||||
auto *penInfo = static_cast<POINTER_PEN_INFO *>(vPenInfo);
|
||||
|
||||
RECT pRect, dRect;
|
||||
if (!QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect))
|
||||
|
||||
BOOL bResultDeviceRects = QWindowsContext::user32dll.getPointerDeviceRects ?
|
||||
QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect) :
|
||||
vxkex::GetPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect);
|
||||
|
||||
if (!bResultDeviceRects)
|
||||
return false;
|
||||
|
||||
const auto systemId = (qint64)penInfo->pointerInfo.sourceDevice;
|
||||
@ -673,7 +708,8 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
|
||||
wumPlatformWindow->applyCursor();
|
||||
}
|
||||
}
|
||||
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
|
||||
const auto *keyMapper = QWindowsContext::instance()->keyMapper();
|
||||
const Qt::KeyboardModifiers keyModifiers = keyMapper->queryKeyboardModifiers();
|
||||
|
||||
QWindowSystemInterface::handleTabletEvent(target, device.data(),
|
||||
localPos, hiResGlobalPos, mouseButtons,
|
||||
@ -762,7 +798,8 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
|
||||
: QWindowsGeometryHint::mapFromGlobal(targetHwnd, globalPos);
|
||||
}
|
||||
|
||||
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
|
||||
const auto *keyMapper = QWindowsContext::instance()->keyMapper();
|
||||
const Qt::KeyboardModifiers keyModifiers = keyMapper->queryKeyboardModifiers();
|
||||
QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
|
||||
|
||||
if (et == QtWindows::MouseWheelEvent)
|
||||
|
@ -32,6 +32,8 @@
|
||||
#include <setupapi.h>
|
||||
#include <shellscalingapi.h>
|
||||
|
||||
#include "vxkex.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
using namespace Qt::StringLiterals;
|
||||
@ -43,12 +45,18 @@ static inline QDpi deviceDPI(HDC hdc)
|
||||
|
||||
static inline QDpi monitorDPI(HMONITOR hMonitor)
|
||||
{
|
||||
if (QWindowsContext::shcoredll.isValid()) {
|
||||
UINT dpiX;
|
||||
UINT dpiY;
|
||||
if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY)))
|
||||
return QDpi(dpiX, dpiY);
|
||||
}
|
||||
UINT dpiX;
|
||||
UINT dpiY;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (QWindowsContext::shcoredll.isValid())
|
||||
hr = QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
|
||||
else
|
||||
hr = vxkex::GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
return QDpi(dpiX, dpiY);
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
@ -579,51 +587,58 @@ QRect QWindowsScreen::virtualGeometry(const QPlatformScreen *screen) // cf QScre
|
||||
bool QWindowsScreen::setOrientationPreference(Qt::ScreenOrientation o)
|
||||
{
|
||||
bool result = false;
|
||||
if (QWindowsContext::user32dll.setDisplayAutoRotationPreferences) {
|
||||
ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
||||
switch (o) {
|
||||
case Qt::PrimaryOrientation:
|
||||
break;
|
||||
case Qt::PortraitOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_PORTRAIT;
|
||||
break;
|
||||
case Qt::LandscapeOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE;
|
||||
break;
|
||||
case Qt::InvertedPortraitOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED;
|
||||
break;
|
||||
case Qt::InvertedLandscapeOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED;
|
||||
break;
|
||||
}
|
||||
result = QWindowsContext::user32dll.setDisplayAutoRotationPreferences(orientationPreference);
|
||||
ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
||||
switch (o) {
|
||||
case Qt::PrimaryOrientation:
|
||||
break;
|
||||
case Qt::PortraitOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_PORTRAIT;
|
||||
break;
|
||||
case Qt::LandscapeOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE;
|
||||
break;
|
||||
case Qt::InvertedPortraitOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED;
|
||||
break;
|
||||
case Qt::InvertedLandscapeOrientation:
|
||||
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED;
|
||||
break;
|
||||
}
|
||||
if (QWindowsContext::user32dll.setDisplayAutoRotationPreferences)
|
||||
result = QWindowsContext::user32dll.setDisplayAutoRotationPreferences(orientationPreference);
|
||||
else
|
||||
result = vxkex::SetDisplayAutoRotationPreferences(orientationPreference);
|
||||
return result;
|
||||
}
|
||||
|
||||
Qt::ScreenOrientation QWindowsScreen::orientationPreference()
|
||||
{
|
||||
Qt::ScreenOrientation result = Qt::PrimaryOrientation;
|
||||
if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences) {
|
||||
DWORD orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
||||
if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences(&orientationPreference)) {
|
||||
switch (orientationPreference) {
|
||||
case ORIENTATION_PREFERENCE_NONE:
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_LANDSCAPE:
|
||||
result = Qt::LandscapeOrientation;
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_PORTRAIT:
|
||||
result = Qt::PortraitOrientation;
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED:
|
||||
result = Qt::InvertedLandscapeOrientation;
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED:
|
||||
result = Qt::InvertedPortraitOrientation;
|
||||
break;
|
||||
}
|
||||
ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
|
||||
|
||||
BOOL bResult = TRUE;
|
||||
|
||||
if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences)
|
||||
bResult = QWindowsContext::user32dll.getDisplayAutoRotationPreferences((DWORD *)&orientationPreference);
|
||||
else
|
||||
bResult = vxkex::GetDisplayAutoRotationPreferences(&orientationPreference);
|
||||
|
||||
if (bResult) {
|
||||
switch (orientationPreference) {
|
||||
case ORIENTATION_PREFERENCE_NONE:
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_LANDSCAPE:
|
||||
result = Qt::LandscapeOrientation;
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_PORTRAIT:
|
||||
result = Qt::PortraitOrientation;
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED:
|
||||
result = Qt::InvertedLandscapeOrientation;
|
||||
break;
|
||||
case ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED:
|
||||
result = Qt::InvertedPortraitOrientation;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -704,11 +719,15 @@ void QWindowsScreenManager::initialize()
|
||||
handleScreenChanges();
|
||||
}
|
||||
|
||||
QWindowsScreenManager::~QWindowsScreenManager()
|
||||
void QWindowsScreenManager::destroyWindow()
|
||||
{
|
||||
qCDebug(lcQpaScreen) << "Destroying display change observer" << m_displayChangeObserver;
|
||||
DestroyWindow(m_displayChangeObserver);
|
||||
m_displayChangeObserver = nullptr;
|
||||
}
|
||||
|
||||
QWindowsScreenManager::~QWindowsScreenManager() = default;
|
||||
|
||||
bool QWindowsScreenManager::isSingleScreen()
|
||||
{
|
||||
return QWindowsContext::instance()->screenManager().screens().size() < 2;
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "qwindowsmenu.h"
|
||||
#include "qwindowsdialoghelpers.h"
|
||||
#include "qwindowscontext.h"
|
||||
#include "qwindowsiconengine.h"
|
||||
#include "qwindowsintegration.h"
|
||||
#if QT_CONFIG(systemtrayicon)
|
||||
# include "qwindowssystemtrayicon.h"
|
||||
@ -27,6 +28,7 @@
|
||||
#include <QtCore/qthread.h>
|
||||
#include <QtCore/qmutex.h>
|
||||
#include <QtCore/qwaitcondition.h>
|
||||
#include <QtCore/qoperatingsystemversion.h>
|
||||
#include <QtGui/qcolor.h>
|
||||
#include <QtGui/qpalette.h>
|
||||
#include <QtGui/qguiapplication.h>
|
||||
@ -42,7 +44,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <VersionHelpers.h>
|
||||
#include "vxkex.h"
|
||||
|
||||
#if QT_CONFIG(cpp_winrt)
|
||||
# include <QtCore/private/qt_winrtbase_p.h>
|
||||
@ -81,11 +83,11 @@ static inline QColor mixColors(const QColor &c1, const QColor &c2)
|
||||
(c1.blue() + c2.blue()) / 2};
|
||||
}
|
||||
|
||||
static inline QColor getSysColor(int index)
|
||||
{
|
||||
COLORREF cr = GetSysColor(index);
|
||||
return QColor(GetRValue(cr), GetGValue(cr), GetBValue(cr));
|
||||
}
|
||||
enum AccentColorLevel {
|
||||
AccentColorDarkest,
|
||||
AccentColorNormal,
|
||||
AccentColorLightest
|
||||
};
|
||||
|
||||
#if QT_CONFIG(cpp_winrt)
|
||||
static constexpr QColor getSysColor(winrt::Windows::UI::Color &&color)
|
||||
@ -94,6 +96,54 @@ static constexpr QColor getSysColor(winrt::Windows::UI::Color &&color)
|
||||
}
|
||||
#endif
|
||||
|
||||
[[maybe_unused]] [[nodiscard]] static inline QColor qt_accentColor(AccentColorLevel level)
|
||||
{
|
||||
QColor accent;
|
||||
QColor accentLight;
|
||||
QColor accentDarkest;
|
||||
|
||||
#if QT_CONFIG(cpp_winrt)
|
||||
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10)
|
||||
{
|
||||
using namespace winrt::Windows::UI::ViewManagement;
|
||||
const auto settings = UISettings();
|
||||
accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
|
||||
accentLight = getSysColor(settings.GetColorValue(UIColorType::AccentLight1));
|
||||
accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!accent.isValid())
|
||||
{
|
||||
const QWinRegistryKey registry(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\DWM)");
|
||||
if (!registry.isValid())
|
||||
return {};
|
||||
const QVariant value = registry.value(L"AccentColor");
|
||||
if (!value.isValid())
|
||||
return {};
|
||||
// The retrieved value is in the #AABBGGRR format, we need to
|
||||
// convert it to the #AARRGGBB format which Qt expects.
|
||||
const QColor abgr = QColor::fromRgba(qvariant_cast<DWORD>(value));
|
||||
if (!abgr.isValid())
|
||||
return {};
|
||||
accent = QColor::fromRgb(abgr.blue(), abgr.green(), abgr.red(), abgr.alpha());
|
||||
accentLight = accent.lighter(120);
|
||||
accentDarkest = accent.darker(120 * 120 * 120);
|
||||
}
|
||||
|
||||
if (level == AccentColorDarkest)
|
||||
return accentDarkest;
|
||||
else if (level == AccentColorLightest)
|
||||
return accentLight;
|
||||
return accent;
|
||||
}
|
||||
|
||||
static inline QColor getSysColor(int index)
|
||||
{
|
||||
COLORREF cr = GetSysColor(index);
|
||||
return QColor(GetRValue(cr), GetGValue(cr), GetBValue(cr));
|
||||
}
|
||||
|
||||
// QTBUG-48823/Windows 10: SHGetFileInfo() (as called by item views on file system
|
||||
// models has been observed to trigger a WM_PAINT on the mainwindow. Suppress the
|
||||
// behavior by running it in a thread.
|
||||
@ -223,44 +273,17 @@ static QColor placeHolderColor(QColor textColor)
|
||||
return textColor;
|
||||
}
|
||||
|
||||
[[maybe_unused]] [[nodiscard]] static inline QColor qt_accentColor()
|
||||
{
|
||||
const QWinRegistryKey registry(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\DWM)");
|
||||
if (!registry.isValid())
|
||||
return {};
|
||||
const QVariant value = registry.value(L"AccentColor");
|
||||
if (!value.isValid())
|
||||
return {};
|
||||
// The retrieved value is in the #AABBGGRR format, we need to
|
||||
// convert it to the #AARRGGBB format which Qt expects.
|
||||
const QColor abgr = QColor::fromRgba(qvariant_cast<DWORD>(value));
|
||||
if (!abgr.isValid())
|
||||
return {};
|
||||
return QColor::fromRgb(abgr.blue(), abgr.green(), abgr.red(), abgr.alpha());
|
||||
}
|
||||
|
||||
/*
|
||||
This is used when the theme is light mode, and when the theme is dark but the
|
||||
application doesn't support dark mode. In the latter case, we need to check.
|
||||
*/
|
||||
static void populateLightSystemBasePalette(QPalette &result)
|
||||
{
|
||||
QColor background = getSysColor(COLOR_BTNFACE);
|
||||
QColor textColor = getSysColor(COLOR_WINDOWTEXT);
|
||||
QColor accent = qt_accentColor();
|
||||
QColor accentDarkest = accent.darker(120 * 120 * 120);
|
||||
const QColor background = getSysColor(COLOR_BTNFACE);
|
||||
const QColor textColor = getSysColor(COLOR_WINDOWTEXT);
|
||||
|
||||
#if QT_CONFIG(cpp_winrt)
|
||||
if (IsWindows10OrGreater())
|
||||
{
|
||||
// respect the Windows 11 accent color
|
||||
using namespace winrt::Windows::UI::ViewManagement;
|
||||
const auto settings = UISettings();
|
||||
|
||||
accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
|
||||
accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
|
||||
}
|
||||
#endif
|
||||
const QColor accent = qt_accentColor(AccentColorNormal);
|
||||
const QColor accentDarkest = qt_accentColor(AccentColorDarkest);
|
||||
|
||||
const QColor linkColor = accent;
|
||||
const QColor btnFace = background;
|
||||
@ -298,7 +321,7 @@ static void populateDarkSystemBasePalette(QPalette &result)
|
||||
{
|
||||
QColor foreground = Qt::white;
|
||||
QColor background = QColor(0x1E, 0x1E, 0x1E);
|
||||
QColor accent = qt_accentColor();
|
||||
QColor accent = qt_accentColor(AccentColorNormal);
|
||||
QColor accentDark = accent.darker(120);
|
||||
QColor accentDarker = accentDark.darker(120);
|
||||
QColor accentDarkest = accentDarker.darker(120);
|
||||
@ -307,7 +330,7 @@ static void populateDarkSystemBasePalette(QPalette &result)
|
||||
QColor accentLightest = accentLighter.lighter(120);
|
||||
|
||||
#if QT_CONFIG(cpp_winrt)
|
||||
if (IsWindows10OrGreater())
|
||||
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10)
|
||||
{
|
||||
using namespace winrt::Windows::UI::ViewManagement;
|
||||
const auto settings = UISettings();
|
||||
@ -472,7 +495,10 @@ static inline QStringList iconThemeSearchPaths()
|
||||
|
||||
static inline QStringList styleNames()
|
||||
{
|
||||
return { QStringLiteral("WindowsVista"), QStringLiteral("Windows") };
|
||||
QStringList styles = { QStringLiteral("WindowsVista"), QStringLiteral("Windows") };
|
||||
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows11)
|
||||
styles.prepend(QStringLiteral("Windows11"));
|
||||
return styles;
|
||||
}
|
||||
|
||||
static inline int uiEffects()
|
||||
@ -537,6 +563,8 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const
|
||||
|
||||
Qt::ColorScheme QWindowsTheme::colorScheme() const
|
||||
{
|
||||
if (queryHighContrast())
|
||||
return Qt::ColorScheme::Unknown;
|
||||
return QWindowsContext::isDarkMode() ? Qt::ColorScheme::Dark : Qt::ColorScheme::Light;
|
||||
}
|
||||
|
||||
@ -559,24 +587,10 @@ void QWindowsTheme::refreshPalettes()
|
||||
m_palettes[MenuPalette] = new QPalette(menuPalette(*m_palettes[SystemPalette], light));
|
||||
m_palettes[MenuBarPalette] = menuBarPalette(*m_palettes[MenuPalette], light);
|
||||
if (!light) {
|
||||
QColor accent = qt_accentColor();
|
||||
QColor accentLight = accent.lighter(120);
|
||||
QColor accentDarkest = accent.darker(120 * 120 * 120);
|
||||
|
||||
#if QT_CONFIG(cpp_winrt)
|
||||
if (IsWindows10OrGreater())
|
||||
{
|
||||
using namespace winrt::Windows::UI::ViewManagement;
|
||||
const auto settings = UISettings();
|
||||
accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
|
||||
accentLight = getSysColor(settings.GetColorValue(UIColorType::AccentLight1));
|
||||
accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
|
||||
}
|
||||
#endif
|
||||
m_palettes[CheckBoxPalette] = new QPalette(*m_palettes[SystemPalette]);
|
||||
m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Base, accent);
|
||||
m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Button, accentLight);
|
||||
m_palettes[CheckBoxPalette]->setColor(QPalette::Inactive, QPalette::Base, accentDarkest);
|
||||
m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Base, qt_accentColor(AccentColorNormal));
|
||||
m_palettes[CheckBoxPalette]->setColor(QPalette::Active, QPalette::Button, qt_accentColor(AccentColorLightest));
|
||||
m_palettes[CheckBoxPalette]->setColor(QPalette::Inactive, QPalette::Base, qt_accentColor(AccentColorDarkest));
|
||||
m_palettes[RadioButtonPalette] = new QPalette(*m_palettes[CheckBoxPalette]);
|
||||
}
|
||||
}
|
||||
@ -586,15 +600,15 @@ QPalette QWindowsTheme::systemPalette(Qt::ColorScheme colorScheme)
|
||||
QPalette result = standardPalette();
|
||||
|
||||
switch (colorScheme) {
|
||||
case Qt::ColorScheme::Light:
|
||||
populateLightSystemBasePalette(result);
|
||||
break;
|
||||
case Qt::ColorScheme::Dark:
|
||||
populateDarkSystemBasePalette(result);
|
||||
break;
|
||||
default:
|
||||
qFatal("Unknown color scheme");
|
||||
break;
|
||||
case Qt::ColorScheme::Light:
|
||||
populateLightSystemBasePalette(result);
|
||||
break;
|
||||
case Qt::ColorScheme::Dark:
|
||||
populateDarkSystemBasePalette(result);
|
||||
break;
|
||||
default:
|
||||
qFatal("Unknown color scheme");
|
||||
break;
|
||||
}
|
||||
|
||||
if (result.window() != result.base()) {
|
||||
@ -675,14 +689,11 @@ void QWindowsTheme::refreshFonts()
|
||||
fixedFont.setStyleHint(QFont::TypeWriter);
|
||||
|
||||
LOGFONT lfIconTitleFont;
|
||||
QFont iconTitleFont;
|
||||
if (QWindowsContext::user32dll.systemParametersInfoForDpi) {
|
||||
if (QWindowsContext::user32dll.systemParametersInfoForDpi)
|
||||
QWindowsContext::user32dll.systemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
|
||||
iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont, dpi);
|
||||
} else {
|
||||
SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
|
||||
iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont);
|
||||
}
|
||||
else
|
||||
vxkex::SystemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
|
||||
const QFont iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont, dpi);
|
||||
|
||||
m_fonts[SystemFont] = new QFont(QWindowsFontDatabase::systemDefaultFont());
|
||||
m_fonts[MenuFont] = new QFont(menuFont);
|
||||
@ -856,15 +867,18 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz
|
||||
}
|
||||
|
||||
if (stockId != SIID_INVALID) {
|
||||
QPixmap pixmap;
|
||||
SHSTOCKICONINFO iconInfo;
|
||||
memset(&iconInfo, 0, sizeof(iconInfo));
|
||||
iconInfo.cbSize = sizeof(iconInfo);
|
||||
stockFlags |= (pixmapSize.width() > 16 ? SHGFI_LARGEICON : SHGFI_SMALLICON);
|
||||
if (SHGetStockIconInfo(stockId, SHGFI_ICON | stockFlags, &iconInfo) == S_OK) {
|
||||
pixmap = qt_pixmapFromWinHICON(iconInfo.hIcon);
|
||||
DestroyIcon(iconInfo.hIcon);
|
||||
return pixmap;
|
||||
stockFlags |= SHGSI_ICONLOCATION;
|
||||
if (SHGetStockIconInfo(stockId, stockFlags, &iconInfo) == S_OK) {
|
||||
const auto iconSize = pixmapSize.width();
|
||||
HICON icon;
|
||||
if (SHDefExtractIcon(iconInfo.szPath, iconInfo.iIcon, 0, &icon, nullptr, iconSize) == S_OK) {
|
||||
QPixmap pixmap = qt_pixmapFromWinHICON(icon);
|
||||
DestroyIcon(icon);
|
||||
return pixmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1088,6 +1102,11 @@ QIcon QWindowsTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOpt
|
||||
return QIcon(new QWindowsFileIconEngine(fileInfo, iconOptions));
|
||||
}
|
||||
|
||||
QIconEngine *QWindowsTheme::createIconEngine(const QString &iconName) const
|
||||
{
|
||||
return new QWindowsIconEngine(iconName);
|
||||
}
|
||||
|
||||
static inline bool doUseNativeMenus()
|
||||
{
|
||||
const unsigned options = QWindowsIntegration::instance()->options();
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <QtGui/qwindow.h>
|
||||
#include <QtGui/qregion.h>
|
||||
#include <QtGui/qopenglcontext.h>
|
||||
#include <QtGui/private/qwindowsthemecache_p.h>
|
||||
#include <private/qwindow_p.h> // QWINDOWSIZE_MAX
|
||||
#include <private/qguiapplication_p.h>
|
||||
#include <private/qhighdpiscaling_p.h>
|
||||
@ -43,6 +44,8 @@
|
||||
|
||||
#include <shellscalingapi.h>
|
||||
|
||||
#include "vxkex.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
using QWindowCreationContextPtr = QSharedPointer<QWindowCreationContext>;
|
||||
@ -526,8 +529,8 @@ static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::Windo
|
||||
return QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi)
|
||||
+ QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
||||
}
|
||||
|
||||
return GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
|
||||
else
|
||||
return vxkex::GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + vxkex::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -537,16 +540,22 @@ static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::Windo
|
||||
|
||||
static QMargins invisibleMargins(QPoint screenPoint)
|
||||
{
|
||||
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10) {
|
||||
POINT pt = {screenPoint.x(), screenPoint.y()};
|
||||
if (HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
|
||||
if (QWindowsContext::shcoredll.isValid()) {
|
||||
UINT dpiX;
|
||||
UINT dpiY;
|
||||
if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY))) {
|
||||
const int gap = getResizeBorderThickness(dpiX);
|
||||
return QMargins(gap, 0, gap, gap);
|
||||
}
|
||||
POINT pt = {screenPoint.x(), screenPoint.y()};
|
||||
if (HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
|
||||
if (QWindowsContext::shcoredll.isValid()) {
|
||||
UINT dpiX;
|
||||
UINT dpiY;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10)
|
||||
hr = QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
|
||||
else
|
||||
hr = vxkex::GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
const int gap = getResizeBorderThickness(dpiX);
|
||||
return QMargins(gap, 0, gap, gap);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -555,12 +564,10 @@ static QMargins invisibleMargins(QPoint screenPoint)
|
||||
|
||||
[[nodiscard]] static inline QMargins invisibleMargins(const HWND hwnd)
|
||||
{
|
||||
if (QWindowsContext::user32dll.getDpiForWindow) {
|
||||
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
|
||||
const int gap = getResizeBorderThickness(dpi);
|
||||
return QMargins(gap, 0, gap, gap);
|
||||
}
|
||||
return QMargins();
|
||||
const UINT dpi = (QWindowsContext::user32dll.getDpiForWindow) ? QWindowsContext::user32dll.getDpiForWindow(hwnd) : vxkex::GetDpiForWindow(hwnd);
|
||||
|
||||
const int gap = getResizeBorderThickness(dpi);
|
||||
return QMargins(gap, 0, gap, gap);
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -848,6 +855,10 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
|
||||
// NOTE: WS_EX_TRANSPARENT flag can make mouse inputs fall through a layered window
|
||||
if (flagsIn & Qt::WindowTransparentForInput)
|
||||
exStyle |= WS_EX_LAYERED | WS_EX_TRANSPARENT;
|
||||
|
||||
// Currently only compatible with D3D surfaces, use it with care.
|
||||
if (qEnvironmentVariableIntValue("QT_QPA_DISABLE_REDIRECTION_SURFACE"))
|
||||
exStyle |= WS_EX_NOREDIRECTIONBITMAP;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1074,10 +1085,17 @@ QMargins QWindowsGeometryHint::frame(const QWindow *w, DWORD style, DWORD exStyl
|
||||
return {};
|
||||
RECT rect = {0,0,0,0};
|
||||
style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
|
||||
if (QWindowsContext::user32dll.adjustWindowRectExForDpi &&
|
||||
QWindowsContext::user32dll.adjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi))) == FALSE) {
|
||||
qErrnoWarning("%s: AdjustWindowRectExForDpi failed", __FUNCTION__);
|
||||
if (QWindowsContext::user32dll.adjustWindowRectExForDpi)
|
||||
{
|
||||
if (QWindowsContext::user32dll.adjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi))) == FALSE)
|
||||
qErrnoWarning("%s: AdjustWindowRectExForDpi failed", __FUNCTION__);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vxkex::AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi))) == FALSE)
|
||||
qErrnoWarning("%s: vxkex::AdjustWindowRectExForDpi failed", __FUNCTION__);
|
||||
}
|
||||
|
||||
const QMargins result(qAbs(rect.left), qAbs(rect.top),
|
||||
qAbs(rect.right), qAbs(rect.bottom));
|
||||
qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << " style="
|
||||
@ -1364,6 +1382,8 @@ QWindowsForeignWindow::QWindowsForeignWindow(QWindow *window, HWND hwnd)
|
||||
, m_hwnd(hwnd)
|
||||
, m_topLevelStyle(0)
|
||||
{
|
||||
if (QPlatformWindow::parent())
|
||||
setParent(QPlatformWindow::parent());
|
||||
}
|
||||
|
||||
void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow)
|
||||
@ -1539,6 +1559,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
|
||||
QWindowsWindow::~QWindowsWindow()
|
||||
{
|
||||
setFlag(WithinDestroy);
|
||||
QWindowsThemeCache::clearThemeCache(m_data.hwnd);
|
||||
if (testFlag(TouchRegistered))
|
||||
UnregisterTouchWindow(m_data.hwnd);
|
||||
destroyWindow();
|
||||
@ -1568,7 +1589,7 @@ void QWindowsWindow::initialize()
|
||||
}
|
||||
}
|
||||
QWindowsWindow::setSavedDpi(QWindowsContext::user32dll.getDpiForWindow ?
|
||||
QWindowsContext::user32dll.getDpiForWindow(handle()) : 96);
|
||||
QWindowsContext::user32dll.getDpiForWindow(handle()) : vxkex::GetDpiForWindow(handle()));
|
||||
}
|
||||
|
||||
QSurfaceFormat QWindowsWindow::format() const
|
||||
@ -2018,6 +2039,9 @@ void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||
const UINT dpi = HIWORD(wParam);
|
||||
const qreal scale = dpiRelativeScale(dpi);
|
||||
setSavedDpi(dpi);
|
||||
|
||||
QWindowsThemeCache::clearThemeCache(hwnd);
|
||||
|
||||
// Send screen change first, so that the new screen is set during any following resize
|
||||
checkForScreenChanged(QWindowsWindow::FromDpiChange);
|
||||
|
||||
@ -2060,20 +2084,17 @@ void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
|
||||
|
||||
void QWindowsWindow::handleDpiChangedAfterParent(HWND hwnd)
|
||||
{
|
||||
if (QWindowsContext::user32dll.getDpiForWindow)
|
||||
{
|
||||
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
|
||||
const qreal scale = dpiRelativeScale(dpi);
|
||||
setSavedDpi(dpi);
|
||||
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow ? QWindowsContext::user32dll.getDpiForWindow(hwnd) : vxkex::GetDpiForWindow(hwnd);
|
||||
const qreal scale = dpiRelativeScale(dpi);
|
||||
setSavedDpi(dpi);
|
||||
|
||||
checkForScreenChanged(QWindowsWindow::FromDpiChange);
|
||||
checkForScreenChanged(QWindowsWindow::FromDpiChange);
|
||||
|
||||
// Child windows do not get WM_GETDPISCALEDSIZE messages to inform
|
||||
// Windows about the new size, so we need to manually scale them.
|
||||
QRect currentGeometry = geometry();
|
||||
QRect scaledGeometry = QRect(currentGeometry.topLeft() * scale, currentGeometry.size() * scale);
|
||||
setGeometry(scaledGeometry);
|
||||
}
|
||||
// Child windows do not get WM_GETDPISCALEDSIZE messages to inform
|
||||
// Windows about the new size, so we need to manually scale them.
|
||||
QRect currentGeometry = geometry();
|
||||
QRect scaledGeometry = QRect(currentGeometry.topLeft() * scale, currentGeometry.size() * scale);
|
||||
setGeometry(scaledGeometry);
|
||||
}
|
||||
|
||||
static QRect normalFrameGeometry(HWND hwnd)
|
||||
@ -2485,6 +2506,11 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
|
||||
GetWindowPlacement(m_data.hwnd, &windowPlacement);
|
||||
const RECT geometry = RECTfromQRect(m_data.restoreGeometry);
|
||||
windowPlacement.rcNormalPosition = geometry;
|
||||
// Even if the window is hidden, windowPlacement's showCmd is not SW_HIDE, so change it
|
||||
// manually to avoid unhiding a hidden window with the subsequent call to
|
||||
// SetWindowPlacement().
|
||||
if (!isVisible())
|
||||
windowPlacement.showCmd = SW_HIDE;
|
||||
SetWindowPlacement(m_data.hwnd, &windowPlacement);
|
||||
}
|
||||
// QTBUG-17548: We send expose events when receiving WM_Paint, but for
|
||||
|
430
qtbase/src/plugins/platforms/windows/vxkex.h
Normal file
430
qtbase/src/plugins/platforms/windows/vxkex.h
Normal file
@ -0,0 +1,430 @@
|
||||
#pragma once
|
||||
|
||||
#include <shtypes.h>
|
||||
#include <winuser.h>
|
||||
#include <windef.h>
|
||||
#include <shellscalingapi.h>
|
||||
|
||||
#define MDT_MAXIMUM_DPI 3
|
||||
|
||||
namespace vxkex {
|
||||
|
||||
static INT GetSystemMetricsForDpi(
|
||||
IN INT Index,
|
||||
IN UINT Dpi)
|
||||
{
|
||||
INT Value;
|
||||
|
||||
Value = GetSystemMetrics(Index);
|
||||
|
||||
switch (Index) {
|
||||
case SM_CXVSCROLL:
|
||||
case SM_CYHSCROLL:
|
||||
case SM_CYCAPTION:
|
||||
case SM_CYVTHUMB:
|
||||
case SM_CXHTHUMB:
|
||||
case SM_CXICON:
|
||||
case SM_CYICON:
|
||||
case SM_CXCURSOR:
|
||||
case SM_CYCURSOR:
|
||||
case SM_CYMENU:
|
||||
case SM_CYVSCROLL:
|
||||
case SM_CXHSCROLL:
|
||||
case SM_CXMIN:
|
||||
case SM_CXMINTRACK:
|
||||
case SM_CYMIN:
|
||||
case SM_CYMINTRACK:
|
||||
case SM_CXSIZE:
|
||||
case SM_CXFRAME:
|
||||
case SM_CYFRAME:
|
||||
case SM_CXICONSPACING:
|
||||
case SM_CYICONSPACING:
|
||||
case SM_CXSMICON:
|
||||
case SM_CYSMICON:
|
||||
case SM_CYSMCAPTION:
|
||||
case SM_CXSMSIZE:
|
||||
case SM_CYSMSIZE:
|
||||
case SM_CXMENUSIZE:
|
||||
case SM_CYMENUSIZE:
|
||||
case SM_CXMENUCHECK:
|
||||
case SM_CYMENUCHECK:
|
||||
// These are pixel values that have to be scaled according to DPI.
|
||||
Value *= Dpi;
|
||||
Value /= USER_DEFAULT_SCREEN_DPI;
|
||||
break;
|
||||
}
|
||||
|
||||
return Value;
|
||||
}
|
||||
|
||||
static BOOL SystemParametersInfoForDpi(
|
||||
IN UINT Action,
|
||||
IN UINT Parameter,
|
||||
IN OUT PVOID Data,
|
||||
IN UINT WinIni,
|
||||
IN UINT Dpi)
|
||||
{
|
||||
switch (Action) {
|
||||
case SPI_GETICONTITLELOGFONT:
|
||||
return SystemParametersInfo(Action, Parameter, Data, 0);
|
||||
case SPI_GETICONMETRICS:
|
||||
{
|
||||
BOOL Success;
|
||||
PICONMETRICS IconMetrics;
|
||||
|
||||
Success = SystemParametersInfo(Action, Parameter, Data, 0);
|
||||
|
||||
if (Success) {
|
||||
IconMetrics = (PICONMETRICS) Data;
|
||||
|
||||
IconMetrics->iHorzSpacing *= Dpi;
|
||||
IconMetrics->iVertSpacing *= Dpi;
|
||||
IconMetrics->iHorzSpacing /= USER_DEFAULT_SCREEN_DPI;
|
||||
IconMetrics->iVertSpacing /= USER_DEFAULT_SCREEN_DPI;
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
case SPI_GETNONCLIENTMETRICS:
|
||||
{
|
||||
BOOL Success;
|
||||
PNONCLIENTMETRICS NonClientMetrics;
|
||||
|
||||
Success = SystemParametersInfo(Action, Parameter, Data, 0);
|
||||
|
||||
if (Success) {
|
||||
NonClientMetrics = (PNONCLIENTMETRICS) Data;
|
||||
|
||||
NonClientMetrics->iBorderWidth *= Dpi;
|
||||
NonClientMetrics->iScrollWidth *= Dpi;
|
||||
NonClientMetrics->iScrollHeight *= Dpi;
|
||||
NonClientMetrics->iCaptionWidth *= Dpi;
|
||||
NonClientMetrics->iCaptionHeight *= Dpi;
|
||||
NonClientMetrics->iSmCaptionWidth *= Dpi;
|
||||
NonClientMetrics->iSmCaptionHeight *= Dpi;
|
||||
NonClientMetrics->iMenuWidth *= Dpi;
|
||||
NonClientMetrics->iMenuHeight *= Dpi;
|
||||
NonClientMetrics->iPaddedBorderWidth *= Dpi;
|
||||
|
||||
NonClientMetrics->iBorderWidth /= USER_DEFAULT_SCREEN_DPI;
|
||||
NonClientMetrics->iScrollWidth /= USER_DEFAULT_SCREEN_DPI;
|
||||
NonClientMetrics->iScrollHeight /= USER_DEFAULT_SCREEN_DPI;
|
||||
NonClientMetrics->iCaptionWidth /= USER_DEFAULT_SCREEN_DPI;
|
||||
NonClientMetrics->iCaptionHeight /= USER_DEFAULT_SCREEN_DPI;
|
||||
NonClientMetrics->iSmCaptionWidth /= USER_DEFAULT_SCREEN_DPI;
|
||||
NonClientMetrics->iSmCaptionHeight /= USER_DEFAULT_SCREEN_DPI;
|
||||
NonClientMetrics->iMenuWidth /= USER_DEFAULT_SCREEN_DPI;
|
||||
NonClientMetrics->iMenuHeight /= USER_DEFAULT_SCREEN_DPI;
|
||||
NonClientMetrics->iPaddedBorderWidth /= USER_DEFAULT_SCREEN_DPI;
|
||||
}
|
||||
|
||||
return Success;
|
||||
}
|
||||
default:
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT GetScaleFactorForMonitor(
|
||||
IN HMONITOR Monitor,
|
||||
OUT DEVICE_SCALE_FACTOR *ScaleFactor)
|
||||
{
|
||||
HDC DeviceContext;
|
||||
ULONG LogPixelsX;
|
||||
|
||||
DeviceContext = GetDC(NULL);
|
||||
if (!DeviceContext) {
|
||||
*ScaleFactor = SCALE_100_PERCENT;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
LogPixelsX = GetDeviceCaps(DeviceContext, LOGPIXELSX);
|
||||
ReleaseDC(NULL, DeviceContext);
|
||||
|
||||
*ScaleFactor = (DEVICE_SCALE_FACTOR) (9600 / LogPixelsX);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT GetDpiForMonitor(
|
||||
IN HMONITOR Monitor,
|
||||
IN MONITOR_DPI_TYPE DpiType,
|
||||
OUT UINT * DpiX,
|
||||
OUT UINT * DpiY)
|
||||
{
|
||||
HDC DeviceContext;
|
||||
|
||||
if (DpiType >= MDT_MAXIMUM_DPI) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (!DpiX || !DpiY) {
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
if (!IsProcessDPIAware()) {
|
||||
*DpiX = USER_DEFAULT_SCREEN_DPI;
|
||||
*DpiY = USER_DEFAULT_SCREEN_DPI;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
DeviceContext = GetDC(NULL);
|
||||
if (!DeviceContext) {
|
||||
*DpiX = USER_DEFAULT_SCREEN_DPI;
|
||||
*DpiY = USER_DEFAULT_SCREEN_DPI;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
*DpiX = GetDeviceCaps(DeviceContext, LOGPIXELSX);
|
||||
*DpiY = GetDeviceCaps(DeviceContext, LOGPIXELSY);
|
||||
|
||||
if (DpiType == MDT_EFFECTIVE_DPI) {
|
||||
DEVICE_SCALE_FACTOR ScaleFactor;
|
||||
|
||||
// We have to multiply the DPI values by the scaling factor.
|
||||
vxkex::GetScaleFactorForMonitor(Monitor, &ScaleFactor);
|
||||
|
||||
*DpiX *= ScaleFactor;
|
||||
*DpiY *= ScaleFactor;
|
||||
*DpiX /= 100;
|
||||
*DpiY /= 100;
|
||||
}
|
||||
|
||||
ReleaseDC(NULL, DeviceContext);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static UINT GetDpiForSystem(
|
||||
VOID)
|
||||
{
|
||||
HDC DeviceContext;
|
||||
ULONG LogPixelsX;
|
||||
|
||||
if (!IsProcessDPIAware()) {
|
||||
return 96;
|
||||
}
|
||||
|
||||
DeviceContext = GetDC(NULL);
|
||||
if (!DeviceContext) {
|
||||
return 96;
|
||||
}
|
||||
|
||||
LogPixelsX = GetDeviceCaps(DeviceContext, LOGPIXELSX);
|
||||
ReleaseDC(NULL, DeviceContext);
|
||||
|
||||
return LogPixelsX;
|
||||
}
|
||||
|
||||
static UINT GetDpiForWindow(
|
||||
IN HWND Window)
|
||||
{
|
||||
if (!IsWindow(Window)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return vxkex::GetDpiForSystem();
|
||||
}
|
||||
|
||||
static BOOL AdjustWindowRectExForDpi(
|
||||
IN OUT LPRECT Rect,
|
||||
IN ULONG WindowStyle,
|
||||
IN BOOL HasMenu,
|
||||
IN ULONG WindowExStyle,
|
||||
IN ULONG Dpi)
|
||||
{
|
||||
// I'm not sure how to implement this function properly.
|
||||
// If it turns out to be important, I'll have to do some testing
|
||||
// on a Win10 VM.
|
||||
|
||||
return AdjustWindowRectEx(
|
||||
Rect,
|
||||
WindowStyle,
|
||||
HasMenu,
|
||||
WindowExStyle);
|
||||
}
|
||||
|
||||
static BOOL SetDisplayAutoRotationPreferences(
|
||||
IN ORIENTATION_PREFERENCE Orientation)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL GetDisplayAutoRotationPreferences(
|
||||
OUT ORIENTATION_PREFERENCE * Orientation)
|
||||
{
|
||||
*Orientation = ORIENTATION_PREFERENCE_NONE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// scaling.c
|
||||
|
||||
static BOOL SetProcessDpiAwarenessContext(
|
||||
IN DPI_AWARENESS_CONTEXT DpiContext)
|
||||
{
|
||||
switch ((ULONG_PTR)DpiContext) {
|
||||
case (ULONG_PTR)DPI_AWARENESS_CONTEXT_UNAWARE:
|
||||
//NOTHING;
|
||||
break;
|
||||
case (ULONG_PTR)DPI_AWARENESS_CONTEXT_SYSTEM_AWARE:
|
||||
case (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE:
|
||||
case (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2:
|
||||
SetProcessDPIAware();
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL AreDpiAwarenessContextsEqual(
|
||||
IN DPI_AWARENESS_CONTEXT Value1,
|
||||
IN DPI_AWARENESS_CONTEXT Value2)
|
||||
{
|
||||
return (Value1 == Value2);
|
||||
}
|
||||
|
||||
static BOOL IsValidDpiAwarenessContext(
|
||||
IN DPI_AWARENESS_CONTEXT Value)
|
||||
{
|
||||
switch ((ULONG_PTR)Value) {
|
||||
case (ULONG_PTR)DPI_AWARENESS_CONTEXT_UNAWARE:
|
||||
case (ULONG_PTR)DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED:
|
||||
case (ULONG_PTR)DPI_AWARENESS_CONTEXT_SYSTEM_AWARE:
|
||||
case (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE:
|
||||
case (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2:
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL EnableNonClientDpiScaling(
|
||||
IN HWND Window)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static DPI_AWARENESS_CONTEXT GetThreadDpiAwarenessContext(
|
||||
VOID)
|
||||
{
|
||||
if (IsProcessDPIAware()) {
|
||||
return DPI_AWARENESS_CONTEXT_SYSTEM_AWARE;
|
||||
} else {
|
||||
return DPI_AWARENESS_CONTEXT_UNAWARE;
|
||||
}
|
||||
}
|
||||
|
||||
static DPI_AWARENESS_CONTEXT GetWindowDpiAwarenessContext(
|
||||
IN HWND Window)
|
||||
{
|
||||
ULONG WindowThreadId;
|
||||
ULONG WindowProcessId;
|
||||
|
||||
WindowThreadId = GetWindowThreadProcessId(Window, &WindowProcessId);
|
||||
if (!WindowThreadId) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// looks like there's a bug in vxkex, here should be == instead of =
|
||||
// and if is always true
|
||||
// anyway I don't want to deal with Windows kernel mode structures here
|
||||
|
||||
if (1) { //if (WindowProcessId = (ULONG) NtCurrentTeb()->ClientId.UniqueProcess) {
|
||||
return vxkex::GetThreadDpiAwarenessContext();
|
||||
}
|
||||
|
||||
return DPI_AWARENESS_CONTEXT_UNAWARE;
|
||||
}
|
||||
|
||||
// pointer.c
|
||||
|
||||
static BOOL GetPointerType(
|
||||
IN UINT32 PointerId,
|
||||
OUT POINTER_INPUT_TYPE *PointerType)
|
||||
{
|
||||
*PointerType = PT_MOUSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL GetPointerFrameTouchInfo(
|
||||
IN UINT32 PointerId,
|
||||
IN OUT UINT32 *PointerCount,
|
||||
OUT LPVOID TouchInfo)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL GetPointerFrameTouchInfoHistory(
|
||||
IN UINT32 PointerId,
|
||||
IN OUT UINT32 *EntriesCount,
|
||||
IN OUT UINT32 *PointerCount,
|
||||
OUT LPVOID TouchInfo)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL GetPointerPenInfo(
|
||||
IN UINT32 PointerId,
|
||||
OUT LPVOID PenInfo)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL GetPointerPenInfoHistory(
|
||||
IN UINT32 PointerId,
|
||||
IN OUT UINT32 *EntriesCount,
|
||||
OUT LPVOID PenInfo)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL SkipPointerFrameMessages(
|
||||
IN UINT32 PointerId)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL GetPointerDeviceRects(
|
||||
IN HANDLE Device,
|
||||
OUT LPRECT PointerDeviceRect,
|
||||
OUT LPRECT DisplayRect)
|
||||
{
|
||||
PointerDeviceRect->top = 0;
|
||||
PointerDeviceRect->left = 0;
|
||||
PointerDeviceRect->bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
||||
PointerDeviceRect->right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
||||
|
||||
DisplayRect->top = 0;
|
||||
DisplayRect->left = 0;
|
||||
DisplayRect->bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
||||
DisplayRect->right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL GetPointerInfo(
|
||||
IN DWORD PointerId,
|
||||
OUT POINTER_INFO *PointerInfo)
|
||||
{
|
||||
PointerInfo->pointerType = PT_MOUSE;
|
||||
PointerInfo->pointerId = PointerId;
|
||||
PointerInfo->frameId = 0;
|
||||
PointerInfo->pointerFlags = POINTER_FLAG_NONE;
|
||||
PointerInfo->sourceDevice = NULL;
|
||||
PointerInfo->hwndTarget = NULL;
|
||||
GetCursorPos(&PointerInfo->ptPixelLocation);
|
||||
GetCursorPos(&PointerInfo->ptHimetricLocation);
|
||||
GetCursorPos(&PointerInfo->ptPixelLocationRaw);
|
||||
GetCursorPos(&PointerInfo->ptHimetricLocationRaw);
|
||||
PointerInfo->dwTime = 0;
|
||||
PointerInfo->historyCount = 1;
|
||||
PointerInfo->InputData = 0;
|
||||
PointerInfo->dwKeyStates = 0;
|
||||
PointerInfo->PerformanceCount = 0;
|
||||
PointerInfo->ButtonChangeType = POINTER_CHANGE_NONE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} // namespace vxkex
|
Reference in New Issue
Block a user