changeset 2995:a74b30a9d744

Win/OS2: Implement DW_FEATURE_RENDER_SAFE. Defaults to disabled. When enabled drawing functions will fail when not in an EXPOSE callback. Untested on OS/2... will followup if it doesn't work there.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Thu, 04 May 2023 00:39:33 +0000
parents 8311be624877
children 84b8e4917a0d
files mac/dw.m os2/dw.c win/dw.c
diffstat 3 files changed, 115 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/mac/dw.m	Wed May 03 23:29:17 2023 +0000
+++ b/mac/dw.m	Thu May 04 00:39:33 2023 +0000
@@ -755,7 +755,7 @@
                 exp.width = rect.size.width;
                 exp.height = rect.size.height;
                 /* The render expose is only valid for render class windows */
-                if(_dw_is_render(object))
+                if(_dw_render_safe_mode == DW_FEATURE_ENABLED && _dw_is_render(object))
                     _dw_render_expose = object;
                 int result = exposefunc(object, &exp, handler->data);
                 _dw_render_expose = oldrender;
@@ -13626,7 +13626,7 @@
         /* These features are supported and configurable */
         case DW_FEATURE_RENDER_SAFE:
         {
-            if (state == DW_FEATURE_ENABLED || state == DW_FEATURE_DISABLED)
+            if(state == DW_FEATURE_ENABLED || state == DW_FEATURE_DISABLED)
             {
                 _dw_render_safe_mode = state;
                 return DW_ERROR_NONE;
--- a/os2/dw.c	Wed May 03 23:29:17 2023 +0000
+++ b/os2/dw.c	Thu May 04 00:39:33 2023 +0000
@@ -124,6 +124,27 @@
 HWND _dw_lasthcnr = 0, _dw_lastitem = 0, _dw_popup = 0, _dw_desktop;
 HMOD _dw_wpconfig = 0, _dw_pmprintf = 0, _dw_pmmerge = 0, _dw_gbm = 0;
 static char _dw_exec_dir[MAX_PATH+1] = {0};
+static int _dw_render_safe_mode = DW_FEATURE_DISABLED;
+static HWND _dw_render_expose = DW_NOHWND;
+
+/* 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(HWND handle)
+{
+    if(_dw_render_safe_mode == DW_FEATURE_DISABLED || 
+       (handle && _dw_render_expose == handle))
+           return TRUE;
+    return FALSE;
+}
+
+int _dw_is_render(HWND handle)
+{
+   if(dw_window_get_data(hwndframe, "_dw_render"))
+       return TRUE;
+   return FALSE;
+}
 
 #ifdef UNICODE
 /* Atom for "text/unicode" clipboard format */
@@ -3122,13 +3143,17 @@
                if(hWnd == tmp->window)
                {
                   int height = _dw_get_height(hWnd);
+                  HWND oldrender = _dw_render_expose;
 
                   hps = WinBeginPaint(hWnd, 0L, &rc);
                   exp.x = rc.xLeft;
                   exp.y = height - rc.yTop;
                   exp.width = rc.xRight - rc. xLeft;
                   exp.height = rc.yTop - rc.yBottom;
+                  if(_dw_render_safe_mode == DW_FEATURE_ENABLED && _dw_is_render(hWnd))
+                     _dw_render_expose = hWnd;
                   result = exposefunc(hWnd, &exp, tmp->data);
+                  _dw_render_expose = oldrender;
                   WinEndPaint(hps);
                }
             }
@@ -10833,7 +10858,7 @@
    int height;
    POINTL ptl;
 
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
    {
       hps = _dw_set_colors(handle);
       height = _dw_get_height(handle);
@@ -10869,7 +10894,7 @@
    int height;
    POINTL ptl[2];
 
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
    {
       hps = _dw_set_colors(handle);
       height = _dw_get_height(handle);
@@ -10936,7 +10961,7 @@
     char fontname[128];
     POINTL aptl[TXTBOX_COUNT];
 
-    if(handle)
+    if(handle && _dw_render_safe_check(handle))
     {
         hps = _dw_set_colors(handle);
         height = _dw_get_height(handle);
@@ -11027,7 +11052,7 @@
  *       width: Width of rectangle.
  *       height: Height of rectangle.
  */
-void API dw_draw_polygon( HWND handle, HPIXMAP pixmap, int flags, int npoints, int *x, int *y )
+void API dw_draw_polygon(HWND handle, HPIXMAP pixmap, int flags, int npoints, int *x, int *y)
 {
    HPS hps;
    int thisheight;
@@ -11035,7 +11060,7 @@
    POINTL start;
    int i;
 
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
    {
       hps = _dw_set_colors(handle);
       thisheight = _dw_get_height(handle);
@@ -11099,7 +11124,7 @@
    int thisheight;
    POINTL ptl[2];
 
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
    {
       hps = _dw_set_colors(handle);
       thisheight = _dw_get_height(handle);
@@ -11150,7 +11175,7 @@
    POINTL pts[2];
    double r, a1, a2, a;
 
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
    {
       hps = _dw_set_colors(handle);
       thisheight = _dw_get_height(handle);
@@ -11539,7 +11564,7 @@
    if((srcheight == -1 || srcwidth == -1) && srcheight != srcwidth)
       return DW_ERROR_GENERAL;
 
-   if(dest)
+   if(dest && _dw_render_safe_check(dest))
    {
       hpsdest = WinGetPS(dest);
       dheight = _dw_get_height(dest);
@@ -13955,6 +13980,8 @@
                 return DW_FEATURE_ENABLED;
             return DW_FEATURE_UNSUPPORTED;
         }
+        case DW_FEATURE_RENDER_SAFE:
+            return _dw_render_safe_mode;
         default:
             return DW_FEATURE_UNSUPPORTED;
     }
@@ -13995,6 +14022,15 @@
             return DW_FEATURE_UNSUPPORTED;
         }
         /* 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/win/dw.c	Wed May 03 23:29:17 2023 +0000
+++ b/win/dw.c	Thu May 04 00:39:33 2023 +0000
@@ -306,6 +306,31 @@
 static char _dw_exec_dir[MAX_PATH+1] = {0};
 static char _dw_app_id[_DW_APP_ID_SIZE+1]= {0};
 static char _dw_app_name[_DW_APP_ID_SIZE+1]= {0};
+static int _dw_render_safe_mode = DW_FEATURE_DISABLED;
+static HWND _dw_render_expose = DW_NOHWND;
+
+/* 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(HWND handle)
+{
+    if(_dw_render_safe_mode == DW_FEATURE_DISABLED || 
+       (handle && _dw_render_expose == handle))
+           return TRUE;
+    return FALSE;
+}
+
+int _dw_is_render(HWND handle)
+{
+   TCHAR tmpbuf[100] = {0};
+
+   GetClassName(handle, tmpbuf, 99);
+
+   if(_tcsnicmp(tmpbuf, ObjectClassName, _tcslen(ObjectClassName)+1) == 0)
+       return TRUE;
+   return FALSE;
+}
 
 int main(int argc, char *argv[]);
 
@@ -2462,14 +2487,19 @@
                      DWExpose exp;
                      int (DWSIGNAL *exposefunc)(HWND, DWExpose *, void *) = tmp->signalfunction;
 
-                     if ( hWnd == tmp->window )
+                     if(hWnd == tmp->window)
                      {
+                        HWND oldrender = _dw_render_expose;
+
                         BeginPaint(hWnd, &ps);
                         exp.x = ps.rcPaint.left;
                         exp.y = ps.rcPaint.top;
                         exp.width = ps.rcPaint.right - ps.rcPaint.left;
                         exp.height = ps.rcPaint.bottom - ps.rcPaint.top;
+                        if(_dw_render_safe_mode == DW_FEATURE_ENABLED && _dw_is_render(hWnd))
+                            _dw_render_expose = hWnd;
                         result = exposefunc(hWnd, &exp, tmp->data);
+                        _dw_render_expose = oldrender;
                         EndPaint(hWnd, &ps);
                      }
                   }
@@ -11242,7 +11272,7 @@
 #else
    HDC hdcPaint;
 
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
       hdcPaint = GetDC(handle);
    else if(pixmap)
       hdcPaint = pixmap->hdc;
@@ -11270,7 +11300,7 @@
    GpGraphics *graphics = NULL;
    GpPen *pen = TlsGetValue(_dw_gppen);
 
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
       GdipCreateFromHWND(handle, &graphics);
    else if(pixmap)
       GdipCreateFromHDC(pixmap->hdc, &graphics);
@@ -11284,7 +11314,7 @@
    HDC hdcPaint;
    HPEN oldPen;
 
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
       hdcPaint = GetDC(handle);
    else if(pixmap)
       hdcPaint = pixmap->hdc;
@@ -11358,7 +11388,7 @@
    {
       GpGraphics *graphics = NULL;
 
-      if(handle)
+      if(handle && _dw_render_safe_check(handle))
          GdipCreateFromHWND(handle, &graphics);
       else if(pixmap)
          GdipCreateFromHDC(pixmap->hdc, &graphics);
@@ -11390,9 +11420,9 @@
    {
       HDC hdcPaint;
 
-      if ( handle )
+      if(handle && _dw_render_safe_check(handle))
          hdcPaint = GetDC( handle );
-      else if ( pixmap )
+      else if(pixmap)
          hdcPaint = pixmap->hdc;
       else
          return;
@@ -11434,7 +11464,7 @@
 #ifdef GDIPLUS
    GpGraphics *graphics = NULL;
 
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
       GdipCreateFromHWND(handle, &graphics);
    else if(pixmap)
       GdipCreateFromHDC(pixmap->hdc, &graphics);
@@ -11462,7 +11492,7 @@
    HDC hdcPaint;
    RECT Rect;
 
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
       hdcPaint = GetDC(handle);
    else if(pixmap)
       hdcPaint = pixmap->hdc;
@@ -11498,7 +11528,7 @@
    GpGraphics *graphics = NULL;
    GpPen *pen = TlsGetValue(_dw_gppen);
 
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
       GdipCreateFromHWND(handle, &graphics);
    else if(pixmap)
       GdipCreateFromHDC(pixmap->hdc, &graphics);
@@ -11547,7 +11577,7 @@
    double r = sqrt(dx*dx + dy*dy);
    int ri = (int)r;
 
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
       hdcPaint = GetDC(handle);
    else if(pixmap)
       hdcPaint = pixmap->hdc;
@@ -11616,7 +11646,7 @@
    COLORREF background;
    TCHAR *wtext = UTF8toWide(text);
 
-   if(handle)
+   if(handle && _dw_render_safe_check(handle))
       hdc = GetDC(handle);
    else if(pixmap)
       hdc = pixmap->hdc;
@@ -12109,16 +12139,16 @@
    int swidth = srcwidth, sheight = srcheight;
 
    /* Do some sanity checks */
-   if ( dest )
-      hdcdest = GetDC( dest );
-   else if ( destp )
+   if(dest && _dw_render_safe_check(dest))
+      hdcdest = GetDC(dest);
+   else if(destp)
       hdcdest = destp->hdc;
    else
       return DW_ERROR_GENERAL;
 
-   if ( src )
-      hdcsrc = GetDC( src );
-   else if ( srcp )
+   if(src)
+      hdcsrc = GetDC(src);
+   else if(srcp)
       hdcsrc = srcp->hdc;
    else
       return DW_ERROR_GENERAL;
@@ -12141,27 +12171,27 @@
 #endif
 
    /* If it is a 32bpp bitmap (with alpha) use AlphaBlend unless it fails */
-   if ( srcp && srcp->depth == 32 && AlphaBlend( hdcdest, xdest, ydest, width, height, hdcsrc, xsrc, ysrc, swidth, sheight, bf ) )
+   if(srcp && srcp->depth == 32 && AlphaBlend(hdcdest, xdest, ydest, width, height, hdcsrc, xsrc, ysrc, swidth, sheight, bf))
    {
         /* Don't do anything */
    }
    /* Otherwise perform special bitblt with manual transparency */
-   else if ( srcp && srcp->transcolor != DW_RGB_TRANSPARENT )
+   else if(srcp && srcp->transcolor != DW_RGB_TRANSPARENT)
    {
       TransparentBlt( hdcdest, xdest, ydest, width, height, hdcsrc, xsrc, ysrc, swidth, sheight, RGB( DW_RED_VALUE(srcp->transcolor), DW_GREEN_VALUE(srcp->transcolor), DW_BLUE_VALUE(srcp->transcolor)) );
    }
    else
    {
       /* Finally fall back to the classic BitBlt */
-      if( srcwidth == -1 && srcheight == -1)
-         BitBlt( hdcdest, xdest, ydest, width, height, hdcsrc, xsrc, ysrc, SRCCOPY );
+      if(srcwidth == -1 && srcheight == -1)
+         BitBlt(hdcdest, xdest, ydest, width, height, hdcsrc, xsrc, ysrc, SRCCOPY);
       else
-         StretchBlt( hdcdest, xdest, ydest, width, height, hdcsrc, xsrc, ysrc, swidth, sheight, SRCCOPY );
-   }
-   if ( !destp )
-      ReleaseDC( dest, hdcdest );
-   if ( !srcp )
-      ReleaseDC( src, hdcsrc );
+         StretchBlt(hdcdest, xdest, ydest, width, height, hdcsrc, xsrc, ysrc, swidth, sheight, SRCCOPY);
+   }
+   if(!destp)
+      ReleaseDC(dest, hdcdest);
+   if(!srcp)
+      ReleaseDC(src, hdcsrc);
 
    return DW_ERROR_NONE;
 }
@@ -13975,6 +14005,8 @@
         case DW_FEATURE_TREE:
         case DW_FEATURE_WINDOW_PLACEMENT:
             return DW_FEATURE_ENABLED;
+        case DW_FEATURE_RENDER_SAFE:
+            return _dw_render_safe_mode;
 #if defined(BUILD_HTML) && defined(BUILD_EDGE)
         case DW_FEATURE_HTML_MESSAGE:
             return _DW_EDGE_DETECTED ? DW_FEATURE_ENABLED : DW_FEATURE_UNSUPPORTED;
@@ -14078,6 +14110,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;
+        }
 #ifdef AEROGLASS
         case DW_FEATURE_DARK_MODE:
         {