Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5eb2d0f661 |
@@ -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
|
or per-element, so every helper returns `nil` instead of force-unwrapping. The
|
||||||
`enumerate()` routine is `nonisolated static` so `--self-test` can run it.
|
`enumerate()` routine is `nonisolated static` so `--self-test` can run it.
|
||||||
- Items are keyed by `pid-index`; `MenuBarItem` equality ignores the AX element.
|
- 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
|
- Reading another app's UI is the only TCC permission needed; there is no Screen
|
||||||
Recording or Apple Events usage.
|
Recording or Apple Events usage.
|
||||||
|
|
||||||
|
|||||||
@@ -68,11 +68,23 @@ final class MenuBarItemManager: ObservableObject {
|
|||||||
guard let bar = extrasMenuBar(of: axApp),
|
guard let bar = extrasMenuBar(of: axApp),
|
||||||
let children = children(of: bar) else { continue }
|
let children = children(of: bar) else { continue }
|
||||||
|
|
||||||
|
var seenTitles = Set<String>()
|
||||||
for (index, child) in children.enumerated() {
|
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)
|
let title = stringAttribute(child, kAXDescriptionAttribute)
|
||||||
?? stringAttribute(child, kAXTitleAttribute)
|
?? stringAttribute(child, kAXTitleAttribute)
|
||||||
?? app.localizedName
|
?? app.localizedName
|
||||||
?? "Item"
|
?? "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(
|
found.append(MenuBarItem(
|
||||||
id: "\(pid)-\(index)",
|
id: "\(pid)-\(index)",
|
||||||
pid: pid,
|
pid: pid,
|
||||||
|
|||||||
Reference in New Issue
Block a user