From 61d2689cbc3e88df277a1d9ab9082f5c2854b843 Mon Sep 17 00:00:00 2001 From: TZGyn Date: Sun, 27 Sep 2026 02:25:50 +0800 Subject: [PATCH] Reveal hidden tray icons while the panel is open MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pressing a tray tile did nothing visible because the item was hidden off-screen, so its menu opened where it could not be seen. Temporarily put the icons back on the menu bar while the panel is open, so clicking a tile opens that app's real menu in view. 💘 Generated with Crush Assisted-by: Crush:deepseek-v4.1-flash --- AGENTS.md | 6 ++++++ Sources/SimpleTopBar/App.swift | 17 ++++++++++++++++- Sources/SimpleTopBar/MenuBarItems.swift | 16 ++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/AGENTS.md b/AGENTS.md index 86681bd..fcc052e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -134,6 +134,12 @@ preferred position controls where the hidden/kept boundary lands: - Verified with `--diag-hide` across positions 100–400. Below ~200 Wi-Fi gets hidden too; above ~300 app icons (Now Playing, TextInput) leak back. - `debug.spacerPos` (Double) overrides the seed for tuning without rebuilding. +- Pressing a tray tile calls `MenuBarItemManager.press` (`kAXPressAction`, then + `kAXShowMenuAction`). Because a hidden item sits off-screen, its menu would + open off-screen; `AppDelegate` therefore calls `MenuBarHider.suspend()` + (`popoverWillShow`) to reveal items while the panel is open and `resume()` + 0.6s after `popoverDidClose`. `suspend`/`resume` do not change the user's + `enabled` preference. - **Order matters**: `AppDelegate` must call `setupStatusItem()` *before* `MenuBarHider.shared.prepare()`. If the hider contracts the bar first, the hamburger is created into the collapsed space and lands off-screen. diff --git a/Sources/SimpleTopBar/App.swift b/Sources/SimpleTopBar/App.swift index 4cdc96c..91d9139 100644 --- a/Sources/SimpleTopBar/App.swift +++ b/Sources/SimpleTopBar/App.swift @@ -17,7 +17,7 @@ struct SimpleTopBarApp: App { /// full menu bar, a brand new item lands under the notch and is invisible; /// writing `NSStatusItem Preferred Position ` into defaults puts it in a /// visible slot, and the autosave name lets the user's own drag persist. -final class AppDelegate: NSObject, NSApplicationDelegate { +final class AppDelegate: NSObject, NSApplicationDelegate, NSPopoverDelegate { private var statusItem: NSStatusItem? private var popover: NSPopover? @@ -103,6 +103,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate { let popover = NSPopover() popover.behavior = .transient popover.animates = false + popover.delegate = self popover.contentViewController = NSHostingController( rootView: TopBarView( model: AppListModel.shared, @@ -113,6 +114,20 @@ final class AppDelegate: NSObject, NSApplicationDelegate { self.popover = popover } + // Reveal the hidden menu bar items while the panel is open so pressing a + // tray icon opens that app's menu at its real, on-screen position. + func popoverWillShow(_ notification: Notification) { + MenuBarHider.shared.suspend() + } + + func popoverDidClose(_ notification: Notification) { + // Small delay so a menu just opened from a tray tile is fully on screen + // before the bar contracts again. + DispatchQueue.main.asyncAfter(deadline: .now() + 0.6) { + MenuBarHider.shared.resume() + } + } + @objc private func togglePopover() { guard let popover, let button = statusItem?.button else { return } if popover.isShown { diff --git a/Sources/SimpleTopBar/MenuBarItems.swift b/Sources/SimpleTopBar/MenuBarItems.swift index ff025e3..df108c2 100644 --- a/Sources/SimpleTopBar/MenuBarItems.swift +++ b/Sources/SimpleTopBar/MenuBarItems.swift @@ -252,6 +252,22 @@ final class MenuBarHider: ObservableObject { isHiding = hiding } + /// Temporarily reveal the items (e.g. while the panel is open) so pressing + /// a tray icon opens its menu at its real, on-screen position. Keeps the + /// user's `enabled` preference untouched. + func suspend() { + guard enabled else { return } + spacer?.length = 0 + isHiding = false + } + + /// Restore hiding after a `suspend()`. + func resume() { + guard enabled else { return } + spacer?.length = Self.hiddenLength + isHiding = true + } + /// Put the menu bar back the way we found it. Called on quit. Leaves the /// user's preference intact. func restore() {