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); }; }