diff --git a/Makefile b/Makefile index 5996913..10df65e 100644 --- a/Makefile +++ b/Makefile @@ -144,6 +144,17 @@ else ifeq ($(SCENIC_LOCAL_TARGET),cairo-fb) $(CAIRO_COMMON_SRCS) \ c_src/device/cairo/cairo_fb.c +else ifeq ($(SCENIC_LOCAL_TARGET),cairo-gtk) +# need libgtk-3-dev libsystemd-dev libwebp-dev libzstd-dev + LDFLAGS += `pkg-config --static --libs freetype2 cairo gtk+-3.0` + CFLAGS += `pkg-config --static --cflags freetype2 cairo gtk+-3.0` + LDFLAGS += -lm + CFLAGS ?= -O2 -Wall -Wextra -Wno-unused-parameter -pedantic + CFLAGS += -std=gnu99 + + DEVICE_SRCS += \ + $(CAIRO_COMMON_SRCS) \ + c_src/device/cairo/cairo_gtk.c else $(info ------ no SCENIC_LOCAL_TARGET set ------) $(info If you get here, then you are probably using a custom Nerves system) diff --git a/c_src/device/cairo/cairo_gtk.c b/c_src/device/cairo/cairo_gtk.c new file mode 100644 index 0000000..3161739 --- /dev/null +++ b/c_src/device/cairo/cairo_gtk.c @@ -0,0 +1,144 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "cairo_ctx.h" +#include "comms.h" +#include "device.h" +#include "fontstash.h" +#include "script_ops.h" + +typedef struct { + GThread* main; + GtkWidget* window; + GMutex draw_mutex; + GCond draw_finished; +} cairo_gtk_t; + +cairo_gtk_t g_cairo_gtk; + +extern device_info_t g_device_info; +extern device_opts_t g_opts; + +static gpointer cairo_gtk_main(gpointer user_data) +{ + gtk_widget_show_all((GtkWidget*)g_cairo_gtk.window); + gtk_main(); + + return NULL; +} + +static gboolean on_draw(GtkWidget* widget, + cairo_t* cr, + gpointer data) +{ + g_mutex_lock (&g_cairo_gtk.draw_mutex); + + scenic_cairo_ctx_t* p_ctx = (scenic_cairo_ctx_t*)data; + cairo_set_source_surface(cr, p_ctx->surface, 0, 0); + cairo_paint(cr); + + g_cond_signal(&g_cairo_gtk.draw_finished); + g_mutex_unlock(&g_cairo_gtk.draw_mutex); + + return FALSE; +} + +static gboolean +on_delete_event(GtkWidget* widget, + GdkEvent* event, + gpointer data) +{ + send_close(0); + return TRUE; +} + +int device_init(const device_opts_t* p_opts, + device_info_t* p_info, + driver_data_t* p_data) +{ + if (g_opts.debug_mode) { + log_error("cairo %s", __func__); + } + + scenic_cairo_ctx_t* p_ctx = scenic_cairo_init(p_opts, p_info); + if (!p_ctx) { + log_error("cairo %s failed", __func__); + return -1; + } + + gtk_init(NULL, NULL); + + g_cairo_gtk.window = gtk_window_new(GTK_WINDOW_TOPLEVEL); + gtk_window_set_title(GTK_WINDOW(g_cairo_gtk.window), "scenic_driver_local: cairo"); + gtk_window_set_default_size(GTK_WINDOW(g_cairo_gtk.window), p_info->width, p_info->height); + gtk_window_set_resizable(GTK_WINDOW(g_cairo_gtk.window), FALSE); + + g_signal_connect(G_OBJECT(g_cairo_gtk.window), "delete-event", G_CALLBACK(on_delete_event), NULL); + + GtkDrawingArea* drawing_area = (GtkDrawingArea*)gtk_drawing_area_new(); + gtk_container_add(GTK_CONTAINER(g_cairo_gtk.window), (GtkWidget*)drawing_area); + g_signal_connect((GtkWidget*)drawing_area, "draw", G_CALLBACK(on_draw), p_ctx); + + g_cairo_gtk.main = g_thread_new("gtk_main", cairo_gtk_main, NULL); + + return 0; +} + +int device_close(device_info_t* p_info) +{ + if (g_opts.debug_mode) { + log_info("cairo %s", __func__); + } + + scenic_cairo_ctx_t* p_ctx = (scenic_cairo_ctx_t*)p_info->v_ctx; + gtk_main_quit(); + g_thread_join(g_cairo_gtk.main); + scenic_cairo_fini(p_ctx); +} + +void device_poll() +{ +} + +void device_begin_render(driver_data_t* p_data) +{ + if (g_opts.debug_mode) { + log_info("cairo %s", __func__); + } + + scenic_cairo_ctx_t* p_ctx = (scenic_cairo_ctx_t*)p_data->v_ctx; + + // Paint surface to clear color + cairo_set_source_rgba(p_ctx->cr, + p_ctx->clear_color.red, + p_ctx->clear_color.green, + p_ctx->clear_color.blue, + p_ctx->clear_color.alpha); + cairo_paint(p_ctx->cr); +} + +void device_end_render(driver_data_t* p_data) +{ + if (g_opts.debug_mode) { + log_info("cairo %s", __func__); + } + + scenic_cairo_ctx_t* p_ctx = (scenic_cairo_ctx_t*)p_data->v_ctx; + + g_mutex_lock(&g_cairo_gtk.draw_mutex); + + g_cond_clear(&g_cairo_gtk.draw_finished); + gtk_widget_queue_draw((GtkWidget*)g_cairo_gtk.window); + g_cond_wait(&g_cairo_gtk.draw_finished, &g_cairo_gtk.draw_mutex); + + g_mutex_unlock(&g_cairo_gtk.draw_mutex); +}