changeset 2281:0e93b09ed0e1

GTK4: Cache the cairo context during the drawing area callback. This allows drawing to work for now. However drawing outside of the callback to widgets is currently broken, and not entirely sure it can be fixed with GTK4.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Wed, 03 Feb 2021 07:43:18 +0000
parents 7902be60c542
children b045bb67922d
files gtk4/dw.c
diffstat 1 files changed, 133 insertions(+), 90 deletions(-) [+]
line wrap: on
line diff
--- a/gtk4/dw.c	Wed Feb 03 06:40:36 2021 +0000
+++ b/gtk4/dw.c	Wed Feb 03 07:43:18 2021 +0000
@@ -545,18 +545,20 @@
 
 static gint _dw_expose_event(GtkWidget *widget, cairo_t *cr, int width, int height, gpointer data)
 {
-   SignalHandler work = _dw_get_signal_handler(data);
    int retval = FALSE;
 
-   if(work.window)
+   if(widget && GTK_IS_DRAWING_AREA(widget))
    {
       DWExpose exp;
-      int (*exposefunc)(HWND, DWExpose *, void *) = work.func;
+      int (*exposefunc)(HWND, DWExpose *, void *) = g_object_get_data(G_OBJECT(widget), "_dw_expose_func");
 
       exp.x = exp.y = 0;
       exp.width = width;
       exp.height = height;
-      retval = exposefunc(work.window, &exp, work.data);
+      /* Save the cairo context for use in the drawing functions */
+      g_object_set_data(G_OBJECT(widget), "_dw_cr", (gpointer)cr);
+      retval = exposefunc((HWND)widget, &exp, data);
+      g_object_set_data(G_OBJECT(widget), "_dw_cr", NULL);
    }
    return retval;
 }
@@ -5474,21 +5476,27 @@
 {
    cairo_t *cr = NULL;
    GdkDrawContext *dc = NULL;
+   int cached = FALSE;
 
    if(handle)
    {
-      GtkNative *native = gtk_widget_get_native(handle);
-      GdkSurface *surface = gtk_native_get_surface(native);
-
-      if((dc = GDK_DRAW_CONTEXT(gdk_surface_create_cairo_context(surface))))
-      {
-         cairo_region_t *region = cairo_region_create();
-         gdk_draw_context_begin_frame(dc, region);
-         cr = gdk_cairo_context_cairo_create(GDK_CAIRO_CONTEXT(dc));
-         cairo_region_destroy(region);
-      }
+      if((cr = g_object_get_data(G_OBJECT(handle), "_dw_cr")))
+         cached = TRUE;
       else
-         return;
+      {
+         GtkNative *native = gtk_widget_get_native(handle);
+         GdkSurface *surface = gtk_native_get_surface(native);
+
+         if((dc = GDK_DRAW_CONTEXT(gdk_surface_create_cairo_context(surface))))
+         {
+            cairo_region_t *region = cairo_region_create();
+            gdk_draw_context_begin_frame(dc, region);
+            cr = gdk_cairo_context_cairo_create(GDK_CAIRO_CONTEXT(dc));
+            cairo_region_destroy(region);
+         }
+         else
+            return;
+      }
    }
    else if(pixmap)
       cr = cairo_create(pixmap->image);
@@ -5505,7 +5513,7 @@
        */
       if(dc)
          gdk_draw_context_end_frame(dc);
-      else
+      else if(!cached)
          cairo_destroy(cr);
    }
 }
@@ -5523,21 +5531,27 @@
 {
    cairo_t *cr = NULL;
    GdkDrawContext *dc = NULL;
+   int cached = FALSE;
 
    if(handle)
    {
-      GtkNative *native = gtk_widget_get_native(handle);
-      GdkSurface *surface = gtk_native_get_surface(native);
-
-      if((dc = GDK_DRAW_CONTEXT(gdk_surface_create_cairo_context(surface))))
-      {
-         cairo_region_t *region = cairo_region_create();
-         gdk_draw_context_begin_frame(dc, region);
-         cr = gdk_cairo_context_cairo_create(GDK_CAIRO_CONTEXT(dc));
-         cairo_region_destroy(region);
-      }
+      if((cr = g_object_get_data(G_OBJECT(handle), "_dw_cr")))
+         cached = TRUE;
       else
-         return;
+      {
+         GtkNative *native = gtk_widget_get_native(handle);
+         GdkSurface *surface = gtk_native_get_surface(native);
+
+         if((dc = GDK_DRAW_CONTEXT(gdk_surface_create_cairo_context(surface))))
+         {
+            cairo_region_t *region = cairo_region_create();
+            gdk_draw_context_begin_frame(dc, region);
+            cr = gdk_cairo_context_cairo_create(GDK_CAIRO_CONTEXT(dc));
+            cairo_region_destroy(region);
+         }
+         else
+            return;
+      }
    }
    else if(pixmap)
       cr = cairo_create(pixmap->image);
@@ -5555,7 +5569,7 @@
        */
       if(dc)
          gdk_draw_context_end_frame(dc);
-      else
+      else if(!cached)
          cairo_destroy(cr);
    }
 }
