Phase 5: Hardware- und Netzwerkmonitor, Panel und Menüleiste

Sechs neue Widgets (CPU, GPU, Speicher, Akku, Sensoren, Netzwerk) und dieselben
sechs als einzeln aktivierbare Menüleisten-Module mit fünf Darstellungsarten.

Panel-Widget und Menüleisten-Modul derselben Größe teilen sich die Messschleife
über Referenzzählung. Ohne das liefe für jede Anzeige ein eigener Timer mit
denselben IOKit- und SMC-Abfragen — bei sechs Modulen und ebenso vielen Widgets
ein Vielfaches der nötigen Arbeit. Meldet sich der letzte Konsument ab, hört die
Schleife auf; im Ruhezustand misst Onyx nichts.

Die Differenzrechnung ist testgetrieben, und die Tests haben zwei echte Fehler
gefunden. Erstens: mein Überlaufschutz beim Durchsatz hielt einen
zurückgesetzten Zähler (Interface-Wechsel) für einen Überlauf und zeigte
4,3 GB/s. Da if_data64 64-Bit-Zähler liefert, die bei 10 Gbit/s erst nach
470 Jahren umlaufen, ist ein kleinerer Wert immer ein Zurücksetzen — die
Unterscheidung produzierte nur den Ausreißer, den sie verhindern sollte.
Zweitens: ByteCountFormatter schrieb bei null „Zero KB/s" statt „0 KB/s".

Bei den CPU-Zählern bleibt der Überlaufschutz nötig: die sind 32 Bit breit und
laufen nach gut 400 Tagen wirklich um, deshalb `&-` statt `-`.

Sensoren kommen über den SMC-Leser aus Spike A statt über die private
IOHID-Schnittstelle — auf dieser Maschine nachweislich verifiziert, und die
dort gefundene Little-Endian-Eigenheit ist berücksichtigt. Nur eine kurze Liste
benannter Fühler statt aller 3486 Keys: eine Wand aus Kürzeln ist keine
Information.

Gegengemessen statt vermutet: 15 Kerne, 39,8 W, GPU 50 %, 16,6/24 GB mit
kritischem Druck, Akku 68 Zyklen bei 100 % Gesundheit, fünf Sensoren, zwei
Lüfter, en0 mit 661 KB/s.

Menüleisten-Module zeichnen in labelColor statt in den Onyx-Farben — nur die
Systemfarbe passt sich heller wie dunkler Leiste an. Feste Breite je
Darstellungsart, sonst schiebt jeder Messwert die halbe Leiste hin und her.

Standardmäßig ist kein Modul aktiv: sechs neue Symbole beim ersten Start wären
eine Zumutung.

145 Tests grün.
This commit is contained in:
Guido Schmit
2026-08-10 21:48:47 +02:00
parent a198d88104
commit 594d7c422a
21 changed files with 2897 additions and 350 deletions

View File

@@ -20,6 +20,8 @@
A529046C33E6B00C0E9508FF /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 508DECB5C05264E6130C373E /* Localizable.xcstrings */; };
B6CD48B41866A468AE7A1BC7 /* OnyxMenuBar in Frameworks */ = {isa = PBXBuildFile; productRef = A7FD7A4864E5ED4B95C211AF /* OnyxMenuBar */; };
C041F171FB69F4381309D978 /* AppModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B83C4E3CB821F903F3977E88 /* AppModel.swift */; };
C1F651D2BA69358344927F26 /* MetricsProvider in Frameworks */ = {isa = PBXBuildFile; productRef = 6CACA1C2A58DEFDE46F71499 /* MetricsProvider */; };
C390C5B65769A007A49C3A80 /* NetworkProvider in Frameworks */ = {isa = PBXBuildFile; productRef = FF4E99C8BF0D8944C314A8AF /* NetworkProvider */; };
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 */; };
@@ -53,6 +55,8 @@
CD501EBAE39807F5D354C5B2 /* CalendarProvider in Frameworks */,
5BE38CAFCDA4B9CBE787CABA /* WeatherProvider in Frameworks */,
1E2D654EFDDF55AEA75DBB7C /* MediaProvider in Frameworks */,
C1F651D2BA69358344927F26 /* MetricsProvider in Frameworks */,
C390C5B65769A007A49C3A80 /* NetworkProvider in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -135,6 +139,8 @@
A3E3949D664131D593CBEEDC /* CalendarProvider */,
D4578EB64F7A3372B49BC50C /* WeatherProvider */,
349226D70F51196CCD1C94F8 /* MediaProvider */,
6CACA1C2A58DEFDE46F71499 /* MetricsProvider */,
FF4E99C8BF0D8944C314A8AF /* NetworkProvider */,
);
productName = Onyx;
productReference = 0804288DC4A8146DD9F3FC3E /* Onyx.app */;
@@ -444,6 +450,10 @@
isa = XCSwiftPackageProductDependency;
productName = OnyxDesign;
};
6CACA1C2A58DEFDE46F71499 /* MetricsProvider */ = {
isa = XCSwiftPackageProductDependency;
productName = MetricsProvider;
};
A3E3949D664131D593CBEEDC /* CalendarProvider */ = {
isa = XCSwiftPackageProductDependency;
productName = CalendarProvider;
@@ -464,6 +474,10 @@
isa = XCSwiftPackageProductDependency;
productName = OnyxWidgetKit;
};
FF4E99C8BF0D8944C314A8AF /* NetworkProvider */ = {
isa = XCSwiftPackageProductDependency;
productName = NetworkProvider;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 32F5E88F3CF35AE8C0E00613 /* Project object */;