1
\documentclass[10pt]{article}
5
\lstset{language=Delphi}%
6
\lstset{basicstyle=\sffamily\small}%
7
\lstset{commentstyle=\itshape}%
8
\lstset{keywordstyle=\bfseries}%
9
\lstset{blankstring=true}%
11
\ifx\pdfoutput\undefined
18
\title{Programming GTK in Free Pascal}
19
\author{Florian Kl\"ampfl\\and\\Micha\"el Van Canneyt}
22
\section{Introduction}
23
The GTK library is a popular widget library for the X-Windows system.
24
It is used as the basis for the GIMP graphical manipulation program
25
and for the GNOME application framework. With its ports to Microsoft
26
Windows and BeOS, it allows to program a graphical interface for any
27
application in a platform independent way.
29
GTK is implemented in C, but it is possible to access its functionality from
30
Free Pascal. For this, its headers have been translated to Pascal,
31
so a program written in Free Pascal can make use of the functionality
32
offered by GTK and its companion libraries GDK and GLIB. In fact, there is
33
an open source project (Lazarus) which makes use of GTK in order to build
34
an open-source alternative to the visual classes offered by Inprise's
37
This article intends to present an introduction to programming GTK in
38
Free Pascal. It by no means covers all of the functionality that GTK
39
offers, as this would probably require a complete manual.
41
The first section gives some general considerations on the GTK toolkit.
43
\section{GTK is a C library}
44
Since GTK is an external library, some import units describing the calls in
45
the libraries are needed. Three libraries make up the GTK programming kit:
47
\item[glib] this library contains some general programming tools, and
48
defines platform independent types, which are used throughout the other
49
libraries. To use this library, it is sufficient to include the
50
\lstinline|glib| unit in your \lstinline|uses| clause.
51
\item[gdk] encapsulates the Windowing system (X or Windows) underlying GTK.
52
It contains routines to draw on the screen, and react to various mouse or
53
keyboard events. To use these
54
routines, the \lstinline|gdk| unit must be included in the \lstinline|uses|
55
clause of a unit or program.
56
\item[gtk] contains the widget library. This is a series of controls such
57
as edit boxes, drop-down lists and many more, which are organised in an OOP
58
structure. Since the library is written in C, there is no programming
59
language support for this structure.
61
All definitions of the gtk library are contained in the gtk unit, which
62
must be included in the \lstinline|uses| clause of any program or unit that needs their
66
The GTK toolkit was programmed in C. This has some consequences for the
67
Pascal interface, since some C constructs do not port easily to Pascal.
68
When using the Pascal translation of the C headers, the following must be
72
\item Reserved words: Pascal reserved words in types, record element names
73
etc. have been prepended with the word 'the'. For example \lstinline|label|
74
becomes \lstinline|thelabel|.
75
\item Functions and procedures have been kept with the same names.
76
\item Types have been prepended with T, that is, the C type
77
\lstinline|GtkWidget| has become \lstinline|TGtkWidget|.
78
\item Pointers to types have been defined as the type name, prepended with a
79
P. \lstinline|GtkWidget *| becomes \lstinline|PGtkWidget|.
80
\item Records with bit-size elements: C allows to store parts of a record in
81
individual bits; whereas in Pascal, the minimum size of an element in a
82
record is a byte. To accommodate this, functions were defined to retrieve
83
or set single bits from a record. The functions to retrieve a bit
84
have the name of the record field. The procedure to set a bit has
85
the name of the field prepended with 'set\_'.
87
\begin{lstlisting}[language=c]{cpackedstruct}
96
\begin{lstlisting}{ppackedstruct}
101
function visible(var a: TGtkCListColumn): guint;
102
procedure set_visible(var a: TGtkCListColumn; __visible: guint);
103
function resizeable(var a: TGtkCListColumn): guint;
104
procedure set_resizeable(var a: TGtkCListColumn;__resizeable: guint);
106
\item Macros. Many C macros have not been translated. The typecasting
107
macros have been dropped, since they're useless under Pascal.
108
Macros to access record members have been translated, but they are to be
109
considered as {read-only}. So they can be used to retrieve a value, but
110
not to store one. e.g.
111
\begin{lstlisting}{macro}
112
function GTK_WIDGET_FLAGS(wid : pgtkwidget) : longint;
114
can be used to retrieve the widget flags, but not to set them. so things like
115
\begin{lstlisting}{invaliduseofmacro}
116
GTK_WIDGET_FLAGS(wid):=GTK_WIDGET_FLAGS(wid) and someflag;
118
will not work, since this is a function, and NOT a macro as in C.
119
\item Calling conventions: A C compiler uses another calling convention
120
than the Free Pascal compiler. Since many GTK functions need a callback,
121
these callback must use the C calling convention. This means that every
122
function that is called by GTK code, should have the \lstinline|cdecl|
123
modifier as a part of its declaration.
126
Compiling a GTK application is no different than compiling any other Free
127
Pascal application. The only thing that needs to be done is to tell the free
128
Pascal compiler where the gtk, gdk and glib libraries are located on your
129
system. This can be done with the \verb|-Fl| command-line switch. For
130
example, supposing the gtk library is located in \verb|/usr/X11/lib|, the
131
following command-line could be used to compile your application:
133
ppc386 -Fl/usr/X11/lib mygtkapp.pp
135
This example supposes that the gtk unit is be in your unit search path. If
136
it is not, you can add it with the \verb|-Fu| switch.
138
\section{The bricks of a GTK application}
139
The building-blocks of a a GTK application are the {\em widgets}.
140
Widgets are the equivalent of Delphi's controls. And although GTK
141
is not an object oriented library, the library defines a record
142
\lstinline|TGtkWidget| which contains all settings common to all
143
widgets; all widgets start with this record, and add their own
144
specific data to it. This creates a tree-like structure with all
145
the widgets present in the GTK library, to which your own widgets
148
All functions that create a particular widget return a pointer
149
to a \lstinline|TGtkWidget| record. It is not recommended to
150
manipulate the contents of the widget record directly; GTK offers
151
many functions to manipulate the members of the record, e.g.
152
\lstinline|gtk_widget_set_parent| or \lstinline|gtk_widget_get_name|.
153
To this set of functions, each new widget adds a few functions that are
154
specific to this particular widget.
156
Each widget has a specific function and a specific look; there are many
157
widgets to choose from. A complete list of widgets is outside the scope of
158
this article; the GTK reference manual offers an overview of available
159
widgets. In general it can be said that most widgets one would expect
160
are present in the GTK library: Edit fields, buttons, check-boxes, various
161
lists, menus, combo-boxes, tree views, and some pre-defined dialogs.
163
Any of these widgets is created with a \lstinline|gtk_WIDGET NAME_new| call.
164
This call can accept arguments; The number and type of arguments depend
166
For example, to create a button that displays a text, the call is defined
169
gtk_button_new_with_label(ALAbel : PChar)
171
All widgets can be destroyed with the \lstinline|gtk_widget_destroy| call,
172
irrespective of their type.
174
\section{Showing things on the screen}
175
To show things on the screen, it is necessary to create a window. A window
176
is created with the the \lstinline|gtk_window_new| call. This call accepts
177
as an argument the type of window to be created.
179
Creating a window creates it's structure in memory, but doesn't show it on
180
screen. To show this window on the screen,a call to the
181
\lstinline|gtk_widget_show| function is needed, as can been seen in
183
\lstinputlisting{gtkex/ex1.pp}
184
If the window contains widgets, the \lstinline|gtk_widget_show| function
185
must be called for each widget.
187
Looking at example 1, one notices 2 special calls: \lstinline|gtk_init| and
188
\lstinline|gtk_main|. These calls should be present in any program that uses
191
The first call initialises the GTK library. Among other things, it reads
192
the command-line to see e.g. which display should be used.
194
The second call is the heart of the GTK widget library: It starts the
195
message loop of GTK. This call will not return, unless somewhere else
196
in the program \lstinline|gtk_main_quit| is called. As long as the call
197
doesn't return, GTK will wait for events such as mouse clicks, key-presses
198
and so on. It will handle these events, but it will not notify you of any
199
of these events except if you specifically ask for it.
201
A window by itself is of course not very interesting. To make it more
202
interesting, some elements should be added.
204
Adding a widget to a parent is done with the \lstinline|gtk_container_add|
205
call. This call places a widget in a container. A container is a widget
206
which can contain other widgets; not all widgets are containers, however.
208
Example 2 shows how to add a widget (a button) to a container (the window
209
in this case). It also shows that the container has some specific
210
properties, which can be manipulated as well (in this case, the border
211
width). Since not each widget is a container, the window pointer must be
212
typecasted to \lstinline|GTK_CONTAINER| in order to be accepted by the
213
container handling calls.
215
\lstinputlisting{gtkex/ex2.pp}
217
Adding more than 1 widget to a container is not trivial in GTK. The reason
218
for this is that GTK has not been designed to set widgets at a specific
219
location in their parent widget. Instead, GTK asks that you 'pack' your
220
objects in their parent widget. This means that if the parent widget is
221
resized, it's child widgets are resized as well, depending on the packing
222
options that were set.
224
One of the reasons that the GTK library was set up this way, is that the
225
size of a widget is not well-defined. For instance, the size of a button
226
depends on whether it is the default widget of the window or not. Given
227
that this is so, the placement of such a button is not well-defined either.
229
The most common ways of packing widgets in a parent widget are the
232
\item using a vertical box.
233
\item using a horizontal box.
236
We'll discuss these ways in the subsequent. There are other ways, but these
237
are probably the most important ones.
239
\subsection{Using boxes}
241
A horizontal or vertical box can be used to contain a row or column of
242
widgets. Various options can be set to modify the spacing between the
243
widgets, the alignment of the widgets in the box, or the behaviour of
244
the box when the user resizes the parent widget. Boxes work only in
245
one direction. The widgets inside a horizontal box always have the height of
246
the box, and widgets in a vertical box always have the width of the vertical
249
You can create a horizontal box with the \lstinline|gtk_hbox_new| call.
250
It accepts 2 arguments: The first one is a boolean. It tells GTK whether the
251
children should have the same space in the box. The second one is an
252
integer, which tells GTK how much space to leave between the widgets in the
253
box. Likewise, a vertical box can be created with the
254
\lstinline|gtk_vbox_new| call. This call accepts the same arguments as the
257
Adding widgets to a box happens with the \lstinline|gtk_box_pack_start| or
258
\lstinline|gtk_box_pack_end| calls. The former adds a widget at the start
259
of the box, the latter adds a widget at the end of the box. Both functions
260
accept the same arguments:
261
\begin{lstlisting}{boxarguments}
262
(Box : PGtkBox; Widget: PGtkWidget;
263
expand gboolean; fill : gboolean;padding : guint);
265
The \lstinline|expand| argument tells the box whether it should take the
266
size of it's parent widget, or whether it should resize itself so that it is
267
just large enough to fit the widgets. The latter allows to justify the
268
widgets in the box (but only if the box is {\em not} homogeneous.
269
If the box should keep the size of it's parent, then the \lstinline|fill|
270
argument decides what is done with the extra space available.
272
If \lstinline|fill| is \lstinline|True| then the extra space is
273
divided over the widgets. If \lstinline|fill| is \lstinline|False| then the
274
extra space is put in between the widgets.
276
The \lstinline|padding| adding tells the box to add extra space for this
279
The following program shows the use of a box:
280
\lstinputlisting{gtkex/ex3.pp}
281
What the program does is the following: It creates a window, which it splits
282
up in two halves by means of the \lstinline|totalbox| widget. This is a
283
vertical box, which will contain two other boxes: a vertical box and a
284
horizontal box. Each of these two boxes is filled with buttons.
285
The behaviour of the boxes can be seen when the window is resized.
287
The effect of the various arguments to the pack calls can be seen by
288
changing the arguments and recompiling the example.
290
\subsection{Using tables}
291
A table is used to set widgets in a grid inside the parent widget. It acts
292
like a grid with cells, in which you can 'hang' your widgets. If the user
293
resizes the parent widget, then the size of the grid cells changes, and
294
the widgets will change their location and size, based on the size of the
297
To create a table to manage a window's layout, the \lstinline|gtk_table_new|
298
call is used. It accepts 3 arguments: the number of rows, the number of
299
columns and a boolean which tells GTK whether the cells should always have
300
the same size or not.
302
To add a widget to a table, the \lstinline|gtk_table_attach| call is used.
305
gtk_table_attach(Table: PGtkTable;Widget: PGtkWidget;
306
Left, right, top, bottom : guint;
307
Xoptions,Yoptions : TGtkAttachOptions;
308
Xpadding,Ypadding : Guint);
310
The first two options of this call are self-explanatory. The next four
311
options, however, need some explanation. Contrary to what the name 'table'
312
suggests, these do {\em not} specify the coordinates of cells; instead, they
313
specify the grid lines that delimit the cells.
316
\caption{Placing widgets in a table.\label{fig:table}}
319
\epsfig{file=table.pdf}
321
\epsfig{file=table.eps}
326
Figure \ref{fig:table} represents a table with 5 rows and 5 columns, with
327
cells of the same size. The call to create this table could be:
329
maintable:=gtk_table_new(5,5,TRUE);
331
To hang a widget in this table, so it starts in cell (2,1) and ends in cell
332
(3,2), where the cells are counted starting with 0, it is necessary to tell
333
GTK that the widget starts at horizontal grid line 2, and ends at horizontal
334
grid line 4. Vertically, it starts at grid line 1, and ends at grid line 3.
335
This means that the following call would place the widget at its correct
338
gtk_table_attach(maintable,mybutton,
340
GTK_EXPAND OR GTK_FILL,GTK_EXPAND OR GTK_FILL,
343
GTK delivers a shorter form of this call:
345
gtk_table_attach_defaults(maintable,mybutton,2,4,1,3);
347
The parameter \lstinline|GTK_EXPAND or GTK_FILL| tells GTK that the widget
348
should always take up the full space assigned to it.
350
The following example program illustrates the use of a table in a gtk
352
\lstinputlisting{gtkex/ex4.pp}
353
The example creates a table with 6 rows and 6 columns. It places 3 buttons,
354
each at a different location in the table, with different sizes. The first
355
button has a width and height of 1 cell and is located at cell (1,1). The
356
second has a width and height of two cells, and is located at cell (3,1).
357
The last button is 4 cells wide and has a height of 1 cell, and is located
358
at cell (1,4). When the window is resized, the cells are resized as well,
359
and the buttons follow the size of the cells.
361
{\em Remark:} because the table has homogeneous cells, the minimum width
362
and height of the cells is determined by the first button (in this case).
363
Since all cells must have the same size, this means that the minimum size
364
of the window is 6 times the size of the first button (plus a border).
366
\section{Reacting to user input}
367
So far, the example programs did not react to button clicks or any other user
368
action other than closing the window. To make a window respond to user
369
actions, it is necessary to install signal callbacks or event handlers.
371
The difference between signals and events is that signals come from the GTK
372
toolkit. Events come from the underlying window system (X or Windows).
373
For example, 'button\_pressed' is an event that is generated by the window
374
system when the user clicks with his mouse. It is possible to react to
377
On the other hand, a button widget defines a signal 'clicked'.
378
The 'clicked' event will occur when the user clicks on the button.
379
So, many signals that are defined by GTK widgets are just a translation
380
of events to something specific for that widget.
382
Since calls to connect to a signal or to an event are the same, in what
383
follows the discussion will be restricted to signals, but all that is
384
said is also true for events.
386
GTK has essentially 2 ways to install signal callbacks. The only difference
387
between these calls is the arguments that the callback function accepts.
389
The first way to install a callback is using the
390
\lstinline|gtk_signal_connect| function. This function is declared as
393
TGtkSignalFunc = procedure ;cdecl;
394
Function gtk_signal_connect(TheObject:PGtkObject;Name:Pgchar;
395
Func:TGtkSignalFunc;Data:gpointer):guint;cdecl;
398
The first argument of this call (\lstinline|TheObject|) is the object
399
(usually a widget) to which you want to assign an event handler. The second
400
parameter, \lstinline|Name|, is the event you wish to catch with this
401
callback (an example could be 'clicked' for a button). The third argument
402
(\lstinline|Func|) is the function that should be called when the event occurs.
403
The \lstinline|Data| argument is a pointer to arbitrary data. This pointer
404
will be passed on to the callback function \lstinline|func| when the event
407
The \lstinline|gtk_signal_connect| function returns an integer. This integer
408
is the number of the callback for this event. It is possible to attach more
409
than one callback to an event in GTK. When the event occurs, the callbacks
410
will be executed in the order that they have been attached to the widget.
412
The declaration of the \lstinline|TGtkSignalFunc| type requires that every
413
callback function that is passed to GTK must be typecast. Since GTK defines
414
only one function to set a signal handler, this is necessary, since
415
callbacks can have different forms. This mechanism is error-prone, since
416
in this manner it is possible to pass a function to GTK which has the wrong
419
However, most callbacks must be of the form:
421
Function (Widget : PGtkWidget; Data : GPointer) : guint;cdecl;
423
Such a callback function accepts 2 arguments: the first argument
424
(\lstinline|Widget|) is the widget which caused the event
425
(for example, the button which was clicked). The second argument is a
426
pointer to arbitrary data. This is the pointer that was passed as
427
\lstinline|Data| when the callback was installed.
429
Signals are identified by their name. The GTK reference guide contains a
430
complete list of supported signals.
432
The first example shows how a handler for the 'destroy' signal of the
433
window is installed. When the window-manager kills the window, this
434
signal is sent. The \lstinline|gtk_main_quit| instructs GTK that it
435
should stop processing X events and exit the \lstinline|gtk_main| call.
437
A second method to connect a callback to a signal is using the
438
\lstinline|gtk_signal_connect_object| call. This call is defined as
441
Function gtk_signal_connect_object(theobject:PGtkObject;
444
slot_object:PGtkObject):guint;cdecl
446
It is similar in function to the \lstinline|gtk_signal_connect| function,
447
only it doesn't allow to pass arbitrary data to the signal handler. Instead,
448
the handler must {\em always} be of the following form:
451
Function (AnObject : PGtkObject);
453
The \lstinline|slot_object| pointer that was provided in the call to
454
\lstinline|gtk_signal_connect_object| will be passed as the
455
\lstinline|AnObject| argument to this function. Many GTK functions have the
456
above form; this makes it possible to attach a GTK internal function to a
459
To illustrate this, the second example is modified so that clicking the button
460
will also close the window:
461
\lstinputlisting{gtkex/ex5.pp}
462
In the example, the call to \lstinline|gtk_signal_connect_object| will
463
connect the 'clicked' signal of the button to the
464
\lstinline|gtk_widget_destroy| function of GTK, and passes the pointer to
465
the window widget to it. When the user clicks the button, the
466
\lstinline|gtk_widget_destroy| function will be called with as argument the
467
pointer of the window object. As a result, the window widget will be
468
destroyed, it's 'destroy' signal will be activated, and the
469
\lstinline|gtk_main_quit| function will be called through the program's
470
'destroy' handler for the window.
472
Since the signal handler connect call returns an integer by which it can
473
be identified, it is possible to manipulate or even remove the handler
474
once it has been installed.
476
For instance it is possible to temporarily disable a signal handler with the
477
\lstinline|gtk_signal_handler_block| call, and to enable it again with the
478
\lstinline|gtk_signal_handler_unblock| call. An example of how to do this
479
can be found in the following example:
480
\lstinputlisting{gtkex/ex6.pp}
481
There are other things that one can do with signal handlers, but a complete
482
discussion of all possibilities is outside the scope of this article.
484
Some widgets do not have their own window; i.e. they do not receive events
485
from the underlying windowing system. An example of such a widget is a
486
label. A label just draws it's text on it's parent widget, and nothing else.
488
To be able to respond to certain events, an event-box must be used, and the
489
window-less widget must be placed in it. An event-box can be created with
490
the \lstinline|gtk_event_box_new| call. This call accepts no arguments.
492
To this event-box, a window-less widget can be added. The event-bow will
493
then capture events for the window-less widget. The following example shows
494
how to use an event-box to detect when the mouse pointer is moved over a
496
\lstinputlisting{gtkex/ex7.pp}
497
If the mouse pointer is moved over the first label, the text of the second
498
label is adapted accordingly. The example also shows the use of
499
\lstinline|gtk_widget_show_all|, which shows a widget and all widgets
502
\section{A touch of style}
503
The look of a GTK application is controlled through the use of styles. A
504
style controls the colors in which a widget is drawn, in various states.
505
As an example: a widget may be drawn differently depending on whether it
506
has focus or not. How to draw the widget in each of this states is described
507
in the style of the widget.
509
GTK recognizes the following states of a widget:
511
\item[NORMAL] The normal state of a widget. No mouse over it.
512
\item[PRELIGHT] Is the state of a widget when the mouse is over it.
513
\item[ACTIVE] Is the state of a widget when it is pressed or
515
\item[INSENSITIVE] if the widgets is disabled ('grayed').
516
\item[SELECTED] When the object is selected.
517
The GTK unit has a constant for each of these states; it is the above name
518
with \lstinline|GTK_STATE_| prefixed, so e.g. \lstinline|GTK_STATE_NORMAL|
519
for the normal state.
524
Each widget class has a default style in which it is drawn. If you wish to
525
change the way all these widgets look, you should change the default style
526
of this class. If you want to change the way one particular widget looks,
527
you should make a new style, and apply it to that particular widget. It is
528
possible to make a copy of an existing style and modify the copy before
531
It is also possible to change the default style of widgets. Changing the
532
default style of widgets will have effect on all widgets created after the
533
new style was set. Widgets created before that will be unaffected.
535
The following example shows how to set the color of a label. It takes a
536
copy of the standard label style, and modifies it so the foreground color
537
becomes red. It then applies the modified style to the first label.
538
The second label is unaffected by this change
539
\lstinputlisting{gtkex/ex8.pp}
541
The last example shows how to change the color of a button when the mouse
543
\lstinputlisting{gtkex/ex9.pp}
545
\section{Carrying on}
546
In the previous sections, some basic concepts of GTK have been introduced.
547
However, GTK is a big toolkit and much more can be said about it. It is
548
outside of the scope of the current article to describe all Widgets in the
549
GTK library. The range of offered widgets is broad, and there probably is a
550
widget for each conceivable task. If there is a missing widget, it is always
551
possible to write a new widget.
553
In principle, therefore, GTK is suitable to write large applications, also
554
when writing in Free Pascal. However, the fact that it is written in C and
555
it's interface is C oriented, justifies the writing of a small Pascal Object
556
Oriented wrapper around it.
557
The following arguments show the need for such a wrapper:
559
\item C has no object-oriented language constructs. This makes it necessary
560
to do a lot of typecasts in GTK calls. Using Classes or Objects, this is no
561
longer necessary, and will improve code readability substantially.
562
\item C uses null-terminated strings. It can be useful to wrap calls that
563
need a null-terminated string into one that accepts a normal string as an
564
argument. Using ansistrings will make the conversion to null-terminated
566
\item The signal mechanism of GTK destroys the strong type checking of
567
Pascal. When compiling the statement
569
Button.OnClick:=@MyForm.OnButtonClick
571
The compiler checks that the \lstinline|OnButtonClick| method can be
572
assigned to the \lstinline|OnClick| event. Under GTK, it is possible
573
to pass any function as a handler for a signal, as in
575
gtk_signal_connect (PGTKOBJECT (window), 'destroy',
576
GTK_SIGNAL_FUNC (@destroy), NULL);
578
This can lead to errors if the \lstinline|destroy| procedure accepts a
579
different number of arguments, or other arguments than the ones that
580
GTK provides. Therefore it would be a good idea to implement methods that
581
would force type checking, e.g:
583
Button.AddOnClick(@MyForm.OnButtonClick);
585
Such a statement would only compile if the \lstinline|OnButtonClick| would
586
be of the right type.
588
Additional benefits of making such a wrapper would be simpler code, and
589
hence better readability. Both improve the maintainability of the code as well,
590
which are all important factors when writing a large application.