Hierarchical drawing

During the Paint phase GTK receives a single “render” signal on the toplevel surface. The signal handler will create a snapshot object (which is a helper for creating a scene graph) and call the GtkWidget::snapshot() vfunc, which will propagate down the widget hierarchy. This lets each widget snapshot its content at the right place and time, correctly handling things like partial transparencies and overlapping widgets.

During the snapshotting of each widget, GTK automatically handles the CSS rendering according to the CSS box model. It snapshots first the background, then the border, then the widget content itself, and finally the outline.

To avoid excessive work when generating scene graphs, GTK caches render nodes. Each widget keeps a reference to its render node (which in turn, will refer to the render nodes of children, and grandchildren, and so on), and will reuse 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 produce a snapshot.