2 <!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
3 "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
5 <refentry id="chap-drawing-model">
7 <refentrytitle>The GTK+ Drawing Model</refentrytitle>
8 <manvolnum>3</manvolnum>
9 <refmiscinfo>GTK Library</refmiscinfo>
13 <refname>The GTK+ Drawing Model</refname>
15 The GTK+ drawing model in detail
20 <refsect1 id="drawing-overview">
21 <title>Overview of the drawing model</title>
24 This chapter describes the GTK+ drawing model in detail. If you
25 are interested in the procedure which GTK+ follows to draw its
26 widgets and windows, you should read this chapter; this will be
27 useful to know if you decide to implement your own widgets. This
28 chapter will also clarify the reasons behind the ways certain
29 things are done in GTK+; for example, why you cannot change the
30 background color of all widgets with the same method.
34 Programs that run in a windowing system generally create
35 rectangular regions in the screen called
36 <firstterm>windows</firstterm>. Traditional windowing systems
37 do not automatically save the graphical content of windows, and
38 instead ask client programs to repaint those windows whenever it
39 is needed. For example, if a window that is stacked below other
40 windows gets raised to the top, then a client program has to
41 repaint the area that was previously obscured. When the
42 windowing system asks a client program to redraw part of a
43 window, it sends an <firstterm>exposure event</firstterm> to the
44 program for that window.
48 Here, "windows" means "rectangular regions with automatic
49 clipping", instead of "toplevel application windows". Most
50 windowing systems support nested windows, where the contents of
51 child windows get clipped by the boundaries of their parents.
52 Although GTK+ and GDK in particular may run on a windowing
53 system with no such notion of nested windows, GDK presents the
54 illusion of being under such a system. A toplevel window may
55 contain many subwindows and sub-subwindows, for example, one for
56 the menu bar, one for the document area, one for each scrollbar,
57 and one for the status bar. In addition, controls that receive
58 user input, such as clickable buttons, are likely to have their
59 own subwindows as well.
63 Generally, the drawing cycle begins when GTK+ receives an
64 exposure event from the underlying windowing system: if the
65 user drags a window over another one, the windowing system will
66 tell the underlying window that it needs to repaint itself. The
67 drawing cycle can also be initiated when a widget itself decides
68 that it needs to update its display. For example, when the user
69 types a character in a <link
70 linkend="GtkEntry"><classname>GtkEntry</classname></link>
71 widget, the entry asks GTK+ to queue a redraw operation for
76 The following sections describe how GTK+ decides which widgets
77 need to be repainted, and how widgets work internally in terms
78 of the resources they use from the windowing system.
81 <refsect2 id="window-no-window-widgets">
82 <title>Window and no-window widgets</title>
85 A <link linkend="GdkWindow"><classname>GdkWindow</classname></link>
86 represents a window from the underlying windowing system on which GTK+
87 is running. For example, on X11 it corresponds to a
88 <type>Window</type>; on Win32, it corresponds to a <type>HANDLE</type>.
89 The windowing system generates events for these windows. The GDK
90 interface to the windowing system translates such native events into
91 <link linkend="GdkEvent"><structname>GdkEvent</structname></link>
92 structures and sends them on to the GTK layer. In turn, the GTK layer
93 finds the widget that corresponds to a particular
94 <classname>GdkWindow</classname> and emits the corresponding event
95 signals on that widget.
99 When the program needs to redraw a region of a
100 <classname>GdkWindow</classname>, GDK generates an event of
102 linkend="GDK_EVENT_EXPOSE"><constant>GDK_EVENT_EXPOSE</constant></link>
103 for that window. The GTK+ widget layer in turn finds the
104 widget that corresponds to that window, and emits the <link
105 linkend="GtkWidget-expose-event">expose-event signal</link>
110 In principle, each widget could have a
111 <classname>GdkWindow</classname> of its own. With such a
112 scheme, the drawing cycle would be trivial: when GDK notifies
113 the GTK layer about an exposure event for a
114 <classname>GdkWindow</classname>, the GTK layer would simply
115 emit the <link linkend="GtkWidget-expose-event">expose-event
116 signal</link> for that widget. The widget's expose event
117 handler would subsequently repaint the widget. No further
118 work would be necessary; the windowing system would generate
119 exposure events for each window that needs it, and then each
120 corresponding widget would draw itself in turn.
124 However, in practice it is convenient to have widgets which do
125 not have a <classname>GdkWindow</classname> of their own, but
126 rather share the one from their parent widget. Such widgets
127 have the <constant>GTK_NO_WINDOW</constant> <link
128 linkend="GtkWidgetFlags">widget flag</link> turned on; this
129 can be tested easily with the <link
130 linkend="GTK-WIDGET-NO-WINDOW-CAPS"><function>GTK_WIDGET_NO_WINDOW()</function></link>
131 macro. As such, these are called <firstterm>no-window
136 No-window widgets are useful for various reasons:
142 Some widgets may want the parent's background to show through, even
143 when they draw on parts of it. For example, consider a theme that
144 uses textured backgrounds, such as gradients or repeating
145 patterns. If each widget had its own window, and in turn its own
146 gradient background, labels would look bad because there would be a
147 visible break with respect to their surroundings. <xref
148 linkend="figure-windowed-label"/> shows this undesirable effect.
151 <figure id="figure-windowed-label">
152 <title>Windowed label vs. no-window label</title>
154 <graphic fileref="figure-windowed-label.png" format="png"/>
160 Reducing the number of windows creates less traffic between GTK+ and
161 the underlying windowing system, especially when getting events.
167 On the other hand, widgets that would benefit from having a "hard"
168 clipping region may find it more convenient to create their own
169 windows. Also, widgets which want to receive events resulting from
170 user interaction may find it convenient to use windows of their own as
171 well. Widgets may have more than one window if they want to
172 define different regions for capturing events.
176 <refsect2 id="hierarchical-drawing">
177 <title>Hierarchical drawing</title>
180 When the GTK layer receives an exposure event from GDK, it
181 finds the widget that corresponds to the window which received
182 the event. By definition, this corresponds to a widget that
183 has the <constant>GTK_NO_WINDOW</constant> flag turned
184 <emphasis>off</emphasis> (otherwise, the widget wouldn't own
185 the window!). First this widget paints its background, and
186 then, if it is a container widget, it tells each of its
187 <constant>GTK_NO_WINDOW</constant> children to paint
188 themselves. This process is applied recursively for all the
189 <constant>GTK_NO_WINDOW</constant> descendants of the original
194 Note that this process does not get propagated to widgets
195 which have windows of their own, that is, to widgets which
196 have the <constant>GTK_NO_WINDOW</constant> flag turned off.
197 If such widgets require redrawing, then the windowing system
198 will already have sent exposure events to their corresponding
199 windows. As such, there is no need to
200 <firstterm>propagate</firstterm> the exposure to them on the
206 linkend="figure-hierarchical-drawing"/> shows how a simple toplevel window would
207 paint itself when it contains only <constant>GTK_NO_WINDOW</constant> descendants:
212 The outermost, thick rectangle is a toplevel <link
213 linkend="GtkWindow"><classname>GtkWindow</classname></link>,
214 which is not a <constant>GTK_NO_WINDOW</constant> widget —
215 as such, it does receive its exposure event as it comes from GDK.
216 First the <classname>GtkWindow</classname> would paint its own
217 background. Then, it would ask its only child to paint itself,
223 The dotted rectangle represents a <link
224 linkend="GtkVBox"><classname>GtkVBox</classname></link>, which
225 has been made the sole child of the
226 <classname>GtkWindow</classname>. Boxes are just layout
227 containers that do not paint anything by themselves, so this
228 <classname>GtkVBox</classname> would draw nothing, but rather ask
229 its children to draw themselves. The children are numbered 3 and
235 The thin rectangle is a <link
236 linkend="GtkFrame"><classname>GtkFrame</classname></link>,
237 which has two children: a label for the frame, numbered 4, and
238 another label inside, numbered 5. First the frame would draw its
239 own beveled box, then ask the frame label and its internal child to
245 The frame label has no children, so it just draws its text: "Frame Label".
250 The internal label has no children, so it just draws its text: "This
251 is some text inside the frame!".
256 The dotted rectangle represents a <link
257 linkend="GtkHBox"><classname>GtkHBox</classname></link>. Again,
258 this does not draw anything by itself, but rather asks its children
259 to draw themselves. The children are numbered 7 and 9.
264 The thin rectangle is a <link
265 linkend="GtkButton"><classname>GtkButton</classname></link> with
266 a single child, numbered 8. First the button would draw its
267 beveled box, and then it would ask its child to draw itself.
272 This is a text label which has no children, so it just draws its
278 Similar to number 7, this is a button with a single child, numbered
279 10. First the button would draw its beveled box, and then it would
280 ask its child to draw itself.
285 Similar to number 8, this is a text label which has no children,
286 so it just draws its own text: "OK".
292 <figure id="figure-hierarchical-drawing">
293 <title>Hierarchical drawing order</title>
295 <graphic fileref="figure-hierarchical-drawing.png" format="png"/>
299 To avoid the flickering that would result from each widget drawing
300 itself in turn, GTK+ uses a double-buffering mechanism. The following
301 sections describe this mechanism in detail.
305 <refsect2 id="notes-on-drawing-no-window-widgets">
306 <title>Notes on drawing no-window widgets</title>
309 Remember that the coordinates in a <link
310 linkend="GdkEventExpose">GdkEventExpose</link> are relative to
311 the <classname>GdkWindow</classname> that received the event,
312 <emphasis>not</emphasis> to the widget whose expose-event
313 handler is being called. If your widget owns the window, then
314 these coordinates are probably what you expect. However, if
315 you have a <constant>GTK_NO_WINDOW</constant> widget that
316 shares its parent's window, then the event's coordinates will
317 be offset by your widget's allocation: remember that the
318 allocation is always relative to the parent
319 <emphasis>window</emphasis> of the widget, not to the parent
320 <emphasis>widget</emphasis> itself.
324 For example, if you have a no-window widget whose allocation
325 is { x=5, y=6,
326 <replaceable>width</replaceable>, <replaceable>height</replaceable> },
327 then your drawing origin should be at (5, 6), not at
332 <refsect2 id="include-inferiors">
333 <title>Drawing over child windows</title>
336 When you draw on a <classname>GdkWindow</classname>, your
337 drawing gets clipped by any child windows that it may
338 intersect. Sometimes you need to draw over your child windows
339 as well; for example, when drawing a drag-handle to resize
340 something. In this case, turn on the <link
341 linkend="GDK-INCLUDE-INFERIORS:CAPS">GDK_INCLUDE_INFERIORS</link>
342 subwindow mode for the <link
343 linkend="gdk-Graphics-Contexts">GdkGC</link> which you use for
349 <refsect1 id="double-buffering">
350 <title>Double buffering</title>
353 When the GTK layer receives an exposure event from GDK, it first finds
354 the <literal>!<constant>GTK_NO_WINDOW</constant></literal> widget that
355 corresponds to the event's window. Then, it emits the <link
356 linkend="GtkWidget-expose-event">expose-event signal</link> for that
357 widget. As described above, that widget will first draw its background,
358 and then ask each of its <constant>GTK_NO_WINDOW</constant> children to
363 If each of the drawing calls made by each subwidget's
364 <literal>expose-event</literal> handler were sent directly to the
365 windowing system, flicker could result. This is because areas may get
366 redrawn repeatedly: the background, then decorative frames, then text
367 labels, etc. To avoid flicker, GTK+ employs a <firstterm>double
368 buffering</firstterm> system at the GDK level. Widgets normally don't
369 know that they are drawing to an off-screen buffer; they just issue their
370 normal drawing commands, and the buffer gets sent to the windowing system
371 when all drawing operations are done.
374 <!-- FIXME: figure with a timeline of non-double-buffered and
375 double-buffered paints:
395 Two basic functions in GDK form the core of the double-buffering
397 linkend="gdk_window_begin_paint_region"><function>gdk_window_begin_paint_region()</function></link>
399 linkend="gdk_window_end_paint"><function>gdk_window_end_paint()</function></link>.
400 The first function tells a <classname>GdkWindow</classname> to
401 create a temporary off-screen buffer for drawing. All
402 subsequent drawing operations to this window get automatically
403 redirected to that buffer. The second function actually paints
404 the buffer onto the on-screen window, and frees the buffer.
407 <refsect2 id="automatic-double-buffering">
408 <title>Automatic double buffering</title>
411 It would be inconvenient for all widgets to call
412 <function>gdk_window_begin_paint_region()</function> and
413 <function>gdk_window_end_paint()</function> at the beginning
414 and end of their expose-event handlers.
418 To make this easier, most GTK+ widgets have the
419 <constant>GTK_DOUBLE_BUFFERED</constant> <link
420 linkend="GtkWidgetFlags">widget flag</link> turned on by
421 default. When GTK+ encounters such a widget, it automatically
422 calls <function>gdk_window_begin_paint_region()</function>
423 before emitting the expose-event signal for the widget, and
424 then it calls <function>gdk_window_end_paint()</function>
425 after the signal has been emitted. This is convenient for
426 most widgets, as they do not need to worry about creating
427 their own temporary drawing buffers or about calling those
432 However, some widgets may prefer to disable this kind of
433 automatic double buffering and do things on their own. To do
434 this, turn off the <constant>GTK_DOUBLE_BUFFERED</constant>
435 flag in your widget's constructor.
438 <example id="disabling-double-buffering">
439 <title>Disabling automatic double buffering</title>
443 my_widget_init (MyWidget *widget)
447 GTK_WIDGET_UNSET_FLAGS (widget, GTK_DOUBLE_BUFFERED);
455 When is it convenient to disable double buffering? Generally,
456 this is the case only if your widget gets drawn in such a way
457 that the different drawing operations do not overlap each
458 other. For example, this may be the case for a simple image
459 viewer: it can just draw the image in a single operation.
460 This would <emphasis>not</emphasis> be the case with a word
461 processor, since it will need to draw and over-draw the page's
462 background, then the background for highlighted text, and then
467 Even if you turn off the
468 <constant>GTK_DOUBLE_BUFFERED</constant> flag on a widget, you
470 <function>gdk_window_begin_paint_region()</function> and
471 <function>gdk_window_end_paint()</function> by hand to use
472 temporary drawing buffers.
477 <refsect1 id="app-paintable-widgets">
478 <title>App-paintable widgets</title>
481 Generally, applications use the pre-defined widgets in GTK+ and
482 they do not draw extra things on top of them (the exception
483 being <classname>GtkDrawingArea</classname>). However,
484 applications may sometimes find it convenient to draw directly
485 on certain widgets like toplevel windows or event boxes. When
486 this is the case, GTK+ needs to be told not to overwrite your
487 drawing afterwards, when the window gets to drawing its default
492 <classname>GtkWindow</classname> and
493 <classname>GtkEventBox</classname> are the only two widgets
494 which will draw their default contents unless you turn on the
495 <constant>GTK_APP_PAINTABLE</constant> <link
496 linkend="GtkWidgetFlags">widget flag</link>. If you turn on
497 this flag, then they will not draw their contents and let you do
502 The expose-event handler for <classname>GtkWindow</classname> is
503 implemented effectively like this:
508 gtk_window_expose (GtkWidget *widget,
509 GdkEventExpose *event)
511 if (!GTK_WIDGET_APP_PAINTABLE (widget))
512 gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL,
513 GTK_SHADOW_NONE, event->area, widget, "base", 0, 0, -1, -1);
515 if (GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event)
516 return GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event (widget, event);
523 The expose-event handler for <classname>GtkEventBox</classname>
524 is implemented in a similar fashion.
528 Since the <link linkend="GtkWidget-expose-event">expose-event
529 signal</link> runs user-connected handlers
530 <emphasis>before</emphasis> the widget's default handler, what
537 Your own expose-event handler gets run. It paints something
538 on the window or the event box.
544 The widget's default expose-event handler gets run. If
545 <constant>GTK_APP_PAINTABLE</constant> is turned off (this
546 is the default), <emphasis>your drawing will be
547 overwritten</emphasis>. If that flag is turned on, the
548 widget will not draw its default contents and preserve your
555 The expose-event handler for the parent class gets run.
556 Since both <classname>GtkWindow</classname> and
557 <classname>GtkEventBox</classname> are descendants of
558 <classname>GtkContainer</classname>, their no-window
559 children will be asked to draw themselves recursively, as
560 described in <xref linkend="hierarchical-drawing"/>.
566 <title>Summary of app-paintable widgets</title>
569 Turn on the <constant>GTK_APP_PAINTABLE</constant> flag if you
570 intend to draw your own content directly on a
571 <classname>GtkWindow</classname> and
572 <classname>GtkEventBox</classname>. You seldom need to draw
573 on top of other widgets, and
574 <classname>GtkDrawingArea</classname> ignores this flag, as it
575 <emphasis>is</emphasis> intended to be drawn on.
584 sgml-parent-document: ("gtk-docs.sgml" "book" "part" "refentry")