pcb-rnd knowledge pool
GTK4 rant: scrollbar gizmo is a css trick
gtk4r_css_gizmo by Tibor 'Igor2' Palinkas on 2021-12-23
Tags: insight, gtk4, rant, css, scrollbar, gizmo
This rant is part of a series.
Replacing the theme
Gtk used to have its own theme engine, because users wanted to have dark or light background, large font, etc. Somewhere during gtk3 they switched from this theme engine to css. This first sounds like a good idea: css is a well specified language and is widely used on the web. However, it has many shortcomings.
pcb-rnd top window is a complex set of widgets. The central piece is a drawing area with two scrollbar widgets. Because there are a lot of other widgets around, gtk4 is doing a lot of calculations to figure optimal size of each widget. Scrollbars need a size too.
There is a bug in gtk 4.4.0 which makes this size allocation fail, rendering the scrollbar unusable: the little slider is simply not drawn at all. There is also an error message about allocation fails for a GtkGizmo. Which was strange, as I never placed a Gizmo and honestly, I didn't have an idea what a Gizmo is. Gtk4 doc didn't help either. I had to dive down in gtk4 sources to figure, and I didn't like what I've found.
So I first tried to figure why the slider is not drawn. I thought it'd be easy: I just go there in the source, to the scrollbar implementation, and find the piece that actually draws the slider. Hah, my optimism! I spent about two hours looking for the code, through layers and layers of administrative code, functions that don't do anything useful just call through the mazes of OOP. I tried to look at it from many different directions and search keywords, but I just couldn't find any code that draws in the scrollbar implementation!
And then I figured: the slider is not drawn. At least not from code. What really happens is this:
- The scrollbar is a widget, which consists of the empty box, a rather boring background, specified by css
- The slider in it, actually called gizmo, is another widget and somehow the widget size allocation algorithm is used to calculate its placement within the scrollbar
- But the gizmo is not drawn, it's really an empty box; the only reason you see anything rendered is because a background is put on it from css! And that background happens to be a round rectangle of some color different from the background color of the scrollbar.
Now that explains all symptoms: the gizmo allocation failure error message indicated that it failed to calculate the initial size or position of the gizmo widget within the scrollbar widget. Once that happened, the gizmo disappeared (well, or it never really appeared in the first place). Once disappears, it never appears again.
The other problem is that what I really wanted to have is a simple widget that has a slider on it at a position I set and if the user moves the slider I get notified so I can update the drawing. Instead, gtk tries to provide a whole complicated, large OOP infrastructure to connect the scrollbar to scrollable widgets. Those connections are things I would have to work around even if scrollbar worked.
So my conclusion was to go for simplicity: instead of trying to work around the allocation problem of the embedded gizmo and the scrollable connections, I figured I just need a simple scrollbar that just draws a slider and doesn't try to be smart. I sat down and implemented that, and it took less time than figuring what a gizmo was and how ti was (not) drawn. The final custom scrollbar widget implementation is 210 sloc. Unlike gtk4's, it does only one thing, but it does that well.