diff --git a/AGENTS.md b/AGENTS.md index be386c9..e9f0f18 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -38,6 +38,10 @@ executable SwiftPM package, no external dependencies (all Apple frameworks). or per-element, so every helper returns `nil` instead of force-unwrapping. The `enumerate()` routine is `nonisolated static` so `--self-test` can run it. - Items are keyed by `pid-index`; `MenuBarItem` equality ignores the AX element. +- Control Center is special: its extras menu bar lists **every module it owns**, + including ones not in the bar, which are parked off-screen at `y≈982`. + `enumerate()` drops items whose AX position `y > 60` and de-duplicates by + title per app, otherwise the tray fills with identical "Control Center" tiles. - Reading another app's UI is the only TCC permission needed; there is no Screen Recording or Apple Events usage. diff --git a/Sources/SimpleTopBar/MenuBarItems.swift b/Sources/SimpleTopBar/MenuBarItems.swift index f6b11c4..f2965f1 100644 --- a/Sources/SimpleTopBar/MenuBarItems.swift +++ b/Sources/SimpleTopBar/MenuBarItems.swift @@ -68,11 +68,23 @@ final class MenuBarItemManager: ObservableObject { guard let bar = extrasMenuBar(of: axApp), let children = children(of: bar) else { continue } + var seenTitles = Set() for (index, child) in children.enumerated() { + // Control Center reports every module it owns, including the + // ones not in the menu bar, which are parked off-screen around + // y=982. Keep only items actually sitting in the bar. + if let position = pointAttribute(child, kAXPositionAttribute), position.y > 60 { + continue + } + let title = stringAttribute(child, kAXDescriptionAttribute) ?? stringAttribute(child, kAXTitleAttribute) ?? app.localizedName ?? "Item" + // Several Control Center modules share the generic title + // "Control Center"; show each distinct title once per app. + if !seenTitles.insert(title).inserted { continue } + found.append(MenuBarItem( id: "\(pid)-\(index)", pid: pid,