Search code examples
cgtk3cairo

Access to Cairo context 'cr' in GTK window


In this simple example, inside the function do_draw cairo knows on which surface to draw since it is using the argument cairo_t * cr . I don't understand where cr comes from, I suppose it was automatically created by GTK with the creation of the widget drawarea.
I want to draw (more complicated) stuff on that same cr from outside the do_draw function, but I don't know how to access cr from another function?

#include <cairo.h>
#include <gtk/gtk.h>

// gcc move.c -o move $(pkg-config --cflags --libs cairo --libs gtk+-3.0)

gboolean timer = TRUE;
int i = 1;


static gboolean do_draw(GtkWidget *widget, cairo_t *cr, gpointer user_data)
{
    cairo_select_font_face(cr, "Courier", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
    cairo_set_font_size(cr, 60);
    cairo_move_to(cr, i, 300);
    cairo_show_text(cr, "moving");
    return FALSE;
}

static gboolean time_handler(GtkWidget *widget)
{
    if (i > 15) return FALSE;
    printf("drawing frame %d\n", i);
    gtk_widget_queue_draw(widget);
    i++;
    return TRUE;
}


int main(int argc, char *argv[])
{
    // gtk inits
    gtk_init(&argc, &argv);
    GtkWidget *window  = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    GtkWidget *drawarea = gtk_drawing_area_new();
    gtk_container_add(GTK_CONTAINER(window), drawarea);
    gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
    g_signal_connect(G_OBJECT(drawarea), "draw", G_CALLBACK(do_draw), NULL);
    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
    // timer
    g_timeout_add(200, (GSourceFunc) time_handler, (gpointer) window);
    gtk_widget_show_all(window);
    gtk_main();
    return 0;
}

`


Solution

  • As far as i understand, it looks as if 'cr' was automatically created by GTK with the creation of the widget drawarea.

    No, it's a wrapper around the graphics context provided by the windowing system draw event. Whether or not that is re-created every draw is windowing system-dependent, but you cannot get that handle without being in a draw event.

    Under Windows, for example, WM_PAINT gets the drawing context with BeginPaint in its handler. But if you want to create your own context elsewhere you use GetDC to get one instead.

    Gtk however only supports the paint event to draw on widgets (ie the first half of the above). So you cannot get a drawing context outside a paint event, you need to trigger the paint event and let it draw itself.