Windows: Add support for PerMonitorV2 DPI awareness
Add support for opting in to PerMonitorV2 DPI awareness on the command line: -platform windows:dpiawareness=3 This mode is supported on Windows 10 and up. Setting it requires using the new SetProcessDpiAwarenessContext API, which can be resolved from user32.dll. Task-number: QTBUG-68712 Change-Id: I37821e27a67e08c2e9fef25e494cfd7abed13314 Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
parent
d9a7d1a89c
commit
c35643dba3
@ -76,6 +76,14 @@
|
||||
# define WM_POINTERHWHEEL 0x024F
|
||||
#endif // WM_POINTERUPDATE
|
||||
|
||||
#if !defined(_DPI_AWARENESS_CONTEXTS_)
|
||||
# define DPI_AWARENESS_CONTEXT_UNAWARE ((HANDLE)-1)
|
||||
# define DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ((HANDLE)-2)
|
||||
# define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ((HANDLE)-3)
|
||||
# define DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 ((HANDLE)-4)
|
||||
# define DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED ((HANDLE)-5)
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace QtWindows
|
||||
@ -167,7 +175,8 @@ enum ProcessDpiAwareness
|
||||
{
|
||||
ProcessDpiUnaware,
|
||||
ProcessSystemDpiAware,
|
||||
ProcessPerMonitorDpiAware
|
||||
ProcessPerMonitorDpiAware,
|
||||
ProcessPerMonitorV2DpiAware // Qt extension (not in Process_DPI_Awareness)
|
||||
};
|
||||
|
||||
} // namespace QtWindows
|
||||
|
@ -192,6 +192,7 @@ void QWindowsUser32DLL::init()
|
||||
{
|
||||
QSystemLibrary library(QStringLiteral("user32"));
|
||||
setProcessDPIAware = (SetProcessDPIAware)library.resolve("SetProcessDPIAware");
|
||||
setProcessDpiAwarenessContext = (SetProcessDpiAwarenessContext)library.resolve("SetProcessDpiAwarenessContext");
|
||||
|
||||
addClipboardFormatListener = (AddClipboardFormatListener)library.resolve("AddClipboardFormatListener");
|
||||
removeClipboardFormatListener = (RemoveClipboardFormatListener)library.resolve("RemoveClipboardFormatListener");
|
||||
@ -278,9 +279,11 @@ struct QWindowsContextPrivate {
|
||||
HPOWERNOTIFY m_powerNotification = nullptr;
|
||||
HWND m_powerDummyWindow = nullptr;
|
||||
static bool m_darkMode;
|
||||
static bool m_v2DpiAware;
|
||||
};
|
||||
|
||||
bool QWindowsContextPrivate::m_darkMode = false;
|
||||
bool QWindowsContextPrivate::m_v2DpiAware = false;
|
||||
|
||||
QWindowsContextPrivate::QWindowsContextPrivate()
|
||||
: m_oleInitializeResult(OleInitialize(nullptr))
|
||||
@ -505,6 +508,23 @@ void QWindowsContext::setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiA
|
||||
}
|
||||
}
|
||||
|
||||
void QWindowsContext::setProcessDpiV2Awareness()
|
||||
{
|
||||
qCDebug(lcQpaWindows) << __FUNCTION__;
|
||||
const BOOL ok = QWindowsContext::user32dll.setProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
|
||||
if (ok) {
|
||||
QWindowsContextPrivate::m_v2DpiAware = true;
|
||||
} else {
|
||||
const HRESULT errorCode = GetLastError();
|
||||
// E_ACCESSDENIED means set externally (MSVC manifest or external app loading Qt plugin).
|
||||
// Silence warning in that case unless debug is enabled.
|
||||
if (errorCode != E_ACCESSDENIED || lcQpaWindows().isDebugEnabled()) {
|
||||
qWarning().noquote().nospace() << "setProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) failed: "
|
||||
<< QWindowsContext::comErrorString(errorCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool QWindowsContext::isDarkMode()
|
||||
{
|
||||
return QWindowsContextPrivate::m_darkMode;
|
||||
@ -1098,6 +1118,7 @@ static inline bool resizeOnDpiChanged(const QWindow *w)
|
||||
bool QWindowsContext::shouldHaveNonClientDpiScaling(const QWindow *window)
|
||||
{
|
||||
return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10
|
||||
&& !QWindowsContextPrivate::m_v2DpiAware // V2 implies NonClientDpiScaling; no need to enable
|
||||
&& window->isTopLevel()
|
||||
&& !window->property(QWindowsWindow::embeddedNativeParentHandleProperty).isValid()
|
||||
#if QT_CONFIG(opengl) // /QTBUG-62901, EnableNonClientDpiScaling has problems with GL
|
||||
|
@ -98,6 +98,7 @@ struct QWindowsUser32DLL
|
||||
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 *);
|
||||
@ -123,6 +124,9 @@ struct QWindowsUser32DLL
|
||||
// Windows Vista onwards
|
||||
SetProcessDPIAware setProcessDPIAware = nullptr;
|
||||
|
||||
// Windows 10 version 1703 onwards
|
||||
SetProcessDpiAwarenessContext setProcessDpiAwarenessContext = 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;
|
||||
@ -227,6 +231,7 @@ public:
|
||||
static void setTabletAbsoluteRange(int a);
|
||||
void setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness);
|
||||
static int processDpiAwareness();
|
||||
void setProcessDpiV2Awareness();
|
||||
|
||||
static bool isDarkMode();
|
||||
|
||||
|
@ -219,7 +219,7 @@ static inline unsigned parseOptions(const QStringList ¶mList,
|
||||
options |= QWindowsIntegration::DontPassOsMouseEventsSynthesizedFromTouch;
|
||||
} else if (parseIntOption(param, QLatin1String("verbose"), 0, INT_MAX, &QWindowsContext::verbose)
|
||||
|| parseIntOption(param, QLatin1String("tabletabsoluterange"), 0, INT_MAX, tabletAbsoluteRange)
|
||||
|| parseIntOption(param, QLatin1String("dpiawareness"), QtWindows::ProcessDpiUnaware, QtWindows::ProcessPerMonitorDpiAware, dpiAwareness)) {
|
||||
|| parseIntOption(param, QLatin1String("dpiawareness"), QtWindows::ProcessDpiUnaware, QtWindows::ProcessPerMonitorV2DpiAware, dpiAwareness)) {
|
||||
} else if (param == u"menus=native") {
|
||||
options |= QWindowsIntegration::AlwaysUseNativeMenus;
|
||||
} else if (param == u"menus=none") {
|
||||
@ -263,10 +263,19 @@ void QWindowsIntegrationPrivate::parseOptions(QWindowsIntegration *q, const QStr
|
||||
|
||||
if (!dpiAwarenessSet) { // Set only once in case of repeated instantiations of QGuiApplication.
|
||||
if (!QCoreApplication::testAttribute(Qt::AA_PluginApplication)) {
|
||||
m_context.setProcessDpiAwareness(dpiAwareness);
|
||||
qCDebug(lcQpaWindows)
|
||||
<< __FUNCTION__ << "DpiAwareness=" << dpiAwareness
|
||||
<< "effective process DPI awareness=" << QWindowsContext::processDpiAwareness();
|
||||
|
||||
// DpiAwareV2 requires using new API
|
||||
bool hasDpiAwarenessContext = QWindowsContext::user32dll.setProcessDpiAwarenessContext != nullptr;
|
||||
if (dpiAwareness == QtWindows::ProcessPerMonitorV2DpiAware && hasDpiAwarenessContext) {
|
||||
m_context.setProcessDpiV2Awareness();
|
||||
qCDebug(lcQpaWindows)
|
||||
<< __FUNCTION__ << "DpiAwareness: DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2";
|
||||
} else {
|
||||
m_context.setProcessDpiAwareness(dpiAwareness);
|
||||
qCDebug(lcQpaWindows)
|
||||
<< __FUNCTION__ << "DpiAwareness=" << dpiAwareness
|
||||
<< "effective process DPI awareness=" << QWindowsContext::processDpiAwareness();
|
||||
}
|
||||
}
|
||||
dpiAwarenessSet = true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user