diff --git a/docs/reference/gtk/drawing-model.xml b/docs/reference/gtk/drawing-model.xml index 35c230d4ec..ec762e78db 100644 --- a/docs/reference/gtk/drawing-model.xml +++ b/docs/reference/gtk/drawing-model.xml @@ -78,42 +78,72 @@ of the resources they use from the windowing system. + + A GdkWindow + represents a window from the underlying windowing system on which GTK+ + is running. For example, on X11 it corresponds to a + Window; on Win32, it corresponds to a HANDLE. + The windowing system generates events for these windows. The GDK + interface to the windowing system translates such native events into + GdkEvent + structures and sends them on to the GTK layer. In turn, the GTK layer + finds the widget that corresponds to a particular + GdkWindow and emits the corresponding event + signals on that widget. + + + + Emission of the draw event + + + When the program needs to redraw a region of a + GdkWindow, generates an event of + type GDK_EVENT_EXPOSE + for that window, specifying the region to redraw in the process. + + + + When generating the event, GDK also sets up double buffering to + avoid the flickering that would result from each widget drawing + itself in turn. describes + the double buffering mechanism in detail. + + + + When the GTK+ widget layer receives the event, it finds the widget that + corresponds to the window, and causes it to render itself using the + widget's #GtkWidget::draw signal. For this purpose it creates a + cairo context. It then clips the context + to the area that needs to be drawn. This makes sure that the minimal + amount of work is done if only a small part of the widget needs to be + repainted. After translating the context so that its (0, 0) coordinate + corresponds to the top left corner of the widget, it effectively calls + the widget's gtk_widget_draw function. + + + + gtk_widget_draw takes care of drawing the widget + to the cairo context. It first checks that the widget actually needs to + be drawn. Widgets might for example be empty or outside of the cairo + context's clipped area, which would make drawing them not do anything. + Usually they will need to be drawn. In this case, the context will be + clipped to the widget's allocated size and the + draw signal will be emitted on + the widget which will finally draw the widget. + + + Window and no-window widgets - - A GdkWindow - represents a window from the underlying windowing system on which GTK+ - is running. For example, on X11 it corresponds to a - Window; on Win32, it corresponds to a HANDLE. - The windowing system generates events for these windows. The GDK - interface to the windowing system translates such native events into - GdkEvent - structures and sends them on to the GTK layer. In turn, the GTK layer - finds the widget that corresponds to a particular - GdkWindow and emits the corresponding event - signals on that widget. - - - - When the program needs to redraw a region of a - GdkWindow, GDK generates an event of - type GDK_EVENT_EXPOSE - for that window. The GTK+ widget layer in turn finds the - widget that corresponds to that window, and emits the expose-event signal - for that widget. - - In principle, each widget could have a GdkWindow of its own. With such a scheme, the drawing cycle would be trivial: when GDK notifies the GTK layer about an exposure event for a GdkWindow, the GTK layer would simply - emit the expose-event - signal for that widget. The widget's expose event + emit the #GtkWidget::draw signal for that widget. The signal handler would subsequently repaint the widget. No further work would be necessary; the windowing system would generate exposure events for each window that needs it, and then each @@ -293,56 +323,8 @@ - - - To avoid the flickering that would result from each widget drawing - itself in turn, GTK+ uses a double-buffering mechanism. The following - sections describe this mechanism in detail. - - - Notes on drawing no-window widgets - - - Remember that the coordinates in a GdkEventExpose are relative to - the GdkWindow that received the event, - not to the widget whose expose-event - handler is being called. If your widget owns the window, then - these coordinates are probably what you expect. However, if - you have a GTK_NO_WINDOW widget that - shares its parent's window, then the event's coordinates will - be offset by your widget's allocation: remember that the - allocation is always relative to the parent - window of the widget, not to the parent - widget itself. - - - - For example, if you have a no-window widget whose allocation - is { x=5, y=6, - widthheight }, - then your drawing origin should be at (5, 6), not at - (0, 0). - - - - - Drawing over child windows - - - When you draw on a GdkWindow, your - drawing gets clipped by any child windows that it may - intersect. Sometimes you need to draw over your child windows - as well; for example, when drawing a drag-handle to resize - something. In this case, turn on the GDK_INCLUDE_INFERIORS - subwindow mode for the GdkGC which you use for - drawing. - - @@ -351,8 +333,8 @@ When the GTK layer receives an exposure event from GDK, it first finds the !GTK_NO_WINDOW widget that - corresponds to the event's window. Then, it emits the expose-event signal for that + corresponds to the event's window. Then, it emits the + #GtkWidget::draw signal for that widget. As described above, that widget will first draw its background, and then ask each of its GTK_NO_WINDOW children to draw themselves. @@ -360,7 +342,7 @@ If each of the drawing calls made by each subwidget's - expose-event handler were sent directly to the + draw handler were sent directly to the windowing system, flicker could result. This is because areas may get redrawn repeatedly: the background, then decorative frames, then text labels, etc. To avoid flicker, GTK+ employs a double @@ -410,7 +392,7 @@ It would be inconvenient for all widgets to call gdk_window_begin_paint_region() and gdk_window_end_paint() at the beginning - and end of their expose-event handlers. + and end of their draw handlers. @@ -419,7 +401,7 @@ linkend="GtkWidgetFlags">widget flag turned on by default. When GTK+ encounters such a widget, it automatically calls gdk_window_begin_paint_region() - before emitting the expose-event signal for the widget, and + before emitting the #GtkWidget::draw signal for the widget, and then it calls gdk_window_end_paint() after the signal has been emitted. This is convenient for most widgets, as they do not need to worry about creating @@ -430,8 +412,9 @@ However, some widgets may prefer to disable this kind of automatic double buffering and do things on their own. To do - this, turn off the GTK_DOUBLE_BUFFERED - flag in your widget's constructor. + this, call the + gtk_widget_set_double_buffered() function + in your widget's constructor. @@ -463,8 +446,7 @@ my_widget_init (MyWidget *widget) - Even if you turn off the - GTK_DOUBLE_BUFFERED flag on a widget, you + Even if you turn off double buffering on a widget, you can still call gdk_window_begin_paint_region() and gdk_window_end_paint() by hand to use @@ -489,69 +471,42 @@ my_widget_init (MyWidget *widget) GtkWindow and - GtkEventBox are the only two widgets - which will draw their default contents unless you turn on the - GTK_APP_PAINTABLE widget flag. If you turn on - this flag, then they will not draw their contents and let you do + GtkEventBox are the two widgets that allow + turning off drawing of default contents by calling + gtk_widget_set_app_paintable(). If you call + this function, they will not draw their contents and let you do it instead. - The expose-event handler for GtkWindow is - implemented effectively like this: - - - -static gint -gtk_window_expose (GtkWidget *widget, - GdkEventExpose *event) -{ - if (!gtk_widget_get_app_paintable (widget)) - gtk_paint_flat_box (widget->style, widget->window, GTK_STATE_NORMAL, - GTK_SHADOW_NONE, event->area, widget, "base", 0, 0, -1, -1); - - if (GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event) - return GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event (widget, event); - - return FALSE; -} - - - - The expose-event handler for GtkEventBox - is implemented in a similar fashion. - - - - Since the expose-event - signal runs user-connected handlers + Since the #GtkWidget::draw signal runs user-connected handlers before the widget's default handler, what - happens is this: + usually happens is this: - Your own expose-event handler gets run. It paints something + Your own draw handler gets run. It paints something on the window or the event box. - The widget's default expose-event handler gets run. If - GTK_APP_PAINTABLE is turned off (this + The widget's default draw handler gets run. If + gtk_widget_set_app_paintable() has not + been called to turn off widget drawing (this is the default), your drawing will be - overwritten. If that flag is turned on, the - widget will not draw its default contents and preserve your - drawing instead. + overwritten. An app paintable widget will not + draw its default contents however and preserve your drawing + instead. - The expose-event handler for the parent class gets run. + The draw handler for the parent class gets run. Since both GtkWindow and GtkEventBox are descendants of GtkContainer, their no-window @@ -565,7 +520,7 @@ gtk_window_expose (GtkWidget *widget, Summary of app-paintable widgets - Turn on the GTK_APP_PAINTABLE flag if you + Call gtk_widget_set_app_paintable() if you intend to draw your own content directly on a GtkWindow and GtkEventBox. You seldom need to draw