From 57ceebf5ab343fc619db6a70cd91dc567317ea53 Mon Sep 17 00:00:00 2001 From: Dennis van der Stelt Date: Wed, 15 Jul 2026 13:49:39 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20Dismiss=20the=20tray=20menu=20wh?= =?UTF-8?q?en=20clicking=20away=20from=20it?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A hand-shown tray ContextMenuStrip never gets foreground activation, so clicking outside it did not close it: you were stuck opening an item to dismiss the menu. Call SetForegroundWindow on the menu before showing it (the classic Win32 tray fix) so click-away closes it normally. --- src/ClickLightWin/Interop/NativeMethods.cs | 9 +++++++++ src/ClickLightWin/Tray/TrayIcon.cs | 9 +++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/ClickLightWin/Interop/NativeMethods.cs b/src/ClickLightWin/Interop/NativeMethods.cs index 54f86a9..4b57a3a 100644 --- a/src/ClickLightWin/Interop/NativeMethods.cs +++ b/src/ClickLightWin/Interop/NativeMethods.cs @@ -89,6 +89,15 @@ public static partial bool SetWindowPos( [return: MarshalAs(UnmanagedType.Bool)] public static partial bool DestroyIcon(nint hIcon); + // ---- Foreground activation ----------------------------------------------- + + // A tray context menu shown by hand never gets foreground activation, so a + // click outside it fails to dismiss it. Forcing our process to the foreground + // first restores the normal click-away close (the classic Win32 tray fix). + [LibraryImport("user32.dll")] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool SetForegroundWindow(nint hWnd); + // ---- Global hotkeys ------------------------------------------------------ public const int WM_HOTKEY = 0x0312; diff --git a/src/ClickLightWin/Tray/TrayIcon.cs b/src/ClickLightWin/Tray/TrayIcon.cs index 07fc584..baa89f0 100644 --- a/src/ClickLightWin/Tray/TrayIcon.cs +++ b/src/ClickLightWin/Tray/TrayIcon.cs @@ -1,5 +1,6 @@ using System.Drawing; using System.Windows.Forms; // NotifyIcon, ContextMenuStrip +using ClickLightWin.Interop; namespace ClickLightWin.Tray; @@ -83,8 +84,12 @@ public TrayIcon(Settings settings, LaunchAtLoginController launchAtLogin, // screen, so this stays correct for other taskbar positions too. _icon.MouseUp += (_, e) => { - if (e.Button == MouseButtons.Right) - menu.Show(Cursor.Position, ToolStripDropDownDirection.AboveLeft); + if (e.Button != MouseButtons.Right) return; + // Give our process the foreground first; without it a hand-shown tray + // menu won't dismiss when you click elsewhere (you'd be stuck picking an + // item to close it). See NativeMethods.SetForegroundWindow. + NativeMethods.SetForegroundWindow(menu.Handle); + menu.Show(Cursor.Position, ToolStripDropDownDirection.AboveLeft); }; }