From 7e9535f8c71dbc956f0f1b46817a86d5ab937891 Mon Sep 17 00:00:00 2001 From: Yuhang Zhao <2546789017@qq.com> Date: Sat, 12 Feb 2022 16:46:26 +0800 Subject: Windows QPA: Add some offset to the system menu when appropriate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this patch, the system menu will always appear on the top-left corner of the window if the window doesn't have the standard window frame. However, this doesn't look very good on most situations, especially when the window has a homemade title bar. This patch adds an extra check for this kind of situations. This patch will automatically apply an appropriate offset for the system menu if the user is trying to use a self-made title bar for their frameless or customized windows. Change-Id: I55e1c4ac26a4051ca48928d4a2ac3456dce117d1 Reviewed-by: André de la Rocha (cherry picked from commit 77d0ad6657997b24e760f9a510676c08fc952eca) Reviewed-by: Qt Cherry-pick Bot --- .../platforms/windows/qwindowskeymapper.cpp | 24 +++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index 5954f35b07..7ee1d1e7d8 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -785,6 +785,27 @@ static inline QString messageKeyText(const MSG &msg) return ch.isNull() ? QString() : QString(ch); } +[[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; +} + +[[nodiscard]] static inline bool isSystemMenuOffsetNeeded(const Qt::WindowFlags flags) +{ + static constexpr const Qt::WindowFlags titleBarHints = + Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint; + return (flags & Qt::WindowSystemMenuHint) && (flags & Qt::WindowTitleHint) && !(flags & titleBarHints) + && (flags & (Qt::FramelessWindowHint | Qt::CustomizeWindowHint)); +} + static void showSystemMenu(QWindow* w) { QWindow *topLevel = QWindowsWindow::topLevelOf(w); @@ -826,9 +847,10 @@ static void showSystemMenu(QWindow* w) #undef enabled #undef disabled const QPoint pos = QHighDpi::toNativePixels(topLevel->geometry().topLeft(), topLevel); + const int titleBarOffset = isSystemMenuOffsetNeeded(topLevel->flags()) ? getTitleBarHeight(topLevelHwnd) : 0; const int ret = TrackPopupMenuEx(menu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD, - pos.x(), pos.y(), + pos.x(), pos.y() + titleBarOffset, topLevelHwnd, nullptr); if (ret) -- cgit v1.2.3