Rapicorn Gtk

These days Gtk+ is a fairly large and widely deployed GUI toolkit. In terms of deployment, it is a very successful toolkit. However, maintenance and continuous development of a project at this scope and scale come at significant costs in terms of development flexibility and compatibility.

It is not anymore a suitable place for evolution of new experimental GUI technologies and quick paradigm shifts. So radically new toolkit approaches or design ideas now need to be explored elsewhere and only if successful and applicable can reflect back onto Gtk+ development. Rapicorn explores some approaches which are simply different from established Gtk+ paradigms.

The following list is meant to record resulting findings about existing shortcomings in Gtk+ and where possible suggests future improvements.

X-Event-Motion
X event model motion event delivery. Gtk+ follows the X event model very closely, so multiple event types deliver pointer motion event information, in particular the event types motion (motion-hint), button-press, button-release, enter and leave. One consequence of this approach is that pointer position bookkeeping code has to be replicated in various places. The replication process is fairly bug vulnerable and makes future adoptions hard to impossible (e.g. adoption to multi-pointer awareness, see | MPX). Rapicorn employs a different approach that could possibly be adapted compatibly by Gtk+: Rapicorn Technology.

Paired-X-Events
Paired event delivery. In Gtk+, the user or widget developer has to keep track and work around event pairedness on his own. E.g. a button-press event may or may not be followed by a button-release depending on a large amount of external conditions (such as pointer grabs or the widget becoming temporarily insensitive and/or hidden). Still, regardless of previous event history (unpaired presses, or enter events, spurious releases and leaves), the widgets are supposed to remain working in full effect for future presses, enter events, etc. This produces lots of buggy cases in Gtk+ widget implementations, ranging from subtle buglets to sometimes serous destabilization. The introduction of the "grab-broken" Event helped to work around a restricted subset of the resulting bugs, but couldn't fully solve the more general problem. Rapicorn introduces dedicated cancellation events which may also be applicable to improve the reliability of event delivery in Gtk+: Rapicorn Technology.

Multiple-Selections
Multiple views, multiple selections. The GtkTextView and GtkTreeView widgets suffer majorly from a complexity boost introduced by support for multiple views and multiple selections. In some situations, multiple views onto program specific data can have interesting applications. For the vast majority of user interfaces, multiple views are however not critically needed. Complexity escalates if multiple selections are supported. Tying data model selections to the model implementation vastly simplifies implementation and interface complexity, for some model types it can even be a hard requirement. Other mechanisms like application scripting may be severely impacted by multiple selection models, because selection-aware scripting generally relies on a unique model/selection relationship that's also presented transparently to the GUI user. In terms of usability aspects, support for multiple selections per model is generally rarely advisable, if at all, only expert users can make use of such functionality. While Gtk+ can not be compatibly reduced to single-view or single-selection view modes for the existing interfaces, confinement to single-selection mode could at least be a future development directive.

Resizing-Hysteresis
Resizing hysteresis. The general resizing model in Gtk+ is fairly simple, in a first run all widgets are asked for their size requisition, and in a second run the available space is divided up between all visible widgets according to container specific partitioning of their respective child areas. This doesn't leave room for multi-stage layout strategies that are e.g. required for proper width-for-height or height-for-width management that is often needed by text elements. Other widgets, in particular GtkScrolledWindow break with the resizing contracts when they occasionally re-queue additional resizes, and apply resizing thresholds which depend on previous size negotiations. The outcome are resizing hysteresis effects that can feel unnatural to the enduser and possibly result in an overall layout with clearly suboptimal size allocations. Rapicorn allows arbitrary multi-stage size negotiations, and employs dedicated strategies to stabilize the resizing process: Rapicorn Technology.

Shrinking-Widgets
Many factors influence widgets sizes in various ways lots of which are outside of the application developers control, for instance user selectable themes, font sizes, monitor sizes and display resolutions, display transformation, zoom effects and more. The combination of such factors can often lead widgets size allocations to be significantly smaller than the optimum for widget display. Consequently, all widgets supplied by Rapicorn are meant to be usable when allocated sizes that are smaller than their natural size requisition. In particular, text widgets use various kinds of ellipses to indicate shrinkage below their optimum size, and containers attempt to distribute shrinkage evenly between their children. The current table shrinking logic implementation prioritizes allocations for outermost widgets higher than innermost widgets. This way, dialog control buttons or menu bars are more likely to stay visible and operable in case of size underallocation. So far, these strategies work out well, and many dialogs turn out to stay usable for a large range of shrinking beyond their optimum size allocation. Gtk+ containers should be able to also benefit from shrinking logic much the same way. E.g. the shrinking modifications to the Rapicorn table code is compatible with GtkTable's allocation logic for the unshrunken case, and it also covers all layout features needed by GtkHBox and GtkVBox, so the improvements are transferable to the Gtk+ code base.

Child-Properties
Gtk+ supports setting properties on container<->child links to affect layout behavior (e.g. to indicate that a particular child should be expanded, while another one possibly should be shrunken). The neccessary logic to support this feature is fairly complicated, both in terms of API and particularly in the implementation. First versions of Rapicorn emulated this behaviour for HBox/VBox/Table/Arrangement containers with the Container::ChildPacker structure. Similar to GObject and Gtk+, portions of the object property implementations could be reused to provide this mechanism, but the implementation basis was still quite complex. Newer versions replaced the ChildPacker structure with regular Item properties, stored in an Item::PackInfo structure that'll allocate memory for pack properties on demand.

Given that Gtk+ also doesn't make much use of this facility (Gtk+-2.13.1 contains merely 40 child property registrations), it could also benefit in terms of implementation simplicity and API consolidation from removing the child property mechanism alltogether and providing widget packing information as GtkWidget properties when required. That is, provided Gtk+'s API may be broken incompatibly.

Apart from the simplification, storing packing information on the actual child turns out to be quite useful sometimes, in particular when moving a child from one container to another. Child property information like GTK_EXPAND or GTK_FILL often depend on the child and its contents and are thus useful to keep when moving the child between containers.

Finally, a major motivational aspect for the ChildPacker removal in Rapicorn was preparation for containers with switchable layout algorithms. For example, a future container may provide Table, HBox or VBox layout functionality, depending on an exchangable layout algorithm. In such a scenario, packing information for a particular child needs to be stored on the child itself, preferably in some kind of canonicalized form, so different layout algorithms are enabled to share or reuse packing information where it makes sense. Needless to say that such containers could become interesting for Gtk+ in the future as well.