Primitivas de dibujo

Tomando el ejemplo de Ventana Dummy, agregamos un área de dibujo que pinta figuras simples utilizando Cairo cada vez que recibe el evento draw. La ventana se cierra con un botón que dispara el evento de destruir con un g_signal_connect_swapped.

/* vim: set et sw=4 sts=4 :
 *
 * Basado en un ejemplo de
 * https://developer.gnome.org/gtk3/stable/ch01s05.html
 *
 * Se compila con:
 * gcc main.c $(pkg-config --cflags --libs gtk+-3.0)
 *
 */
 //Se incluyen todos los tipos de la librería (no óptimo)
#include <gtk/gtk.h>
 //Callback para imprimir dibujar una figura simple
static gboolean draw(GtkWidget *widget, cairo_t *cr, gpointer data)
{
  int width = gtk_widget_get_allocated_width(widget);
  int height = gtk_widget_get_allocated_height(widget);
  cairo_surface_t *surface = gdk_window_create_similar_surface(gtk_widget_get_window(widget),
                                               CAIRO_CONTENT_COLOR, width, height);
  cairo_set_source_rgb(cr, 1, 0, 0);
  cairo_rectangle(cr, 0, 0, width / 2, height / 2);
  cairo_fill(cr);
  cairo_move_to (cr, width / 2, height / 2);
  cairo_line_to (cr, width, height / 2);
  cairo_line_to (cr, width, height);
  cairo_line_to (cr, width / 2, height / 2);
  cairo_set_line_width (cr, 4);
  cairo_set_source_rgb(cr, 0, 1, 0);
  cairo_stroke(cr);
  cairo_set_source_rgba(cr, 0, 0, 1, 0.3);
  cairo_move_to (cr, width, 0);
  cairo_line_to (cr, 0, height);
  cairo_line_to (cr, width, height);
  cairo_fill(cr);
   cairo_surface_destroy (surface);
  return FALSE;
}
 //Callback para iniciar la aplicación
static void activate(GtkApplication* app, gpointer data)
{
  //Crea una ventana de aplicación
  GtkWidget *window = gtk_application_window_new(app);
  //Define su título y tamaño
  gtk_window_set_title(GTK_WINDOW(window), "Ejemplo");
  gtk_window_set_default_size(GTK_WINDOW(window), 200, 200);
  //Crea un área para contener al botón
  GtkWidget *box = gtk_button_box_new(GTK_ORIENTATION_VERTICAL);
  gtk_container_add(GTK_CONTAINER(window), box);
   //Crea el área de dibujo y registra la señal para llenarla al exponerse
  GtkWidget *drawing_area = gtk_drawing_area_new();
  gtk_widget_set_size_request(drawing_area, 100, 100);
  g_signal_connect(drawing_area, "draw", G_CALLBACK(draw), NULL);
  gtk_container_add(GTK_CONTAINER(box), drawing_area);
   //Crea al botón y registra la señal de clicked para cerrar la aplicación
  GtkWidget *button = gtk_button_new_with_label("Cerrar");
  g_signal_connect_swapped (button, "clicked", G_CALLBACK (gtk_widget_destroy), window);
  gtk_container_add(GTK_CONTAINER(box), button);
   //Muestra todos sus componentes
  gtk_widget_show_all(window);
}
 int main (int argc, char **argv)
{
  //Crea la aplicación sin nombre ni opciones particulares
  GtkApplication *app = gtk_application_new (NULL, G_APPLICATION_FLAGS_NONE);
  //Define el método de ejecución de la aplicación con el callback
  g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
  //Ejecuta la aplicación y bloquea
  int status = g_application_run (G_APPLICATION (app), argc, argv);
  //Libera el objeto app y todos sus recursos
  g_object_unref (app);
   return status;
}