Skip to content
Snippets Groups Projects
Commit 7e063c67 authored by Fatih Uzunoğlu's avatar Fatih Uzunoğlu Committed by Steve Lhomme
Browse files

qt: do not assume that the interface window is in the primary monitor in `CSDWin32EventHandler`

- `GetSystemMetrics()` function already scales most of the metrics for the
primary monitor [1], evidently because Qt makes the application DPI aware.
- Currently by multiplying the `GetSystemMetrics()` result with
`windowDpi / screenDpi`, we apply the window's DPI which is what is wanted
here.
- If the window is in the primary monitor, there is no problem. If there
are multiple monitors but they share the same DPI, there should also be no
problem. But if there are multiple monitors that have different DPIs, in
that case dragging would be problematic.
- The solution that Windows recommends [2] is using `GetSystemMetricsForDpi`
and `GetDpiForWindow`. Unfortunately these are only available on Windows 10,
so I dynamically load the necessary library and resolve the symbols.
- Handling `WM_DPICHANGED` and calling `SetWindowPos()` should not be
necessary, because Qt already calls it to resize the window according to
the new dpi.

[1] https://learn.microsoft.com/en-us/windows/win32/gdi/multiple-monitor-system-metrics

[2] https://learn.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows#updating-existing-applications
parent 7e31157b
No related branches found
No related tags found
1 merge request!6939qt: do not assume that the interface window is in the primary monitor with csd on Windows
Pipeline #572062 passed with stage
in 13 minutes and 13 seconds
......@@ -40,10 +40,6 @@
#include <QWindow>
#ifndef QT_GUI_PRIVATE
#warning "qplatformnativeinterface.h header is required for MainCtxWin32"
#endif
#include <QtGui/qpa/qplatformnativeinterface.h>
#include <dwmapi.h>
#define WM_APPCOMMAND 0x0319
......@@ -108,13 +104,10 @@ using namespace vlc::playlist;
namespace {
HWND WinId( QWindow *windowHandle )
HWND WinId( const QWindow *window )
{
if( windowHandle && windowHandle->handle() )
return static_cast<HWND>(QGuiApplication::platformNativeInterface()->
nativeResourceForWindow("handle", windowHandle));
else
return 0;
assert(window);
return reinterpret_cast<HWND>(window->winId());
}
class CSDWin32EventHandler : public QObject, public QAbstractNativeEventFilter
......@@ -142,26 +135,44 @@ public:
QApplication::instance()->removeNativeEventFilter(this);
}
static int getSystemMetricsForDpi(int nIndex, UINT dpi)
{
typedef int (WINAPI *GetSystemMetricsForDpiFunc)(int, UINT);
static GetSystemMetricsForDpiFunc getSystemMetricsForDpi = []() {
const auto user32dll = LoadLibraryEx(TEXT("user32.dll"), nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
return reinterpret_cast<GetSystemMetricsForDpiFunc>(GetProcAddress(user32dll, "GetSystemMetricsForDpi"));
}();
if (getSystemMetricsForDpi)
return getSystemMetricsForDpi(nIndex, dpi);
return GetSystemMetrics(nIndex);
}
static int getSystemMetricsForWindow(int nIndex, const QWindow* window)
{
assert(window);
typedef UINT (WINAPI *GetDpiForWindowFunc)(HWND);
static GetDpiForWindowFunc getDpiForWindow = []() {
const auto user32dll = LoadLibraryEx(TEXT("user32.dll"), nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
return reinterpret_cast<GetDpiForWindowFunc>(GetProcAddress(user32dll, "GetDpiForWindow"));
}();
if (getDpiForWindow)
return getSystemMetricsForDpi(nIndex, getDpiForWindow(WinId(window)));
return GetSystemMetrics(nIndex);
}
static int resizeBorderWidth(QWindow *window)
{
// NOTE: When possible, Qt makes the application DPI aware, so `GetSystemMetrics()` would
// already take the screen DPI into account.
const int result = GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
if (result > 0)
return qRound(static_cast<qreal>(result) * (window->devicePixelRatio() / window->screen()->devicePixelRatio()));
else
return qRound(static_cast<qreal>(8) * window->devicePixelRatio());
return getSystemMetricsForWindow(SM_CXSIZEFRAME, window) + getSystemMetricsForWindow(SM_CXPADDEDBORDER, window);
}
static int resizeBorderHeight(QWindow *window)
{
// NOTE: Qt makes the application DPI aware, so `GetSystemMetrics()` would already take
// already take the screen DPI into account.
const int result = GetSystemMetrics(SM_CYSIZEFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
if (result > 0)
return qRound(static_cast<qreal>(result) * (window->devicePixelRatio() / window->screen()->devicePixelRatio()));
else
return qRound(static_cast<qreal>(8) * window->devicePixelRatio());
return getSystemMetricsForWindow(SM_CYSIZEFRAME, window) + getSystemMetricsForWindow(SM_CXPADDEDBORDER, window);
}
bool nativeEventFilter(const QByteArray &, void *message, qintptr *result) override
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment