<<

+

Writing Applications with GTK

Owen Taylor

April

Introduction

Graphical user interfaces have b ecome almost universally familiar However

it may b e worth saying a few words ab out how graphical user interfaces work

in and X from the p oint of view of the The X server is

resp onsible for only the simplest op erations of drawing graphics and text on

the screen and for keeping track of the users mouse and keyboard actions Pro

grams communicate with the server via the Xlib However programming

applications in straight Xlib would b e a tremendous chore Since Xlib provides

only basic drawing commands each application would have to provide their own

co de to user interface elements such as buttons or menus Such user interface

elemenets are called widgets

To avoid such a lab orious job and to provide consistancy b etween dierent

applications the normal practice is to use a to olkit a library that builds on

top of Xlib and handles the details of the user interface The traditional choices

for such a to olkit have b een two libraries built up on X Intrinsics libXt library

distributed with X the Athena Widgets which are distributed with X and Mo

1

tif However Xt is complicated to learn and use the Athena Widgets havent

lo oked stylish since and while somewhat more up to date is large

slow has an app earance disliked by many p eople and most imp ortantly is a

proprietary pro duct without freely available source co de

For these reasons and others much recent development has fo cused on to olk

its that build directly on Xlib There are dozens of such to olkits available Per

haps the most prominent are John Ousterhouts to olkit tightly integrated

2

with the Tcl language and the library by Troll Tech which is written in

C

1

Motif is a registered trademark of The Op en Group

2

Qt is a trademark of Troll Tech AS

History

+

GTK was created as part of the GNU Image Manipulation Package GIMP

Early revisions of the GIMP used Motif but when a ma jor revision was b egun in

Peter Mattis decided that b ecause of its proprietary status Motif was not

suitable and b egan work a new to olkit called the GIMP Toolkit GTK In early

additional ob ject oriented features were added including inheritance and

a exible signal system for callbacks and the to olkit was renamed from GTK to

+ +

GTK Because the original version was never released GTK is often referred

+

to simply as GTK and even when written as GTK is typically pronounced

jeeteekay not jeeteekay plus

+

Why GTK

+

GTK oers a number of advantages over other avaqilable to olkits It is written

entirely in Not only are high quality C compilers universally available but

the Conly makes it very easy to integrate with existing systems as well

+

Interfaces for GTK exist for many dierent languages Well developed

bindings exist for in addition to C C guile and Ob jective C Bindings

also exist or are in development for Python Java Eiel Mo dula OCaml and

TOM As has long b een known by users of TclTk GUI development is much

more ecient when done in a highlevel scripting language Although p orts

of Tk have b een done to a number of languages other than Tcl they have b een

hobbled b ecause Tcl is heavily integrated into the Tk core so each p ort has

required pro ducing a mo died version of Tk or has required interfacing to Tk

+

through Tcl The ob jectoriented design and straightC approach of GTK

+

mean that all the ab ove mentioned bindings use unmo died versions of GTK

+

GTK is licensed under the GNU Library General Public License LGPL

+

his ensures the continued availability of the GTK source co de and mo dica

tions to it and means allows it can b e used without charge in all applications

This contrasts sharply with Motif for which the source co de is not available

without paying large amounts of money and Qt which is free only for non

commercial use

As you might exp ect for a to olkit that originated as part of a graphics pro

+

gram GTK has a very attractive default app earance The user interface el

ements are crisply dened and well spaced The colors fonts and background

pixmaps of GTK widgets can b e conveniently customized by the user via a con

guration le system If that isnt enough work is currently in progress to add

+

Themeability to GTK Themeability b est known from its implementation the

Enlightenment will allow complete customization of the user

interface without recompiling applications

+

GTK also provides transparently provides supp ort for a number of X exten

sions With at most trivial mo dications a GTK program will allow the input

of Chinese and Japanese text via the XIM extension and use shared memory for

+

images via the XShm extension A more unusual feature of GTK is supp ort for

+

the XInput extension Programs using the GTK can again with only minor

mo dications take advantage of pressure and tilt information from a graphics

tablet

Design Principles

+

There are a number basic design decisions that distinguish GTK from other

+

to olkits The most basic one was mentioned ab ove GTK is written in pure C

to allow the maximum p ortability exibility and eciency

+

Another basic principle used in GTK is Evenrything is a widget In

+

most to olkits a button or menu item simply has a xed text In GTK buttons

