diff --git a/date-wizard/Sources/DateWizard/AppDelegate.swift b/date-wizard/Sources/DateWizard/AppDelegate.swift index 8c894610f5..d199c84247 100644 --- a/date-wizard/Sources/DateWizard/AppDelegate.swift +++ b/date-wizard/Sources/DateWizard/AppDelegate.swift @@ -8,14 +8,25 @@ final class DateWizardAppDelegate: NSObject, NSApplicationDelegate { DockIcon.install(prefix: "datewizard") let controller = WizardController() wizard = controller - controller.showWindow(nil) - NSApp.activate(ignoringOtherApps: true) - // Always-on menu bar strip: seven ROYGBIV day circles (S M T W T F S), - // today's lit. Click opens the wizard; the app stays resident so the - // strip is always there even when the window is closed. + // --background (startup/LaunchAgent): come up as a menu-bar-only daemon — + // just the wand icon, no window, no dock, no focus steal. The calendar + // opens on demand when the icon is clicked (which promotes us to .regular + // so the window focuses properly). Without the flag, open straight in. + let background = CommandLine.arguments.contains("--background") + if background { + NSApp.setActivationPolicy(.accessory) + } else { + controller.showWindow(nil) + NSApp.activate(ignoringOtherApps: true) + } + + // Always-on menu bar: a black magic-wand template icon. Click opens the + // wizard; the app stays resident so the icon is always there even when + // the window is closed. let menu = MenuBarDays() menu.onOpen = { [weak controller] in + NSApp.setActivationPolicy(.regular) controller?.showWindow(nil) NSApp.activate(ignoringOtherApps: true) } diff --git a/date-wizard/Sources/DateWizard/MenuBarDays.swift b/date-wizard/Sources/DateWizard/MenuBarDays.swift index 292682e8eb..25c2b4e4c3 100644 --- a/date-wizard/Sources/DateWizard/MenuBarDays.swift +++ b/date-wizard/Sources/DateWizard/MenuBarDays.swift @@ -66,14 +66,13 @@ final class MenuBarDays { if idx != focusedIndex { focusedIndex = idx; refresh() } } - /// Paint the menu-bar face: the hand-pixeled wizard guy. This daemon is the - /// "wizard of wizards" now (the date is built in), so it wears the wizard, - /// not the day strip. + /// Paint the menu-bar face: a plain black magic wand (template image, so it + /// tints to the bar like Menu Band's note glyph). This daemon is the "wizard + /// of wizards" now (the date is built in) — the costumed wizardGuy lives on + /// only inside the menu/About, where color reads fine. func refresh() { guard let button = statusItem?.button else { return } - let img = wizardGuy(scale: 1) - img.isTemplate = false // keep his colors; don't tint as a template - button.image = img + button.image = wandGlyph() } // ── input ───────────────────────────────────────────────────────── diff --git a/date-wizard/Sources/DateWizard/WizardRoster.swift b/date-wizard/Sources/DateWizard/WizardRoster.swift index cc575326df..55932f24b6 100644 --- a/date-wizard/Sources/DateWizard/WizardRoster.swift +++ b/date-wizard/Sources/DateWizard/WizardRoster.swift @@ -50,6 +50,19 @@ func wizardGuy(scale s: CGFloat) -> NSImage { } } +// The menu-bar face: a plain black magic wand. It's a *template* image, so macOS +// tints it to match the bar (black on light, white on dark) exactly like Menu +// Band's note glyph — unlike the multicolored wizardGuy, which stays a costume +// for the About window and the summon roster. SF Symbol so it stays crisp at any +// bar thickness; wizardGuy is the fallback if the symbol is ever missing. +func wandGlyph(pointSize: CGFloat = 15) -> NSImage { + let cfg = NSImage.SymbolConfiguration(pointSize: pointSize, weight: .regular) + let img = NSImage(systemSymbolName: "wand.and.stars", accessibilityDescription: "Wizard")? + .withSymbolConfiguration(cfg) ?? wizardGuy(scale: 1) + img.isTemplate = true + return img +} + struct WizardEntry { let dir: String // package dir under the repo root let exe: String // executable / target name