mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-10 19:00:08 +00:00
Update drawing model docs
Include material from Alex' blog post about the modern GTK+ rendering model.
This commit is contained in:
parent
eae9513cbd
commit
7806684592
@ -30,77 +30,172 @@
|
||||
background color of all widgets with the same method.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Programs that run in a windowing system generally create
|
||||
rectangular regions in the screen called
|
||||
<firstterm>windows</firstterm>. Traditional windowing systems
|
||||
do not automatically save the graphical content of windows, and
|
||||
instead ask client programs to repaint those windows whenever it
|
||||
is needed. For example, if a window that is stacked below other
|
||||
windows gets raised to the top, then a client program has to
|
||||
repaint the area that was previously obscured. When the
|
||||
windowing system asks a client program to redraw part of a
|
||||
window, it sends an <firstterm>exposure event</firstterm> to the
|
||||
program for that window.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Here, "windows" means "rectangular regions with automatic
|
||||
clipping", instead of "toplevel application windows". Most
|
||||
windowing systems support nested windows, where the contents of
|
||||
child windows get clipped by the boundaries of their parents.
|
||||
Although GTK+ and GDK in particular may run on a windowing
|
||||
system with no such notion of nested windows, GDK presents the
|
||||
illusion of being under such a system. A toplevel window may
|
||||
contain many subwindows and sub-subwindows, for example, one for
|
||||
the menu bar, one for the document area, one for each scrollbar,
|
||||
and one for the status bar. In addition, controls that receive
|
||||
user input, such as clickable buttons, are likely to have their
|
||||
own subwindows as well.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Generally, the drawing cycle begins when GTK+ receives an
|
||||
exposure event from the underlying windowing system: if the
|
||||
user drags a window over another one, the windowing system will
|
||||
tell the underlying window that it needs to repaint itself. The
|
||||
drawing cycle can also be initiated when a widget itself decides
|
||||
that it needs to update its display. For example, when the user
|
||||
types a character in a <link
|
||||
linkend="GtkEntry"><classname>GtkEntry</classname></link>
|
||||
widget, the entry asks GTK+ to queue a redraw operation for
|
||||
itself.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The following sections describe how GTK+ decides which widgets
|
||||
need to be repainted, and how widgets work internally in terms
|
||||
of the resources they use from the windowing system.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
A <link linkend="GdkWindow"><classname>GdkWindow</classname></link>
|
||||
represents a window from the underlying windowing system on which GTK+
|
||||
is running. For example, on X11 it corresponds to a
|
||||
<type>Window</type>; on Win32, it corresponds to a <type>HANDLE</type>.
|
||||
The windowing system generates events for these windows. The GDK
|
||||
interface to the windowing system translates such native events into
|
||||
<link linkend="GdkEvent"><structname>GdkEvent</structname></link>
|
||||
structures and sends them on to the GTK layer. In turn, the GTK layer
|
||||
finds the widget that corresponds to a particular
|
||||
<classname>GdkWindow</classname> and emits the corresponding event
|
||||
signals on that widget.
|
||||
</para>
|
||||
|
||||
<refsect2 id="emission of the draw event">
|
||||
<title>Emission of the draw event</title>
|
||||
<refsect2 id="drawing model windows">
|
||||
<title>Windows and events</title>
|
||||
|
||||
<para>
|
||||
When the program needs to redraw a region of a
|
||||
<classname>GdkWindow</classname>, generates an event of
|
||||
type <link
|
||||
linkend="GDK_EVENT_EXPOSE"><constant>GDK_EVENT_EXPOSE</constant></link>
|
||||
for that window, specifying the region to redraw in the process.
|
||||
Programs that run in a windowing system generally create
|
||||
rectangular regions in the screen called
|
||||
<firstterm>windows</firstterm>. Traditional windowing systems
|
||||
do not automatically save the graphical content of windows, and
|
||||
instead ask client programs to repaint those windows whenever it
|
||||
is needed. For example, if a window that is stacked below other
|
||||
windows gets raised to the top, then a client program has to
|
||||
repaint the area that was previously obscured. When the
|
||||
windowing system asks a client program to redraw part of a
|
||||
window, it sends an <firstterm>exposure event</firstterm> to the
|
||||
program for that window.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Here, "windows" means "rectangular regions with automatic
|
||||
clipping", instead of "toplevel application windows". Most
|
||||
windowing systems support nested windows, where the contents of
|
||||
child windows get clipped by the boundaries of their parents.
|
||||
Although GTK+ and GDK in particular may run on a windowing
|
||||
system with no such notion of nested windows, GDK presents the
|
||||
illusion of being under such a system. A toplevel window may
|
||||
contain many subwindows and sub-subwindows, for example, one for
|
||||
the menu bar, one for the document area, one for each scrollbar,
|
||||
and one for the status bar. In addition, controls that receive
|
||||
user input, such as clickable buttons, are likely to have their
|
||||
own subwindows as well.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
In practice, most windows in modern GTK+ application are client-side
|
||||
constructs. Only few windows (in particular toplevel windows) are
|
||||
<emphasis>native</emphasis>, which means that they represent a
|
||||
window from the underlying windowing system on which GTK+ is running.
|
||||
For example, on X11 it corresponds to a <type>Window</type>; on Win32,
|
||||
it corresponds to a <type>HANDLE</type>.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Generally, the drawing cycle begins when GTK+ receives an
|
||||
exposure event from the underlying windowing system: if the
|
||||
user drags a window over another one, the windowing system will
|
||||
tell the underlying window that it needs to repaint itself. The
|
||||
drawing cycle can also be initiated when a widget itself decides
|
||||
that it needs to update its display. For example, when the user
|
||||
types a character in a <link
|
||||
linkend="GtkEntry"><classname>GtkEntry</classname></link>
|
||||
widget, the entry asks GTK+ to queue a redraw operation for
|
||||
itself.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The windowing system generates events for native windows. The GDK
|
||||
interface to the windowing system translates such native events into
|
||||
<link linkend="GdkEvent"><structname>GdkEvent</structname></link>
|
||||
structures and sends them on to the GTK layer. In turn, the GTK layer
|
||||
finds the widget that corresponds to a particular
|
||||
<classname>GdkWindow</classname> and emits the corresponding event
|
||||
signals on that widget.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The following sections describe how GTK+ decides which widgets
|
||||
need to be repainted in response to such events, and how widgets
|
||||
work internally in terms of the resources they use from the
|
||||
windowing system.
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2 id="frameclock">
|
||||
<title>The frame clock</title>
|
||||
|
||||
<para>
|
||||
All GTK+ applications are mainloop-driven, which means that most
|
||||
of the time the app is idle inside a loop that just waits for
|
||||
something to happen and then calls out to the right place when
|
||||
it does. On top of this GTK+ has a frame clock that gives a
|
||||
“pulse” to the application. This clock beats at a steady rate,
|
||||
which is tied to the framerate of the output (this is synced to
|
||||
the monitor via the window manager/compositor). The clock has
|
||||
several phases:
|
||||
<itemizedlist>
|
||||
<listitem><para>Events</para></listitem>
|
||||
<listitem><para>Update</para></listitem>
|
||||
<listitem><para>Layout</para></listitem>
|
||||
<listitem><para>Paint</para></listitem>
|
||||
</itemizedlist>
|
||||
The phases happens in this order and we will always run each
|
||||
phase through before going back to the start.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The Events phase is a long stretch of time between each
|
||||
redraw where we get input events from the user and other events
|
||||
(like e.g. network I/O). Some events, like mouse motion are
|
||||
compressed so that we only get a single mouse motion event per
|
||||
clock cycle.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Once the Events phase is over we pause all external events and
|
||||
run the redraw loop. First is the Update phase, where all
|
||||
animations are run to calculate the new state based on the
|
||||
estimated time the next frame will be visible (available via
|
||||
the frame clock). This often involves geometry changes which
|
||||
drives the next phase, Layout. If there are any changes in
|
||||
widget size requirements we calculate a new layout for the
|
||||
widget hierarchy (i.e. we assign sizes and positions). Then
|
||||
we go to the Paint phase where we redraw the regions of the
|
||||
window that need redrawing.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If nothing requires the Update/Layout/Paint phases we will
|
||||
stay in the Events phase forever, as we don’t want to redraw
|
||||
if nothing changes. Each phase can request further processing
|
||||
in the following phases (e.g. the Update phase will cause there
|
||||
to be layout work, and layout changes cause repaints).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
There are multiple ways to drive the clock, at the lowest level
|
||||
you can request a particular phase with
|
||||
gdk_frame_clock_request_phase() which will schedule a clock beat
|
||||
as needed so that it eventually reaches the requested phase.
|
||||
However, in practice most things happen at higher levels:
|
||||
<itemizedlist>
|
||||
<listitem><para>
|
||||
If you are doing an animation, you can use
|
||||
gtk_widget_add_tick_callback() which will cause a regular
|
||||
beating of the clock with a callback in the Update phase
|
||||
until you stop the tick.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
If some state changes that causes the size of your widget
|
||||
to change you call gtk_widget_queue_resize() which will
|
||||
request a Layout phase and mark your widget as needing
|
||||
relayout.
|
||||
</para></listitem>
|
||||
<listitem><para>
|
||||
If some state changes so you need to redraw some area of
|
||||
your widget you use the normal gtk_widget_queue_draw()
|
||||
set of functions. These will request a Paint phase and
|
||||
mark the region as needing redraw.
|
||||
</para></listitem>
|
||||
</itemizedlist>
|
||||
There are also a lot of implicit triggers of these from the
|
||||
CSS layer (which does animations, resizes and repaints as needed).
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2 id="hierarchical-drawing">
|
||||
<title>Hierarchical drawing</title>
|
||||
|
||||
<para>
|
||||
During the Paint phase we will send a single expose event to
|
||||
the toplevel window. The event handler will create a cairo
|
||||
context for the window and emit a GtkWidget::draw() signal
|
||||
on it, which will propagate down the entire widget hierarchy
|
||||
in back-to-front order, using the clipping and transform of
|
||||
the cairo context. This lets each widget draw its content at
|
||||
the right place and time, correctly handling things like
|
||||
partial transparencies and overlapping widgets.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
@ -111,218 +206,55 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
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
|
||||
<link linkend="#cairo_t">cairo context</link>. 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 <function>gtk_widget_draw</function> function.
|
||||
Normally, there is only a single cairo context which is used in
|
||||
the entire repaint, rather than one per GdkWindow. This means you
|
||||
have to respect (and not reset) existing clip and transformations
|
||||
set on it.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<function>gtk_widget_draw</function> 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
|
||||
<link linkend="GtkWidget::draw">draw signal</link> will be emitted on
|
||||
the widget which will finally draw the widget.
|
||||
Most widgets, including those that create their own GdkWindows have
|
||||
a transparent background, so they draw on top of whatever widgets
|
||||
are below them. This was not the case in GTK+ 2 where the theme set
|
||||
the background of most widgets to the default background color. (In
|
||||
fact, transparent GdkWindows used to be impossible.)
|
||||
</para>
|
||||
|
||||
<para>
|
||||
The whole rendering hierarchy is captured in the call stack, rather
|
||||
than having multiple separate draw emissions, so you can use effects
|
||||
like e.g. cairo_push/pop_group() which will affect all the widgets
|
||||
below you in the hierarchy. This makes it possible to have e.g.
|
||||
partially transparent containers.
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2 id="window-no-window-widgets">
|
||||
<title>Window and no-window widgets</title>
|
||||
<refsect2 id="scrolling drawing model">
|
||||
<title>Scrolling</title>
|
||||
|
||||
<para>
|
||||
In principle, each widget could have a
|
||||
<classname>GdkWindow</classname> 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
|
||||
<classname>GdkWindow</classname>, the GTK layer would simply
|
||||
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
|
||||
corresponding widget would draw itself in turn.
|
||||
Traditionally, GTK+ has used self-copy operations to implement
|
||||
scrolling with native windows. With transparent backgrounds, this
|
||||
no longer works. Instead, we just mark the entire affected area for
|
||||
repainting when these operations are used. This allows (partially)
|
||||
transparent backgrounds, and it also more closely models modern
|
||||
hardware where self-copy operations are problematic (they break the
|
||||
rendering pipeline).
|
||||
</para>
|
||||
|
||||
<para>
|
||||
However, in practice it is convenient to have widgets which do
|
||||
not have a <classname>GdkWindow</classname> of their own, but
|
||||
rather share the one from their parent widget. Such widgets
|
||||
have called <function>gtk_widget_set_has_window</function> to
|
||||
disable it; this can be tested easily with the <link
|
||||
linkend="gtk-widget-get-has-window"><function>gtk_widget_get_has_window()</function></link>
|
||||
function. As such, these are called <firstterm>no-window
|
||||
widgets</firstterm>.
|
||||
Since the above causes some overhead, we introduce a caching mechanism.
|
||||
Containers that scroll a lot (GtkViewport, GtkTextView, GtkTreeView,
|
||||
etc) allocate an offscreen image during scrolling and render their
|
||||
children to it (which is possible since drawing is fully hierarchical).
|
||||
The offscreen image is a bit larger than the visible area, so most of
|
||||
the time when scrolling it just needs to draw the offscreen in a
|
||||
different position. This matches contemporary graphics hardware much
|
||||
better, as well as allowing efficient transparent backgrounds.
|
||||
In order for this to work such containers need to detect when child
|
||||
widgets are redrawn so that it can update the offscreen. This can be
|
||||
done with the new gdk_window_set_invalidate_handler() function.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
No-window widgets are useful for various reasons:
|
||||
</para>
|
||||
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Some widgets may want the parent's background to show through, even
|
||||
when they draw on parts of it. For example, consider a theme that
|
||||
uses textured backgrounds, such as gradients or repeating
|
||||
patterns. If each widget had its own window, and in turn its own
|
||||
gradient background, labels would look bad because there would be a
|
||||
visible break with respect to their surroundings. <xref
|
||||
linkend="figure-windowed-label"/> shows this undesirable effect.
|
||||
</para>
|
||||
|
||||
<figure id="figure-windowed-label">
|
||||
<title>Windowed label vs. no-window label</title>
|
||||
|
||||
<graphic fileref="figure-windowed-label.png" format="png"/>
|
||||
</figure>
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para>
|
||||
Reducing the number of windows creates less traffic between GTK+ and
|
||||
the underlying windowing system, especially when getting events.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
|
||||
<para>
|
||||
On the other hand, widgets that would benefit from having a "hard"
|
||||
clipping region may find it more convenient to create their own
|
||||
windows. Also, widgets which want to receive events resulting from
|
||||
user interaction may find it convenient to use windows of their own as
|
||||
well. Widgets may have more than one window if they want to
|
||||
define different regions for capturing events.
|
||||
</para>
|
||||
</refsect2>
|
||||
|
||||
<refsect2 id="hierarchical-drawing">
|
||||
<title>Hierarchical drawing</title>
|
||||
|
||||
<para>
|
||||
When the GTK layer receives an exposure event from GDK, it
|
||||
finds the widget that corresponds to the window which received
|
||||
the event. By definition, this corresponds to a widget that
|
||||
has the <constant>GTK_NO_WINDOW</constant> flag turned
|
||||
<emphasis>off</emphasis> (otherwise, the widget wouldn't own
|
||||
the window!). First this widget paints its background, and
|
||||
then, if it is a container widget, it tells each of its
|
||||
<constant>GTK_NO_WINDOW</constant> children to paint
|
||||
themselves. This process is applied recursively for all the
|
||||
<constant>GTK_NO_WINDOW</constant> descendants of the original
|
||||
widget.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Note that this process does not get propagated to widgets
|
||||
which have windows of their own, that is, to widgets which
|
||||
have the <constant>GTK_NO_WINDOW</constant> flag turned off.
|
||||
If such widgets require redrawing, then the windowing system
|
||||
will already have sent exposure events to their corresponding
|
||||
windows. As such, there is no need to
|
||||
<firstterm>propagate</firstterm> the exposure to them on the
|
||||
GTK+ side.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<xref
|
||||
linkend="figure-hierarchical-drawing"/> shows how a simple toplevel window would
|
||||
paint itself when it contains only <constant>GTK_NO_WINDOW</constant> descendants:
|
||||
|
||||
<orderedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
The outermost, thick rectangle is a toplevel <link
|
||||
linkend="GtkWindow"><classname>GtkWindow</classname></link>,
|
||||
which is not a <constant>GTK_NO_WINDOW</constant> widget —
|
||||
as such, it does receive its exposure event as it comes from GDK.
|
||||
First the <classname>GtkWindow</classname> would paint its own
|
||||
background. Then, it would ask its only child to paint itself,
|
||||
numbered 2.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The dotted rectangle represents a <link
|
||||
linkend="GtkVBox"><classname>GtkVBox</classname></link>, which
|
||||
has been made the sole child of the
|
||||
<classname>GtkWindow</classname>. Boxes are just layout
|
||||
containers that do not paint anything by themselves, so this
|
||||
<classname>GtkVBox</classname> would draw nothing, but rather ask
|
||||
its children to draw themselves. The children are numbered 3 and
|
||||
6.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The thin rectangle is a <link
|
||||
linkend="GtkFrame"><classname>GtkFrame</classname></link>,
|
||||
which has two children: a label for the frame, numbered 4, and
|
||||
another label inside, numbered 5. First the frame would draw its
|
||||
own beveled box, then ask the frame label and its internal child to
|
||||
draw themselves.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The frame label has no children, so it just draws its text: "Frame Label".
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The internal label has no children, so it just draws its text: "This
|
||||
is some text inside the frame!".
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The dotted rectangle represents a <link
|
||||
linkend="GtkHBox"><classname>GtkHBox</classname></link>. Again,
|
||||
this does not draw anything by itself, but rather asks its children
|
||||
to draw themselves. The children are numbered 7 and 9.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
The thin rectangle is a <link
|
||||
linkend="GtkButton"><classname>GtkButton</classname></link> with
|
||||
a single child, numbered 8. First the button would draw its
|
||||
beveled box, and then it would ask its child to draw itself.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
This is a text label which has no children, so it just draws its
|
||||
own text: "Cancel".
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Similar to number 7, this is a button with a single child, numbered
|
||||
10. First the button would draw its beveled box, and then it would
|
||||
ask its child to draw itself.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Similar to number 8, this is a text label which has no children,
|
||||
so it just draws its own text: "OK".
|
||||
</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
</para>
|
||||
|
||||
<figure id="figure-hierarchical-drawing">
|
||||
<title>Hierarchical drawing order</title>
|
||||
|
||||
<graphic fileref="figure-hierarchical-drawing.png" format="png"/>
|
||||
</figure>
|
||||
</refsect2>
|
||||
|
||||
</refsect1>
|
||||
@ -330,16 +262,6 @@
|
||||
<refsect1 id="double-buffering">
|
||||
<title>Double buffering</title>
|
||||
|
||||
<para>
|
||||
When the GTK layer receives an exposure event from GDK, it first finds
|
||||
the <literal>!<constant>GTK_NO_WINDOW</constant></literal> widget 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 <constant>GTK_NO_WINDOW</constant> children to
|
||||
draw themselves.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
If each of the drawing calls made by each subwidget's
|
||||
<literal>draw</literal> handler were sent directly to the
|
||||
@ -352,26 +274,6 @@
|
||||
when all drawing operations are done.
|
||||
</para>
|
||||
|
||||
<!-- FIXME: figure with a timeline of non-double-buffered and
|
||||
double-buffered paints:
|
||||
|
||||
onscreen:
|
||||
[garbage]
|
||||
[background]
|
||||
[button-frame]
|
||||
[icon]
|
||||
[label]
|
||||
|
||||
|
||||
onscreen: offscreen:
|
||||
[garbage]
|
||||
[background]
|
||||
[button-frame]
|
||||
[icon]
|
||||
[label]
|
||||
[final result]
|
||||
-->
|
||||
|
||||
<para>
|
||||
Two basic functions in GDK form the core of the double-buffering
|
||||
mechanism: <link
|
||||
@ -396,14 +298,11 @@
|
||||
</para>
|
||||
|
||||
<para>
|
||||
To make this easier, most GTK+ widgets have the
|
||||
<constant>GTK_DOUBLE_BUFFERED</constant> <link
|
||||
linkend="GtkWidgetFlags">widget flag</link> turned on by
|
||||
default. When GTK+ encounters such a widget, it automatically
|
||||
calls <function>gdk_window_begin_paint_region()</function>
|
||||
before emitting the #GtkWidget::draw signal for the widget, and
|
||||
To make this easier, GTK+ normally calls
|
||||
<function>gdk_window_begin_paint_region()</function>
|
||||
before emitting the #GtkWidget::draw signal, and
|
||||
then it calls <function>gdk_window_end_paint()</function>
|
||||
after the signal has been emitted. This is convenient for
|
||||
after the signal has been emitted. This is convenient for
|
||||
most widgets, as they do not need to worry about creating
|
||||
their own temporary drawing buffers or about calling those
|
||||
functions.
|
||||
@ -411,10 +310,12 @@
|
||||
|
||||
<para>
|
||||
However, some widgets may prefer to disable this kind of
|
||||
automatic double buffering and do things on their own. To do
|
||||
this, call the
|
||||
<function>gtk_widget_set_double_buffered()</function> function
|
||||
in your widget's constructor.
|
||||
automatic double buffering and do things on their own.
|
||||
To do this, call the
|
||||
<function>gtk_widget_set_double_buffered()</function>
|
||||
function in your widget's constructor. Double buffering
|
||||
can only be turned off for widgets that have a native
|
||||
window.
|
||||
</para>
|
||||
|
||||
<example id="disabling-double-buffering">
|
||||
|
Loading…
Reference in New Issue
Block a user