# HG changeset patch # User bsmith@81767d24-ef19-dc11-ae90-00e081727c95 # Date 1683160773 0 # Node ID a74b30a9d744e6c66300077bc28b60b4cff924b1 # Parent 8311be624877e0f7dc1d567f7a44140700d39fb6 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. diff -r 8311be624877 -r a74b30a9d744 mac/dw.m --- 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; diff -r 8311be624877 -r a74b30a9d744 os2/dw.c --- 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; } diff -r 8311be624877 -r a74b30a9d744 win/dw.c --- 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: {