win7 compatibility with fallbacks to newer behaviour on later windows, qrhi3d11 not tested

This commit is contained in:
kleuter
2023-11-01 17:47:09 +01:00
parent 85d238dfda
commit bbe896803b
19 changed files with 926 additions and 288 deletions

View File

@ -58,43 +58,73 @@ public:
} // namespace ABI
#endif // HAS_UI_VIEW_SETTINGS
// based on SDL approach
// see SDL_windows_gaming_input.c, SDL_windows.c
void * WIN_LoadComBaseFunction(const char *name)
{
static bool s_bLoaded = false;
static HMODULE s_hComBase = NULL;
if (!s_bLoaded) {
s_hComBase = ::LoadLibraryEx(L"combase.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
s_bLoaded = true;
}
if (s_hComBase) {
return ::GetProcAddress(s_hComBase, name);
} else {
return NULL;
}
}
QT_BEGIN_NAMESPACE
// Return tablet mode, note: Does not work for GetDesktopWindow().
bool qt_windowsIsTabletMode(HWND hwnd)
{
bool result = false;
typedef HRESULT (WINAPI *WindowsCreateStringReference_t)(PCWSTR sourceString, UINT32 length, HSTRING_HEADER *hstringHeader, HSTRING* string);
typedef HRESULT (WINAPI *RoGetActivationFactory_t)(HSTRING activatableClassId, REFIID iid, void** factory);
const wchar_t uiViewSettingsId[] = L"Windows.UI.ViewManagement.UIViewSettings";
HSTRING_HEADER uiViewSettingsIdRefHeader;
HSTRING uiViewSettingsIdHs = nullptr;
const auto uiViewSettingsIdLen = UINT32(sizeof(uiViewSettingsId) / sizeof(uiViewSettingsId[0]) - 1);
if (FAILED(WindowsCreateStringReference(uiViewSettingsId, uiViewSettingsIdLen, &uiViewSettingsIdRefHeader, &uiViewSettingsIdHs)))
return false;
WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)WIN_LoadComBaseFunction("WindowsCreateStringReference");
RoGetActivationFactory_t RoGetActivationFactoryFunc = (RoGetActivationFactory_t)WIN_LoadComBaseFunction("RoGetActivationFactory");
IUIViewSettingsInterop *uiViewSettingsInterop = nullptr;
// __uuidof(IUIViewSettingsInterop);
const GUID uiViewSettingsInteropRefId = {0x3694dbf9, 0x8f68, 0x44be,{0x8f, 0xf5, 0x19, 0x5c, 0x98, 0xed, 0xe8, 0xa6}};
if (WindowsCreateStringReferenceFunc && RoGetActivationFactoryFunc)
{
bool result = false;
HRESULT hr = RoGetActivationFactory(uiViewSettingsIdHs, uiViewSettingsInteropRefId,
reinterpret_cast<void **>(&uiViewSettingsInterop));
if (FAILED(hr))
return false;
const wchar_t uiViewSettingsId[] = L"Windows.UI.ViewManagement.UIViewSettings";
HSTRING_HEADER uiViewSettingsIdRefHeader;
HSTRING uiViewSettingsIdHs = nullptr;
const auto uiViewSettingsIdLen = UINT32(sizeof(uiViewSettingsId) / sizeof(uiViewSettingsId[0]) - 1);
if (FAILED(WindowsCreateStringReferenceFunc(uiViewSettingsId, uiViewSettingsIdLen, &uiViewSettingsIdRefHeader, &uiViewSettingsIdHs)))
return false;
// __uuidof(ABI::Windows::UI::ViewManagement::IUIViewSettings);
const GUID uiViewSettingsRefId = {0xc63657f6, 0x8850, 0x470d,{0x88, 0xf8, 0x45, 0x5e, 0x16, 0xea, 0x2c, 0x26}};
ABI::Windows::UI::ViewManagement::IUIViewSettings *viewSettings = nullptr;
hr = uiViewSettingsInterop->GetForWindow(hwnd, uiViewSettingsRefId,
reinterpret_cast<void **>(&viewSettings));
if (SUCCEEDED(hr)) {
ABI::Windows::UI::ViewManagement::UserInteractionMode currentMode;
hr = viewSettings->get_UserInteractionMode(&currentMode);
if (SUCCEEDED(hr))
result = currentMode == 1; // Touch, 1
viewSettings->Release();
IUIViewSettingsInterop *uiViewSettingsInterop = nullptr;
// __uuidof(IUIViewSettingsInterop);
const GUID uiViewSettingsInteropRefId = {0x3694dbf9, 0x8f68, 0x44be,{0x8f, 0xf5, 0x19, 0x5c, 0x98, 0xed, 0xe8, 0xa6}};
HRESULT hr = RoGetActivationFactoryFunc(uiViewSettingsIdHs, uiViewSettingsInteropRefId,
reinterpret_cast<void **>(&uiViewSettingsInterop));
if (FAILED(hr))
return false;
// __uuidof(ABI::Windows::UI::ViewManagement::IUIViewSettings);
const GUID uiViewSettingsRefId = {0xc63657f6, 0x8850, 0x470d,{0x88, 0xf8, 0x45, 0x5e, 0x16, 0xea, 0x2c, 0x26}};
ABI::Windows::UI::ViewManagement::IUIViewSettings *viewSettings = nullptr;
hr = uiViewSettingsInterop->GetForWindow(hwnd, uiViewSettingsRefId,
reinterpret_cast<void **>(&viewSettings));
if (SUCCEEDED(hr)) {
ABI::Windows::UI::ViewManagement::UserInteractionMode currentMode;
hr = viewSettings->get_UserInteractionMode(&currentMode);
if (SUCCEEDED(hr))
result = currentMode == 1; // Touch, 1
viewSettings->Release();
}
uiViewSettingsInterop->Release();
return result;
}
uiViewSettingsInterop->Release();
return result;
return false;
}
QT_END_NAMESPACE
QT_END_NAMESPACE

View File

@ -44,6 +44,7 @@
#include <QtCore/qsysinfo.h>
#include <QtCore/qscopedpointer.h>
#include <QtCore/quuid.h>
#include <QtCore/private/qsystemlibrary_p.h>
#include <QtCore/private/qwinregistry_p.h>
#include <QtCore/private/qfactorycacheregistration_p.h>
#include <QtCore/private/qsystemerror_p.h>
@ -120,15 +121,17 @@ static inline bool sessionManagerInteractionBlocked() { return false; }
static inline int windowDpiAwareness(HWND hwnd)
{
return static_cast<int>(GetAwarenessFromDpiAwarenessContext(GetWindowDpiAwarenessContext(hwnd)));
return QWindowsContext::user32dll.getWindowDpiAwarenessContext && QWindowsContext::user32dll.getAwarenessFromDpiAwarenessContext
? QWindowsContext::user32dll.getAwarenessFromDpiAwarenessContext(QWindowsContext::user32dll.getWindowDpiAwarenessContext(hwnd))
: -1;
}
// Note: This only works within WM_NCCREATE
static bool enableNonClientDpiScaling(HWND hwnd)
{
bool result = false;
if (windowDpiAwareness(hwnd) == 2) {
result = EnableNonClientDpiScaling(hwnd) != FALSE;
if (QWindowsContext::user32dll.enableNonClientDpiScaling && windowDpiAwareness(hwnd) == 2) {
result = QWindowsContext::user32dll.enableNonClientDpiScaling(hwnd) != FALSE;
if (!result) {
const DWORD errorCode = GetLastError();
qErrnoWarning(int(errorCode), "EnableNonClientDpiScaling() failed for HWND %p (%lu)",
@ -138,6 +141,77 @@ static bool enableNonClientDpiScaling(HWND hwnd)
return result;
}
/*!
\class QWindowsUser32DLL
\brief Struct that contains dynamically resolved symbols of User32.dll.
The stub libraries shipped with the MinGW compiler miss some of the
functions. They need to be retrieved dynamically.
In addition, touch-related functions are available only from Windows onwards.
These need to resolved dynamically for Q_CC_MSVC as well.
\sa QWindowsShell32DLL
\internal
*/
void QWindowsUser32DLL::init()
{
QSystemLibrary library(QStringLiteral("user32"));
setProcessDPIAware = (SetProcessDPIAware)library.resolve("SetProcessDPIAware");
setProcessDpiAwarenessContext = (SetProcessDpiAwarenessContext)library.resolve("SetProcessDpiAwarenessContext");
getThreadDpiAwarenessContext = (GetThreadDpiAwarenessContext)library.resolve("GetThreadDpiAwarenessContext");
areDpiAwarenessContextsEqual = (AreDpiAwarenessContextsEqual)library.resolve("AreDpiAwarenessContextsEqual");
addClipboardFormatListener = (AddClipboardFormatListener)library.resolve("AddClipboardFormatListener");
removeClipboardFormatListener = (RemoveClipboardFormatListener)library.resolve("RemoveClipboardFormatListener");
getDisplayAutoRotationPreferences = (GetDisplayAutoRotationPreferences)library.resolve("GetDisplayAutoRotationPreferences");
setDisplayAutoRotationPreferences = (SetDisplayAutoRotationPreferences)library.resolve("SetDisplayAutoRotationPreferences");
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8) {
enableMouseInPointer = (EnableMouseInPointer)library.resolve("EnableMouseInPointer");
getPointerType = (GetPointerType)library.resolve("GetPointerType");
getPointerInfo = (GetPointerInfo)library.resolve("GetPointerInfo");
getPointerDeviceRects = (GetPointerDeviceRects)library.resolve("GetPointerDeviceRects");
getPointerTouchInfo = (GetPointerTouchInfo)library.resolve("GetPointerTouchInfo");
getPointerFrameTouchInfo = (GetPointerFrameTouchInfo)library.resolve("GetPointerFrameTouchInfo");
getPointerFrameTouchInfoHistory = (GetPointerFrameTouchInfoHistory)library.resolve("GetPointerFrameTouchInfoHistory");
getPointerPenInfo = (GetPointerPenInfo)library.resolve("GetPointerPenInfo");
getPointerPenInfoHistory = (GetPointerPenInfoHistory)library.resolve("GetPointerPenInfoHistory");
skipPointerFrameMessages = (SkipPointerFrameMessages)library.resolve("SkipPointerFrameMessages");
}
if (QOperatingSystemVersion::current()
>= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 14393)) {
adjustWindowRectEx = (AdjustWindowRectEx)library.resolve("AdjustWindowRectEx");
adjustWindowRectExForDpi = (AdjustWindowRectExForDpi)library.resolve("AdjustWindowRectExForDpi");
enableNonClientDpiScaling = (EnableNonClientDpiScaling)library.resolve("EnableNonClientDpiScaling");
getWindowDpiAwarenessContext = (GetWindowDpiAwarenessContext)library.resolve("GetWindowDpiAwarenessContext");
getAwarenessFromDpiAwarenessContext = (GetAwarenessFromDpiAwarenessContext)library.resolve("GetAwarenessFromDpiAwarenessContext");
systemParametersInfoForDpi = (SystemParametersInfoForDpi)library.resolve("SystemParametersInfoForDpi");
getDpiForWindow = (GetDpiForWindow)library.resolve("GetDpiForWindow");
getSystemMetricsForDpi = (GetSystemMetricsForDpi)library.resolve("GetSystemMetricsForDpi");
}
}
bool QWindowsUser32DLL::supportsPointerApi()
{
return enableMouseInPointer && getPointerType && getPointerInfo && getPointerDeviceRects
&& getPointerTouchInfo && getPointerFrameTouchInfo && getPointerFrameTouchInfoHistory
&& getPointerPenInfo && getPointerPenInfoHistory && skipPointerFrameMessages;
}
void QWindowsShcoreDLL::init()
{
if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8_1)
return;
QSystemLibrary library(QStringLiteral("SHCore"));
getProcessDpiAwareness = (GetProcessDpiAwareness)library.resolve("GetProcessDpiAwareness");
setProcessDpiAwareness = (SetProcessDpiAwareness)library.resolve("SetProcessDpiAwareness");
getDpiForMonitor = (GetDpiForMonitor)library.resolve("GetDpiForMonitor");
}
QWindowsUser32DLL QWindowsContext::user32dll;
QWindowsShcoreDLL QWindowsContext::shcoredll;
QWindowsContext *QWindowsContext::m_instance = nullptr;
/*!
@ -181,6 +255,9 @@ bool QWindowsContextPrivate::m_v2DpiAware = false;
QWindowsContextPrivate::QWindowsContextPrivate()
: m_oleInitializeResult(OleInitialize(nullptr))
{
QWindowsContext::user32dll.init();
QWindowsContext::shcoredll.init();
if (m_pointerHandler.touchDevice() || m_mouseHandler.touchDevice())
m_systemInfo |= QWindowsContext::SI_SupportsTouch;
m_displayContext = GetDC(nullptr);
@ -299,6 +376,12 @@ bool QWindowsContext::initPointer(unsigned integrationOptions)
if (integrationOptions & QWindowsIntegration::DontUseWMPointer)
return false;
if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8)
return false;
if (!QWindowsContext::user32dll.supportsPointerApi())
return false;
d->m_systemInfo |= QWindowsContext::SI_SupportsPointer;
return true;
}
@ -368,8 +451,9 @@ void QWindowsContext::setDetectAltGrModifier(bool a)
int QWindowsContext::processDpiAwareness()
{
PROCESS_DPI_AWARENESS result;
if (SUCCEEDED(GetProcessDpiAwareness(nullptr, &result))) {
int result;
if (QWindowsContext::shcoredll.getProcessDpiAwareness
&& SUCCEEDED(QWindowsContext::shcoredll.getProcessDpiAwareness(nullptr, &result))) {
return static_cast<int>(result);
}
return -1;
@ -381,34 +465,46 @@ void QWindowsContext::setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiA
if (processDpiAwareness() == int(dpiAwareness))
return;
const HRESULT hr = SetProcessDpiAwareness(static_cast<PROCESS_DPI_AWARENESS>(dpiAwareness));
if (FAILED(hr)) {
qCWarning(lcQpaWindow).noquote().nospace() << "SetProcessDpiAwareness("
<< dpiAwareness << ") failed: " << QSystemError::windowsComString(hr) << ", using "
<< QWindowsContext::processDpiAwareness() << "\nQt's fallback DPI awareness is "
<< "PROCESS_DPI_AWARENESS. If you know what you are doing consider an override in qt.conf";
if (QWindowsContext::shcoredll.isValid()) {
const HRESULT hr = QWindowsContext::shcoredll.setProcessDpiAwareness(static_cast<PROCESS_DPI_AWARENESS>(dpiAwareness));
if (FAILED(hr)) {
qCWarning(lcQpaWindow).noquote().nospace() << "SetProcessDpiAwareness("
<< dpiAwareness << ") failed: " << QSystemError::windowsComString(hr) << ", using "
<< QWindowsContext::processDpiAwareness() << "\nQt's fallback DPI awareness is "
<< "PROCESS_DPI_AWARENESS. If you know what you are doing consider an override in qt.conf";
}
} else {
if (dpiAwareness != QtWindows::ProcessDpiUnaware && QWindowsContext::user32dll.setProcessDPIAware) {
if (!QWindowsContext::user32dll.setProcessDPIAware())
qErrnoWarning("SetProcessDPIAware() failed");
}
}
}
bool QWindowsContext::setProcessDpiV2Awareness()
{
qCDebug(lcQpaWindow) << __FUNCTION__;
auto dpiContext = GetThreadDpiAwarenessContext();
if (AreDpiAwarenessContextsEqual(dpiContext, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
return true;
const BOOL ok = SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
if (!ok) {
const DWORD dwError = GetLastError();
qCWarning(lcQpaWindow).noquote().nospace()
<< "SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) failed: "
<< QSystemError::windowsComString(HRESULT(dwError)) << "\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;
if (QWindowsContext::user32dll.getThreadDpiAwarenessContext) {
auto dpiContext = QWindowsContext::user32dll.getThreadDpiAwarenessContext();
if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual &&
QWindowsContext::user32dll.areDpiAwarenessContextsEqual(dpiContext, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
return true;
}
if (QWindowsContext::user32dll.setProcessDpiAwarenessContext) {
const BOOL ok = QWindowsContext::user32dll.setProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
if (!ok) {
const DWORD dwError = GetLastError();
qCWarning(lcQpaWindow).noquote().nospace()
<< "SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) failed: "
<< QSystemError::windowsComString(HRESULT(dwError)) << "\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 = true;
}
QWindowsContextPrivate::m_v2DpiAware = true;
return true;
}
@ -837,8 +933,8 @@ void QWindowsContext::forceNcCalcSize(HWND hwnd)
bool QWindowsContext::systemParametersInfo(unsigned action, unsigned param, void *out,
unsigned dpi)
{
const BOOL result = dpi != 0
? SystemParametersInfoForDpi(action, param, out, 0, dpi)
const BOOL result = QWindowsContext::user32dll.systemParametersInfoForDpi != nullptr && dpi != 0
? QWindowsContext::user32dll.systemParametersInfoForDpi(action, param, out, 0, dpi)
: SystemParametersInfo(action, param, out, 0);
return result == TRUE;
}

View File

@ -44,6 +44,94 @@ class QPoint;
class QKeyEvent;
class QPointingDevice;
struct QWindowsUser32DLL
{
inline void init();
inline bool supportsPointerApi();
typedef BOOL (WINAPI *EnableMouseInPointer)(BOOL);
typedef BOOL (WINAPI *GetPointerType)(UINT32, PVOID);
typedef BOOL (WINAPI *GetPointerInfo)(UINT32, PVOID);
typedef BOOL (WINAPI *GetPointerDeviceRects)(HANDLE, RECT *, RECT *);
typedef BOOL (WINAPI *GetPointerTouchInfo)(UINT32, PVOID);
typedef BOOL (WINAPI *GetPointerFrameTouchInfo)(UINT32, UINT32 *, PVOID);
typedef BOOL (WINAPI *GetPointerFrameTouchInfoHistory)(UINT32, UINT32 *, UINT32 *, PVOID);
typedef BOOL (WINAPI *GetPointerPenInfo)(UINT32, PVOID);
typedef BOOL (WINAPI *GetPointerPenInfoHistory)(UINT32, UINT32 *, PVOID);
typedef BOOL (WINAPI *SkipPointerFrameMessages)(UINT32);
typedef BOOL (WINAPI *SetProcessDPIAware)();
typedef BOOL (WINAPI *SetProcessDpiAwarenessContext)(HANDLE);
typedef BOOL (WINAPI *AddClipboardFormatListener)(HWND);
typedef BOOL (WINAPI *RemoveClipboardFormatListener)(HWND);
typedef BOOL (WINAPI *GetDisplayAutoRotationPreferences)(DWORD *);
typedef BOOL (WINAPI *SetDisplayAutoRotationPreferences)(DWORD);
typedef BOOL (WINAPI *AdjustWindowRectEx)(LPRECT,DWORD,BOOL,DWORD);
typedef BOOL (WINAPI *AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
typedef BOOL (WINAPI *EnableNonClientDpiScaling)(HWND);
typedef int (WINAPI *GetWindowDpiAwarenessContext)(HWND);
typedef int (WINAPI *GetAwarenessFromDpiAwarenessContext)(int);
typedef BOOL (WINAPI *SystemParametersInfoForDpi)(UINT, UINT, PVOID, UINT, UINT);
typedef int (WINAPI *GetDpiForWindow)(HWND);
typedef BOOL (WINAPI *GetSystemMetricsForDpi)(INT, UINT);
typedef BOOL (WINAPI *AreDpiAwarenessContextsEqual)(int, HANDLE);
typedef int (WINAPI *GetThreadDpiAwarenessContext)();
// Windows pointer functions (Windows 8 or later).
EnableMouseInPointer enableMouseInPointer = nullptr;
GetPointerType getPointerType = nullptr;
GetPointerInfo getPointerInfo = nullptr;
GetPointerDeviceRects getPointerDeviceRects = nullptr;
GetPointerTouchInfo getPointerTouchInfo = nullptr;
GetPointerFrameTouchInfo getPointerFrameTouchInfo = nullptr;
GetPointerFrameTouchInfoHistory getPointerFrameTouchInfoHistory = nullptr;
GetPointerPenInfo getPointerPenInfo = nullptr;
GetPointerPenInfoHistory getPointerPenInfoHistory = nullptr;
SkipPointerFrameMessages skipPointerFrameMessages = nullptr;
// Windows Vista onwards
SetProcessDPIAware setProcessDPIAware = nullptr;
// Windows 10 version 1607 onwards
GetDpiForWindow getDpiForWindow = nullptr;
GetThreadDpiAwarenessContext getThreadDpiAwarenessContext = nullptr;
// Windows 10 version 1703 onwards
SetProcessDpiAwarenessContext setProcessDpiAwarenessContext = nullptr;
AreDpiAwarenessContextsEqual areDpiAwarenessContextsEqual = nullptr;
// Clipboard listeners are present on Windows Vista onwards
// but missing in MinGW 4.9 stub libs. Can be removed in MinGW 5.
AddClipboardFormatListener addClipboardFormatListener = nullptr;
RemoveClipboardFormatListener removeClipboardFormatListener = nullptr;
// Rotation API
GetDisplayAutoRotationPreferences getDisplayAutoRotationPreferences = nullptr;
SetDisplayAutoRotationPreferences setDisplayAutoRotationPreferences = nullptr;
AdjustWindowRectEx adjustWindowRectEx = nullptr;
AdjustWindowRectExForDpi adjustWindowRectExForDpi = nullptr;
EnableNonClientDpiScaling enableNonClientDpiScaling = nullptr;
GetWindowDpiAwarenessContext getWindowDpiAwarenessContext = nullptr;
GetAwarenessFromDpiAwarenessContext getAwarenessFromDpiAwarenessContext = nullptr;
SystemParametersInfoForDpi systemParametersInfoForDpi = nullptr;
GetSystemMetricsForDpi getSystemMetricsForDpi = nullptr;
};
// Shell scaling library (Windows 8.1 onwards)
struct QWindowsShcoreDLL
{
void init();
inline bool isValid() const { return getProcessDpiAwareness && setProcessDpiAwareness && getDpiForMonitor; }
typedef HRESULT (WINAPI *GetProcessDpiAwareness)(HANDLE,int *);
typedef HRESULT (WINAPI *SetProcessDpiAwareness)(int);
typedef HRESULT (WINAPI *GetDpiForMonitor)(HMONITOR,int,UINT *,UINT *);
GetProcessDpiAwareness getProcessDpiAwareness = nullptr;
SetProcessDpiAwareness setProcessDpiAwareness = nullptr;
GetDpiForMonitor getDpiForMonitor = nullptr;
};
class QWindowsContext
{
Q_DISABLE_COPY_MOVE(QWindowsContext)
@ -137,6 +225,9 @@ public:
QWindowsScreenManager &screenManager();
QWindowsTabletSupport *tabletSupport() const;
static QWindowsUser32DLL user32dll;
static QWindowsShcoreDLL shcoredll;
bool asyncExpose() const;
void setAsyncExpose(bool value);

View File

@ -670,7 +670,7 @@ static HRESULT startDoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource,
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
POINTER_INFO pointerInfo{};
if (!GetPointerInfo(pointerId, &pointerInfo))
if (!QWindowsContext::user32dll.getPointerInfo || !QWindowsContext::user32dll.getPointerInfo(pointerId, &pointerInfo))
return E_FAIL;
if (pointerInfo.pointerFlags & POINTER_FLAG_PRIMARY) {

View File

@ -751,15 +751,28 @@ static inline QString messageKeyText(const MSG &msg)
[[nodiscard]] static inline int getTitleBarHeight(const HWND hwnd)
{
const UINT dpi = GetDpiForWindow(hwnd);
const int captionHeight = 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 = GetSystemMetricsForDpi(SM_CYSIZEFRAME, dpi)
+ GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
return captionHeight + frameHeight;
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;
}
}
[[nodiscard]] static inline bool isSystemMenuOffsetNeeded(const Qt::WindowFlags flags)

View File

@ -48,7 +48,7 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
*result = 0;
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
if (!GetPointerType(pointerId, &m_pointerType)) {
if (!QWindowsContext::user32dll.getPointerType(pointerId, &m_pointerType)) {
qWarning() << "GetPointerType() failed:" << qt_error_string();
return false;
}
@ -62,12 +62,12 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
}
case QT_PT_TOUCH: {
quint32 pointerCount = 0;
if (!GetPointerFrameTouchInfo(pointerId, &pointerCount, nullptr)) {
if (!QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, nullptr)) {
qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
return false;
}
QVarLengthArray<POINTER_TOUCH_INFO, 10> touchInfo(pointerCount);
if (!GetPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data())) {
if (!QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data())) {
qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
return false;
}
@ -80,10 +80,10 @@ 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 (!GetPointerFrameTouchInfoHistory(pointerId,
&historyCount,
&pointerCount,
touchInfo.data())) {
if (!QWindowsContext::user32dll.getPointerFrameTouchInfoHistory(pointerId,
&historyCount,
&pointerCount,
touchInfo.data())) {
qWarning() << "GetPointerFrameTouchInfoHistory() failed:" << qt_error_string();
return false;
}
@ -101,7 +101,7 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
}
case QT_PT_PEN: {
POINTER_PEN_INFO penInfo;
if (!GetPointerPenInfo(pointerId, &penInfo)) {
if (!QWindowsContext::user32dll.getPointerPenInfo(pointerId, &penInfo)) {
qWarning() << "GetPointerPenInfo() failed:" << qt_error_string();
return false;
}
@ -113,7 +113,7 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
|| !QCoreApplication::testAttribute(Qt::AA_CompressTabletEvents))) {
QVarLengthArray<POINTER_PEN_INFO, 10> penInfoHistory(historyCount);
if (!GetPointerPenInfoHistory(pointerId, &historyCount, penInfoHistory.data())) {
if (!QWindowsContext::user32dll.getPointerPenInfoHistory(pointerId, &historyCount, penInfoHistory.data())) {
qWarning() << "GetPointerPenInfoHistory() failed:" << qt_error_string();
return false;
}
@ -517,7 +517,7 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
inputIds.insert(touchPoint.id);
// Avoid getting repeated messages for this frame if there are multiple pointerIds
SkipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
QWindowsContext::user32dll.skipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
}
// Some devices send touches for each finger in a different message/frame, instead of consolidating
@ -563,7 +563,7 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
auto *penInfo = static_cast<POINTER_PEN_INFO *>(vPenInfo);
RECT pRect, dRect;
if (!GetPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect))
if (!QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect))
return false;
const auto systemId = (qint64)penInfo->pointerInfo.sourceDevice;

View File

@ -35,10 +35,12 @@ static inline QDpi deviceDPI(HDC hdc)
static inline QDpi monitorDPI(HMONITOR hMonitor)
{
UINT dpiX;
UINT dpiY;
if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY)))
return QDpi(dpiX, dpiY);
if (QWindowsContext::shcoredll.isValid()) {
UINT dpiX;
UINT dpiY;
if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY)))
return QDpi(dpiX, dpiY);
}
return {0, 0};
}
@ -425,47 +427,51 @@ QRect QWindowsScreen::virtualGeometry(const QPlatformScreen *screen) // cf QScre
bool QWindowsScreen::setOrientationPreference(Qt::ScreenOrientation o)
{
bool result = false;
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) {
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);
}
result = SetDisplayAutoRotationPreferences(orientationPreference);
return result;
}
Qt::ScreenOrientation QWindowsScreen::orientationPreference()
{
Qt::ScreenOrientation result = Qt::PrimaryOrientation;
ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
if (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;
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;
}
}
}
return result;

View File

@ -42,6 +42,8 @@
#include <algorithm>
#include <VersionHelpers.h>
#if QT_CONFIG(cpp_winrt)
# include <QtCore/private/qt_winrtbase_p.h>
@ -232,11 +234,15 @@ void QWindowsTheme::populateLightSystemBasePalette(QPalette &result)
QColor accent = getSysColor(COLOR_HIGHLIGHT);
#if QT_CONFIG(cpp_winrt)
// respect the Windows 11 accent color
using namespace winrt::Windows::UI::ViewManagement;
const auto settings = UISettings();
accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
if (IsWindows10OrGreater())
{
// respect the Windows 11 accent color
using namespace winrt::Windows::UI::ViewManagement;
const auto settings = UISettings();
accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
}
#endif
const QColor btnFace = background;
@ -271,41 +277,45 @@ void QWindowsTheme::populateLightSystemBasePalette(QPalette &result)
static void populateDarkSystemBasePalette(QPalette &result)
{
QColor foreground = Qt::white;
QColor background = QColor(0x1E, 0x1E, 0x1E);
QColor accent = QColor(0x00, 0x55, 0xff);
QColor accentDark = accent.darker(120);
QColor accentDarker = accentDark.darker(120);
QColor accentDarkest = accentDarker.darker(120);
QColor accentLight = accent.lighter(120);
QColor accentLighter = accentLight.lighter(120);
QColor accentLightest = accentLighter.lighter(120);
QColor linkColor = Qt::blue;
#if QT_CONFIG(cpp_winrt)
using namespace winrt::Windows::UI::ViewManagement;
const auto settings = UISettings();
// We have to craft a palette from these colors. The settings.UIElementColor(UIElementType) API
// returns the old system colors, not the dark mode colors. If the background is black (which it
// usually), then override it with a dark gray instead so that we can go up and down the lightness.
const QColor foreground = getSysColor(settings.GetColorValue(UIColorType::Foreground));
const QColor background = [&settings]() -> QColor {
auto systemBackground = getSysColor(settings.GetColorValue(UIColorType::Background));
if (systemBackground == Qt::black)
systemBackground = QColor(0x1E, 0x1E, 0x1E);
return systemBackground;
}();
if (IsWindows10OrGreater())
{
using namespace winrt::Windows::UI::ViewManagement;
const auto settings = UISettings();
// We have to craft a palette from these colors. The settings.UIElementColor(UIElementType) API
// returns the old system colors, not the dark mode colors. If the background is black (which it
// usually), then override it with a dark gray instead so that we can go up and down the lightness.
foreground = getSysColor(settings.GetColorValue(UIColorType::Foreground));
background = [&settings]() -> QColor {
auto systemBackground = getSysColor(settings.GetColorValue(UIColorType::Background));
if (systemBackground == Qt::black)
systemBackground = QColor(0x1E, 0x1E, 0x1E);
return systemBackground;
}();
accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
accentDark = getSysColor(settings.GetColorValue(UIColorType::AccentDark1));
accentDarker = getSysColor(settings.GetColorValue(UIColorType::AccentDark2));
accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
accentLight = getSysColor(settings.GetColorValue(UIColorType::AccentLight1));
accentLighter = getSysColor(settings.GetColorValue(UIColorType::AccentLight2));
accentLightest = getSysColor(settings.GetColorValue(UIColorType::AccentLight3));
linkColor = accent;
}
const QColor accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
const QColor accentDark = getSysColor(settings.GetColorValue(UIColorType::AccentDark1));
const QColor accentDarker = getSysColor(settings.GetColorValue(UIColorType::AccentDark2));
const QColor accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
const QColor accentLight = getSysColor(settings.GetColorValue(UIColorType::AccentLight1));
const QColor accentLighter = getSysColor(settings.GetColorValue(UIColorType::AccentLight2));
const QColor accentLightest = getSysColor(settings.GetColorValue(UIColorType::AccentLight3));
const QColor linkColor = accent;
#else
const QColor foreground = Qt::white;
const QColor background = QColor(0x1E, 0x1E, 0x1E);
const QColor accent = QColor(0x00, 0x55, 0xff);
const QColor accentDark = accent.darker(120);
const QColor accentDarker = accentDark.darker(120);
const QColor accentDarkest = accentDarker.darker(120);
const QColor accentLight = accent.lighter(120);
const QColor accentLighter = accentLight.lighter(120);
const QColor accentLightest = accentLighter.lighter(120);
const QColor linkColor = Qt::blue;
#endif
const QColor buttonColor = background.lighter(200);
result.setColor(QPalette::All, QPalette::WindowText, foreground);
@ -562,15 +572,29 @@ void QWindowsTheme::refreshPalettes()
m_palettes[MenuBarPalette] = menuBarPalette(*m_palettes[MenuPalette], light);
if (!light) {
#if QT_CONFIG(cpp_winrt)
using namespace winrt::Windows::UI::ViewManagement;
const auto settings = UISettings();
const QColor accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
const QColor accentLight = getSysColor(settings.GetColorValue(UIColorType::AccentLight1));
const QColor accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
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);
if (IsWindows10OrGreater())
{
using namespace winrt::Windows::UI::ViewManagement;
const auto settings = UISettings();
const QColor accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
const QColor accentLight = getSysColor(settings.GetColorValue(UIColorType::AccentLight1));
const QColor accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
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);
}
else
{
m_palettes[ButtonPalette] = new QPalette(*m_palettes[SystemPalette]);
m_palettes[ButtonPalette]->setColor(QPalette::Button, QColor(0x666666u));
const QColor checkBoxBlue(0x0078d7u);
m_palettes[CheckBoxPalette] = new QPalette(*m_palettes[SystemPalette]);
m_palettes[CheckBoxPalette]->setColor(QPalette::Base, checkBoxBlue);
m_palettes[CheckBoxPalette]->setColor(QPalette::Button, checkBoxBlue);
m_palettes[CheckBoxPalette]->setColor(QPalette::ButtonText, Qt::white);
}
#else
m_palettes[ButtonPalette] = new QPalette(*m_palettes[SystemPalette]);
m_palettes[ButtonPalette]->setColor(QPalette::Button, QColor(0x666666u));
@ -637,8 +661,14 @@ void QWindowsTheme::refreshFonts()
fixedFont.setStyleHint(QFont::TypeWriter);
LOGFONT lfIconTitleFont;
SystemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
const QFont iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont, dpi);
QFont iconTitleFont;
if (QWindowsContext::user32dll.systemParametersInfoForDpi) {
QWindowsContext::user32dll.systemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont, dpi);
} else {
SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont);
}
m_fonts[SystemFont] = new QFont(QWindowsFontDatabase::systemDefaultFont());
m_fonts[MenuFont] = new QFont(menuFont);

View File

@ -516,11 +516,14 @@ static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::Windo
[[nodiscard]] static inline int getResizeBorderThickness(const UINT dpi)
{
// The width of the padded border will always be 0 if DWM composition is
// disabled, but since it will always be enabled and can't be programtically
// disabled from Windows 8, we are safe to go.
return GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi)
+ GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
if (QWindowsContext::user32dll.getSystemMetricsForDpi) {
// The width of the padded border will always be 0 if DWM composition is
// disabled, but since it will always be enabled and can't be programtically
// disabled from Windows 8, we are safe to go.
return QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi)
+ QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
}
return 0;
}
/*!
@ -530,13 +533,17 @@ static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::Windo
static QMargins invisibleMargins(QPoint screenPoint)
{
POINT pt = {screenPoint.x(), screenPoint.y()};
if (HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
UINT dpiX;
UINT dpiY;
if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY))) {
const int gap = getResizeBorderThickness(dpiX);
return QMargins(gap, 0, gap, gap);
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);
}
}
}
}
return QMargins();
@ -544,9 +551,12 @@ static QMargins invisibleMargins(QPoint screenPoint)
[[nodiscard]] static inline QMargins invisibleMargins(const HWND hwnd)
{
const UINT dpi = GetDpiForWindow(hwnd);
const int gap = getResizeBorderThickness(dpi);
return QMargins(gap, 0, gap, gap);
if (QWindowsContext::user32dll.getDpiForWindow) {
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
const int gap = getResizeBorderThickness(dpi);
return QMargins(gap, 0, gap, gap);
}
return QMargins();
}
/*!
@ -1030,7 +1040,8 @@ QMargins QWindowsGeometryHint::frameOnPrimaryScreen(const QWindow *w, DWORD styl
return {};
RECT rect = {0,0,0,0};
style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
if (AdjustWindowRectEx(&rect, style, FALSE, exStyle) == FALSE)
if (QWindowsContext::user32dll.adjustWindowRectEx &&
QWindowsContext::user32dll.adjustWindowRectEx(&rect, style, FALSE, exStyle) == FALSE)
qErrnoWarning("%s: AdjustWindowRectEx failed", __FUNCTION__);
const QMargins result(qAbs(rect.left), qAbs(rect.top),
qAbs(rect.right), qAbs(rect.bottom));
@ -1054,7 +1065,8 @@ 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 (AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi))) == FALSE) {
if (QWindowsContext::user32dll.adjustWindowRectExForDpi &&
QWindowsContext::user32dll.adjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi))) == FALSE) {
qErrnoWarning("%s: AdjustWindowRectExForDpi failed", __FUNCTION__);
}
const QMargins result(qAbs(rect.left), qAbs(rect.top),
@ -1548,7 +1560,8 @@ void QWindowsWindow::initialize()
QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(w, obtainedGeometry);
}
}
QWindowsWindow::setSavedDpi(GetDpiForWindow(handle()));
QWindowsWindow::setSavedDpi(QWindowsContext::user32dll.getDpiForWindow ?
QWindowsContext::user32dll.getDpiForWindow(handle()) : 96);
}
QSurfaceFormat QWindowsWindow::format() const
@ -1994,59 +2007,64 @@ void QWindowsWindow::handleDpiScaledSize(WPARAM wParam, LPARAM lParam, LRESULT *
void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
{
const UINT dpi = HIWORD(wParam);
setSavedDpi(dpi);
if (QWindowsContext::user32dll.getDpiForWindow) {
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
const qreal scale = qreal(dpi) / qreal(savedDpi());
setSavedDpi(dpi);
// Send screen change first, so that the new screen is set during any following resize
checkForScreenChanged(QWindowsWindow::FromDpiChange);
// Send screen change first, so that the new screen is set during any following resize
checkForScreenChanged(QWindowsWindow::FromDpiChange);
// We get WM_DPICHANGED in one of two situations:
//
// 1. The DPI change is a "spontaneous" DPI change as a result of e.g.
// the user dragging the window to a new screen. In this case Windows
// first sends WM_GETDPISCALEDSIZE, where we set the new window size,
// followed by this event where we apply the suggested window geometry
// to the native window. This will make sure the window tracks the mouse
// cursor during screen change, and also that the window size is scaled
// according to the DPI change.
//
// 2. The DPI change is a result of a setGeometry() call. In this case
// Qt has already scaled the window size for the new DPI. Further, Windows
// does not call WM_GETDPISCALEDSIZE, and also applies its own scaling
// to the already scaled window size. Since there is no need to set the
// window geometry again, and the provided geometry is incorrect, we omit
// making the SetWindowPos() call.
if (!m_inSetgeometry) {
updateFullFrameMargins();
const auto prcNewWindow = reinterpret_cast<RECT *>(lParam);
SetWindowPos(hwnd, nullptr, prcNewWindow->left, prcNewWindow->top,
prcNewWindow->right - prcNewWindow->left,
prcNewWindow->bottom - prcNewWindow->top, SWP_NOZORDER | SWP_NOACTIVATE);
// If the window does not have a frame, WM_MOVE and WM_SIZE won't be
// called which prevents the content from being scaled appropriately
// after a DPI change.
if (m_data.flags & Qt::FramelessWindowHint)
handleGeometryChange();
// We get WM_DPICHANGED in one of two situations:
//
// 1. The DPI change is a "spontaneous" DPI change as a result of e.g.
// the user dragging the window to a new screen. In this case Windows
// first sends WM_GETDPISCALEDSIZE, where we set the new window size,
// followed by this event where we apply the suggested window geometry
// to the native window. This will make sure the window tracks the mouse
// cursor during screen change, and also that the window size is scaled
// according to the DPI change.
//
// 2. The DPI change is a result of a setGeometry() call. In this case
// Qt has already scaled the window size for the new DPI. Further, Windows
// does not call WM_GETDPISCALEDSIZE, and also applies its own scaling
// to the already scaled window size. Since there is no need to set the
// window geometry again, and the provided geometry is incorrect, we omit
// making the SetWindowPos() call.
if (!m_inSetgeometry) {
updateFullFrameMargins();
const auto prcNewWindow = reinterpret_cast<RECT *>(lParam);
SetWindowPos(hwnd, nullptr, prcNewWindow->left, prcNewWindow->top,
prcNewWindow->right - prcNewWindow->left,
prcNewWindow->bottom - prcNewWindow->top, SWP_NOZORDER | SWP_NOACTIVATE);
// If the window does not have a frame, WM_MOVE and WM_SIZE won't be
// called which prevents the content from being scaled appropriately
// after a DPI change.
if (m_data.flags & Qt::FramelessWindowHint)
handleGeometryChange();
}
// Re-apply mask now that we have a new DPI, which have resulted in
// a new scale factor.
setMask(QHighDpi::toNativeLocalRegion(window()->mask(), window()));
}
// Re-apply mask now that we have a new DPI, which have resulted in
// a new scale factor.
setMask(QHighDpi::toNativeLocalRegion(window()->mask(), window()));
}
void QWindowsWindow::handleDpiChangedAfterParent(HWND hwnd)
{
const UINT dpi = GetDpiForWindow(hwnd);
const qreal scale = qreal(dpi) / qreal(savedDpi());
setSavedDpi(dpi);
if (QWindowsContext::user32dll.getDpiForWindow) {
const UINT dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
const qreal scale = qreal(dpi) / qreal(savedDpi());
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)