# HG changeset patch # User bsmith@81767d24-ef19-dc11-ae90-00e081727c95 # Date 1683156557 0 # Node ID 8311be624877e0f7dc1d567f7a44140700d39fb6 # Parent 392f0b3dd502012ba1081c933986839c1bcfead9 Mac/iOS: Implement DW_FEATURE_RENDER_SAFE. iOS always operates in safe render mode. Mac defaults to disabled, enabling will enforce expose event restrictions on drawing to render widgets. diff -r 392f0b3dd502 -r 8311be624877 ios/dw.m --- a/ios/dw.m Tue May 02 11:37:48 2023 +0000 +++ b/ios/dw.m Wed May 03 23:29:17 2023 +0000 @@ -12262,6 +12262,7 @@ case DW_FEATURE_MLE_WORD_WRAP: case DW_FEATURE_UTF8_UNICODE: case DW_FEATURE_TREE: + case DW_FEATURE_RENDER_SAFE: return DW_FEATURE_ENABLED; case DW_FEATURE_CONTAINER_MODE: return _dw_container_mode; @@ -12313,6 +12314,7 @@ case DW_FEATURE_MLE_WORD_WRAP: case DW_FEATURE_UTF8_UNICODE: case DW_FEATURE_TREE: + case DW_FEATURE_RENDER_SAFE: return DW_ERROR_GENERAL; case DW_FEATURE_CONTAINER_MODE: { diff -r 392f0b3dd502 -r 8311be624877 mac/dw.m --- a/mac/dw.m Tue May 02 11:37:48 2023 +0000 +++ b/mac/dw.m Wed May 03 23:29:17 2023 +0000 @@ -521,6 +521,22 @@ static int DWOSMajor, DWOSMinor, DWOSBuild; static char _dw_bundle_path[PATH_MAX+1] = { 0 }; static char _dw_app_id[_DW_APP_ID_SIZE+1]= {0}; +static int _dw_render_safe_mode = DW_FEATURE_DISABLED; +static id _dw_render_expose = nil; + +/* 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(id handle) +{ + if(_dw_render_safe_mode == DW_FEATURE_DISABLED || + (handle && _dw_render_expose == handle)) + return TRUE; + return FALSE; +} + +int _dw_is_render(id handle); /* Create a default colors for a thread */ void _dw_init_colors(void) @@ -732,12 +748,17 @@ DWExpose exp; int (* API exposefunc)(HWND, DWExpose *, void *) = (int (* API)(HWND, DWExpose *, void *))handler->signalfunction; NSRect rect = [object frame]; + id oldrender = _dw_render_expose; exp.x = rect.origin.x; exp.y = rect.origin.y; 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)) + _dw_render_expose = object; int result = exposefunc(object, &exp, handler->data); + _dw_render_expose = oldrender; #ifndef BUILDING_FOR_MOJAVE [[object window] flushWindow]; #endif @@ -1263,6 +1284,14 @@ -(BOOL)acceptsFirstResponder { return YES; } @end +/* So we can check before DWRender is declared */ +int _dw_is_render(id handle) +{ + if([handle isMemberOfClass:[DWRender class]]) + return TRUE; + return FALSE; +} + @implementation DWObject -(void)uselessThread:(id)sender { /* Thread only to initialize threading */ } #ifndef BUILDING_FOR_MOJAVE @@ -7004,17 +7033,22 @@ bi = (id)pixmap->image; else { + if(_dw_render_safe_check(handle)) + { #ifdef BUILDING_FOR_MOJAVE - if([image isMemberOfClass:[DWRender class]]) - { - DWRender *render = image; - - bi = [render cachedDrawingRep]; - } + if([image isMemberOfClass:[DWRender class]]) + { + DWRender *render = image; + + bi = [render cachedDrawingRep]; + } #else - if((bCanDraw = [image lockFocusIfCanDraw]) == YES) - _DWLastDrawable = handle; -#endif + if((bCanDraw = [image lockFocusIfCanDraw]) == YES) + _DWLastDrawable = handle; +#endif + } + else + bCanDraw = NO; } if(bi) { @@ -7068,17 +7102,22 @@ bi = (id)pixmap->image; else { + if(_dw_render_safe_check(handle)) + { #ifdef BUILDING_FOR_MOJAVE - if([image isMemberOfClass:[DWRender class]]) - { - DWRender *render = image; - - bi = [render cachedDrawingRep]; - } + if([image isMemberOfClass:[DWRender class]]) + { + DWRender *render = image; + + bi = [render cachedDrawingRep]; + } #else - if((bCanDraw = [image lockFocusIfCanDraw]) == YES) - _DWLastDrawable = handle; -#endif + if((bCanDraw = [image lockFocusIfCanDraw]) == YES) + _DWLastDrawable = handle; +#endif + } + else + bCanDraw = NO; } if(bi) { @@ -7143,14 +7182,19 @@ } else if(image && [image isMemberOfClass:[DWRender class]]) { - render = image; - font = [render font]; + if(_dw_render_safe_check(handle)) + { + render = image; + font = [render font]; #ifdef BUILDING_FOR_MOJAVE - bi = [render cachedDrawingRep]; + bi = [render cachedDrawingRep]; #else - if((bCanDraw = [image lockFocusIfCanDraw]) == YES) - _DWLastDrawable = handle; -#endif + if((bCanDraw = [image lockFocusIfCanDraw]) == YES) + _DWLastDrawable = handle; +#endif + } + else + bCanDraw = NO; } if(bi) { @@ -7275,20 +7319,25 @@ bi = (id)pixmap->image; else { + if(_dw_render_safe_check(handle)) + { #ifdef BUILDING_FOR_MOJAVE - if([image isMemberOfClass:[DWRender class]]) - { - DWRender *render = image; - - bi = [render cachedDrawingRep]; - } + if([image isMemberOfClass:[DWRender class]]) + { + DWRender *render = image; + + bi = [render cachedDrawingRep]; + } #else - if((bCanDraw = [image lockFocusIfCanDraw]) == YES) - { - _DWLastDrawable = handle; - [[NSGraphicsContext currentContext] setShouldAntialias:(flags & DW_DRAW_NOAA ? NO : YES)]; - } -#endif + if((bCanDraw = [image lockFocusIfCanDraw]) == YES) + { + _DWLastDrawable = handle; + [[NSGraphicsContext currentContext] setShouldAntialias:(flags & DW_DRAW_NOAA ? NO : YES)]; + } +#endif + } + else + bCanDraw = NO; } if(bi) { @@ -7354,20 +7403,25 @@ bi = (id)pixmap->image; else { + if(_dw_render_safe_check(handle)) + { #ifdef BUILDING_FOR_MOJAVE - if([image isMemberOfClass:[DWRender class]]) - { - DWRender *render = image; - - bi = [render cachedDrawingRep]; - } + if([image isMemberOfClass:[DWRender class]]) + { + DWRender *render = image; + + bi = [render cachedDrawingRep]; + } #else - if((bCanDraw = [image lockFocusIfCanDraw]) == YES) - { - _DWLastDrawable = handle; - [[NSGraphicsContext currentContext] setShouldAntialias:(flags & DW_DRAW_NOAA ? NO : YES)]; - } -#endif + if((bCanDraw = [image lockFocusIfCanDraw]) == YES) + { + _DWLastDrawable = handle; + [[NSGraphicsContext currentContext] setShouldAntialias:(flags & DW_DRAW_NOAA ? NO : YES)]; + } +#endif + } + else + bCanDraw = NO; } if(bi) { @@ -7428,20 +7482,25 @@ bi = (id)pixmap->image; else { + if(_dw_render_safe_check(handle)) + { #ifdef BUILDING_FOR_MOJAVE - if([image isMemberOfClass:[DWRender class]]) - { - DWRender *render = image; - - bi = [render cachedDrawingRep]; - } + if([image isMemberOfClass:[DWRender class]]) + { + DWRender *render = image; + + bi = [render cachedDrawingRep]; + } #else - if((bCanDraw = [image lockFocusIfCanDraw]) == YES) - { - _DWLastDrawable = handle; - [[NSGraphicsContext currentContext] setShouldAntialias:(flags & DW_DRAW_NOAA ? NO : YES)]; - } -#endif + if((bCanDraw = [image lockFocusIfCanDraw]) == YES) + { + _DWLastDrawable = handle; + [[NSGraphicsContext currentContext] setShouldAntialias:(flags & DW_DRAW_NOAA ? NO : YES)]; + } +#endif + } + else + bCanDraw = NO; } if(bi) { @@ -9284,7 +9343,8 @@ /* Sanity checks */ if((!dest && !destp) || (!src && !srcp) || - ((srcwidth == -1 || srcheight == -1) && srcwidth != srcheight)) + ((srcwidth == -1 || srcheight == -1) && srcwidth != srcheight) || + (dest && !_dw_render_safe_check(dest))) { DW_LOCAL_POOL_OUT; return DW_ERROR_GENERAL; @@ -13477,6 +13537,8 @@ case DW_FEATURE_TREE: case DW_FEATURE_WINDOW_PLACEMENT: return DW_FEATURE_ENABLED; + case DW_FEATURE_RENDER_SAFE: + return _dw_render_safe_mode; #ifdef BUILDING_FOR_MOJAVE case DW_FEATURE_DARK_MODE: { @@ -13562,6 +13624,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; + } #ifdef BUILDING_FOR_MOJAVE case DW_FEATURE_DARK_MODE: {