X Programming at the Application Level

Toolkit libraries and GUI environments exist to save application writers from having to code at the level of BitBlt or Porter-Duff operators. They hide most rendering operations and most input-event handling behind an abstraction layer of widgets.

A widget is an X window object, possibly composed of a collection of subwidgets which are themselves X windows, Each widget or subwidget has its own event mask and event-handling logic. For example, a button is an X window that ignores keystroke events but captures mouse-button events. A text-entry field, on the other hand, may accept keystroke events but ignore mouse clicks. Some widgets, like toolkit-level window objects, can containers for collections of subwidgets.

GUI programs under X using a toolkit generally start by setting up a collection of widgets, then calling a toolkit-supplied driver function that implements an X event loop. The toolkit's (hidden) event loop takes care of dispatching input events to the appropriate widgets as they come in.

Widgets trigger actions in the program's application logic via callbacks. A callback is a function pointer that a widget will call (possibly supplying some arguments) on some particular event. For example, any button widget will have a place to plug in a callback for whenever the button is clicked.

Programming with this event-loop/callback combination leads to a very different style and organization of code than with CLIs. interfaces. When writing code with a CLI, the main loop is under the programmer's control and directly expresses the expected sequence of operations in the application. Programming is almost entirely imperative, with explicit code expressing what should be done when. This style does not cope naturally with multiplexing several input sources, nor with events coming in in odd sequences at unpredictable times; in fact, these have to be modeled interrupts and processed by callbacks outside the normal flow of program control.

In the event-loop/callback world of GUIs, the main flow of control is implicit (dedicated entirely to waiting on and dispatching the next input event, and everything at application level is a callback processed rather like an interrupt in “normal” program flow. Much of programming is declarative (hooking application functions into the callback slots of widgets) rather than imperative.

Programming in the event-loop/callback world by hand is trickier than CLI programming by hand, but the stereotyped nature of the main event loop and the encapsulation of most input handling in widgets also means that code generators can be proportionately much more helpful. In the next section, we'll survey some tools for easing the GUI coding burden.