I’ve been quietly working in my spare time on a new project, called Monet. The aim is to provide a cross-toolkit widget drawing API and theming architecture. This would allow different toolkits to use the same code to draw their widgets, thus producing a more consistent look and feel across applications. The other motivator is to improve the theming abilities provided by existing toolkits and applications. The main target is to improve GTK+ theming opportunities, but I am also considering extending this beyond traditional widget theming, especially as GTK+ may have client side window decoration support soon.
Following on from the discussions at the theme hackfest last year, with extra input from Benjamin Berg (current maintainer of the gtk-engines package) and other Gnome artists and designers, we’ve created a new widget drawing API, drawing on ideas used in existing toolkits such as GTK+, Qt and Windows.
The main concepts behind the design are fairly simple. Each widget is represented by an object that encapsulates all the information necessary to draw it. This can include geometry, context, state, colours, and other properties such as text. For example, the Button class includes text, background and border colours, as well as certain flags such as whether the button is focused. This information is passed to the theme drawing API (the “theme engine”) with a cairo context, onto which the button will be drawn. More complex widgets are split into sub-elements and passed to the theme engine as a group. More exotic widgets such as window frames could also be added as part of this API. The advantages of using objects to define each widget’s drawing parameters is that they can be sub-classed and provide well documented properties.
Since the drawing API is defined as an abstract class, it is still possible to write new themes in code, just as they are done now in GTK+. However, I would like to include a theme engine that allows artists and theme authors to write new themes without requiring a compiler and even provide GUI tools for creating themes. There are several possible solutions to this:
Using an existing specification such as CSS seems attractive, but on closer inspection it is clear that CSS is not suitable for widget drawing without using images or custom extensions. As author of the Moblin toolkit, which uses CSS exclusively for styling, I have experienced first hand its short comings when it is applied to a widget scene graph, rather than an HTML document. There are several unapparent problems that arise, such as the lack of class hierarchy matching*.
SVG might be an alternative solution, but again there are problems that can only be solved with custom attributes and renderers. These would need to include the ability to keep constant stroke widths and corner radii when scaling. This would necessitate both custom editors and renderers.
Finally, a custom XML format was suggested as a possibility (in fact, by a designer, no less). Personally, I don’t think anyone should have to write XML to create a theme, but luckily it would be trivial to write a custom editor for this type of theme. It also would have the advantage that it is not bound to any existing but ever-so-slightly different use case. It would also be trivial to expose the cairo API in such a format. Metacity also has a drawing API defined in XML and this could be used as a starting point (although, a much simpler schema could be achieved since less geometry needs to be specified).
I would be interested to hear any further thoughts on alternative theme formats.
I have started prototyping these ideas in a git repository on git.gnome.org, under the Monet project. Since the API includes an object for each widget type, I have experimented with implementing this to some success using Vala. The abstract base classes are available, as are classes for simple widgets. There is also an implementation of a GTK+ engine in Vala, which would form the basis of a translational mechanism. A very simple (and limited) test engine is implemented, along with a test case to drive it. Certainly none of it is interesting to users yet.
My hope for the future would be that toolkits gradually begin to start using the new API natively, but to help during the transition period, wrappers can be added to the existing infrastructure. For example, the project will include a traditional GTK+ engine as a proxy to allow GTK+ users to start using the new architecture immediately.
There are certainly problems that the API does not yet solve, such as transition effects. Other considerations might whether to add support for “native” styles on other platforms, such as Windows and Mac OS X, or whether these are best left to each toolkit to implement themselves. I would be interested to hear any suggestions around these areas.
* Qt “solve” this in quite an interesting way, but it changes the semantics of class selectors in CSS.