and menuitems are simply Container widgets The could hold a Lab el widget

to display a text string a Pixmap widget to display a picture and Arrow

widget a DrawingArea widget where the application draws its own graphics

and so forth

General Ideas

Structure

+

The GTK package consists of three libraries The rst libglib provides

two things systemindep endent replacements for nonp ortable routines and

routines for manipulation of generic data structures The extensive use of these

+ +

data structures in the rest of GTK and in GTK applications simplies the

co de and improves p erformance by allowing sophisticated data structures such

as hashes and caches to b e conveniently used

The second library libgdk the GIMP Drawing Kit provides a wrapp er

around the raw Xlib functions This hides much of complications of X from the

+

rest of the co de and should make p orting GTK to other windowing systems

+

somewhat easier Finally libgtk includes the co de for the GTK ob ject system

and for the widgets itself

GtkOb ject

GtkFixed

GtkData

GtkList

GtkAdjustment

GtkMenuShell

GtkTooltips

GtkMenuBar

GtkWidget

GtkMenu

GtkContainer

GtkNoteb o ok

GtkBin

GtkPaned

GtkAlignment

GtkHPaned

GtkEventBox

GtkVPaned

GtkFrame

GtkScrolledWindow

GtkAsp ectFrame

GtkTable

GtkHandleBox

GtkToolbar

GtkItem

GtkTree

GtkListItem

GtkDrawingArea

GtkMenuItem

GtkCurve

GtkCheckMenuItem

GtkEditable

GtkRadioMenuItem

GtkEntry

GtkTreeItem

GtkSpinButton

GtkViewp ort

GtkText

GtkWindow

GtkMisc

GtkColorSelectionDialog

GtkArrow

GtkDialog

GtkImage

GtkInputDialog

GtkLab el

GtkFileSelection

GtkTipsQuery

GtkBox

GtkPixmap

GtkButtonBox

GtkPreview

GtkHButtonBox

GtkProgressBar

GtkVButtonBox

GtkRange

GtkHBox

GtkScale

GtkCombo

GtkHScale

GtkStatusbar

GtkVScale

GtkVBox

GtkScrollbar

GtkColorSelection

GtkHScrollbar

GtkGammaCurve

GtkVScrollbar

GtkButton

GtkRuler

GtkOptionMenu

GtkHRuler

GtkToggleButton

GtkVRuler

GtkCheckButton

GtkSeparator

GtkRadioButton

GtkHSeparator

GtkCList

GtkVSeparator

+

Figure The GTK class heirarchy GtkEntry GtkEntryClass GtkEditable GtkEditableClass GtkWidget GtkWidgetClass GtkObject GtkObjectClass klass "destroy" : gtk_entry_destroy

"show" : gtk_entry_show

"changed":NULL

Figure Memory layout of GtkEntry and GtkEntryClass structures

Inheritance

+

Despite b eing written in C GTK is fully ob ject oriented A metho is

invoked on an ob ject by calling a function that takes the ob ject as its rst

parameter For instance to show a widget on the screen one calls the function

void widgetshow GtkWidget widget

As an another example to set the text in an Entry widget one calls

void gtkentrysettext GtkEntry entry const gchar text

A co de fragment that uses hese functions lo oks like

GtkWidget entry gtkentrynew

gtkentrysettext GTKENTRY entry Edit Me

gtkwidgetshow entry

The interesting thing here to note is the use of the GTKENTRY macro A

GtkWidget was returned by gtkentrynew but gtkentrysettext

exp ects GtkEntry To get from one to the other we use the GTKENTRY

macro Actually we could have written just as well

gtkentrysettext GtkEntry entry Edit Me

+

When debugging checks in GTK are disabled the GTKENTRY macro just

a convenient way to write the cast When debugging is enabled the macro also

do es some checks to make sure the p ointer we are converting into a GtkEntry

actually p oints to an Entry widget So how can the same p ointer p oint b oth

to a GtkWidget and a GtkEntry Do esnt the ob ject in memory have to to b e

either one or the other

For the answer to that see Figure What is going on is that the we

have nested structures Inside the GtkEntry structure is a GtkEditable struc

ture Inside the GtkEditable structure is a GtkWidget structure and inside the

GtkWidget structure is a GtkObject structure All of these structures b egin at

the same place in memory so the the same p ointer can b e used as a GtkEntry

a GtkEditable a GtkWidget or a GtkObject

