App-Icon eingehängt, Menüleistensymbol nutzt dasselbe

Das Icon-Composer-Bündel liegt jetzt im App-Target, actool erzeugt daraus alle
Größen samt der Transluzenz-Darstellung von macOS 26.

Das Menüleistensymbol wird zur Laufzeit aus applicationIconImage auf 18 pt
gebracht — die Leiste ist 22 pt hoch und braucht oben und unten Luft. Bewusst
kein Template-Bild: als Schablone bliebe vom Kristall nur eine schwarze
Silhouette und der Verlauf wäre weg, also genau das Erkennungsmerkmal. Der
Preis ist, dass es sich nicht automatisch an helle und dunkle Menüleisten
anpasst.

Rückfall auf ein SF-Symbol, falls das App-Icon fehlt: ein Menüleisteneintrag
ohne Bild wäre unsichtbar und die App darüber unerreichbar.
This commit is contained in:
Guido Schmit
2026-08-10 20:47:41 +02:00
parent 3d21cac3b7
commit 4b559ba840
5 changed files with 34 additions and 9 deletions

View File

@@ -20,9 +20,11 @@
C041F171FB69F4381309D978 /* AppModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B83C4E3CB821F903F3977E88 /* AppModel.swift */; };
CD501EBAE39807F5D354C5B2 /* CalendarProvider in Frameworks */ = {isa = PBXBuildFile; productRef = A3E3949D664131D593CBEEDC /* CalendarProvider */; };
EA4D6312E8A96E177F10797F /* OnyxNotch in Frameworks */ = {isa = PBXBuildFile; productRef = 3A32CAE6CC4D01D660F0016F /* OnyxNotch */; };
FF97F56CE1C734E59F1B40F4 /* AppIcon.icon in Resources */ = {isa = PBXBuildFile; fileRef = 055263008CB3306A8D09E6D4 /* AppIcon.icon */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
055263008CB3306A8D09E6D4 /* AppIcon.icon */ = {isa = PBXFileReference; lastKnownFileType = wrapper.icon; path = AppIcon.icon; sourceTree = "<group>"; };
0804288DC4A8146DD9F3FC3E /* Onyx.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Onyx.app; sourceTree = BUILT_PRODUCTS_DIR; };
45BD2DF1B775C733C8F75635 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
508DECB5C05264E6130C373E /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
@@ -89,6 +91,7 @@
isa = PBXGroup;
children = (
0FBA13B97C53F1D0D740A633 /* Resources */,
055263008CB3306A8D09E6D4 /* AppIcon.icon */,
B83C4E3CB821F903F3977E88 /* AppModel.swift */,
50A018673EE6BD9C50F1EFA0 /* Info.plist */,
508DECB5C05264E6130C373E /* Localizable.xcstrings */,
@@ -173,6 +176,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FF97F56CE1C734E59F1B40F4 /* AppIcon.icon in Resources */,
A529046C33E6B00C0E9508FF /* Localizable.xcstrings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -200,14 +204,11 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Onyx/Onyx.entitlements;
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
ENABLE_APP_SANDBOX = NO;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
INFOPLIST_FILE = Onyx/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Onyx;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.lifestyle";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
@@ -355,14 +356,11 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = Onyx/Onyx.entitlements;
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
ENABLE_APP_SANDBOX = NO;
ENABLE_USER_SCRIPT_SANDBOXING = NO;
INFOPLIST_FILE = Onyx/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = Onyx;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.lifestyle";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",

View File

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -143,9 +143,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
private func installOnyxStatusItem() {
let item = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)
item.autosaveName = "onyx.menubar.main"
item.button?.image = NSImage(systemSymbolName: "circle.hexagongrid.fill",
accessibilityDescription: "Onyx")
item.button?.image?.isTemplate = true
item.button?.image = Self.menuBarIcon()
let menu = NSMenu()
menu.addItem(withTitle: String(localized: "menu.openPanel"),
@@ -161,6 +159,32 @@ final class AppDelegate: NSObject, NSApplicationDelegate {
onyxItem = item
}
/// Das App-Icon, auf Menüleistengröße gebracht.
///
/// Bewusst **kein** Template-Bild: als Schablone bliebe von dem Kristall nur
/// eine schwarze Silhouette übrig, und der Verlauf das Erkennungsmerkmal
/// des Icons wäre weg. Der Preis dafür ist, dass es sich nicht automatisch
/// an helle und dunkle Menüleisten anpasst.
///
/// 18 pt ist die übliche Höhe für Menüleistensymbole; die Leiste ist 22 pt
/// hoch und braucht oben und unten Luft.
private static func menuBarIcon() -> NSImage {
guard let source = NSApp.applicationIconImage else {
// Sollte nicht vorkommen, aber ein Menüleisteneintrag ohne Symbol
// wäre unsichtbar und die App damit unerreichbar.
return NSImage(systemSymbolName: "circle.hexagongrid.fill",
accessibilityDescription: "Onyx") ?? NSImage()
}
let size = NSSize(width: 18, height: 18)
let image = NSImage(size: size, flipped: false) { rect in
source.draw(in: rect, from: .zero, operation: .sourceOver, fraction: 1)
return true
}
image.accessibilityDescription = "Onyx"
return image
}
private func observeMenuBarPreference() {
guard let model else { return }
withObservationTracking {

View File

@@ -61,3 +61,6 @@ targets:
ENABLE_APP_SANDBOX: NO
ENABLE_USER_SCRIPT_SANDBOXING: NO
COMBINE_HIDPI_IMAGES: YES
# Icon-Composer-Bündel (Onyx/AppIcon.icon). actool übernimmt daraus
# alle Größen und die Transluzenz-Darstellung von macOS 26.
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon