changeset 2997:8450b87e960c

GTK2/3/4: Implement DW_FEATURE_RENDER_SAFE. GTK2: Disabled by default. GTK3: Disabled by default on X11, Always enabled on Wayland and other types. GTK4: Always enabled on any display type.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Thu, 04 May 2023 02:50:45 +0000
parents 84b8e4917a0d
children 4861e9f49907
files gtk/dw.c gtk3/dw.c gtk4/dw.c
diffstat 3 files changed, 122 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/gtk/dw.c	Thu May 04 00:49:05 2023 +0000
+++ b/gtk/dw.c	Thu May 04 02:50:45 2023 +0000
@@ -135,6 +135,26 @@
 #endif
 char *_DWDefaultFont = NULL;
 static char _dw_share_path[PATH_MAX+1] = { 0 };
+static int _dw_render_safe_mode = DW_FEATURE_DISABLED;
+
+/* Return TRUE if it is safe to draw on the window handle.
+ * Either we are in unsafe mode, or we are in an EXPOSE
+ * event for the requested render window handle.
+ */
+int _dw_render_safe_check(GtkWidget *handle)
+{
+    if(_dw_render_safe_mode == DW_FEATURE_DISABLED || 
+       (handle && gtk_object_get_data(GTK_OBJECT(handle), "_dw_expose")))
+           return TRUE;
+    return FALSE;
+}
+
+int _dw_is_render(GtkWidget *handle)
+{
+   if(GTK_IS_DRAWING_AREA(handle))
+       return TRUE;
+   return FALSE;
+}
 
 #if GTK_MAJOR_VERSION < 2
 static int _dw_file_active = 0;
@@ -1464,12 +1484,20 @@
    {
       DWExpose exp;
       int (*exposefunc)(HWND, DWExpose *, void *) = work.func;
+      gpointer oldrender = NULL;
 
       exp.x = event->area.x;
       exp.y = event->area.y;
       exp.width = event->area.width;
       exp.height = event->area.height;
+      if(_dw_render_safe_mode == DW_FEATURE_ENABLED && _dw_is_render(work.window))
+      {
+      	oldrender = gtk_object_get_data(GTK_OBJECT(work.window), "_dw_expose");
+      	gtk_object_set_data(GTK_OBJECT(work.window), "_dw_expose", (gpointer)1);
+      }
       retval = exposefunc(work.window, &exp, work.data);
+      if(_dw_render_safe_mode == DW_FEATURE_ENABLED)
+      	gtk_object_set_data(GTK_OBJECT(work.window), "_dw_expose", oldrender);
    }
    return retval;
 }
@@ -8562,7 +8590,7 @@
 #endif
 
    DW_MUTEX_LOCK;
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
       gc = _dw_set_colors(handle->window);
    else if(pixmap && pixmap->pixmap)
       gc = _dw_set_colors(pixmap->pixmap);
@@ -8606,7 +8634,7 @@
 #endif
 
    DW_MUTEX_LOCK;
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
       gc = _dw_set_colors(handle->window);
    else if(pixmap && pixmap->pixmap)
       gc = _dw_set_colors(pixmap->pixmap);
@@ -8653,7 +8681,7 @@
 #endif
 
    DW_MUTEX_LOCK;
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
       gc = _dw_set_colors(handle->window);
    else if(pixmap && pixmap->pixmap)
       gc = _dw_set_colors(pixmap->pixmap);
@@ -8717,7 +8745,7 @@
 #endif
 
    DW_MUTEX_LOCK;
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
       gc = _dw_set_colors(handle->window);
    else if(pixmap && pixmap->pixmap)
       gc = _dw_set_colors(pixmap->pixmap);
@@ -8778,7 +8806,7 @@
    int height = width;
 
    DW_MUTEX_LOCK;
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
       gc = _dw_set_colors(handle->window);
    else if(pixmap && pixmap->pixmap)
       gc = _dw_set_colors(pixmap->pixmap);
@@ -8871,7 +8899,7 @@
       return;
 
    DW_MUTEX_LOCK;
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
    {
       if((tmpname = (char *)gtk_object_get_data(GTK_OBJECT(handle), "_dw_fontname")))
          fontname = tmpname;
@@ -9403,7 +9431,7 @@
       return retval;
 
    DW_MUTEX_LOCK;
-   if(dest)
+   if(dest && _dw_render_safe_check(dest))
    {
       GdkWindow *window = gtk_widget_get_window(dest);
       /* Safety check for non-existant windows */
@@ -9520,7 +9548,7 @@
       return retval;
 
    DW_MUTEX_LOCK;
-   if(dest)
+   if(dest && _dw_render_safe_check(dest))
       gc = _dw_set_colors(dest->window);
    else if(src)
       gc = _dw_set_colors(src->window);
@@ -9529,7 +9557,7 @@
    else if(srcp)
       gc = gdk_gc_new(srcp->pixmap);
 
-   if ( gc )
+   if(gc)
    {
 #if GTK_MAJOR_VERSION > 1
       if(srcwidth != -1)
@@ -9567,25 +9595,25 @@
          /*
           * If we have a bitmap (mask) in the source pixmap, then set the clipping region
           */
-         if ( srcp && srcp->bitmap )
-         {
-            gdk_gc_set_clip_mask( gc, srcp->bitmap );
-            gdk_gc_set_clip_origin( gc, xdest, ydest );
-         }
-         gdk_draw_pixmap( dest ? dest->window : destp->pixmap, gc, src ? src->window : srcp->pixmap, xsrc, ysrc, xdest, ydest, width, height );
+         if(srcp && srcp->bitmap)
+         {
+            gdk_gc_set_clip_mask(gc, srcp->bitmap);
+            gdk_gc_set_clip_origin(gc, xdest, ydest);
+         }
+         gdk_draw_pixmap(dest ? dest->window : destp->pixmap, gc, src ? src->window : srcp->pixmap, xsrc, ysrc, xdest, ydest, width, height);
 
       }
 
       /*
        * Reset the clipping region
        */
-      if ( srcp && srcp->bitmap )
-      {
-         gdk_gc_set_clip_mask( gc, NULL );
-         gdk_gc_set_clip_origin( gc, 0, 0 );
-      }
-
-      gdk_gc_unref( gc );
+      if(srcp && srcp->bitmap)
+      {
+         gdk_gc_set_clip_mask(gc, NULL);
+         gdk_gc_set_clip_origin(gc, 0, 0);
+      }
+
+      gdk_gc_unref(gc);
       retval = DW_ERROR_NONE;
    }
    DW_MUTEX_UNLOCK;
@@ -14126,6 +14154,8 @@
         case DW_FEATURE_TREE:
         case DW_FEATURE_WINDOW_PLACEMENT:
             return DW_FEATURE_ENABLED;
+        case DW_FEATURE_RENDER_SAFE:
+            return _dw_render_safe_mode;
         default:
             return DW_FEATURE_UNSUPPORTED;
     }
@@ -14168,6 +14198,15 @@
         case DW_FEATURE_WINDOW_PLACEMENT:
             return DW_ERROR_GENERAL;
         /* These features are supported and configurable */
+        case DW_FEATURE_RENDER_SAFE:
+        {
+            if(state == DW_FEATURE_ENABLED || state == DW_FEATURE_DISABLED)
+            {
+                _dw_render_safe_mode = state;
+                return DW_ERROR_NONE;
+            }
+            return DW_ERROR_GENERAL;
+        }
         default:
             return DW_FEATURE_UNSUPPORTED;
     }
--- a/gtk3/dw.c	Thu May 04 00:49:05 2023 +0000
+++ b/gtk3/dw.c	Thu May 04 02:50:45 2023 +0000
@@ -188,6 +188,26 @@
 #endif
 char *_DWDefaultFont = NULL;
 static char _dw_share_path[PATH_MAX+1] = { 0 };
+static int _dw_render_safe_mode = DW_FEATURE_UNSUPPORTED;
+
+/* Return TRUE if it is safe to draw on the window handle.
+ * Either we are in unsafe mode, or we are in an EXPOSE
+ * event for the requested render window handle.
+ */
+int _dw_render_safe_check(GtkWidget *handle)
+{
+    if(_dw_render_safe_mode == DW_FEATURE_DISABLED || 
+       (handle && g_object_get_data(G_OBJECT(handle), "_dw_expose")))
+           return TRUE;
+    return FALSE;
+}
+
+int _dw_is_render(GtkWidget *handle)
+{
+   if(GTK_IS_DRAWING_AREA(handle))
+       return TRUE;
+   return FALSE;
+}
 
 typedef struct
 {
@@ -1605,6 +1625,7 @@
    {
       DWExpose exp;
       int (*exposefunc)(HWND, DWExpose *, void *) = work.func;
+      gpointer oldrender = NULL;
 
       /* Remove the currently drawn widget from the dirty list */
       _dw_dirty_list = g_list_remove(_dw_dirty_list, widget);
@@ -1613,7 +1634,14 @@
       exp.width = gtk_widget_get_allocated_width(widget);
       exp.height = gtk_widget_get_allocated_height(widget);
       g_object_set_data(G_OBJECT(work.window), "_dw_cr", (gpointer)cr);
+      if(_dw_render_safe_mode == DW_FEATURE_ENABLED && _dw_is_render(work.window))
+      {
+      	oldrender = g_object_get_data(G_OBJECT(work.window), "_dw_expose");
+      	g_object_set_data(G_OBJECT(work.window), "_dw_expose", (gpointer)1);
+      }
       retval = exposefunc(work.window, &exp, work.data);
+      if(_dw_render_safe_mode == DW_FEATURE_ENABLED)
+      	g_object_set_data(G_OBJECT(work.window), "_dw_expose", oldrender);
       g_object_set_data(G_OBJECT(work.window), "_dw_cr", NULL);
    }
    return retval;
@@ -2243,7 +2271,19 @@
       g_application_activate(_DWApp);
    }
 #endif
