[PATCH 2/5] winemac.drv: Use a mask layer to support window regions.

Chip Davis cdavis at codeweavers.com
Tue Aug 31 17:27:34 CDT 2021


Signed-off-by: Chip Davis <cdavis at codeweavers.com>
---
 dlls/winemac.drv/cocoa_window.h |  2 -
 dlls/winemac.drv/cocoa_window.m | 89 ++++++++++++++++-----------------
 2 files changed, 44 insertions(+), 47 deletions(-)

diff --git a/dlls/winemac.drv/cocoa_window.h b/dlls/winemac.drv/cocoa_window.h
index f9c3902dc36..d04961f8251 100644
--- a/dlls/winemac.drv/cocoa_window.h
+++ b/dlls/winemac.drv/cocoa_window.h
@@ -51,8 +51,6 @@ @interface WineWindow : NSPanel <NSWindowDelegate>
     NSRect wineFrame;
     NSRect roundedWineFrame;
 
-    NSBezierPath* shape;
-    NSData* shapeData;
     BOOL shapeChangedSinceLastDraw;
 
     BOOL colorKeyed;
diff --git a/dlls/winemac.drv/cocoa_window.m b/dlls/winemac.drv/cocoa_window.m
index bc06a9506ee..4d7aa570552 100644
--- a/dlls/winemac.drv/cocoa_window.m
+++ b/dlls/winemac.drv/cocoa_window.m
@@ -321,6 +321,22 @@ - (BOOL) layer:(CALayer*)layer shouldInheritContentsScale:(CGFloat)newScale from
 #endif
 
 
+ at interface CAShapeLayer (WineShapeMaskExtensions)
+
+ at property(readonly, nonatomic, getter=isEmptyShaped) BOOL emptyShaped;
+
+ at end
+
+ at implementation CAShapeLayer (WineShapeMaskExtensions)
+
+    - (BOOL) isEmptyShaped
+    {
+        return CGRectEqualToRect(CGPathGetBoundingBox(self.path), CGRectZero);
+    }
+
+ at end
+
+
 @interface WineBaseView : NSView
 @end
 
@@ -388,8 +404,6 @@ @interface WineWindow ()
 @property (nonatomic) void* surface;
 @property (nonatomic) pthread_mutex_t* surface_mutex;
 
- at property (copy, nonatomic) NSBezierPath* shape;
- at property (copy, nonatomic) NSData* shapeData;
 @property (nonatomic) BOOL shapeChangedSinceLastDraw;
 @property (readonly, nonatomic) BOOL needsTransparency;
 
@@ -402,6 +416,8 @@ @interface WineWindow ()
 
 @property (readonly, copy, nonatomic) NSArray* childWineWindows;
 
+    - (void) setShape:(CGPathRef)newShape;
+
     - (void) updateForGLSubviews;
 
     - (BOOL) becameEligibleParentOrChild;
@@ -494,17 +510,6 @@ - (void) drawRect:(NSRect)rect
         if ([window contentView] != self)
             return;
 
-        if (window.drawnSinceShown && window.shapeChangedSinceLastDraw && window.shape && !window.colorKeyed && !window.usePerPixelAlpha)
-        {
-            [[NSColor clearColor] setFill];
-            NSRectFill(rect);
-
-            [window.shape addClip];
-
-            [[NSColor windowBackgroundColor] setFill];
-            NSRectFill(rect);
-        }
-
         if (window.surface && window.surface_mutex &&
             !pthread_mutex_lock(window.surface_mutex))
         {
@@ -517,8 +522,6 @@ - (void) drawRect:(NSRect)rect
                 CGContextRef context;
                 int i;
 
-                [window.shape addClip];
-
                 context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
                 CGContextSetBlendMode(context, kCGBlendModeCopy);
                 CGContextSetInterpolationQuality(context, retina_on ? kCGInterpolationHigh : kCGInterpolationNone);
@@ -968,7 +971,7 @@ @implementation WineWindow
     @synthesize disabled, noActivate, floating, fullscreen, fakingClose, latentParentWindow, hwnd, queue;
     @synthesize drawnSinceShown;
     @synthesize surface, surface_mutex;
-    @synthesize shape, shapeData, shapeChangedSinceLastDraw;
+    @synthesize shapeChangedSinceLastDraw;
     @synthesize colorKeyed, colorKeyRed, colorKeyGreen, colorKeyBlue;
     @synthesize usePerPixelAlpha;
     @synthesize imeData, commandDone;
@@ -1069,8 +1072,6 @@ - (void) dealloc
         [queue release];
         [latentChildWindows release];
         [latentParentWindow release];
-        [shape release];
-        [shapeData release];
         [super dealloc];
     }
 