+

In this manner GTK implements a heirarchy of widgets along with a few

nonwidget ob jects See Figure At the base of the heirarchy is the GtkOb

ject type which provides various functionality common to all Ob jects such as

memory management

There is actual a second set of structures nested in the same Russiandoll

fashion This is illustrated by our other call gtkwidgetshow entry As

you might imagine dierent things are involved in showing an Entry widget

on the screen than in showing say a CheckButton So how do es the co de in

gtkwidgetshow which has to handle b oth know what to do Information

ab out such op erations is stored in a second structure nested in the same way the

Class Structure There is a separate GtkEntry structure for each Entry widget

but only a single GtkEntryClass structure that all GtkEntry structures p oint

to In this GtkEntryClass structure is among other things a p ointer to the

function gtkentryshow which actual shows the widget After doing some

general setup gtkwidgetshow calls this function which p erforms actions

sp ecic to showing an Entry widget

+

Actually it do esnt call that function directly but instead uses GTK s

signal mechanism Which brings us to the next topic

Signals

+

One of the most distinctive and exible features of GTK is its signal system

Signals provide a mechanism for applications to control what happ ens when the

+

user do es something by providing a callback co de that GTK calls when the

event o ccurs Callbacks in most C libraries are set up by simply by providing

a function p ointer and this is essentially what you are doing when you call

gtksignalconnect but signals oer a number of additional b enets over a

simple callback mechanism To list a few

 Multiple callbacks can b e attached to a single signal

 By using gtksignalconnect or gtksignalconnectafter the user

callback can b e run b efore or after the default handler

 Type information ab out the callback arguments is provided to language

bindings so the arguments can b e converted appropriately

 Applications can create their own signal types and attach them to existing

ob jects

Each type of o ccurrence has a separate signal type identied by a string

Using the example of the signal that is pressed when the user clicks on a button

adding a callback to a signal lo oks like

void

mycallback GtkWidget widget gpointer data

gprint The button was pressedn

gtksignalconnect GTKOBJECT button clicked

GTKSIGNALFUNC callback NULL

The last argument NULL in this example allows arbitrary data to b e passed

as the second argument of the callback

Geometry management

In keeping with the general principle that everything is a widget layout in GTK

+

is done by using widgets the contain other widgets All of these widgets inherit

from the Container widget and are known as containers The most commonly

used containers for layout are the HBox and VBox which are used to group

widgets into a horizontal or vertical b ox and the Table widget which allows for

exible two dimensional layout But there are other types of Containers as

well The container nature of many of these is less obvious for instance the

Button widget as mentioned ab ove is a container

Memory Management

In a typical C program the programmer is completely resp onsible for freeing

memory that they have allo cated This works well if the program uses memory

than frees it in a predictable manner But imagine the diculties in guring

out when to free the memory of a GtkOb ject A p ointer to a widget may b e

+

used in many places internal to GTK and from application co de A complex

application might allow scripting in a language such as Perl and a p ointer

could b e kept there as well If the memory of the ob ject is freed b efore all of

these p ointer are removed they will b e left p ointing into empty space and a

segmentation fault would b e the likely consequence

The problem of guring out when there are no p ointers to a piece of memory

left is called in general garbage collection Because once all the p ointers are

gone the ob ject is useless and hence garbage that needs to b e removed

Many sophisticated schemes have b een invented for doing this most of which

require extensive supp ort from the compiler and sometimes from the op erating

system

+

Because GTK is meant to b e useable in conjunction with many dierent

languages and external systems it would not b e practical to implement a full

+

garbagecollection system in GTK Instead it uses a limited form of garbage

collection called reference counting In reference counting each ob ject keeps

track of the number of of p ointer to that ob ject that exist When this count

go es to zero the ob ject frees its memory

When one stores a p ointer to an ob ject one calls the function

gtkwidgetrefGtkObject object

which increments the reference count When one no longer needs the p ointer

one calls

gtkwidgetunrefGtkObject object

There is one notable danger with reference counting If a cycle exists where

one ob ject references another and the second references the rst than neither

ob ject will ever have its reference count drop to zero and they will never b e

+

freed To reduce the likelyhoo d of this happ ening GTK also includes a manual

destruction step

Manual destruction is a natural idea for a Once an

ob ject app ears on the screen the user will typically cause it to go away through

an explicit action such as clicking a close button or selecting Quit from a menu

