Simdock jetzt mit Compositing und GTK3
Tuesday, 5. December 2023
Simdock ist mein Dock für den Linuxdesktop, das ich seit ein paar Jahren pflege. Jetzt konnte ich dem Code ein großes Update verpassen und damit das Projekt für die nächste Zeit absichern.
Kurzfassung
- Simdock läuft nun mit der GTK3-Version von wxWidgets, bei mir ist das das sehr neue wxWidgets-3.2.4. Dadurch wird es auch auf modernen Systemen wieder kompilieren.
- Durch den Wechsel zu GTK3 musste auch die genutzte Library Wnck aktualisiert werden, die Version 1 zuvor setzte auf GTK2, das kollidierte. Nebeneffekt davon ist, dass für die dynamischen Programmanzeigen größere Icons gewählt werden sollten.
- Dank der neuen Version von wxWidgets konnte durch wenige Codeänderungen Compositing für den Dockhintergrund aktiviert werden. Die Pseudotransparenz funktioniert weiterhin, wenn kein Compositor am Laufen ist.
- Es werden wieder AppImages gebaut. Die gab es für Simdock schonmal, die waren aber durch den Wegfall von Travis CI ausgefallen. Die AppImages hatten (zumindest aber auf meinem System) noch einen Bug mit dem neuen Compositing, mehr dazu unten.
Der allgemeine Hintergrund des Updates
Simdock lief die letzten Jahre relativ zuverlässig vor sich hin. Aber der Wechsel zu GTK3 war eine große Gefahr für die weitere Existenz des Projekts und die Migration jahrelang durch eine fehlende Funktion von GTK3 blockiert.
Nun war der Wechsel aber unumgänglich, es musste etwas passieren. Denn selbst auf meinem eigenen System konnte ich Simdock nicht mehr bauen. Void Linux hatte wxWidgets auf GTK3 umgestellt, ohne die GTK2-Version weiterhin bereitzustellen. Und das alte AppImage lief auch nicht, neue wurden sowieso nicht mehr gebaut. Ich rechnete eigentlich damit, das Projekt aufgeben zu müssen – und stolperte dann gestern doch über die Lösung.
Als Simdock vor ~2 Monaten für mich wegbrach hatte ich noch mit keiner Lösung gerechnet und mir stattdessen Alternativen angeschaut. Und tatsächlich auch gefunden: Plank ist mittlerweile eine hervorrage Alternative. Es fehlen die konfigurierbaren Starter, dafür kann es sich selbst verstecken (Auto-Hide) und und ist so platzsparend, außerdem hatte es schon lange echte Transparenz. Ich nutzte es mit Openbox und jetzt nochmal mit IceWM (da kollidierte es erst mit meiner Konfiguration, aber mit der Versteckenfunktion passte es). Die Existenz der Alternative war entspannend! Aber jetzt nachziehen zu können befriedigt dann doch meinen Ehrgeiz. Und es war die bessere Lösung in meiner derzeitigen Projektaufräumaktion, so statt dem Aufgeben genau wie bei izulu nach Jahren des Zeitmangels die Modernisierung umsetzen zu können.
Technische Erklärungen
Warum war der Wechsel zu GTK3 so problematisch? Es sollte überraschen, denn wxWidgets abstrahiert das Toolkit eigentlich weg, ob da jetzt GTK2, GTK3 oder gar QT läuft sollte egal sein. Gleichzeitig ist wxWidgets eines dieser großartigen Projekte, bei denen Upgrades generell schmerzlos sind, ich musste genau null Zeilen wxWidget-Code anpassen.
Das Problem war diese Funktion: gdk_pixmap_foreign_new()
. Simdock benutzte sie, um den Hintergrund des X11-Desktops zu holen und den dann als Hintergrund des eigenen Fensters zu setzen. Klassische Pseudotransparenz. Und für diese Funktion gibt es in GTK3 einfach keinen direkten Ersatz. Der Code sah leicht vereinfacht so aus:
wxBitmap* backImage = new wxBitmap(); WnckScreen *screen = wnck_screen_get_default (); // The XID of the background pixmap Pixmap pm = wnck_screen_get_background_pixmap(screen); if (pm != None) { wxBitmap* backImage = new wxBitmap( gdk_pixmap_foreign_new( pm ) ); return backImage; }
Da wurde also auch Wnck genutzt, dessen Details sich ebenfalls ändern würden, das verstellte weiter den Blick auf die Lösung. Es gibt einfach keinen dokumentierten Weg, die Pixmap des XServers mit GTK3 in ein Grafikobjekt zu quetschen um sie dann wxBitmap zu übergeben.
Stattdessen sah meine Lösung schließlich so aus:
wxSize sz = wxGetDisplaySize(); wxBitmap* backImage = new wxBitmap( gdk_pixbuf_get_from_window( gdk_x11_window_foreign_new_for_display( gdk_display_get_default(), gdk_x11_get_default_root_xwindow() ), 0, 0, sz.GetWidth(), sz.GetHeight() ) );
Das benutzt jetzt also GDK-Funktionen ohne den Wnck-Umweg. Und war nur möglich, weil ich mit der Hilfeseite zu X Window System Interaction endlich über die passende Dokumentation gestolpert war. Der Code holt sich das Root-XWindows mit gdk_x11_get_default_root_xwindow()
, macht daraus ein GDK-Window mit gdk_x11_window_foreign_new_for_display
und davon kann gdk_pixbuf_get_from_window
dann eine Grafik ziehen. Dass dadrin ebenfalls gdk_display_get_default
benutzt wird folgte direkt der Dokumentation.
Jedoch: Das ist nicht ganz das gleiche! Denn die Grafik beinhaltet auch alle offenen Fenster. Es ist eben nicht der X-Hintergrund, an den ist einfach nicht ranzukommen. Doch für Simdock war das gut genug: Normalerweise sind eh keine Fenster hinter einem Dock, und ich schaffte es, Simdock vor dem Ziehen dieses Screenshots auszublenden. Flickert ganz kurz, aber da das nur bei Hintergrundbildwechseln passiert sollte das okay sein.
Damit war die Makefile anpassbar. Wnck-3.0 und wxWidgets-GTK3 konnten ins Projekt, Simdock damit wieder auf modernen Systemen gebaut worden. Und die nächste langjährige Baustelle war angehbar.
Echte Transparenz mittels eines Compositors hätte das Problem mit der oberen schwierigen Umsetzung von Pseudotransparenz umgangen. Diese Transparenz sollte wxWidgets eigentlich können, es gibt mit wxBG_STYLE_TRANSPARENT
einen passenden setzbaren Hintergrund, der echte Transparenz bringen soll. Doch bei mir hatte das in vorherigen Tests nie geklappt.
Mit GTK3 und einer neuen Version von wxWidgets testete ich das erneut. Und tatsächlich: Es brauchte nur minimale Codeänderungen und die Transparenz lief direkt. Ein echter Durchbruch. Simdock soll weiterhin Pseudotransparenz unterstützen – das war das originale Alleinstellungsmerkmal des Programms, weswegen ich es überhaupt übernommen habe – aber echte Transparenz zusätzlich anbieten zu können ist super. Vor allem, wenn es jegliches Flickern vermeidet.
Die Lösung folgt genau der Dokumentation, wie ich sie vorher schonmal verlinkt hatte: Im Konstuktor des wxWindow, in diesem Fall dem wxFrame, SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
setzen und erst danach mit Create(parent, ...);
das Fenster erstellen. Vorher sah der Anfang des Konstruktors so aus:
MyFrame::MyFrame (wxWindow parent, simSettings set, ImagesArray array, wxWindowID id, const wxString & title, const wxPoint & pos, const wxSize & size, long style): wxFrame (parent, id, title, pos, size, style) { … SetBackgroundStyle(wxBG_STYLE_PAINT); }
Daraus wurde das hier:
MyFrame::MyFrame (wxWindow parent, simSettings set, ImagesArray array, wxWindowID id, const wxString & title, const wxPoint & pos, const wxSize & size, long style): wxFrame() { // This enables full composited transparency: SetBackgroundStyle(wxBG_STYLE_TRANSPARENT); Create(parent, id, title, pos, size, style); … }
Da veränderte sich also ebenfalls die Definition des Konstruktors, plus dem schnelleren Setzen von wxBG_STYLE_TRANSPARENT
vor dem Create
.
Ausstehende Probleme
Simdock hat relativ früh AppImages bereitgestellt. Ich war auf der Froscon in einem Vortrag des AppImage-Projekts und fand die Idee super. Die wurden aber die letzten Jahre nicht mehr gebaut, weil die Travis-CI nicht mehr kostenlos war.
Also stellte ich die Buildpipeline wieder her. Diesmal mit Github-CI, und weil linuxdeployqt einen Fehler produzierte wechselte ich zu linuxdeploy mit dem GTK-Plugin. Das funktionierte an sich! Aber: Das AppImage bleibt bei mir schwarz, wenn Compositing aktiviert ist.
Ich habe ein Issue dafür auf, in dem ich auch mehr der Details zu den AppImages erkläre. Den gewählten Ansatz finde ich wirklich geschickt, die Logik hauptsächlich in eine zweite Makefile zu packen. Das hält die Github-CI-Workflowdatei simpel. Aber das Ergebnis muss eben auch funktioniere. Bis sich da eine Lösung auftut werde ich das AppImage weiter bauen lassen, aber nicht bewerben.
Mit all den Änderungen hat Simdock technisch einen großen Schritt getan und ich freue mich, dass das möglich war. Es wäre zu schade gewesen, das Projekt wegen den GTK-Migrationsproblemen aufgeben zu müssen. Und wer ein nettes Dock mit gutem Fenstermanagement sucht, mit Plank aber aus irgendwelchen Gründen nicht warm wird, dem kann ich Simdock jetzt wieder guten Gewissens empfehlen. Die Installation per Kompilierung wird im Readme beschrieben.
- Ideen für Simdocks nächste Dekade
- Simdock 1.5.2 repariert und verschönert
- Simdock 1.5: Vektorgrafiken
- Simdock und die richtige Animation
- PPA für simdock