Windows QPA: Use new EnableNonClientDpiScaling() for Windows decoration

Use newly introduced EnableNonClientDpiScaling() function to fix
the decoration having the wrong size in multimonitor setups with
per-monitor DPI awareness.

Task-number: QTBUG-53255
Change-Id: Ic6e2f2a92f790259107d2a0837b96177cf3adb5f
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
bb10
Friedemann Kleint 2016-11-07 14:22:37 +01:00
parent babc7c5929
commit e8ecde99df
3 changed files with 44 additions and 1 deletions

View File

@ -102,6 +102,7 @@ enum WindowsEventType // Simplify event types
TouchEvent = TouchEventFlag + 1,
NonClientMouseEvent = NonClientEventFlag + MouseEventFlag + 1,
NonClientHitTest = NonClientEventFlag + 2,
NonClientCreate = NonClientEventFlag + 3,
KeyEvent = KeyEventFlag + 1,
KeyDownEvent = KeyEventFlag + KeyDownEventFlag + 1,
KeyboardLayoutChangeEvent = KeyEventFlag + 2,
@ -177,6 +178,8 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI
return QtWindows::HideEvent;
case WM_SIZE:
return QtWindows::ResizeEvent;
case WM_NCCREATE:
return QtWindows::NonClientCreate;
case WM_NCCALCSIZE:
return QtWindows::CalculateSize;
case WM_NCHITTEST:

View File

@ -128,6 +128,28 @@ static inline QWindowsSessionManager *platformSessionManager() {
}
#endif
static inline int windowDpiAwareness(HWND hwnd)
{
return QWindowsContext::user32dll.getWindowDpiAwarenessContext && QWindowsContext::user32dll.getWindowDpiAwarenessContext
? QWindowsContext::user32dll.getAwarenessFromDpiAwarenessContext(QWindowsContext::user32dll.getWindowDpiAwarenessContext(hwnd))
: -1;
}
// Note: This only works within WM_NCCREATE
static bool enableNonClientDpiScaling(HWND hwnd)
{
bool result = 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)",
hwnd, errorCode);
}
}
return result;
}
/*!
\class QWindowsUser32DLL
\brief Struct that contains dynamically resolved symbols of User32.dll.
@ -148,7 +170,8 @@ QWindowsUser32DLL::QWindowsUser32DLL() :
registerTouchWindow(0), unregisterTouchWindow(0),
getTouchInputInfo(0), closeTouchInputHandle(0), setProcessDPIAware(0),
addClipboardFormatListener(0), removeClipboardFormatListener(0),
getDisplayAutoRotationPreferences(0), setDisplayAutoRotationPreferences(0)
getDisplayAutoRotationPreferences(0), setDisplayAutoRotationPreferences(0),
enableNonClientDpiScaling(0), getWindowDpiAwarenessContext(0), getAwarenessFromDpiAwarenessContext(0)
{
}
@ -162,6 +185,12 @@ void QWindowsUser32DLL::init()
getDisplayAutoRotationPreferences = (GetDisplayAutoRotationPreferences)library.resolve("GetDisplayAutoRotationPreferences");
setDisplayAutoRotationPreferences = (SetDisplayAutoRotationPreferences)library.resolve("SetDisplayAutoRotationPreferences");
if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS10) { // Appears in 10.0.14393, October 2016
enableNonClientDpiScaling = (EnableNonClientDpiScaling)library.resolve("EnableNonClientDpiScaling");
getWindowDpiAwarenessContext = (GetWindowDpiAwarenessContext)library.resolve("GetWindowDpiAwarenessContext");
getAwarenessFromDpiAwarenessContext = (GetAwarenessFromDpiAwarenessContext)library.resolve("GetAwarenessFromDpiAwarenessContext");
}
}
bool QWindowsUser32DLL::initTouch()
@ -928,6 +957,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::MoveEvent:
d->m_creationContext->obtainedGeometry.moveTo(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
return true;
case QtWindows::NonClientCreate:
if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS10 && d->m_creationContext->window->isTopLevel())
enableNonClientDpiScaling(msg.hwnd);
return false;
case QtWindows::CalculateSize:
return QWindowsGeometryHint::handleCalculateSize(d->m_creationContext->customMargins, msg, result);
case QtWindows::GeometryChangingEvent:

View File

@ -94,6 +94,9 @@ struct QWindowsUser32DLL
typedef BOOL (WINAPI *RemoveClipboardFormatListener)(HWND);
typedef BOOL (WINAPI *GetDisplayAutoRotationPreferences)(DWORD *);
typedef BOOL (WINAPI *SetDisplayAutoRotationPreferences)(DWORD);
typedef BOOL (WINAPI *EnableNonClientDpiScaling)(HWND);
typedef int (WINAPI *GetWindowDpiAwarenessContext)(HWND);
typedef int (WINAPI *GetAwarenessFromDpiAwarenessContext)(int);
// Touch functions from Windows 7 onwards (also for use with Q_CC_MSVC).
IsTouchWindow isTouchWindow;
@ -113,6 +116,10 @@ struct QWindowsUser32DLL
// Rotation API
GetDisplayAutoRotationPreferences getDisplayAutoRotationPreferences;
SetDisplayAutoRotationPreferences setDisplayAutoRotationPreferences;
EnableNonClientDpiScaling enableNonClientDpiScaling;
GetWindowDpiAwarenessContext getWindowDpiAwarenessContext;
GetAwarenessFromDpiAwarenessContext getAwarenessFromDpiAwarenessContext;
};
// Shell scaling library (Windows 8.1 onwards)