From ca851b33171e652b740efbc47d41b8cf906ecd3d Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Thu, 28 Mar 2024 07:22:43 +0100 Subject: [PATCH] Unify behavior of QSystemTrayIcon::geometry for hidden icons on Windows When a system tray icon on Windows wasn't visible (hidden behind the ^ icon in the task bar) our previous implementation gave different results on Windows 10 and Windows 11. On Windows 10 the geometry returned the geometry of the ^ icon itself while we returned a geometry outside of the screen geometry on Windows 11 (that was what the Windows API gave us). We work around this problem by using version specific hacks to be able to check for the visibility of the system tray icon itself. If the icon is hidden we just return QRect(). [ChangeLog][Windows] The geometry of a hidden QSystemTrayIcon was unified over different Windows versions. It will always return QRect() now. Change-Id: Iee7dea184936a13a9221df9c421400ba304a4c38 Reviewed-by: Miguel Costa --- .../windows/qwindowssystemtrayicon.cpp | 26 +++++++++++++++++++ .../windows/qwindowssystemtrayicon.h | 1 + 2 files changed, 27 insertions(+) diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp index ed88e250a21..6f0680ac23a 100644 --- a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp +++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp @@ -184,6 +184,9 @@ void QWindowsSystemTrayIcon::updateToolTip(const QString &tooltip) QRect QWindowsSystemTrayIcon::geometry() const { + if (!isIconVisible()) + return QRect(); + NOTIFYICONIDENTIFIER nid; memset(&nid, 0, sizeof(nid)); nid.cbSize = sizeof(nid); @@ -307,6 +310,29 @@ bool QWindowsSystemTrayIcon::setIconVisible(bool visible) return Shell_NotifyIcon(NIM_MODIFY, &tnd) == TRUE; } +bool QWindowsSystemTrayIcon::isIconVisible() const +{ + NOTIFYICONIDENTIFIER nid; + memset(&nid, 0, sizeof(nid)); + nid.cbSize = sizeof(nid); + nid.hWnd = m_hwnd; + nid.uID = q_uNOTIFYICONID; + RECT rect; + const HRESULT hr = Shell_NotifyIconGetRect(&nid, &rect); + // Windows 10 returns S_FALSE if the icon is hidden + if (FAILED(hr) || hr == S_FALSE) + return false; + + HMONITOR monitor = MonitorFromWindow(m_hwnd, MONITOR_DEFAULTTONEAREST); + MONITORINFO info; + info.cbSize = sizeof(MONITORINFO); + GetMonitorInfo(monitor, &info); + // Windows 11 seems to return a geometry outside of the current monitor's geometry in case of + // the icon being hidden. As it's impossible to change the alignment of the task bar on Windows + // 11 this check should be fine. + return rect.bottom <= info.rcMonitor.bottom; +} + bool QWindowsSystemTrayIcon::sendTrayMessage(DWORD msg) { NOTIFYICONDATA tnd; diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.h b/src/plugins/platforms/windows/qwindowssystemtrayicon.h index a50865c950f..3ad5feb125a 100644 --- a/src/plugins/platforms/windows/qwindowssystemtrayicon.h +++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.h @@ -49,6 +49,7 @@ private: void ensureCleanup(); bool sendTrayMessage(DWORD msg); bool setIconVisible(bool visible); + bool isIconVisible() const; HICON createIcon(const QIcon &icon); QIcon m_icon;