Problem solved.
To prevent flashes of the black screen during configure-event we need to implicitly call actual drawing procedure right after the off-screen buffer is recreated.

static gboolean configureCanvas(GtkWidget *widget, GdkEventConfigure *event ) {
if (pixmap) g_object_unref(pixmap);
pixmap = gdk_pixmap_new(widget->window, widget->allocation.width, widget->allocation.height, -1);
drawAll(); // just add this!
return TRUE;
}

Full source of my test application is in the attachment - may be it would be useful for other cairo-newbies :)

On 12/13/2011 1:30 PM, George Brink wrote:
I am trying to make an animated image:
----------------------------------------------
static gboolean exposeCanvas(GtkWidget *widget, GdkEventExpose *event,
gpointer data) {
cairo_t *cr = gdk_cairo_create (event->window);
gdk_cairo_set_source_pixmap (cr, pixmap, 0, 0);
gdk_cairo_rectangle (cr, &event->area);
cairo_fill (cr);
cairo_destroy (cr);
return FALSE;
}

static gboolean configureCanvas(GtkWidget *widget, GdkEventConfigure
*event ) {
if (pixmap) g_object_unref(pixmap);
pixmap = gdk_pixmap_new(widget->window, widget->allocation.width,
widget->allocation.height, -1);
return TRUE;
}

GtkWidget *canvas = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(mainWindow), canvas);
g_signal_connect(G_OBJECT(canvas), "expose_event",
G_CALLBACK(exposeCanvas), NULL);
g_signal_connect(G_OBJECT(canvas), "configure_event",
G_CALLBACK(configureCanvas), NULL);
----------------------------------------------

It works fine on a static window, but when I actually change the size of
the window the whole drawing area goes black for a moment.
What am I doing wrong?

#include <glib.h>
#include <gtk/gtk.h>
#include <math.h>


static GdkPixmap *pixmap = NULL;

void drawAll() {
        static gdouble angle=0;

        // actual drawing - moving line over the grid
        #define WIDTH 20
        #define HEIGHT 20
        #define LINE_LENGTH 5

        guint width, height;
        gdk_drawable_get_size(pixmap, &width, &height);

        cairo_t *cr = gdk_cairo_create(pixmap);
        cairo_set_source_rgb (cr, 0.8, 0.8, 0.8);
        cairo_paint(cr);

        guint x = (width -2)/WIDTH;
        guint y = (height -2)/HEIGHT;
        guint8 cellSize = x<y ? x : y;
        guint leftPadding = (width - WIDTH*cellSize) / 2;
        guint topPadding = (height - HEIGHT*cellSize) / 2;

        cairo_set_line_width (cr, 1.0);
        cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
        cairo_set_source_rgb (cr, 0.3, 0.3, 0.3);

        for(x=0; x<=WIDTH; x++) {
                cairo_move_to (cr, leftPadding+x*cellSize, topPadding);
                cairo_line_to (cr, leftPadding+x*cellSize, 
topPadding+HEIGHT*cellSize);
        }
        for(y=0; y<=HEIGHT; y++) {
                cairo_move_to (cr, leftPadding, topPadding+y*cellSize);
                cairo_line_to (cr, leftPadding+WIDTH*cellSize, 
topPadding+y*cellSize);
        }
        cairo_stroke(cr);

        cairo_set_line_width (cr, 3.0);
        cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
        cairo_move_to (cr, width/2, height/2);
        cairo_line_to (cr, width/2 + cos(angle)*LINE_LENGTH*cellSize, height/2 
+ sin(angle)*LINE_LENGTH*cellSize);
        angle += M_PI/180.0;
        if(angle> 2*M_PI) angle=0;

        cairo_stroke(cr);
        cairo_destroy(cr);
}


static gboolean exposeCanvas(GtkWidget *widget, GdkEventExpose *event, gpointer 
data) {
        cairo_t *cr = gdk_cairo_create (event->window);
        gdk_cairo_set_source_pixmap (cr, pixmap, 0, 0);
        gdk_cairo_rectangle (cr, &event->area);
        cairo_fill (cr);
        cairo_destroy (cr);
        return FALSE;
}

static gboolean configureCanvas(GtkWidget *widget, GdkEventConfigure *event ) {
        if (pixmap) g_object_unref(pixmap);
        pixmap = gdk_pixmap_new(widget->window, widget->allocation.width, 
widget->allocation.height, -1);
        drawAll();
        return TRUE;
}

static gboolean timerTick(gpointer data) {
        drawAll();

        GDK_THREADS_ENTER ();
        gtk_widget_queue_draw (GTK_WIDGET(data));
        GDK_THREADS_LEAVE ();
        return TRUE;
}



int main(int argc, char **argv) {
        gtk_init(&argc, &argv);

        GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        g_signal_connect(window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
        gtk_window_set_title(GTK_WINDOW(window), "test");

        GtkWidget *canvas = gtk_drawing_area_new();
        gtk_container_add(GTK_CONTAINER(window), canvas);
        g_signal_connect(G_OBJECT(canvas), "expose_event", 
G_CALLBACK(exposeCanvas), NULL);
        g_signal_connect(G_OBJECT(canvas), "configure_event", 
G_CALLBACK(configureCanvas), NULL);
        guint timerID = g_timeout_add(100, timerTick, canvas);

        gtk_widget_show_all(window);
        gtk_main();
        return 0;
}
_______________________________________________
gtk-list mailing list
[email protected]
http://mail.gnome.org/mailman/listinfo/gtk-list

Reply via email to