# HG changeset patch # User bsmith@81767d24-ef19-dc11-ae90-00e081727c95 # Date 1683168645 0 # Node ID 8450b87e960c0cd2a34465d64df9a22bc651765d # Parent 84b8e4917a0d8e5c79824c690f309b97da2ea84f 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. diff -r 84b8e4917a0d -r 8450b87e960c gtk/dw.c --- 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; } diff -r 84b8e4917a0d -r 8450b87e960c gtk3/dw.c --- 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; } diff -r 84b8e4917a0d -r 8450b87e960c gtk4/dw.c --- 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);