From 92a57308b74dd5be12290e7cccdc67345bfb78c2 Mon Sep 17 00:00:00 2001 From: TZGyn Date: Sun, 27 Sep 2026 00:35:05 +0800 Subject: [PATCH] Explain which menu bar items can be hidden MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hiding other apps' icons worked, but Apple pins Spotlight, Clock, Battery and Control Center to the right of the menu bar, so a third-party item can never be placed after them to push them away. Document the real limit so the behaviour is not mistaken for a bug. 💘 Generated with Crush Assisted-by: Crush:deepseek-v4.1-flash --- AGENTS.md | 13 +++++++++++++ README.md | 20 +++++++++++++++----- Sources/SimpleTopBar/App.swift | 8 ++++++++ Sources/SimpleTopBar/MenuBarItems.swift | 8 ++++++++ Sources/SimpleTopBar/TopBarView.swift | 2 +- build-app.sh | 2 +- 6 files changed, 46 insertions(+), 7 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 5c11c3f..1912677 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -112,6 +112,19 @@ no control over this, so the app creates its own `NSStatusItem` and: `/tmp/simpletopbar-items.txt`; use it to verify the icon is not under the notch (x should be ~1200, not ~765). +## Hiding other menu bar items + +`MenuBarHider` creates a zero-width spacer `NSStatusItem` at launch and grows its +length to `hiddenLength` (10_000) to push the icons on its left off-screen. +Verified with `--diag-hide`: + +- All third-party apps' icons go to x < 0 (cmux, Kapture, moomoo, WireGuard, + TextInputMenuAgent, Now Playing) and so does Wi-Fi. +- **Spotlight, Clock, Battery and Control Center stay**: macOS pins them to the + far right, and a third-party item can never be inserted to their right, so the + spacer has nothing to push them with. Do not try to "fix" this; it is a macOS + constraint, not a bug. + ## Gotchas - `AppListModel` is `@MainActor`; the `NSWorkspace` observers hop back with diff --git a/README.md b/README.md index cd5ed7a..722f37c 100644 --- a/README.md +++ b/README.md @@ -27,11 +27,21 @@ still works. macOS has no public API to move another app's status item. The **Hide items from the menu bar** toggle uses the spacer technique: a zero-width status item is -created at launch whose length is expanded to push the items to its left -off-screen. This is reliable only when SimpleTopBar starts at login (its spacer -then sits to the right of later-launched apps' items) and may need re-toggling -after items move around. It is off by default and always undone on quit; if the -app dies, macOS removes the spacer automatically. +created at launch whose length is expanded to push the other icons off-screen so +they only live in this panel. It is off by default and always undone on quit; if +the app dies, macOS removes the spacer automatically. + +What it can and cannot hide: + +- It hides **other third-party apps' icons** (and can also catch some Apple + items such as Wi-Fi). +- It **cannot** hide **Spotlight, Clock, Battery, or Control Center**. macOS + reserves the far right of the menu bar for those, and a third-party app cannot + place its item to their right, so there is nothing to push them with. (This is + the same limit Bartender and Ice hit; they cover the area with their own + overlay bar instead.) +- Newly launched apps are placed to the left of the spacer, so they are hidden + automatically. ## Install with Homebrew diff --git a/Sources/SimpleTopBar/App.swift b/Sources/SimpleTopBar/App.swift index 5f8fe28..0a5a7c9 100644 --- a/Sources/SimpleTopBar/App.swift +++ b/Sources/SimpleTopBar/App.swift @@ -53,6 +53,14 @@ final class AppDelegate: NSObject, NSApplicationDelegate { return } + if CommandLine.arguments.contains("--diag-hide") { + MenuBarHider.shared.enabled = true + DispatchQueue.main.asyncAfter(deadline: .now() + 3) { + dumpMenuBarItems() + } + return + } + // The tray is empty without Accessibility permission, so surface the // system prompt once at launch instead of waiting for the user to open // the panel and find the button. diff --git a/Sources/SimpleTopBar/MenuBarItems.swift b/Sources/SimpleTopBar/MenuBarItems.swift index d301303..df7aae5 100644 --- a/Sources/SimpleTopBar/MenuBarItems.swift +++ b/Sources/SimpleTopBar/MenuBarItems.swift @@ -165,7 +165,15 @@ final class MenuBarHider: ObservableObject { /// Create the spacer early (at launch) so it lands as far right as possible. func prepare() { guard spacer == nil else { return } + let name = "SimpleTopBarHider" + let key = "NSStatusItem Preferred Position \(name)" + // Seed just left of the hamburger so growing the spacer pushes the + // third-party icons on its left off-screen while ours stays put. + if UserDefaults.standard.object(forKey: key) == nil { + UserDefaults.standard.set(150.0, forKey: key) + } let item = NSStatusBar.system.statusItem(withLength: 0) + item.autosaveName = name item.button?.isHidden = true spacer = item } diff --git a/Sources/SimpleTopBar/TopBarView.swift b/Sources/SimpleTopBar/TopBarView.swift index 0fd873f..1e4e5c7 100644 --- a/Sources/SimpleTopBar/TopBarView.swift +++ b/Sources/SimpleTopBar/TopBarView.swift @@ -115,7 +115,7 @@ struct TopBarView: View { .controlSize(.mini) .padding(.horizontal, 12) .padding(.top, 6) - .help("Best-effort: pushes the real items off the menu bar so they only live here. Reliable when SimpleTopBar starts at login.") + .help("Best-effort: pushes other apps' icons off the menu bar so they only live here. Apple's Spotlight, Clock, Battery and Control Center stay pinned on the right and cannot be moved by any third-party app.") } } } diff --git a/build-app.sh b/build-app.sh index 1f859d2..99d36e6 100755 --- a/build-app.sh +++ b/build-app.sh @@ -2,7 +2,7 @@ set -euo pipefail cd "$(dirname "$0")" -VERSION="${1:-0.2.2}" +VERSION="${1:-0.2.3}" swift build -c release