In resp onse to such an action the program will call gtkwidgetdestroy on

the relevant widget For instance on the window This will cause all references

+

that the widget holds inside of GTK to b e released the widget to b e removed

from the screen and gtkwidgetquit to b e called on all the widgets children

Note that there is a distinction b etween destruction the step mentioned ab ove

and actually freeing the ob ject which is called nalization

+

Most commonly only a single reference to a GTK widget exists which is

held by the the container widget that holds them Their parent Since this is

removed when a widget is destroyed the widgets reference count then drops to

zero and it is nalized when immediately after b eing destroyed

The Event Lo op

Programs with graphical user interfaces are by nature event driven That is

instead of p erforming some computations then exiting immediately they wait

for the user to do things and then resp ond to the users actions This is done by

+

callbacks The most common form of callbacks in GTK programs are signals

However there are several types of callback that can b e set up indep endent of

widgets as well

Timeouts are called at sp eciedintervals Idle functions are called when no

events or timeouts need to b e pro cessed Input callbacks are called for events

on le descriptors For instance you might use an input callback if you were

waiting for data to arrive on a so cket

+

Writing a GTK application

+

Figures show a very short example of a GTK program as implemented in

C Perl and guile A window widget is created a button is added to it and a

callback is set up so that when the button is clicked Hello World is printed

and the application quits

+

Writing a substant application in GTK follows much the same route One

gures out how the application should lo ok and creates the appropriate wid

gets Then one connects callbacks to the appropriate signals so the application

actually do es something

Tips Traps and Techniques

+

+

Compile GTK with enabledebug When you are developing a GTK

+

program you should use a copy of GTK congured with the enabledebug

ag This turns on runtime checks that will help catch your programming errors

when they rst o ccur as well as allowing the use of some very handy debugging

information that is available by setting the GTKDEBUG environment variable

+

See the le docsdebuggingtxt in the GTK distribution

Make sure one window has a destroy handler If all of the applications

windows are closed but the event lo op keeps running then from the users p oint

of view your application will app ear to have hung instead of quitting If the

user is running your application from a menu instead of from a shell they may

well end up with copies running at once

To avoid this identify a main window for your application and make sure

there is a destroy handler for that window that quits the main lo op when the

window is destroyed

GtkWidget window windownew GTKWINDOWTOPLEVEL

gtksignalconnect GTKOBJECT window destroy

GTKSIGNALFUNC gtkmainquit NULL

+

Future Directions for GTK

+

Although GTK as it currently exists is suitable for writing p owerful and full

featured applications work is currently b eginning on a version that will b e

even b etter

Some of the things planned include themeability as mentioned ab ove more

extensive internationalization including most likely a switch to Unico de for the

internal enco ding and the integration of the Imlib library for image loading and

+

manipulation into the GTK core

Further information

+

For further information ab out GTK and links to the language bindings men

tioned ab ove visit httpwwwgtkorg The author can b e contacted at

otaylorgtkorg

include gtkgtkh

void

buttonclicked GtkWidget button GtkWidget window

gprint Hello worldn

gtkwidgetdestroy window

int

main int argc char argv

GtkWidget window

GtkWidget button

gtkinit argc argv

window gtkwindownew GTKWINDOWTOPLEVEL

gtksignalconnect GTKOBJECT window destroy

GTKSIGNALFUNC gtkmainquit NULL

button gtkbuttonnewwithlabel Click Me

gtkcontaineradd GTKCONTAINER window button

gtkwidgetshow button

gtksignalconnect GTKOBJECT button clicked

GTKSIGNALFUNC buttonclicked window

gtkwidgetshow window

gtkmain

return

+

Figure GTK Hello World in C

use Gtk

Gtkinit

my window new GtkWindow toplevel

windowsignalconnectdestroy Gtkmainquit

my button new GtkButton Click Me

windowaddbutton

buttonshow

buttonsignalconnectclicked sub

print Hellon

windowdestroy

windowshow

Gtkmain

+

Figure GTK Hello World in Perl

usemodules toolkits gtk

let window gtkwindownew toplevel

button gtkbuttonnewwithlabel Click Me

gtksignalconnect window destroy

lambda gtkmainquit

gtksignalconnect button clicked

lambda

display Hello World

newline

gtkwidgetdestroy window

gtkcontaineradd window button

gtkwidgetshowall window

gtkmain

+

Figure GTK Hello World in guile