2008-11-21 08:21:28 +00:00
|
|
|
|
<?xml version="1.0"?>
|
|
|
|
|
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
|
|
|
|
|
"http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
|
|
|
|
|
]>
|
2008-12-26 06:41:23 +00:00
|
|
|
|
<refentry id="chap-drawing-model">
|
|
|
|
|
<refmeta>
|
2019-02-05 09:14:31 +00:00
|
|
|
|
<refentrytitle>The GTK Drawing Model</refentrytitle>
|
2008-12-26 06:41:23 +00:00
|
|
|
|
<manvolnum>3</manvolnum>
|
|
|
|
|
<refmiscinfo>GTK Library</refmiscinfo>
|
|
|
|
|
</refmeta>
|
|
|
|
|
|
|
|
|
|
<refnamediv>
|
2019-02-05 09:14:31 +00:00
|
|
|
|
<refname>The GTK Drawing Model</refname>
|
2008-12-26 06:41:23 +00:00
|
|
|
|
<refpurpose>
|
2019-05-03 04:57:58 +00:00
|
|
|
|
How widgets draw
|
2008-12-26 06:41:23 +00:00
|
|
|
|
</refpurpose>
|
|
|
|
|
</refnamediv>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<refsect1 id="drawing-overview">
|
2008-10-29 18:59:40 +00:00
|
|
|
|
<title>Overview of the drawing model</title>
|
|
|
|
|
|
2008-12-26 06:41:23 +00:00
|
|
|
|
<para>
|
2019-02-05 09:14:31 +00:00
|
|
|
|
This chapter describes the GTK drawing model in detail. If you
|
|
|
|
|
are interested in the procedure which GTK follows to draw its
|
2008-12-26 06:41:23 +00:00
|
|
|
|
widgets and windows, you should read this chapter; this will be
|
|
|
|
|
useful to know if you decide to implement your own widgets. This
|
|
|
|
|
chapter will also clarify the reasons behind the ways certain
|
2019-02-23 17:51:35 +00:00
|
|
|
|
things are done in GTK.
|
2008-12-26 06:41:23 +00:00
|
|
|
|
</para>
|
|
|
|
|
|
2013-11-10 08:25:48 +00:00
|
|
|
|
<refsect2 id="drawing model windows">
|
2008-10-29 18:59:40 +00:00
|
|
|
|
|
2019-02-23 17:51:35 +00:00
|
|
|
|
<title>Windows and events</title>
|
2011-03-28 13:03:38 +00:00
|
|
|
|
|
2013-11-10 08:25:48 +00:00
|
|
|
|
<para>
|
2019-02-23 17:51:35 +00:00
|
|
|
|
Applications that use a windowing system generally create
|
|
|
|
|
rectangular regions in the screen called <firstterm>surfaces</firstterm>
|
|
|
|
|
(GTK is following the Wayland terminology, other windowing systems
|
|
|
|
|
such as X11 may call these <firstterm>windows</firstterm>).
|
|
|
|
|
Traditional windowing systems do not automatically save the
|
|
|
|
|
graphical content of surfaces, and instead ask applications to
|
|
|
|
|
provide new content whenever it is needed.
|
|
|
|
|
For example, if a window that is stacked below other
|
|
|
|
|
windows gets raised to the top, then the application has to
|
|
|
|
|
repaint it, so the previously obscured area can be shown.
|
|
|
|
|
When the windowing system asks an application to redraw
|
2019-02-24 15:37:33 +00:00
|
|
|
|
a window, it sends a <firstterm>frame event</firstterm>
|
2019-02-23 17:51:35 +00:00
|
|
|
|
(<firstterm>expose event</firstterm> in X11 terminology)
|
|
|
|
|
for that window.
|
2013-11-10 08:25:48 +00:00
|
|
|
|
</para>
|
2019-02-23 17:51:35 +00:00
|
|
|
|
|
2008-10-29 18:59:40 +00:00
|
|
|
|
<para>
|
2019-02-23 17:51:35 +00:00
|
|
|
|
Each GTK toplevel window or dialog is associated with a
|
|
|
|
|
windowing system surface. Child widgets such as buttons or
|
|
|
|
|
entries don't have their own surface; they use the surface
|
|
|
|
|
of their toplevel.
|
2011-03-28 13:03:38 +00:00
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
<para>
|
2019-02-23 17:51:35 +00:00
|
|
|
|
Generally, the drawing cycle begins when GTK receives
|
|
|
|
|
a frame event from the underlying windowing system: if the
|
2013-11-10 08:25:48 +00:00
|
|
|
|
user drags a window over another one, the windowing system will
|
2019-02-23 17:51:35 +00:00
|
|
|
|
tell the underlying surface that it needs to repaint itself. The
|
2013-11-10 08:25:48 +00:00
|
|
|
|
drawing cycle can also be initiated when a widget itself decides
|
|
|
|
|
that it needs to update its display. For example, when the user
|
2019-02-24 15:37:33 +00:00
|
|
|
|
types a character in an entry widget, the entry asks GTK to queue
|
|
|
|
|
a redraw operation for itself.
|
2011-03-28 13:03:38 +00:00
|
|
|
|
</para>
|
2013-11-10 08:25:48 +00:00
|
|
|
|
|
2011-03-28 13:03:38 +00:00
|
|
|
|
<para>
|
2019-02-23 17:51:35 +00:00
|
|
|
|
The windowing system generates frame events for surfaces. The GDK
|
|
|
|
|
interface to the windowing system translates such events into
|
2019-02-24 15:37:33 +00:00
|
|
|
|
emissions of the ::render signal on the affected surfaces.
|
2019-02-23 17:51:35 +00:00
|
|
|
|
The GTK toplevel window connects to that signal, and reacts appropriately.
|
2008-10-29 18:59:40 +00:00
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
<para>
|
2019-02-05 09:14:31 +00:00
|
|
|
|
The following sections describe how GTK decides which widgets
|
2013-11-10 08:25:48 +00:00
|
|
|
|
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.
|
2008-10-29 18:59:40 +00:00
|
|
|
|
</para>
|
2011-03-28 13:03:38 +00:00
|
|
|
|
</refsect2>
|
|
|
|
|
|
2013-11-10 08:25:48 +00:00
|
|
|
|
<refsect2 id="frameclock">
|
|
|
|
|
<title>The frame clock</title>
|
2008-10-29 18:59:40 +00:00
|
|
|
|
|
|
|
|
|
<para>
|
2019-02-05 09:14:31 +00:00
|
|
|
|
All GTK applications are mainloop-driven, which means that most
|
2013-11-10 08:25:48 +00:00
|
|
|
|
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
|
2019-02-05 09:14:31 +00:00
|
|
|
|
it does. On top of this GTK has a frame clock that gives a
|
2013-11-10 08:25:48 +00:00
|
|
|
|
“pulse” to the application. This clock beats at a steady rate,
|
|
|
|
|
which is tied to the framerate of the output (this is synced to
|
2019-02-23 17:51:35 +00:00
|
|
|
|
the monitor via the window manager/compositor). A typical
|
|
|
|
|
refresh rate is 60 frames per second, so a new “pulse” happens
|
|
|
|
|
roughly every 16 milliseconds.
|
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
<para>
|
|
|
|
|
The clock has several phases:
|
2013-11-10 08:25:48 +00:00
|
|
|
|
<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.
|
2008-10-29 18:59:40 +00:00
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
<para>
|
2019-02-23 17:51:35 +00:00
|
|
|
|
The Events phase is a stretch of time between each redraw where
|
|
|
|
|
GTK processes input events from the user and other events
|
2013-11-10 08:25:48 +00:00
|
|
|
|
(like e.g. network I/O). Some events, like mouse motion are
|
2019-02-23 17:51:35 +00:00
|
|
|
|
compressed so that only a single mouse motion event per clock
|
|
|
|
|
cycle needs to be handled.
|
2008-10-29 18:59:40 +00:00
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
<para>
|
2019-02-23 17:51:35 +00:00
|
|
|
|
Once the Events phase is over, external events are paused and
|
|
|
|
|
the redraw loop is run. First is the Update phase, where all
|
2013-11-10 08:25:48 +00:00
|
|
|
|
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
|
2019-02-23 17:51:35 +00:00
|
|
|
|
drive the next phase, Layout. If there are any changes in
|
|
|
|
|
widget size requirements the new layout is calculated for the
|
|
|
|
|
widget hierarchy (i.e. sizes and positions for all widgets are
|
|
|
|
|
determined). Then comes the Paint phase, where we redraw the
|
|
|
|
|
regions of the window that need redrawing.
|
2008-10-29 18:59:40 +00:00
|
|
|
|
</para>
|
|
|
|
|
|
2013-11-10 08:25:48 +00:00
|
|
|
|
<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>
|
2008-10-29 18:59:40 +00:00
|
|
|
|
|
|
|
|
|
<para>
|
2013-11-10 08:25:48 +00:00
|
|
|
|
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).
|
2008-10-29 18:59:40 +00:00
|
|
|
|
</para>
|
2008-12-26 06:41:23 +00:00
|
|
|
|
</refsect2>
|
2008-10-29 18:59:40 +00:00
|
|
|
|
|
2019-02-23 17:51:35 +00:00
|
|
|
|
<refsect2 id="scene-graph">
|
|
|
|
|
<title>The scene graph</title>
|
2008-10-29 18:59:40 +00:00
|
|
|
|
|
|
|
|
|
<para>
|
2019-02-23 17:51:35 +00:00
|
|
|
|
The first step in “drawing” a window is that GTK creates
|
|
|
|
|
<firstterm>render nodes</firstterm> for all the widgets
|
|
|
|
|
in the window. The render nodes are combined into a tree
|
|
|
|
|
that you can think of as a <firstterm>scene graph</firstterm>
|
|
|
|
|
describing your window contents.
|
2013-11-10 08:25:48 +00:00
|
|
|
|
</para>
|
|
|
|
|
<para>
|
2019-02-23 17:51:35 +00:00
|
|
|
|
Render nodes belong to the GSK layer, and there are various kinds
|
|
|
|
|
of them, for the various kinds of drawing primitives you are likely
|
|
|
|
|
to need when translating widget content and CSS styling. Typical
|
|
|
|
|
examples are text nodes, gradient nodes, texture nodes or clip nodes.
|
2013-11-10 08:25:48 +00:00
|
|
|
|
<para>
|
2008-10-29 18:59:40 +00:00
|
|
|
|
<para>
|
2019-02-23 17:51:35 +00:00
|
|
|
|
In the past, all drawing in GTK happened via cairo. It is still possible
|
|
|
|
|
to use cairo for drawing your custom widget contents, by using a cairo
|
|
|
|
|
render node.
|
2008-10-29 18:59:40 +00:00
|
|
|
|
</para>
|
|
|
|
|
</para>
|
2019-02-23 17:51:35 +00:00
|
|
|
|
A GSK <firstterm>renderer</firstterm> takes these render nodes, transforms
|
|
|
|
|
them into rendering commands for the drawing API it targets, and arranges
|
|
|
|
|
for the resulting drawing to be associated with the right surface. GSK has
|
|
|
|
|
renderers for OpenGL, Vulkan and cairo.
|
2013-11-10 08:25:48 +00:00
|
|
|
|
</para>
|
2008-12-26 06:41:23 +00:00
|
|
|
|
</refsect2>
|
2008-10-29 18:59:40 +00:00
|
|
|
|
|
2019-02-23 17:51:35 +00:00
|
|
|
|
<refsect2 id="hierarchical-drawing">
|
|
|
|
|
<title>Hierarchical drawing</title>
|
2008-10-29 18:59:40 +00:00
|
|
|
|
|
|
|
|
|
<para>
|
2019-02-24 15:37:33 +00:00
|
|
|
|
During the Paint phase GTK receives a single ::render signal on the toplevel
|
2019-02-23 17:51:35 +00:00
|
|
|
|
window. The signal handler will create a snapshot object (which is a
|
|
|
|
|
helper for creating a scene graph) and emit a GtkWidget::snapshot() signal,
|
2019-02-24 15:37:33 +00:00
|
|
|
|
which will propagate down the widget hierarchy. This lets each widget
|
2019-02-23 17:51:35 +00:00
|
|
|
|
snapshot its content at the right place and time, correctly handling things
|
|
|
|
|
like partial transparencies and overlapping widgets.
|
2008-10-29 18:59:40 +00:00
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
<para>
|
2019-02-23 17:51:35 +00:00
|
|
|
|
To avoid excessive work when generating scene graphs, GTK caches render nodes.
|
2019-02-24 15:37:33 +00:00
|
|
|
|
Each widget keeps a reference to its render node (which in turn, will refer to
|
2019-02-23 17:51:35 +00:00
|
|
|
|
the render nodes of children, and grandchildren, and so on), and will reuse
|
2019-02-24 15:37:33 +00:00
|
|
|
|
that node during the Paint phase. Invalidating a widget (by calling
|
|
|
|
|
gtk_widget_queue_draw()) discards the cached render node, forcing the widget
|
|
|
|
|
to regenerate it the next time it needs to handle a ::snapshot.
|
2008-10-29 18:59:40 +00:00
|
|
|
|
</para>
|
2008-12-26 06:41:23 +00:00
|
|
|
|
</refsect2>
|
2019-02-23 17:51:35 +00:00
|
|
|
|
|
2008-12-26 06:41:23 +00:00
|
|
|
|
</refsect1>
|
2008-10-29 18:59:40 +00:00
|
|
|
|
|
2008-12-26 06:41:23 +00:00
|
|
|
|
</refentry>
|