diff options
author | Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | 2018-09-05 13:50:39 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab+samsung@kernel.org> | 2018-09-05 14:18:06 -0300 |
commit | 01fccdeaea087e73c933e71890908a6b6dc23ac1 (patch) | |
tree | 07cc0b86ac81cac09b580beed89ca4aeec8f125d | |
parent | 98a4baa241cfd710e27d51871f17bee3f60930cc (diff) |
callbacks: use a callback to draw at GtkDrawingAreagtk3_improvements
Gtk 3 supports wayland, but there's a catch: while the
current code works properly with X11, it doesn't draw
anything inside the GtkDrawingArea on Wayland.
The fix is trivial, but incompatible with Gtk2: instead of
updating the drawing aea inside the main loop, a callback
has to be used in order to handle gtk draw logic.
As, at least for now, we want to keep supporting Gtk 2,
let's add a compatibility code.
That fixes drawing with Wayland.
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
-rw-r--r-- | data/camorama.ui | 1 | ||||
-rw-r--r-- | src/callbacks.c | 103 | ||||
-rw-r--r-- | src/callbacks.h | 1 | ||||
-rw-r--r-- | src/main.c | 5 | ||||
-rw-r--r-- | src/v4l.h | 1 |
5 files changed, 70 insertions, 41 deletions
diff --git a/data/camorama.ui b/data/camorama.ui index 9f99b38..8a19cbe 100644 --- a/data/camorama.ui +++ b/data/camorama.ui @@ -1372,6 +1372,7 @@ <property name="height_request">240</property> <property name="visible">True</property> <property name="can_focus">False</property> + <signal name="draw" handler="show_buffer" swapped="no"/> </object> </child> </object> diff --git a/src/callbacks.c b/src/callbacks.c index f8a378e..a38a1dc 100644 --- a/src/callbacks.c +++ b/src/callbacks.c @@ -497,12 +497,10 @@ static void apply_filters(cam_t *cam) * https://github.com/bratsche/gtk-/blob/master/gdk/gdkcairo.c * With a small backport. */ +#if GTK_MAJOR_VERSION < 3 static cairo_surface_t *create_from_pixbuf(const GdkPixbuf *pixbuf, GdkWindow *for_window) { -#if GTK_MAJOR_VERSION >= 3 - return gdk_cairo_surface_create_from_pixbuf(pixbuf, 1, for_window); -#else gint width = gdk_pixbuf_get_width(pixbuf); gint height = gdk_pixbuf_get_height(pixbuf); guchar *gdk_pixels = gdk_pixbuf_get_pixels(pixbuf); @@ -567,82 +565,92 @@ static cairo_surface_t *create_from_pixbuf(const GdkPixbuf *pixbuf, cairo_surface_mark_dirty(surface); return surface; -#endif } static void show_buffer(cam_t *cam) { - GdkPixbuf *pb; GtkWidget *widget; GdkWindow *window; cairo_surface_t *surface; cairo_t *cr; - unsigned char *pic_buf = cam->pic_buf; - const GdkRectangle rect = { .x = 0, .y = 0, .width = cam->width, .height = cam->height }; -#if GTK_MAJOR_VERSION >= 3 && GTK_MINOR_VERSION >= 22 - GdkDrawingContext *context; - cairo_region_t *region; -#endif - /* - * refer the frame - */ - if (cam->pixformat == V4L2_PIX_FMT_YUV420) { - yuv420p_to_rgb(cam->pic_buf, cam->tmp, cam->width, cam->height, - cam->bpp / 8); - pic_buf = cam->tmp; - } - - apply_filters(cam); - - /* Use cairo to display the pixel buffer */ - - pb = gdk_pixbuf_new_from_data(pic_buf, GDK_COLORSPACE_RGB, FALSE, 8, - cam->width, cam->height, - (cam->width * cam->bpp / 8), NULL, NULL); + if (!cam->pb) + return; widget = GTK_WIDGET(gtk_builder_get_object(cam->xml, "da")); window = gtk_widget_get_window(widget); - surface = create_from_pixbuf(pb, window); - -#if GTK_MAJOR_VERSION >= 3 && GTK_MINOR_VERSION >= 22 - region = cairo_region_create(); - context = gdk_window_begin_draw_frame(window, region); - cr = gdk_drawing_context_get_cairo_context(context); -#else + surface = create_from_pixbuf(cam->pb, window); cr = gdk_cairo_create(window); -#endif - cairo_set_source_surface(cr, surface, 0, 0); + gdk_cairo_rectangle(cr, &rect); + cairo_fill(cr); + cairo_destroy(cr); + cairo_surface_destroy(surface); -#if GTK_MAJOR_VERSION >= 3 && GTK_MINOR_VERSION >= 22 - gdk_window_end_draw_frame(window, context); + frames++; + frames2++; +} #else - cairo_destroy(cr); - cairo_region_destroy(region); -#endif +/* + * GTK 3 way: use a drawing callback + */ +void draw_callback(GtkWidget *widget, cairo_t *cr, cam_t *cam) +{ + GdkWindow *window; + cairo_surface_t *surface; + const GdkRectangle rect = { + .x = 0, .y = 0, + .width = cam->width, .height = cam->height + }; + if (!cam->pb) + return; + + window = gtk_widget_get_window(widget); + surface = gdk_cairo_surface_create_from_pixbuf(cam->pb, 1, window); + cairo_set_source_surface(cr, surface, 0, 0); + gdk_cairo_rectangle(cr, &rect); + cairo_fill(cr); cairo_surface_destroy(surface); frames++; frames2++; } +static inline void show_buffer(cam_t *cam) +{ + gtk_widget_queue_draw(GTK_WIDGET(gtk_builder_get_object(cam->xml, "da"))); +} +#endif + /* * get image from cam - does all the work ;) */ gint read_timeout_func(cam_t *cam) { + unsigned char *pic_buf = cam->pic_buf; + v4l2_read(cam->dev, cam->pic_buf, (cam->width * cam->height * cam->bpp / 8)); + if (cam->pixformat == V4L2_PIX_FMT_YUV420) { + yuv420p_to_rgb(cam->pic_buf, cam->tmp, cam->width, cam->height, + cam->bpp / 8); + pic_buf = cam->tmp; + } + apply_filters(cam); + cam->pb = gdk_pixbuf_new_from_data(pic_buf, GDK_COLORSPACE_RGB, FALSE, 8, + cam->width, cam->height, + (cam->width * cam->bpp / 8), + NULL, NULL); + show_buffer(cam); return TRUE; @@ -650,9 +658,22 @@ gint read_timeout_func(cam_t *cam) gint timeout_func(cam_t *cam) { + unsigned char *pic_buf = cam->pic_buf; + capture_buffers(cam, cam->pic_buf, cam->width * cam->height * cam->bytesperline); + if (cam->pixformat == V4L2_PIX_FMT_YUV420) { + yuv420p_to_rgb(cam->pic_buf, cam->tmp, cam->width, cam->height, + cam->bpp / 8); + pic_buf = cam->tmp; + } + apply_filters(cam); + cam->pb = gdk_pixbuf_new_from_data(pic_buf, GDK_COLORSPACE_RGB, FALSE, 8, + cam->width, cam->height, + (cam->width * cam->bpp / 8), + NULL, NULL); + show_buffer(cam); return TRUE; diff --git a/src/callbacks.h b/src/callbacks.h index c0c2e1b..30e15b2 100644 --- a/src/callbacks.h +++ b/src/callbacks.h @@ -33,6 +33,7 @@ void ppm_func(GtkWidget *, cam_t *); void rts_func(GtkWidget *, cam_t *); void rjpg_func(GtkWidget *, cam_t *); void rpng_func(GtkWidget *, cam_t *); +void draw_callback(GtkWidget *, cairo_t *, cam_t *cam); gint(*pt2Function) (cam_t *); void rppm_func(GtkWidget *, cam_t *); @@ -217,6 +217,11 @@ int main(int argc, char *argv[]) load_interface(cam); widget = GTK_WIDGET(gtk_builder_get_object(cam->xml, "da")); + +#if GTK_MAJOR_VERSION >= 3 + g_signal_connect(G_OBJECT(widget), "draw", G_CALLBACK(draw_callback), cam); +#endif + gtk_widget_show(widget); cam->idle_id = g_idle_add((GSourceFunc) pt2Function, (gpointer) cam); @@ -79,6 +79,7 @@ typedef struct camera { guint32 timeout_interval; GConfClient *gc; GtkBuilder *xml; + GdkPixbuf *pb; GtkStatusIcon *tray_icon; CamoramaFilterChain *filter_chain; |