Windows: Start using High DPI API available from Windows 8.1 onwards.
Dynamically load shcore.dll, use SetProcessDpiAwareness() instead of SetProcessDPIAware() when available. Add command line parameter to control level. Task-number: QTBUG-37347 Change-Id: I1259b0943b41e50066e7e3870ed3136afd8f18fe Reviewed-by: Oliver Wolff <oliver.wolff@digia.com>bb10
parent
ae7bbe3400
commit
2e44a9e491
|
|
@ -1,7 +1,7 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
|
|
@ -117,6 +117,14 @@ enum WindowsEventType // Simplify event types
|
|||
UnknownEvent = 542
|
||||
};
|
||||
|
||||
// Matches Process_DPI_Awareness (Windows 8.1 onwards), used for SetProcessDpiAwareness()
|
||||
enum ProcessDpiAwareness
|
||||
{
|
||||
ProcessDpiUnaware,
|
||||
ProcessSystemDpiAware,
|
||||
ProcessPerMonitorDpiAware
|
||||
};
|
||||
|
||||
} // namespace QtWindows
|
||||
|
||||
inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamIn)
|
||||
|
|
|
|||
|
|
@ -244,8 +244,26 @@ void QWindowsShell32DLL::init()
|
|||
sHGetImageList = (SHGetImageList)library.resolve("SHGetImageList");
|
||||
}
|
||||
|
||||
QWindowsShcoreDLL::QWindowsShcoreDLL()
|
||||
: getProcessDpiAwareness(0)
|
||||
, setProcessDpiAwareness(0)
|
||||
, getDpiForMonitor(0)
|
||||
{
|
||||
}
|
||||
|
||||
void QWindowsShcoreDLL::init()
|
||||
{
|
||||
if (QSysInfo::windowsVersion() < QSysInfo::WV_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;
|
||||
QWindowsShell32DLL QWindowsContext::shell32dll;
|
||||
QWindowsShcoreDLL QWindowsContext::shcoredll;
|
||||
|
||||
#endif // !Q_OS_WINCE
|
||||
|
||||
|
|
@ -296,9 +314,7 @@ QWindowsContextPrivate::QWindowsContextPrivate()
|
|||
#ifndef Q_OS_WINCE
|
||||
QWindowsContext::user32dll.init();
|
||||
QWindowsContext::shell32dll.init();
|
||||
// Ensure metrics functions report correct data, QTBUG-30063.
|
||||
if (QWindowsContext::user32dll.setProcessDPIAware)
|
||||
QWindowsContext::user32dll.setProcessDPIAware();
|
||||
QWindowsContext::shcoredll.init();
|
||||
|
||||
if (hasTouchSupport(ver) && QWindowsContext::user32dll.initTouch())
|
||||
m_systemInfo |= QWindowsContext::SI_SupportsTouch;
|
||||
|
|
@ -351,6 +367,25 @@ void QWindowsContext::setTabletAbsoluteRange(int a)
|
|||
#endif
|
||||
}
|
||||
|
||||
void QWindowsContext::setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness)
|
||||
{
|
||||
#ifndef Q_OS_WINCE
|
||||
qCDebug(lcQpaWindows) << __FUNCTION__ << dpiAwareness;
|
||||
if (QWindowsContext::shcoredll.isValid()) {
|
||||
const HRESULT hr = QWindowsContext::shcoredll.setProcessDpiAwareness(dpiAwareness);
|
||||
if (FAILED(hr))
|
||||
qWarning() << "SetProcessDpiAwareness failed:" << QWindowsContext::comErrorString(hr);
|
||||
} else {
|
||||
if (dpiAwareness != QtWindows::ProcessDpiUnaware && QWindowsContext::user32dll.setProcessDPIAware) {
|
||||
if (!QWindowsContext::user32dll.setProcessDPIAware())
|
||||
qErrnoWarning("SetProcessDPIAware() failed");
|
||||
}
|
||||
}
|
||||
#else // !Q_OS_WINCE
|
||||
Q_UNUSED(dpiAwareness)
|
||||
#endif
|
||||
}
|
||||
|
||||
QWindowsContext *QWindowsContext::instance()
|
||||
{
|
||||
return m_instance;
|
||||
|
|
|
|||
|
|
@ -126,6 +126,22 @@ struct QWindowsShell32DLL
|
|||
SHGetStockIconInfo sHGetStockIconInfo;
|
||||
SHGetImageList sHGetImageList;
|
||||
};
|
||||
|
||||
// Shell scaling library (Windows 8.1 onwards)
|
||||
struct QWindowsShcoreDLL {
|
||||
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;
|
||||
SetProcessDpiAwareness setProcessDpiAwareness;
|
||||
GetDpiForMonitor getDpiForMonitor;
|
||||
};
|
||||
|
||||
#endif // Q_OS_WINCE
|
||||
|
||||
class QWindowsContext
|
||||
|
|
@ -184,6 +200,7 @@ public:
|
|||
void setWindowCreationContext(const QSharedPointer<QWindowCreationContext> &ctx);
|
||||
|
||||
void setTabletAbsoluteRange(int a);
|
||||
void setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness);
|
||||
|
||||
// Returns a combination of SystemInfoFlags
|
||||
unsigned systemInfo() const;
|
||||
|
|
@ -197,6 +214,7 @@ public:
|
|||
#ifndef Q_OS_WINCE
|
||||
static QWindowsUser32DLL user32dll;
|
||||
static QWindowsShell32DLL shell32dll;
|
||||
static QWindowsShcoreDLL shcoredll;
|
||||
#endif
|
||||
|
||||
static QByteArray comErrorString(HRESULT hr);
|
||||
|
|
|
|||
|
|
@ -167,7 +167,8 @@ struct QWindowsIntegrationPrivate
|
|||
};
|
||||
|
||||
static inline unsigned parseOptions(const QStringList ¶mList,
|
||||
int *tabletAbsoluteRange)
|
||||
int *tabletAbsoluteRange,
|
||||
QtWindows::ProcessDpiAwareness *dpiAwareness)
|
||||
{
|
||||
unsigned options = 0;
|
||||
foreach (const QString ¶m, paramList) {
|
||||
|
|
@ -191,6 +192,8 @@ static inline unsigned parseOptions(const QStringList ¶mList,
|
|||
QWindowsContext::verbose = param.right(param.size() - 8).toInt();
|
||||
} else if (param.startsWith(QLatin1String("tabletabsoluterange="))) {
|
||||
*tabletAbsoluteRange = param.rightRef(param.size() - 20).toInt();
|
||||
} else if (param.startsWith(QLatin1String("dpiawareness="))) {
|
||||
*dpiAwareness = static_cast<QtWindows::ProcessDpiAwareness>(param.rightRef(param.size() - 13).toInt());
|
||||
}
|
||||
}
|
||||
return options;
|
||||
|
|
@ -201,9 +204,13 @@ QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList ¶mL
|
|||
, m_fontDatabase(0)
|
||||
{
|
||||
int tabletAbsoluteRange = -1;
|
||||
m_options = parseOptions(paramList, &tabletAbsoluteRange);
|
||||
// Default to per-monitor awareness to avoid being scaled when monitors with different DPI
|
||||
// are connected to Windows 8.1
|
||||
QtWindows::ProcessDpiAwareness dpiAwareness = QtWindows::ProcessPerMonitorDpiAware;
|
||||
m_options = parseOptions(paramList, &tabletAbsoluteRange, &dpiAwareness);
|
||||
if (tabletAbsoluteRange >= 0)
|
||||
m_context.setTabletAbsoluteRange(tabletAbsoluteRange);
|
||||
m_context.setProcessDpiAwareness(dpiAwareness);
|
||||
}
|
||||
|
||||
QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()
|
||||
|
|
|
|||
|
|
@ -68,6 +68,21 @@ static inline QDpi deviceDPI(HDC hdc)
|
|||
return QDpi(GetDeviceCaps(hdc, LOGPIXELSX), GetDeviceCaps(hdc, LOGPIXELSY));
|
||||
}
|
||||
|
||||
#ifndef Q_OS_WINCE
|
||||
|
||||
static inline QDpi monitorDPI(HMONITOR hMonitor)
|
||||
{
|
||||
if (QWindowsContext::shcoredll.isValid()) {
|
||||
UINT dpiX;
|
||||
UINT dpiY;
|
||||
if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, 0, &dpiX, &dpiY)))
|
||||
return QDpi(dpiX, dpiY);
|
||||
}
|
||||
return QDpi(0, 0);
|
||||
}
|
||||
|
||||
#endif // !Q_OS_WINCE
|
||||
|
||||
static inline QSizeF deviceSizeMM(const QSize &pixels, const QDpi &dpi)
|
||||
{
|
||||
const qreal inchToMM = 25.4;
|
||||
|
|
@ -110,7 +125,12 @@ BOOL QT_WIN_CALLBACK monitorEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM
|
|||
HDC hdc = CreateDC(info.szDevice, NULL, NULL, NULL);
|
||||
#endif
|
||||
if (hdc) {
|
||||
#ifndef Q_OS_WINCE
|
||||
const QDpi dpi = monitorDPI(hMonitor);
|
||||
data.dpi = dpi.first ? dpi : deviceDPI(hdc);
|
||||
#else
|
||||
data.dpi = deviceDPI(hdc);
|
||||
#endif
|
||||
data.depth = GetDeviceCaps(hdc, BITSPIXEL);
|
||||
data.format = data.depth == 16 ? QImage::Format_RGB16 : QImage::Format_RGB32;
|
||||
data.physicalSizeMM = QSizeF(GetDeviceCaps(hdc, HORZSIZE), GetDeviceCaps(hdc, VERTSIZE));
|
||||
|
|
|
|||
Loading…
Reference in New Issue