@@ -5574,21 +5588,27 @@
    cairo_t *cr = NULL;
    int z;
    GdkDrawContext *dc = NULL;
+   int cached = FALSE;
 
    if(handle)
    {
-      GtkNative *native = gtk_widget_get_native(handle);
-      GdkSurface *surface = gtk_native_get_surface(native);
-
-      if((dc = GDK_DRAW_CONTEXT(gdk_surface_create_cairo_context(surface))))
-      {
-         cairo_region_t *region = cairo_region_create();
-         gdk_draw_context_begin_frame(dc, region);
-         cr = gdk_cairo_context_cairo_create(GDK_CAIRO_CONTEXT(dc));
-         cairo_region_destroy(region);
-      }
+      if((cr = g_object_get_data(G_OBJECT(handle), "_dw_cr")))
+         cached = TRUE;
       else
-         return;
+      {
+         GtkNative *native = gtk_widget_get_native(handle);
+         GdkSurface *surface = gtk_native_get_surface(native);
+
+         if((dc = GDK_DRAW_CONTEXT(gdk_surface_create_cairo_context(surface))))
+         {
+            cairo_region_t *region = cairo_region_create();
+            gdk_draw_context_begin_frame(dc, region);
+            cr = gdk_cairo_context_cairo_create(GDK_CAIRO_CONTEXT(dc));
+            cairo_region_destroy(region);
+         }
+         else
+            return;
+      }
    }
    else if(pixmap)
       cr = cairo_create(pixmap->image);
@@ -5614,7 +5634,7 @@
        */
       if(dc)
          gdk_draw_context_end_frame(dc);
-      else
+      else if(!cached)
          cairo_destroy(cr);
    }
 }
@@ -5633,21 +5653,27 @@
 {
    cairo_t *cr = NULL;
    GdkDrawContext *dc = NULL;
+   int cached = FALSE;
 
    if(handle)
    {
-      GtkNative *native = gtk_widget_get_native(handle);
-      GdkSurface *surface = gtk_native_get_surface(native);
-
-      if((dc = GDK_DRAW_CONTEXT(gdk_surface_create_cairo_context(surface))))
-      {
-         cairo_region_t *region = cairo_region_create();
-         gdk_draw_context_begin_frame(dc, region);
-         cr = gdk_cairo_context_cairo_create(GDK_CAIRO_CONTEXT(dc));
-         cairo_region_destroy(region);
-      }
+      if((cr = g_object_get_data(G_OBJECT(handle), "_dw_cr")))
+         cached = TRUE;
       else
-         return;
+      {
+         GtkNative *native = gtk_widget_get_native(handle);
+         GdkSurface *surface = gtk_native_get_surface(native);
+
+         if((dc = GDK_DRAW_CONTEXT(gdk_surface_create_cairo_context(surface))))
+         {
+            cairo_region_t *region = cairo_region_create();
+            gdk_draw_context_begin_frame(dc, region);
+            cr = gdk_cairo_context_cairo_create(GDK_CAIRO_CONTEXT(dc));
+            cairo_region_destroy(region);
+         }
+         else
+            return;
+      }
    }
    else if(pixmap)
       cr = cairo_create(pixmap->image);
@@ -5672,7 +5698,7 @@
        */
       if(dc)
          gdk_draw_context_end_frame(dc);
-      else
+      else if(!cached)
          cairo_destroy(cr);
    }
 }
@@ -5694,21 +5720,27 @@
 {
    cairo_t *cr = NULL;
    GdkDrawContext *dc = NULL;
+   int cached = FALSE;
 
    if(handle)
    {
-      GtkNative *native = gtk_widget_get_native(handle);
-      GdkSurface *surface = gtk_native_get_surface(native);
-
-      if((dc = GDK_DRAW_CONTEXT(gdk_surface_create_cairo_context(surface))))
-      {
-         cairo_region_t *region = cairo_region_create();
-         gdk_draw_context_begin_frame(dc, region);
-         cr = gdk_cairo_context_cairo_create(GDK_CAIRO_CONTEXT(dc));
-         cairo_region_destroy(region);
-      }
+      if((cr = g_object_get_data(G_OBJECT(handle), "_dw_cr")))
+         cached = TRUE;
       else
-         return;
+      {
+         GtkNative *native = gtk_widget_get_native(handle);
+         GdkSurface *surface = gtk_native_get_surface(native);
+
+         if((dc = GDK_DRAW_CONTEXT(gdk_surface_create_cairo_context(surface))))
+         {
+            cairo_region_t *region = cairo_region_create();
+            gdk_draw_context_begin_frame(dc, region);
+            cr = gdk_cairo_context_cairo_create(GDK_CAIRO_CONTEXT(dc));
+            cairo_region_destroy(region);
+         }
+         else
+            return;
+      }
    }
    else if(pixmap)
       cr = cairo_create(pixmap->image);
@@ -5745,7 +5777,7 @@
        */
       if(dc)
          gdk_draw_context_end_frame(dc);
-      else
+      else if(!cached)
          cairo_destroy(cr);
    }
 }
