Artikel mit Tag simdock
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
Monday, 19. July 2021
Neben IceWM ist der eigentliche Kern meines Linux-Desktops wahrscheinlich Simdock. Das kleine Dock habe ich vor ziemlich genau zehn Jahren adoptiert. Seine Daseinsberechtigung: Es macht die Fensterverwaltung einfach richtig und ist perfekt mit kleinen Fenstermanagern kompatibel (mehr dazu im Artikel).
Zwar halte ich das Dock am Laufen, aber das bedeutet eben nicht konstante Weiterentwicklung. Da passierte am Anfang mehr, als das Programm erstmal in Form gebracht werden musste. Allerdings kann Software immer verbessert werden, wie ein kürzlich eingegangener Pull-Request auch zeigte – perfekt ist gar nichts. Für Simdocks Weiterentwicklung habe ich sogar ein paar Ideen. Um die zu sammeln habe ich auf Github ein Projekt erstellt:
Da sind kleinere Verbesserungen dabei, die wirklich machbar wären, wie das verbesserte Klick-Feedback. Und Großprojekte wie die Waylandunterstützung, die wahrscheinlich nicht ansatzweise realistisch ist. Aber wer weiß, vielleicht geht es ja doch, und perspektivisch könnte sie beim zwanzigjährigen Jubiläum der Software (seit meiner Übernahme) notwendig geworden sein.
Ideen zu haben ist zwar nicht das gleiche wie sie umzusetzen, was natürlich am meisten wert wäre. Aber sie könnten als Ankerpunkt für zukünftige Arbeiten dienen, sei es von mir oder von anderen.
Wer Interesse an alternativer Linux-Desktopsoftware und am Perfektionieren eines Docks hat sei daher eingeladen, einen Blick auf Simdock selbst und auf diese Ideen zu werfen. Vielleicht ist ja etwas dabei, was für einen der Leser hier interessant und von ihm umsetzbar wäre.
Simdock 1.5.2 repariert und verschönert
Friday, 11. May 2018
Simdock ist das von mir adoptierte Dock, das Programmstarter und Fensterverwaltung kombiniert sowie bereits gestartete Fenster beim Klicken auf die Programmicons so durchschaltet, dass man alle verschiedenen Fenster eines einzelnen Programms aufrufen kann, ohne jedes einzeln im Dock haben zu müssen. Es unterstützt zudem Pseudo-Transparenz, was bei meinem Fenstermanager einen Bug umgeht und Systemen zugute kommt, die keinen Compositor laufen lassen können.
Mir ist immer noch nicht klar, warum genau simdock heute nicht mehr funktionierte. Aber dem war so: Nach meinem Upgrade auf Funtoo 1.2 startete mein Lieblingsdock nicht mehr. Beim Versuch das zu debuggen musste ich dann feststellen, dass auch das Kompilieren nicht mehr ging.
Das Makefile zu reparieren war die erste Aufgabe. Ich machte es mir einfach und spielte das ursprüngliche simple Makefile wieder ein, auf das ich damals so stolz war. Es hat zwar das Problem, bei jeder Änderung das ganze Programm neu zu kompilieren, aber es funktionierte damals wie heute zuverlässig.
Doch warum ging das Programm nicht mehr? Auch das habe ich nicht genau rausbekommen, aber nun in der Lage simdock mit neuen Debug-Ausgaben zu bauen konnte ich die Stelle eingrenzen. Diese Codezeilen waren das Problem:
wxSVGDocument* svgDoc = new wxSVGDocument; svgDoc->Load(path);
Dort wird versucht ein SVG zu laden, und genau so ging das bisher. Irgendwas im Zusammenspiel der neuen Versionen meiner Systemlibraries scheiterte nun. Ich öffnete einen Bugreport und wechselte gleichzeitig zur librsvg. Das ist ein Gnome-Projekt mit einer simplen API, die ich erst nicht verstand und an dessen fehlenden Tutorials ich erstmal verzweifelte. Dann aber wurde mir klar, dass die librsvg mir mit zwei Befehlen aus der SVG-Datei ein Pixbuf machen konnte, wobei mir bekannt was dass man daraus ziemlich einfach ein wxImage erstellen kann, und genau das war mein Ziel.
Das alles hat den Vorteil, dass wxSVG sowieso aus den Ubuntu-Paketquellen verschwunden war und es deswegen schon länger kein PPA-Paket für neue Ubuntuversionen gab. Deren Kompilierung sollte jetzt wieder anlaufen.
Nachdem simdock nun wieder so funktionierte wie zuvor fand ich dann zusätzlich noch einen Weg, Anti-Aliasing zu aktivieren. Ich kam darauf, weil ich mir von dem Wechsel zu librsvg auch schöner gerenderte Programmicons erhofft hatte, dem aber nicht so war. Dabei wurde mir klar, dass das Problem das Zeichen der Bitmaps auf die Programmoberfläche ist. Die Dokumentation von wxWidgets ist immer noch viel zu spärlich, aber durch Posts wie diesen konnte ich mir dann doch zusammreimen, dass man zwischen das wxDC
(dem Canvas, auf das bisher gezeichnet wurde) ein wxGraphicsContext
schieben kann, das insbesondere Anti-Aliasing unterstützt, und dieses wxGraphicsContext
kann dann wieder einem wxGCDC
übergeben werden, das sich dann wie ein wxDC mit Anti-Aliasing verhält. Im Ergebnis sind die Programmicons im Dock nun weniger pixelig, auch wenn sie nicht in der Originalgröße gezeichnet oder wenn sie gerade vergrößert werden.
Schön an der ganzen Aktion ist nicht nur, dass die Icons jetzt grundsätzlich besser aussehen sollten. Sondern dass ich schon vorher über Systeme gestolpert war, auf denen simdock einfach nicht startete. Eventuell sind die schon damals in den wxSVG-Bug gelaufen und würden jetzt funktionieren.
Simdock 1.5.2 kann vielleicht bald wieder über das PPA bezogen werden, ich habe gerade den Import angestoßen und bin gespannt ob es klappt. Das Gentoo/Funtoo-Overlay konnte ich schon testen, bei mir funktionierte es.
Simdock 1.5: Vektorgrafiken
Thursday, 24. March 2016
Gestern habe ich Version 1.5 von simdock veröffentlicht.
Die große Neuerung ist die Unterstützung von Vektorgrafiken. Im Bildschirmfoto hierdrüber sind Icons aus dem Iconset Numix-Circle zu sehen, das zumindest für mein System ausschließlich mit SVG-Dateien ausgeliefert wird. Darüber stolperte ich in letzter Zeit mehrfach. Simdock aber konnte nur klassische Bildformate einbinden, für Icons waren das immer PNGs. Jetzt funktionieren auch SVGs. Leider kann wxWidgets die noch nicht nativ zeichnen. Die Vektorgrafiken werden daher intern von wxsvg zu wxBitmaps umgewandelt.
Starter bleiben nun bei den ihnen zugewiesenen Icons. Simdock hat ja das Feature, automatisch das Icon im Dock zu wechseln wenn das gerade fokussierte Fenster einer Anwendung ein anderes Icon hat. Das ist praktisch, aber da diese Anwendungsicons nicht immer hübsch sind, und nicht in guter Qualität zurückgegeben werden, sieht das nicht gut aus. Für Starter ist das daher nun deaktiviert, Tasks (Icons für Anwendungen, die keine Starter sind) wechseln aber weiterhin. Sie brauchen das, damit z.B. das kaputte Icon des Splashfensters von Eclipse nicht dauerhaft als Icon gewählt wird.
Ansonsten wurde ein Bug gefixt, sodass Klicks mit der mittleren Maustaste wieder neue Instanzen einer Anwendung starten. Das wurde auch durch einen neuen Toleranzbereich erleichtert, in dem Bewegen der Maus bei gedrückter mittlerer Maustaste noch nicht als Verschieben des Docks gewertet wird.
Technisch schon in einem Zwischenrelease enthalten, aber hier noch nicht erwähnt: Die unterstütze wxWidgets-Version ist nun 3.0. Das erleichtert die Nutzung unter aktuellen Distros wie Funtoo, aber sollte auch unter Ubuntu keine Problem bereiten. Die Builddateien wurden entsprechend angepasst.
Ich bin bisher sehr zufrieden mit diesem Release. Es lief bei mir bisher absolut stabil, und mit den Änderungen sieht simdock gleich besser aus. Insgesamt freut es mich, wie sich das Dock derzeit anfühlt, und auch mit dem Code komme ich inzwischen besser zurecht. Die Änderungen dieses Releases waren angenehm einfach umzusetzen.
Für Ubuntu gibt es ein PPA, für Gentoo und Funtoo ein overlay. Natürlich kann simdock auch manuell kompiliert werden.
Simdock und die richtige Animation
Tuesday, 3. June 2014
Fährt man mit der Maus über die Icons in simdock, vergrößern sich diese in einer Animation. Ich fand das damals ganz nett und habe es drin gelassen, immerhin sieht man so schnell, welches Programm durch einen Klick ausgewählt würde, und es ist deaktivierbar.
Als ich dann später den Code etwas besser überschaute sah ich, dass das geschickt umgesetzt ist: Bei jeder Bewegung des Mauszeigers wird die Distanz zu seinem Mittelpunkt berechnet und die Größe je nach Distanz gewählt. Diese Zoom-Funktion hat einen hübschen Verlauf:
double zoom (int stand_dev, float dist_center, int maximum_size) { return maximum_size * exp (-pow (dist_center, 2) / pow (stand_dev, 2)); }
Für mich sieht das wie eine schöne Animationskurve ist.
Es gab nur ein Problem: Den Mousemove-Event für die Animation mitzubenutzen ist eine naheliegende Lösung, die durch den gesparten Thread/Timer Code und durch wenige geworfene Events CPU spart, dabei vom Nutzer gut zu kontrollieren ist und hinreichend gut aussieht - sie sieht aber eben auch nur hinreichend gut aus. Selbst, nachdem ich die Icongrößenberechnung und Positionsbestimmung so umgeschrieben hatte, dass sich Icons sowohl nach links und rechts (und nicht nur nach rechts) erweitern - was das Bild beruhigen sollte - blieb die Animation immer noch etwas hakelig. Eben genau dann, wenn der Mauszeiger etwas hakelig bewegt wurde, besonders im Grenzbereich zwischen den Icons und beim Sprung von der vorherigen zur Maximalgröße.
So sah es vor dieser Änderung aus:
So mit:
Besser, aber immer noch hakelig. Das Icon selbst, das vergößert wird, ist meist ok. Aber besonders die weiter entfernten Icons und Aktivitätsmarker ruckeln ein bisschen sehr hin und her.
Meine momentane Lösung ist, die Animation von der Mausbewegung zu entkoppeln. In einem Timer, der alle alle 32ms feuert, werden gehoverte Icons animiert vergrößert und die anderen falls nötig ebenso verkleinert, alles unabhängig von der Distanz zum Iconcenter. Das brauchte ein bisschen Optimierungsarbeit, um sauber zu funktionieren und nicht zu viel CPU zu fressen, und man kann sicher noch viel verbessern. Aber bisher bin ich ganz zufrieden.
So sieht die neue Animation aus:
Auf mich wirkt das wesentlich flüssiger, auch wenn ich noch etwas Zeit brauchen werde, um die geringere Kontrolle über die Animation zu verdauen. Netter Nebeneffekt des ganzen ist, dass - entgegen meiner Erwartung und von mir erst nachträglich entdeckt, ich musste diesen Artikel deswegen ein bisschen umschreiben - die CPU-Belastung durch die neue Animation sinkt. In der ersten Variante ging sie während der Animation bis auf 70% hoch, je nach Mauszeigergeschwindigkeit, hiermit pendelt sie auf meinem System unabhängig von der Zeigergeschwindigkeit bei 20%. Das ist immer noch viel, eigentlich zu viel, aber es ist trotzdem besser als vorher.
PPA für simdock
Saturday, 17. May 2014
Es gibt jetzt ein PPA für simdock. Statt Kompilieren zu müssen geht die Installation nun mit:
sudo add-apt-repository ppa:onli/simdock sudo apt-get update sudo apt-get install simdock
Ich hoffe, dass die Abhängigkeiten passen, getestet sind sie unter precise. Aber für trusty sind ein paar Abhängigkeiten bereits angepasst.
Meine PPA-Anleitung musste ich an zwei Stellen leicht korrigieren, aber ansonsten passte sie auch für ein Program mit Kompilierung.
Simdock: xcb und wnck statt Xlib
Thursday, 15. May 2014
Simdock ist nicht perfekt. Ich mag immer noch, dass die Transparenz auf meinem System funktioniert und wie es die Fenster einzeln durchgeht. Aber eines der Probleme ist, dass es gelegentlich abstürzt(e), ohne jegliche Fehlermeldung. Ich habe daher nicht herausgefunden, woran das liegt. Aber ich hatte ein bisschen Code in einer xstuff.cc, den ich weder verstand noch schön fand. Dieser nutzte die Xlib - und dafür gibt es mit xcb eine Alternative, die bei Fehlern etwas seltener das Programm mitreißen sollte.
Warum überhaupt eine X-Library?
Berechtigte Frage. Simdock nutzt eigentlich wxWidgets, eine C++-Multipalttform-Library. Für die eigentliche Fenstererstellung funktioniert das auch ganz gut. Aber ein Dock muss Sachen machen, die andere Programme nicht tun müssen, die näher an der Aufgabe eines Fenstermanagers sind - beispielsweise Fenster anderer Programme aktivieren. Das kann wxWidgets nicht, oder zumindest ist es nicht so dokumentiert, dass ich es finden würde. Die xstuff.cc hatte diese Funktionen (und ein paar Helfer):
void xstuff_raiseWindow unsigned int xstuff_getWindowPID bool xstuff_resizeScreen void xstuff_set_wmspec_strut bool xstuff_setDock
Vorgehen
Man findet zu xcb viel weniger Dokumentation als ich gedacht habe, insbesondere viel weniger Codebeispiele. Was existiert ist aber wenigstens meist hilfreich. So auch MixingCalls, der Hinweis, dass man bestehenden Xlib-Code einfach mit xcb mischen kann. Genau das machte ich beim Ersetzen der xstuff_setDock
, die _NET_WM_WINDOW_TYPE
auf _NET_WM_WINDOW_TYPE_DOCK
setzen soll. Vorher sah die so aus:
/* Stolen from gnome-panel */ bool xstuff_setDock (Display * xdisplay, Window winID) { if (winID == 0) return false; if (!xdisplay) return false; Atom a[2] = { None, None }; a[0] = XInternAtom (xdisplay, "_NET_WM_WINDOW_TYPE_DOCK", FALSE); Atom a2 = XInternAtom (xdisplay, "_NET_WM_WINDOW_TYPE", FALSE); XChangeProperty (xdisplay, winID, a2, XA_ATOM, 32, PropModeReplace, (unsigned char *) a, 1); return true; }
Und danach so:
bool xstuff_setDock (Display * xdisplay, Window winID) { if (winID == 0 || !xdisplay) { return false; } xcb_connection_t *c = XGetXCBConnection(xdisplay); xcb_ewmh_connection_t EWMH; xcb_intern_atom_cookie_t *EWMHCookie = xcb_ewmh_init_atoms(c, &EWMH); if (! xcb_ewmh_init_atoms_replies(&EWMH, EWMHCookie, NULL)) { return false; } xcb_change_property(c, /* Connection to the X server */ XCB_PROP_MODE_REPLACE, /* Property mode */ winID, /* Window */ EWMH._NET_WM_WINDOW_TYPE, /* Property to change */ XCB_ATOM_ATOM, /* Type of the property */ 32, /* Format of the property (8, 16, 32) */ 1, /* Length of the data parameter */ &(EWMH._NET_WM_WINDOW_TYPE_DOCK)); /* Data */ return true; }
Es gibt hier drei Besonderheiten:
- Mit
XGetXCBConnection(xdisplay);
wird Display* von Xlib in xcb als connection benutzt. - xcb reichte nicht aus, weil das
_NET_WM_WINDOW_TYPE
nicht kennt. Man kann aber XInternAtom von Xlib benutzen. Ich habe stattdessen auf xcb_ewmh zurückgegriffen. xcb_ewmh_init_atoms_replies
ist von http://stackoverflow.com/a/13319374/2508518
Weitere Vereinfachungen
Im aktuellen Master ist die Funktion gleich verschwunden. Denn statt xcb gibt es noch eine Alternative: libwnck. Diese Lib nutzt simdock sowieso schon, und mit ihr geht das ganze so:
WnckWindow* window = wnck_window_get(winID); wnck_window_set_window_type(window, WNCK_WINDOW_DOCK);
Weil das ausreichend kurz ist, habe ich mehrere solcher Aufrufe in einer xstuff_setDefaultWindowFlags
kombiniert.
Doch auch für xcb gibt es noch Vereinfachungen, und zwar in xcb_ewmh. Dort sind einige Hilfsfunktionen definiert, mit denen Attribute leichter abgefragt und gesetzt werden können. Statt also mit xcb_get_property - ähnlich aufgebaut wie xcb_change_property - zu arbeiten, kann simdock die PID eines Fensters so erfragen:
unsigned int xstuff_getWindowPID(Window winID) { xcb_connection_t* conn = xcb_connect (NULL, NULL); xcb_ewmh_connection_t ewmh_conn; xcb_intern_atom_cookie_t* ewmh_cookie = xcb_ewmh_init_atoms(conn, &ewmh_conn); if(! xcb_ewmh_init_atoms_replies(&ewmh_conn, ewmh_cookie, NULL)) { return false; } uint32_t pid; xcb_ewmh_get_wm_pid_reply(&ewmh_conn, xcb_ewmh_get_wm_pid(&ewmh_conn, winID), &pid, NULL); xcb_disconnect(conn); return pid; }
Mit ein bisschen besserer Struktur (die connection müsste ja nicht in der Funktion erstellt werden) könnte das fast so simpel sein wie der Wnck-Weg.
Aktueller Stand
So bin ich Funktion für Funktion durch den Code gegangen und habe die Xlib durch xcb oder wnck ersetzt. Hat es was gebracht? Mir zumindest ist simdock bisher nicht mehr abgestürzt, aber das heißt natürlich noch nichts. Es wird sich mit der Zeit zeigen. Aber selbst wenn nun alles gut ist: Ich habe auch ein paar andere Ecken leicht verändert, z.B. die Größenberechnung von Icons und Programm, was auch geholfen haben könnte.
Aber ich glaube, dass schon die Codeersparnis bei weiteren Verbesserungen helfen wird. Und xcb bietet nette Möglichkeiten, Calls zum Xserver zu kombinieren, damit kann man sicher noch einiges verbessern.
pkg-config statt autoconf: Viel weniger Code
Wednesday, 7. May 2014
Als ich damals simdock übernommen hatte, konnte ich es zwar erweitern, Bugs fixen und das Ergebnis kompilieren, aber ich bin nie hinter das Buildsystem gestiegen. Ich bin ja kein C++-Programmierer, diese Welt war und ist mir fremd. Entsprechend wirr war das git-Repository… Ich habe durchaus versucht, das aus dem svn übernommene Chaos aufzuräumen, aber alle Dateien erschienen nötig, und da ich nach einem besonders beherzten Aufräumversuch nicht mehr Kompilieren konnte, machte ich ihn rückgängig und lies bis jetzt davon die Finger. Warum auch an einem funktionierendem System rumdoktorn, nur für die Ästhetik?
Jetzt wurde das dringend, denn unter Ubuntu 14.04 funktioniert die Kompilierung nicht mehr. Und um dort den Fehler zu finden, muss ich das Buildsystems verstehen und die Abhängigkeiten kennen. Daher habe ich das Makefile von izulu (bzw password-store) genommen und versucht, auf dessen Grundlage - ohne autoconf, ohne die herumfliegenden Installationsskripte, ohne Chaos - die Kompilierung neu einzurichten.
Hilfreich war da, dass ich inzwischen den Kompilierungsbefehl herausgefunden hatte. Doch den konnte ich ja nicht einfach ins Makefile schreiben, auf einem anderen System - 64-bit z.B. - würden die Pfade nicht passen. Das fehlende Werkzeug dafür war pkg-config, das mit pkg-config --libs --cflags Library
die Pfade und Flags für g++ erzeugen kann. Für wx kann wx-config das gleiche. Und kombiniert sieht simdocks Makefile nun so aus:
PREFIX ?= /usr DESTDIR ?= BINDIR ?= $(PREFIX)/bin APPDIR ?= $(PREFIX)/share/simdock ICONDIR ?= $(PREFIX)/share/pixmaps SRCDIR ?= src/ SHELL ?= /bin/sh CC ?= g++ CCFLAGS ?= -O2 DEPS = $(shell pkg-config --libs --cflags glib-2.0 gconf-2.0 gtk+-2.0 libwnck-1.0) DEPS += $(shell wx-config --cflags --libs) .PHONY: install uninstall all: $(CC) $(CCFLAGS) $(SRCDIR)*.cc $(DEPS) $(LDLIBS) -o simdock install: @install -d "$(DESTDIR)$(BINDIR)" "$(DESTDIR)$(APPDIR)" "$(DESTDIR)$(ICONDIR)" @install -m 0755 -v simdock "$(DESTDIR)$(BINDIR)/simdock" @install -m 0644 -v gfx/* "$(DESTDIR)$(APPDIR)/" @install -m 0644 -v gfx/simdock.png "$(DESTDIR)$(ICONDIR)/" uninstall: @rm -vf "$(DESTDIR)$(BINDIR)/simdock" "$(DESTDIR)$(APPDIR)/*" "$(DESTDIR)$(ICONDIR)/simdock.png"
Und das ist alles, ein configure gibt es nicht.
Das war eine größere und zeitraubende Aktion. Insgesamt - wobei viele der Dateien da nie reingehört hätten - konnte ich 70k Zeilen aus dem Repo entfernen, wodurch es nun von Github erstmals als C++-Projekt erkannt wird.
Hat jemand Verbesserungsvorschläge?
Simdocks Daseinsberechtigung
Sunday, 24. February 2013
Für heute hatte ich einen schönen Vorsatz: Finde einen Ersatz für Simdock, damit du das Projekt aufgeben kannst. Ich bin gescheitert.
Meine Anforderungen an ein Dock sind ziemlich simpel:
- Icons für gestartete Programme und Programmstarter anzeigen
- Diese minimieren können
- Mit Mittelklick neue Instanzen starten
- Einfache Konfiguration (eigentlich nur wichtig: "Im Panel behalten" als Option haben)
- Transparenz unterstützen
Nun ist es natürlich nicht so, dass es kein anderes Programm gäbe, das dem im Grunde gerecht wird. Aber alle scheitern an der Transparenz - bzw am Zusammenspiel mit compton.
Als mögliche Alternative zu Simdock kenne ich diese Programme:
- Plank
- Wbar
- Avant-Window-Navigator
- Cairo-Dock (Glx-Dock)
Insbesondere Plank ist ein guter Kandidat, Simdock zu ersetzen: Ähnlich schlicht, aktiver entwickelt und mit allen notwendigen und zusätzlich einer Autohide-Funktion. Der einzige Nachteil wäre, dass es keine Pseudotransparenz zu unterstützen scheint. Und ich mag Simdocks Feature, das Programmicon im Dock mit dem Fenstericon zu updaten, was Plank ebenfalls nicht zu können scheint, aber das wäre kein Ausschlusskriterium.
Doch trotzdem funktionieren weder Plank noch die anderen Docks für mich. Wbar ist generell kaputt, die Icons schlieren und es scheint keine Menüs zu haben. Die anderen drei kommen mit compton/xcompmgr nicht zurecht. Hier die Bilder:
Plank
AWN
Cairo-Dock
Sie alle scheitern daran, bei aktiviertem Compositor Transparenz so zu aktivieren, dass der leere Bereich echt transparent ist, bzw bei AWN an der Transparenz des Iconhintergrunds. Dies ist das gleiche Problem, welches ich damals schon hatte und mich überhaupt zum Schrauben am verlassenen Simdock bewegt hat. Damals war es allerdings eine andere Ubuntuversion und andere Hardware, ich habe nicht damit gerechnet, dass das Problem noch existiert.
Hintergrund
Ein Dock muss eigentlich keine echte Transparenz per Compositor unterstützen, da es sowieso nie Fenster hinter sich hat. Die Ausnahme dieser Regel ist die Autohide-Funktion: Wenn das Dock von Vollbild-Fenstern verdrängt wird und vom Bildschirmrand aus über das Vollbild-Fenster fährt, wenn es aktiviert wird. Plank verhält sich so und das ist eigentlich ein schönes Feature.
Ein Dock mit Autohide-Funktion kann also eine Compositor-Funktion gut gebrauchen, ein Dock ohne (wie Simdock) kann probemlos darauf verzichten.
Warum aber ist der schwarze Balken so viel größer als die Docks selbst, was ist der leere Bereich? Ich bin darauf gestoßen, als ich an Simdock gearbeitet habe. Grundsätzlich will ein Dock gerne in Bereiche zeichnen, die erstmal nicht direkt zum Dock gehörig sind. Beispielsweise den Programmnamen in einem Tooltip über den Icons anzeigen oder die Icons nach oben hüpfen lassen, aber ohne den Bereich für sich zu beanspruchen. Ohne in den Code geschaut zu haben gehe ich davon aus, dass Plank und Cairo-Dock sich einen entsprechend großen Bereich als Canvas sichern.
Das wollte ich für Simdock übrigens auch machen, zusätzlich zum bestehenden Fenster mit einer hübschen dafür gedachten Funktion, das hat aber ein wxWidget-Bug verhindert (es hatte schlicht keinen Effekt).
Es scheint nun so, als ob im Zusammenspiel mit AMD-Grafikkartentreibern und xcompmgr/compton die in diesen Docks verwendete Transparenz nicht funktioniert und der von ihnen registrierte Canvasbereich davon ebenfalls betroffen ist.
Simdocks Status
Das soll nicht heißen, dass Simdocks den anderen Docks grundsätzlich überlegen ist - ich bin im Gegenteil überzeugt davon, dass Plank in vielen Fällen eine bessere Wahl ist. Der Vorteil in diesem Fall rührt einfach aus der Beschränkung Simdocks auf Pseudotransparenz - der von Simdock verdeckte Bildschirmhintergrund wird per XServer-Funktion als Bild geholt und hinten eingefügt, was unabhängig vom Compositor zuverlässig zu funktionieren scheint.
Auf Simdocks Seite steht:
- Funktionierende Transparenz
- Menü mit ein paar grundlegenden Einstellungen
- Aktualisierung des Programmicons (wichtig bei Programmen mit Startern, wie Eclipse)
- "Im Starter behalten"-Funktion, zyklisches Minimieren und Öffnen der einzelnen Programmfenster, Instanzenstart per mittlerem Klick
Das sind rein zufällig die grundlegenden Features, die ich gerne in einem Dock hätte.
Gegen Simdock spricht natürlich auch einiges. Zum einen wird es nicht aktiv weiterentwickelt. Ich habe anfangs eingebaut, was ich haben wollte, und danach noch einzelne Bugs gefixt, aber bisher war es das. Zum anderen wird es wenn, dann von mir entwickelt. Das ist von Nachteil, weil ich normalerweise nicht an C++-Programmen arbeite - so gibt es immer noch einen Bug, der manchmal zu Abstürzen führt, der kein mir ersichtliches Schema hat und daher nicht von mir nachstellbar und fixbar ist. Und ich bin durch die nötige Speicherverwaltung schlicht daran gescheitert, Einstellungen on-the-fly übernehmen zu lassen (jemand Lust, mir einen entsprechenden Pull-Request zukommen zu lassen?). Außerdem ist die ganze Library- und Build-Umgebung unter C++ ein für mich schwer durchschaubares Wirrwarr und müsste sicher aufgeräumt werden.
Trotzdem: Für die eigene Desktopumgebung scheint Simdock derzeit meine einzige Wahl zu sein, will ich einen Compositor mit meiner AMD-Grafikkarte nutzen. Oder kennt jemand noch eine von mir übersehene Alternative?
Simdock weiterentwickelt
Thursday, 7. July 2011
Simdock ist ein ziemlich simples Dock für Linux. 2007 war der letzte Commit im svn, der Autor antwortet nicht auf Mails, das Projekt ist also tot. Simdock ist aber auch relativ hübsch und ausreichend und es war das einzige Dock, das mir Transparenz bot - die ganzen Compositing-Docks wie Cairo-Dock hatten bei mir nur einen schwarzen Hintergrund. Ausnahme war Kiba, das Pseudo-Transparenz simulieren kann, aber das stürzte wiederholt ab. Also wählte ich Simdock für meinen Desktop.
Tot wie das Projekt nunmal war fehlten dann aber doch ein paar Features, wie das Hinzufügen von Startern ohne Anpassen der Konfigurationsdatei. Vor allem aber war der Hintergrund an gconf gebunden, ein Wechseln des Desktophintergrunds ohne Änderung dort wurde nicht bemerkt, was ohne Gnome etwas unpraktisch ist. Daher habe ich das Projekt geforkt und versucht, die Mängel auszubessern. Zu finden ist das neue Simdock auf github.
Installation
Entweder man kompiliert es selbst:
Zuerst installiert man die Pakete libwxgtk2.8-dev libwxgtk2.8-0
Dann:
git clone git://github.com/onli/simdock.git cd simdock ./configure make sudo checkinstall oder sudo make install
Alternativ kann man unter 32-Bitsystemen auch dieses per checkinstall erstellte .deb versuchen:
Änderungen
- Statt gconf zu beobachten wird das Hintergrundbild von X direkt ausgelesen und Änderungen dort beobachtet
- Drag & Drop der Icons direkt aktiviert
- Tooltipps mit den Programmnamen beim Hovern der Icons
- Offene Programme können per Rechtsklick-Menü in einen Starter umgewandelt werden (wie bei Unity)
- Bugfix: Icons konnten verschwinden, wenn sie während des Verblassens angeklickt wurden
- Bugfix: Die id mancher Prozesse wurde nicht richtig gespeichert, sodass kein Icon gefunden wurde (z.B. Amarok)