Hi Roger, Would this be similar to using a GtkLayout and a GtkDrawingArea? If you add a drawing area to a layout you get draw scrolling and the layout can update the part of the drawing area shown on the screen even though the drawing might be on a larger area.
Eric -----Original Message----- From: rbd <r...@soest.hawaii.edu> To: gtk-app-devel-list <gtk-app-devel-list@gnome.org> Sent: Fri, Dec 30, 2016 12:24 pm Subject: Re: deprecated gtk_cairo_create Hello Sergei, Unfortunately the use of the gtk3 DrawingArea is a bit obscure and difficult to figure out. However, I have been able to make use of it very effectively in conjunction with Cairo drawing ops. For various reasons I have created a GUI toolkit library which lies between my app code and gtk3. This library includes an object known as a Canvas, which is essentially a toplevel window with scrollbars parenting a DrawingArea. The Canvas object includes a private off-screen Cairo drawing surface which I create and control completely, and I do all of my application drawing onto that surface. Then, I use the gtk3 draw signal mechanism to copy whatever recatngular areas I want from my private surface onto the DrawingArea. gtk3 passes to my drawing event handler a pointer to a Cairo context which addresses the DrawingArea's own Cairo surface, so all I need to do in the draw event handler is set a source surface on that context (in my case, the source surface is my own private Cairo surface), and copy a rectangle. As far as I know there is no safe way to access the Cairo surface of a gtk3 DrawingArea other than through the Cairo context pointer passed into the drawing event handler. Following is some incomplete, stripped down code which may help to explain the above ideas. I hope this helps! Roger Davis Univ. of Hawaii ######### code follows ########### /* Here are the relevant parts of the Canvas structure */ typedef struct { ... GtkWidget *drawarea; /* created by gtk_drawing_area_new() */ int width, height; /* size of DrawingArea */ cairo_surface_t *surface; /* my private Cairo surface */ ... } Canvas; gboolean canvasdrawevt(GtkWidget *w, cairo_t *cr, gpointer gp) /* This internal routine handles draw signals sent by GTK+3 to a Canvas' GtkDrawingArea widget. These signals will typically be generated by expose events or by program calls to gtk_widget_queue_draw_area() generated from within canvasflushregion(). This routine merely copies the rectangle(s) of interest from the off-screen Cairo drawing surface of the canvas into the actual GtkDrawingArea widget. */ { Canvas *c; if (gp == (gpointer) 0) return FALSE; c= (Canvas *) gp; if (w != c->drawarea) return FALSE; /* here I set the source to my private surface which I have already drawn */ cairo_set_source_surface(cr, c->surface, 0, 0); /* note that according to various (and occasionally obscure) GTK+3 docs, the context cr passed into this routine has already been clipped to any exposed rectangle(s) of interest (or whatever canvasflush{reg}() has marked for redraw via its call to gtk_widget_queue_draw_area()), so the following call to copy the whole drawing surface is not as expensive as it looks! */ cairo_rectangle(cr, 0, 0, (double) c->width, (double) c->height); cairo_fill(cr); return TRUE; } /* Here is how the important parts of the Canvas are created ... */ Canvas * canvascreate(gint width, gint height, ... ) { Canvas *c; int i; GtkWidget *win, *lo, *sw; GdkGeometry geom; if ((c= (Canvas *) calloc((MemSizeType) 1, sizeof(Canvas))) == (Canvas *) 0) return (Canvas *) 0; ... /* create the DrawingArea */ c->width= width; c->height= height; if ((c->drawarea= gtk_drawing_area_new()) == (GtkWidget *) 0) { canvasdestroy(c); return (Canvas *) 0; } gtk_widget_set_size_request(c->drawarea, width, height); gtk_widget_set_can_focus(c->drawarea, TRUE); ... /* attach the drawing event handler */ g_signal_connect((gpointer) c->drawarea, "draw", G_CALLBACK(canvasdrawevt), (gpointer) c); ... /* create our private Cairo surface on which we will draw everything */ if ((c->surface= cairo_image_surface_create(CAIRO_FORMAT_ARGB32, (int) width, (int) height)) == (cairo_surface_t *) 0) { canvasdestroy(c); return (GITCanvas *) 0; } ... return c; } /* Call this routine to copy our private Cairo surface to the DrawingArea whenever we want (i.e., after we have done all our drawing into the former). A call to this routine will result in our drawing event handler above being called asynchronously at some later time (but probably just about immediately). */ void canvasflushregion(Canvas *c, int x0, int x1, int y0, int y1) { unsigned int w, h; /* my real code checks x0/x1/y0/y1 for correctness before proceeding! */ ... w= (unsigned int) (x1-x0+1); h= (unsigned int) (y1-y0+1); /* the following call will result in GTK+3/GDK sending a draw signal on the rectangle of interest that will ultimately be handled within canvasdrawevt(); see further comments there */ gtk_widget_queue_draw_area(c->drawarea, px0, py0, w, h); return; } _______________________________________________ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list _______________________________________________ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list