diff win/dw.c @ 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 0e47ca67aab0
children
line wrap: on
line diff
--- 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:
         {