@@ -5764,24 +5796,30 @@
    PangoFontDescription *font;
    char *tmpname, *fontname = "monospace 10";
    GdkDrawContext *dc = NULL;
+   int cached = FALSE;
 
    if(!text)
       return;
 
    if(handle)
    {
-      GtkNative *native = gtk_widget_get_native(handle);
-      GdkSurface *surface = gtk_native_get_surface(native);
-
-      if((dc = GDK_DRAW_CONTEXT(gdk_surface_create_cairo_context(surface))))
-      {
-         cairo_region_t *region = cairo_region_create();
-         gdk_draw_context_begin_frame(dc, region);
-         cr = gdk_cairo_context_cairo_create(GDK_CAIRO_CONTEXT(dc));
-         cairo_region_destroy(region);
-      }
+      if((cr = g_object_get_data(G_OBJECT(handle), "_dw_cr")))
+         cached = TRUE;
       else
-         return;
+      {
+         GtkNative *native = gtk_widget_get_native(handle);
+         GdkSurface *surface = gtk_native_get_surface(native);
+
+         if((dc = GDK_DRAW_CONTEXT(gdk_surface_create_cairo_context(surface))))
+         {
+            cairo_region_t *region = cairo_region_create();
+            gdk_draw_context_begin_frame(dc, region);
+            cr = gdk_cairo_context_cairo_create(GDK_CAIRO_CONTEXT(dc));
+            cairo_region_destroy(region);
+         }
+         else
+            return;
+      }
       if((tmpname = (char *)g_object_get_data(G_OBJECT(handle), "_dw_fontname")))
          fontname = tmpname;
    }
@@ -5842,7 +5880,7 @@
        */
       if(dc)
          gdk_draw_context_end_frame(dc);
-      else
+      else if(!cached)
          cairo_destroy(cr);
    }
 }
@@ -6161,24 +6199,30 @@
    cairo_t *cr = NULL;
    int retval = DW_ERROR_GENERAL;
    GdkDrawContext *dc = NULL;
+   int cached = FALSE;
 
    if((!dest && (!destp || !destp->image)) || (!src && (!srcp || !srcp->image)))
       return retval;
 
    if(dest)
    {
-      GtkNative *native = gtk_widget_get_native(dest);
-      GdkSurface *surface = gtk_native_get_surface(native);
-
-      if((dc = GDK_DRAW_CONTEXT(gdk_surface_create_cairo_context(surface))))
-      {
-         cairo_region_t *region = cairo_region_create();
-         gdk_draw_context_begin_frame(dc, region);
-         cr = gdk_cairo_context_cairo_create(GDK_CAIRO_CONTEXT(dc));
-         cairo_region_destroy(region);
-      }
+      if((cr = g_object_get_data(G_OBJECT(dest), "_dw_cr")))
+         cached = TRUE;
       else
-         return retval;
+      {
+         GtkNative *native = gtk_widget_get_native(dest);
+         GdkSurface *surface = gtk_native_get_surface(native);
+
+         if((dc = GDK_DRAW_CONTEXT(gdk_surface_create_cairo_context(surface))))
+         {
+            cairo_region_t *region = cairo_region_create();
+            gdk_draw_context_begin_frame(dc, region);
+            cr = gdk_cairo_context_cairo_create(GDK_CAIRO_CONTEXT(dc));
+            cairo_region_destroy(region);
+         }
+         else
+            return retval;
+      }
    }
    else if(destp)
       cr = cairo_create(destp->image);
@@ -6209,7 +6253,7 @@
        */
       if(dc)
          gdk_draw_context_end_frame(dc);
-      else
+      else if(!cached)
          cairo_destroy(cr);
       retval = DW_ERROR_NONE;
    }
@@ -9539,9 +9583,8 @@
 {
    if(GTK_IS_DRAWING_AREA(object))
    {
-      /* TODO: Might need to use the disconnect paramater since this isn't a normal signal handler */
+      g_object_set_data(object, "_dw_expose_func", sigfunc);
       gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(object), signal->func, data, NULL);
-      _dw_set_signal_handler(object, (HWND)object, sigfunc, data, signal->func, discfunc);
       return NULL;
    }
    return object;