-   return TRUE;
+   if(_dw_render_safe_mode == DW_FEATURE_UNSUPPORTED)
+   {
+#ifdef GDK_WINDOWING_X11
+   	GdkDisplay *display = gdk_display_get_default();
+   
+	   /* If we are in X11 mode safe mode should be disabled by default */
+	   if(display && GDK_IS_X11_DISPLAY(display))
+	   	_dw_render_safe_mode = DW_FEATURE_DISABLED;
+	   else
+#endif
+			_dw_render_safe_mode = DW_FEATURE_ENABLED;
+	}
+	return DW_ERROR_NONE;
 }
 
 /*
@@ -7483,7 +7523,7 @@
 #endif
 
    DW_MUTEX_LOCK;
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
    {
       GdkDisplay *display = gdk_display_get_default();
 
@@ -7559,7 +7599,7 @@
 #endif
 
    DW_MUTEX_LOCK;
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
    {
       GdkDisplay *display = gdk_display_get_default();
       
@@ -7637,7 +7677,7 @@
 #endif
 
    DW_MUTEX_LOCK;
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
    {
       GdkDisplay *display = gdk_display_get_default();
       
@@ -7723,7 +7763,7 @@
 #endif
 
    DW_MUTEX_LOCK;
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
    {
       GdkDisplay *display = gdk_display_get_default();
       
@@ -7811,7 +7851,7 @@
 #endif
 
    DW_MUTEX_LOCK;
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
    {
       GdkDisplay *display = gdk_display_get_default();
       
@@ -7911,7 +7951,7 @@
       return;
 
    DW_MUTEX_LOCK;
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
    {
       GdkDisplay *display = gdk_display_get_default();
       
@@ -8388,7 +8428,7 @@
       return retval;
 
    DW_MUTEX_LOCK;
-   if(dest)
+   if(dest && _dw_render_safe_check(dest))
    {
       GdkDisplay *display = gdk_display_get_default();
       
@@ -12905,6 +12945,8 @@
         case DW_FEATURE_MLE_WORD_WRAP:
         case DW_FEATURE_TREE:
             return DW_FEATURE_ENABLED;
+        case DW_FEATURE_RENDER_SAFE:
+            return _dw_render_safe_mode;
 #ifdef GDK_WINDOWING_X11
         case DW_FEATURE_WINDOW_PLACEMENT:
         {
@@ -12980,6 +13022,15 @@
         }
 #endif
         /* These features are supported and configurable */
+        case DW_FEATURE_RENDER_SAFE:
+        {
+            if(state == DW_FEATURE_ENABLED || state == DW_FEATURE_DISABLED)
+            {
+                _dw_render_safe_mode = state;
+                return DW_ERROR_NONE;
+            }
+            return DW_ERROR_GENERAL;
+        }
         default:
             return DW_FEATURE_UNSUPPORTED;
     }
--- a/gtk4/dw.c	Thu May 04 00:49:05 2023 +0000
+++ b/gtk4/dw.c	Thu May 04 02:50:45 2023 +0000
@@ -11447,6 +11447,7 @@
         case DW_FEATURE_UTF8_UNICODE:
         case DW_FEATURE_MLE_WORD_WRAP:
         case DW_FEATURE_TREE:
+        case DW_FEATURE_RENDER_SAFE:
             return DW_FEATURE_ENABLED;
         case DW_FEATURE_WINDOW_PLACEMENT:
             return dw_x11_check(DW_FEATURE_ENABLED, DW_FEATURE_UNSUPPORTED);
@@ -11482,6 +11483,7 @@
         case DW_FEATURE_UTF8_UNICODE:
         case DW_FEATURE_MLE_WORD_WRAP:
         case DW_FEATURE_TREE:
+        case DW_FEATURE_RENDER_SAFE:
             return DW_ERROR_GENERAL;
         case DW_FEATURE_WINDOW_PLACEMENT:
             return dw_x11_check(DW_ERROR_GENERAL, DW_FEATURE_UNSUPPORTED);