Hire Me!

Gtk+ Theming Woes for Embedded GUIs

written by Mickey on 2006-10-28

In the project I'm working on, we want to have a visual user experience that is guaranteed to blow you away. Eye candy and usability combined. This is about eye candy.

In theory, the Gtk+ theming capabilities are good. In practice, it sucks. I won't go into complaining about the most underdocumented area of Gtk+, but if you want to attract commercial developers who need to rely on being productive and effective right from the start, then Gtk+ is giving you a lot of headaches.

The usage of X11 and Gtk+ as the GUI foundation for embedded devices is increasing steadily, however the Gtk+ theming possibilities are merely adressing the needs of desktop systems. Of course, I am not the first one realizing that. Nokia decided to fork Gtk+ for their Maemo UI -- between you and me, one of their worst decisions as developers really hate having to compile a seperate Gtk+ version for Maemo developing. Consequently, this is a no-no for our project.

The worst thing is that Gtk+ treats widgets (instead of images) as first class entities, that means it will scale your images according to the size request of the widgets, not vice versa. Widgets are scaled according to their layout and the internal widget layout and size -- which is defined through hardcoded widget code. If you don't let images to be stretched, they might be clipped (e.g. in a checkbox) or drawn partly outside the parent widget (e.g. for an arrow).

This scaling facility is nice for desktop systems, but in embedded systems this is a nuisance, because you usually

  1. know your display size in advance and want to have every pixel match the layout given by the designer, and
  2. the display size rarely changes (only few people use their mobile phone applications to display via remote-X).

Another requirement is overlapping widgets. The Gtk+ team canon is "Gtk+ doesn't support overlapping widgets". Well, this is really bad. A typical use case is a dashboard kind of user interface which contains the static portions of the UI in form of a bitmap. Since you don't want to implement all widgets on your own, but reuse the GUI toolkit logic, you need to overlay stock Gtk+ widgets on top of this fixed bitmap / layout.

Gtk+ just can't do that. Even if you think you are smart -- e.g. trying to a set a background pixmap to a GtkVBox or a GtkAlignment, hoping it will shine through the widgets you add to the container -- you lose. GtkContainer derived widgets are transparent widgets by definition, they don't have a GdkWindow and they don't draw anything on their own. So what now? How about forking Gtk+ now? No no no no... there must be a better way...

I have found one. After three days and nights wrapping my head around Gtk+ code, I managed to write a couple of widgets which support overlapping. I have derived custom widgets from

which not only support a background pixmap overlapped by Gtk+ widgets, but also the option to hardcode the size through the style sheet, i.e.

style "mydashboard" {
bg_pixmap[NORMAL] = "dashboard.png"
GtkFixedOverlay::size-request = { 0, 480, 0, 120 }
GtkFixedOverlay::cargo-border = { 40, 380, 10, 80 }
}
widget "*.mydashboard-widget" style "mydashboard"

It's not perfect, because for some cases it still involves hardcoding inside the application, but it's a huge step forward for dashboard-style embedded user interfaces. These classes have been created for my current client, but will be open sourced soon -- together with the complete project as well.