Projekte / FF00 Video Wallpaper Manager / Technischer Anhang
0.1.0-alpha.1 / quellcodegestützter Entwurfsnachweis
Warum der FF00 Video Wallpaper Manager so aufgebaut ist
Dieser Anhang beginnt bei den Grundlagen. Er soll ohne X11-Vorwissen lesbar bleiben und zugleich genügend genaue Grenzen, Codebeispiele und Kompromisse zeigen, damit auch erfahrene Linux-Nutzerinnen und -Nutzer die Entscheidungen prüfen können.
Kurz gesagt erstellt FF00-vwm für jeden zugewiesenen XRandR-Ausgang ein echtes X11-Desktopfenster, bettet je einen externen mpv-Prozess ein, speichert den Benutzerwunsch in TOML und protokolliert genügend Linux-Prozessidentität, um nur eigene Renderer zu beenden. Das GTK-Fenster ist ein Bedienfeld, nicht das Wallpaper. Es darf geschlossen werden.
Die Entscheidungen gelten innerhalb einer klaren Grenze: Linux x86_64, X11, lokale Dateien, ein Desktop-Benutzer und eine Alpha mit i3 als primär getesteten Fenstermanager. Kompromisse und offene Prüfpunkte bleiben sichtbar.
Zu den Beispielen: Die Ausschnitte erhalten das Verhalten der veröffentlichten Version, lassen aber teilweise Imports und wiederholte Fehlerumwandlung weg. Das markierte Repository bleibt massgebend.
1. Problem und Produktgrenze
Ein Standbild kann einmal gezeichnet werden. Ein Video-Wallpaper braucht einen Decoder, der laufend Bilder in einem Fenster darstellt, das der Fenstermanager als Hintergrund behandelt. Bei mehreren Bildschirmen ist der X11-Desktop ein gemeinsamer Koordinatenraum. Ausgänge links oder oberhalb des Ursprungs besitzen negative Koordinaten.
Der manuelle Prototyp verwendete xwinwrap. Dieses Werkzeug erstellt ein
Fenster und ersetzt je nach Variante einen Platzhalter durch dessen numerische
ID. Darum scheiterte --wid=WID: WID ist kein mpv-Schlüsselwort. Erreicht der
Text mpv unverändert, ist er zu Recht keine Ganzzahl.
FF00-vwm übernimmt deshalb nur den kleinen benötigten X11-Teil selbst. Enthalten sind lokale Dateien pro Ausgang, vier Skalierungsarten, stilles Endlosspiel, manuelles Aktualisieren, optionale X11-Anmeldewiederherstellung und gezieltes Beenden eigener Prozesse. Netzwerkquellen, Downloads, Audio, Wiedergabelisten, Zeitpläne, automatisches Hotplugging und Wayland bleiben ausserhalb der Alpha.
2. Prozessmodell
Die GUI besitzt das Wallpaper nicht. Für jeden Ausgang startet dasselbe Programm
seinen versteckten __renderer-Modus; jeder Renderer überwacht ein mpv-Kind:
ff00-vwm GUI oder `ff00-vwm apply`
+-- ff00-vwm __renderer --output DP-1 ...
| +-- mpv --wid=<Fenster-ID> ... video-a.mp4
+-- ff00-vwm __renderer --output HDMI-1 ...
+-- mpv --wid=<Fenster-ID> ... video-b.mp4So bleibt nur eine Binärdatei, aber eine echte Lebensdauergrenze. GTK kann geschlossen oder neu gestartet werden, ohne gesunde Wallpaper zu beenden. Mehr Prozesse verbrauchen etwas Speicher, machen Eigentum und Fehler pro Ausgang aber klarer als ein einziger grosser GUI-Prozess.
3. Warum zuerst X11
X11 erlaubt einem Client, ein Kindfenster des Root-Fensters zu erzeugen, globale Koordinaten zu wählen und Window-Manager-Hinweise zu setzen. Wayland verbietet willkürliche globale Platzierung bewusst; dort hängt Wallpaper-Verhalten von Compositor-Protokollen wie Layer-Shell ab.
Eine angeblich gemeinsame Abstraktion würde den wichtigsten Unterschied verdecken: Wer besitzt Platzierung und Ebene? Eine spätere Wayland-Unterstützung muss deshalb ein eigener Renderer mit benannten, getesteten Protokollen sein. Ein gewöhnliches XWayland-Fenster wäre kein ehrliches Wayland-Wallpaper.
4. Wallpaper-Fenster ohne xwinwrap
Der Renderer erstellt ein X11-INPUT_OUTPUT-Fenster direkt unter dem Root. Die
Geometrie entspricht dem aktuellen Ausgang. override_redirect verhindert die
Behandlung als normales i3-Fenster.
let attributes = CreateWindowAux::new()
.background_pixel(screen.black_pixel)
.border_pixel(screen.black_pixel)
.override_redirect(1)
.event_mask(EventMask::STRUCTURE_NOTIFY);Zusätzlich setzt er _NET_WM_WINDOW_TYPE_DESKTOP, sticky, skip-taskbar und
skip-pager, bildet das Fenster ab und fordert die unterste Stapelposition an.
Diese Signale überschneiden sich absichtlich: Override-redirect sorgt unter i3
für die Platzierung, EWMH erklärt anderen X11-Werkzeugen die Rolle. Kein Hint
garantiert identisches Verhalten auf jedem WM; deshalb wird kein universeller
X11-Support behauptet. Schwarz als Anfangshintergrund verhindert undefinierte
Pixel vor dem ersten mpv-Bild.
5. Direkte XRandR-Abfrage und vorzeichenbehaftete Geometrie
x11rb spricht das RandR-Protokoll direkt an. Menschenlesbare und eventuell
lokalisierte xrandr-Ausgabe wird nicht geparst.
let reply = connection.randr_get_monitors(root, true)?.reply()?;
let monitor = Monitor {
name: atom_name(&connection, monitor.name)?,
width: u32::from(monitor.width),
height: u32::from(monitor.height),
x: i32::from(monitor.x),
y: i32::from(monitor.y),
primary: monitor.primary,
};x = -1920 ist gültig und wichtig. Vor dem Übergang in die 16-Bit-Felder des
X11-Protokolls werden Grenzen geprüft; ein nicht darstellbarer Wert erzeugt
einen Fehler statt Überlauf.
Gespeichert wird der Ausgangsname wie DP-1, nie die Koordinate. Beim Anwenden
wird die aktuelle Topologie neu gelesen. Ein abgetrennter Ausgang wird
übersprungen, aber seine Zuweisung bleibt bestehen. Docks oder Treiber können
Namen ändern; EDID-Identität wäre eine spätere Entscheidung mit eigenen
Mehrdeutigkeits- und Datenschutzfragen.
6. Warum mpv ein externer Prozess bleibt
FF00-vwm implementiert keinen Decoder. mpv besitzt bereits Codec-, Hardware-, Farb- und Darstellungslogik. Das externe Programm hält die native Grenze sichtbar und lässt Distributionen Codec-Sicherheitsupdates liefern. libmpv würde Prozesse sparen, aber API-Oberfläche und Decoder-Lebensdauer enger an die Rust-Anwendung koppeln.
mpv --wid=4194305 --loop-file=inf --no-audio ... -- /pfad/video.mp4Die Fenster-ID ist beim Start konkret. Ein Prozess pro Ausgang kostet Speicher, isoliert dafür defekte Dateien und beendet nicht automatisch andere Ausgänge.
7. Argumentsicherheit
Der Dateipfad wird nie in einen Shell-String eingebaut:
Command::new("mpv")
.arg(format!("--wid={window}"))
.args(common_mpv_arguments())
.args(mode_arguments(mode))
.arg("--")
.arg(&video_path)
.spawn()?;Leerzeichen, Unicode, Anführungszeichen, Semikolons oder $() bleiben Teil des
Dateinamens. -- beendet die Optionsauswertung, damit ein Dateiname mit -
nicht zur mpv-Option wird. Vor dem Ersatz eines Renderers muss der Pfad eine
normale Datei sein. mpv muss die Datei weiterhin sicher decodieren; die Grenze
verhindert zusätzliche Shell-Injektion, nicht jeden Codec-Fehler.
8. Vier Skalierungsarten
| Modus | mpv-Politik | Ergebnis |
|---|---|---|
| Fit | Seitenverhältnis, panscan 0 | Ganzes Bild, eventuell Balken. |
| Fill | Seitenverhältnis, panscan 1 | Fläche gefüllt, Rand beschnitten. |
| Stretch | Seitenverhältnis aus | Exakte Fläche, mögliche Verzerrung. |
| Center | unskaliert | Native Grösse und Zentrierung. |
Fill ist Standard, weil ein Wallpaper meist die gesamte Fläche bedecken soll. Die Wahl bleibt sichtbar. Audio, OSC und Eingabebindungen sind deaktiviert, damit der Hintergrund nach der Anmeldung weder spricht noch wie ein normaler Player reagiert.
9. Lebensdauer, Bereitschaft und Überwachung
Ein erfolgreicher Prozessstart beweist noch kein sichtbares Wallpaper. Der Renderer erstellt das Fenster, startet mpv, wartet 300 ms auf unmittelbares Scheitern und schreibt danach die Fenster-ID in eine temporäre Ready-Datei. Der Elternprozess wartet höchstens fünf Sekunden.
Elternprozess Renderer mpv
| neue Prozessgruppe | |
|-------------------------->| X11-Fenster erstellen |
| | --wid=<id> starten |
| |------------------------>|
| höchstens 5 s warten | Prozess prüfen |
|<--------------------------| Ready-Datei schreiben |
| Eigentum erfassen | Kind überwachen |Die Datei ist nur ein Treffpunkt und wird entfernt. Ein Socket könnte später reichere Diagnosen übertragen. Das Fünf-Sekunden-Limit verhindert dauerhaft hängende Bedienung; abgetrennte Ausgaben bedeuten derzeit weniger Detail in der GUI.
10. Prozesseigentum und sicheres Beenden
pkill mpv würde auch einen normalen Film des Benutzers beenden. Eine PID
allein genügt wegen Wiederverwendung ebenfalls nicht. Der Renderer führt eine
eigene Prozessgruppe; mpv bleibt darin. Gespeichert werden Protokollversion,
PID, Gruppen-ID, Kernel-Startzeit, ausführbare Datei, Ausgang und Geometrie.
Protokollversion stimmt
/proc/<pid>/stat-Startzeit stimmt
/proc/<pid>/exe entspricht der erwarteten ff00-vwm-DateiErst dann geht SIGTERM an die Gruppe. Nach zwei Sekunden folgt nur bei erneut
bestätigtem Eigentum SIGKILL. Veraltete Einträge werden verworfen. Der manuelle
Test, dass ein fremdes mpv --idle Stop überlebt, prüft genau diese Grenze.
11. Lesbare, atomare Konfiguration
version = 1
restore_on_login = false
[outputs.DP-1]
video = "/home/user/Videos/ambient loop.mp4"
mode = "fill"TOML passt zu kleinem, von Menschen prüfbarem Zustand. Eine BTreeMap liefert
deterministische Reihenfolge. Eine unbekannte Schema-Version wird abgelehnt,
statt ihre Bedeutung zu erraten. Koordinaten fehlen absichtlich, da XRandR sie
aktuell liefert.
Beim Speichern entsteht zuerst eine temporäre Datei im selben Verzeichnis. Nach Schreiben und Synchronisieren ersetzt sie atomar das Ziel. Ein Absturz soll die alte vollständige Datei hinterlassen, nicht ein halbes TOML-Dokument.
12. Flüchtiger Laufzeitstatus
Prozesseigentum liegt unter $XDG_RUNTIME_DIR/ff00-vwm/state.json. Der
benutzer- und sitzungsbezogene Ort verschwindet üblicherweise beim Neustart;
alte PIDs dürfen danach keine Autorität besitzen. JSON erleichtert Diagnose,
ist aber weder Sperre noch Beweis. Nach jedem Laden folgt erneute Identitätsprüfung.
13. GTK4 als dünne Oberfläche
GTK4 liefert native Widgets, Tastaturverhalten, Barrierefreiheitssemantik und Desktop-Integration. Callbacks bauen jedoch keine Shell-Kommandos, parsen keine XRandR-Ausgabe und signalisieren keine beliebigen PIDs. Sie ändern typisierte Konfiguration und rufen Kernfunktionen auf.
Rc und RefCell genügen dem einzelnen GTK-Hauptthread. Ein Async-Runtime oder
grosses State-Framework würde derzeit Komplexität ohne gelöstes Problem bringen.
Automatische RandR-Ereignisse könnten diese Entscheidung später verändern.
14. Dateiauswahl an das System delegieren
FileChooserNative übernimmt Navigation, Mounts, Lesezeichen und Tastaturzugriff.
Ein Video-MIME-Filter hilft, All Files bleibt wegen unvollständiger MIME-Daten
erhalten. Auswahl ändert nur den Entwurf; erst Apply startet. So ersetzt ein
versehentlicher Klick nicht sofort das laufende Wallpaper.
Ein eigener Dateimanager wäre keine kleine Funktion, sondern eine schlechte Neuentwicklung von Berechtigungen, Wechselmedien, Suche und Barrierefreiheit.
15. Fehlerisolation pro Ausgang
Jede Zuweisung wird unabhängig angewendet. Abgetrennte Ausgänge werden übersprungen; Fehler werden gesammelt, während andere Ausgänge weiterlaufen. Apply All kann teilweise erfolgreich sein und trotzdem einen Gesamtfehler melden. Später sollten strukturierte Resultate pro Ausgang erscheinen.
Heute wird der alte Renderer vor bestätigter Bereitschaft des neuen beendet. Das verhindert zwei konkurrierende Desktopfenster, kann bei defektem Ersatz aber kurz Schwarz hinterlassen. Ein transaktionaler Wechsel ist sinnvolle Folgearbeit.
Eine weitere Alpha-Unschärfe betrifft die Oberfläche: Apply innerhalb einer
Monitor-Karte ruft den gemeinsamen save_and_apply-Pfad auf. Dieser führt
apply_saved für alle gespeicherten und verbundenen Ausgänge aus. Die Meldung
nennt nur den Ausgang der Karte, andere konfigurierte Ausgänge können aber
ebenfalls neu gestartet werden. Die Kernlogik isoliert Fehler weiterhin pro
Ausgang; später muss die Schaltfläche entweder wirklich einzeln arbeiten oder
klarer beschriftet werden.
16. Opt-in-Anmeldewiederherstellung
Installation aktiviert nichts automatisch. Der Schalter schreibt einen
XDG-Autostart-Eintrag mit absolutem, korrekt maskiertem Pfad und apply.
[Desktop Entry]
Type=Application
Name=FF00-vwm
Exec="/absoluter/pfad/ff00-vwm" apply
Terminal=false
X-VideoWallpaperManager-Owned=trueDer Eigentumsmarker verhindert Überschreiben oder Löschen einer fremden Datei. Echte Wiederherstellung hängt weiterhin vom XDG-kompatiblen X11-Sitzungsstart ab und bleibt deshalb ein ausdrücklicher Alpha-Prüfpunkt.
17. CLI und Fehleroberfläche
ff00-vwm apply
ff00-vwm refresh
ff00-vwm status
ff00-vwm stopApply und Refresh lesen die Topologie neu und wenden gespeicherte Absicht an. Status zeigt mpv, Konfigurationspfad, Login-Option, Ausgänge, Zuweisungen und aktive Renderer. Der versteckte Renderer ist internes Protokoll, keine stabile CLI. Fehlercodes unterscheiden Abhängigkeit, Display, Konfiguration und Laufzeit, damit Skripte keinen englischen Text parsen müssen.
18. Abhängigkeitspolitik
Rust-Abhängigkeiten sind gesperrt. Wildcards, unbekannte Git-Quellen und nicht
erlaubte Lizenzen werden abgelehnt. cargo audit prüft Advisories; cargo deny
prüft zusätzlich Lizenzen und Quellen. mpv unter 0.36.0 wird abgelehnt; über der
höchsten getesteten 0.41.0-Version wird es zugelassen, aber ehrlich als neuer als
getestet bezeichnet. Es gibt keinen Laufzeit-Updater.
19. Nix und native Paketierung
Der gesperrte Nix-Flake ist die Referenz. Er baut Rust, installiert Desktopdatei
und Icon und stellt getestetes mpv im Laufzeit-PATH bereit. Das native
x86_64-Archiv nutzt Debian 12 als Basis und installiert gewöhnlich nach
~/.local; mpv, GTK und X11 werden nicht gebündelt.
Diese Bibliotheken haben eigene Sicherheitszyklen. Bündelung würde die Alpha für veraltete Codecs und ABIs verantwortlich machen. Nativ ist konventionell, aber weniger portabel; Nix ist reproduzierbarer. Sortierte Archive, Commit-Zeitstempel und timestamp-freies gzip reduzieren variable Ausgabe. SHA-256 prüft Integrität aus einem vertrauenswürdigen Kanal, ist aber keine Signatur der Maintainer-Identität.
20. Installations- und Deinstallationssicherheit
Der Installer verlangt ein absolutes Präfix und verweigert /, das Home selbst
und Zeilenumbrüche. Vor Kopien müssen alle erwarteten Archivdateien existieren.
Fehlendes mpv erzeugt eine Warnung; kein Paketmanager wird erraten oder mit
Rootrechten gestartet.
Die Deinstallation liest ein exaktes Manifest und bestätigt, dass jeder Pfad unter dem Präfix liegt. Nur diese Dateien und danach leere Verzeichnisse werden entfernt. Konfiguration und Videos gehören nicht zum Manifest.
21. Privatsphäre und Bedrohungsmodell
Es gibt keine Telemetrie, Konten, Kataloge, Downloads oder Netzwerkdienste. Die
App liest ausgewählte Dateien, X11-Zustand, eigene XDG-Dateien und begrenzte
/proc-Identität eigener Prozesse. Dateinamen bleiben lokal, sind für andere
Prozesse desselben Benutzers aber nicht geheim.
X11 selbst isoliert Clients derselben Sitzung nur schwach. FF00-vwm repariert das nicht. Die engeren Versprechen sind prüfbar: keine Shell-Auswertung des Pfads, kein breites Töten, kein Überschreiben fremder Autostarts und kein versteckter Download.
22. Lizenz- und Beitragsgrenze
Der öffentliche Strom steht unter AGPL-3.0-or-later; Hinweise und
Abhängigkeitslizenzen werden mitgeliefert. Das Projekt ist unabhängig von mpv,
GTK, Rust, X.Org, i3, NixOS und Distributionen.
Beiträge verlangen eine separat ausgeführte Urheberrechtsübertragung. Damit bleibt zentrale Dual-Lizenzierung möglich, während der öffentliche Strom in der zugesicherten Copyleft-Grenze bleibt. Beitragende können diesen Tausch annehmen oder ablehnen; entscheidend ist die Veröffentlichung vor der Arbeit. Diese Erklärung ist keine Rechtsberatung, massgebend sind die Repository-Dokumente.
23. Nachweise, Tests und offene Punkte
Die Alpha bestand Formatierung, striktes Clippy, 17 Rust-Tests, Release-Builds, RustSec, cargo-deny, Nix-Flake-Prüfung, ShellCheck, actionlint, XML- und Privatsphäre-Scans, saubere Debian-Installation, exakte Deinstallation und Prüfsummen. Ein fremdes mpv überlebte den Stop-Test.
Getestet werden unter anderem vorzeichenbehaftete Geometrie, TOML-Roundtrip und
Schemaverweigerung, mpv-Versionsparser, Modusargumente, sichere Laufzeitnamen,
/proc-Startzeit, ungültige Dateien, JSON-Roundtrip und Autostart-Maskierung.
Offen dokumentiert blieben vollständige manuelle Nachweise für jeden Skalierungsmodus, den gesonderten Einzelmonitorfall, Schliessen/Öffnen mit Statusprüfung, abgetrennte Zuweisung, frischen echten X11-Login und die komplette Darstellung fehlender Datei oder Abhängigkeit. Ungeprüft bedeutet fehlender Nachweis, nicht automatisch bekannter Defekt. Genau deshalb heisst die Version Alpha.
24. Verworfene Alternativen
xwinwrap als Pflicht: Forks und Platzhaltersyntax unterscheiden sich; der benötigte X11-Teil ist klein genug für direkte Kontrolle.
Nur Shell: gut als Prototyp, aber Quoting, Teilfehler, Prozesseigentum, Persistenz und UI bilden schnell ein fragiles zweites Programm.
GUI besitzt Playback: würde Schliessen und GUI-Absturz zum Wallpaper-Ausfall machen.
mpv nach Name töten: Programmname beweist kein Eigentum.
xrandr-Text parsen: Präsentation ist kein stabiles Protokoll.
Eigener Dateimanager: dupliziert komplexes Desktopverhalten.
Alle Bibliotheken bündeln: verschiebt Codec- und ABI-Pflege zur kleinen Alpha; Nix bietet die reproduzierbare Alternative.
XWayland als Wayland-Wallpaper: löst die falsche Ebene nicht.
25. Nächste Arbeit
Zuerst sollten die manuelle Abnahmematrix, strukturierte Fehler pro Ausgang und transaktionaler Rendererwechsel abgeschlossen werden. Danach kann RandR- Ereignisüberwachung Dockwechsel verbessern.
Wayland braucht einen expliziten Backend-Entwurf mit benannten Compositoren. Weitere sinnvolle Arbeit umfasst EDID-Identität mit Datenschutzanalyse, maschinenlesbaren Status, Tastatur- und Barrierefreiheitsprüfung sowie signierte Release-Provenienz. Netzwerkmedien, Downloads, Audio und Zeitpläne bleiben eigenständige Produktentscheidungen.
aktuelle RandR-Ausgänge lesen
-> Topologie mit gespeicherter Absicht verbinden
-> je Zuweisung ein Desktop-X11-Fenster erstellen
-> stilles mpv mit konkreter Fenster-ID starten
-> begrenzt auf Bereitschaft warten
-> Linux-Prozessidentität erfassen und prüfen
-> auf Wunsch nur diese eigene Prozessgruppe beendenKeine Cloud, kein privilegierter Daemon und kein Shell-ausgewerteter Medienpfad verbergen sich dahinter. Übrig bleibt echte Desktopkomplexität. Sichtbarkeit dieser Mechanismen schafft mehr Vertrauen als ihre Auslassung.