@@ -2013,7 +2014,7 @@ - (void) setDisabled:(BOOL)newValue
 
     - (BOOL) needsTransparency
     {
-        return self.shape || self.colorKeyed || self.usePerPixelAlpha ||
+        return self.contentView.layer.mask || self.colorKeyed || self.usePerPixelAlpha ||
                 (gl_surface_mode == GL_SURFACE_BEHIND && [(WineContentView*)self.contentView hasGLDescendant]);
     }
 
@@ -2035,22 +2036,27 @@ - (void) checkTransparency
         }
     }
 
-    - (void) setShape:(NSBezierPath*)newShape
+    - (void) setShape:(CGPathRef)newShape
     {
-        if (shape == newShape) return;
+        CALayer* layer = [[self contentView] layer];
+        CAShapeLayer* mask = layer.mask;
+        if (CGPathEqualToPath(newShape, mask.path)) return;
 
-        if (shape)
-        {
-            [[self contentView] setNeedsDisplayInRect:[shape bounds]];
-            [shape release];
-        }
+        if (newShape && !layer.mask)
+            layer.mask = mask = [CAShapeLayer layer];
+        else if (!newShape)
+            layer.mask = mask = nil;
+
+        if (mask.path)
+            [[self contentView] setNeedsDisplayInRect:NSRectFromCGRect(CGPathGetBoundingBox(mask.path))];
         if (newShape)
-            [[self contentView] setNeedsDisplayInRect:[newShape bounds]];
+            [[self contentView] setNeedsDisplayInRect:NSRectFromCGRect(CGPathGetBoundingBox(newShape))];
 
-        shape = [newShape copy];
+        mask.path = newShape;
         self.shapeChangedSinceLastDraw = TRUE;
 
         [self checkTransparency];
+        [self checkEmptyShaped];
     }
 
     - (void) makeFocused:(BOOL)activate
@@ -2247,7 +2253,7 @@ - (void) checkWineDisplayLink
 
     - (BOOL) isEmptyShaped
     {
-        return (self.shapeData.length == sizeof(CGRectZero) && !memcmp(self.shapeData.bytes, &CGRectZero, sizeof(CGRectZero)));
+        return ([[[self contentView] layer].mask isEmptyShaped]);
     }
 
     - (BOOL) canProvideSnapshot
@@ -2650,8 +2656,7 @@ - (void) setRetinaMode:(int)mode
 
         [transform scaleBy:scale];
 
-        if (shape)
-            [shape transformUsingAffineTransform:transform];
+        [[self contentView] layer].mask.contentsScale = mode ? 2.0 : 1.0;
 
         for (WineBaseView* subview in [self.contentView subviews])
         {
@@ -3456,25 +3461,19 @@ void macdrv_set_window_shape(macdrv_window w, const CGRect *rects, int count)
     OnMainThread(^{
         if (!rects || !count)
         {
-            window.shape = nil;
-            window.shapeData = nil;
+            [window setShape:NULL];
             [window checkEmptyShaped];
         }
         else
         {
-            size_t length = sizeof(*rects) * count;
-            if (window.shapeData.length != length || memcmp(window.shapeData.bytes, rects, length))
-            {
-                NSBezierPath* path;
-                unsigned int i;
+            CGMutablePathRef path;
+            unsigned int i;
 
-                path = [NSBezierPath bezierPath];
-                for (i = 0; i < count; i++)
-                    [path appendBezierPathWithRect:NSRectFromCGRect(cgrect_mac_from_win(rects[i]))];
-                window.shape = path;
-                window.shapeData = [NSData dataWithBytes:rects length:length];
-                [window checkEmptyShaped];
-            }
+            path = CGPathCreateMutable();
+            for (i = 0; i < count; i++)
+                CGPathAddRect(path, NULL, cgrect_mac_from_win(rects[i]));
+            [window setShape:path];
+            CGPathRelease(path);
         }
     });
 
-- 
2.33.0




More information about the wine-devel mailing list