Signed-off-by: Chip Davis cdavis@codeweavers.com --- v2: Add casts to accomodate headers that don't yet use __kindof. --- dlls/winemac.drv/cocoa_window.h | 2 - dlls/winemac.drv/cocoa_window.m | 90 ++++++++++++++++----------------- 2 files changed, 45 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..96636f6d788 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
+@interface CAShapeLayer (WineShapeMaskExtensions) + +@property(readonly, nonatomic, getter=isEmptyShaped) BOOL emptyShaped; + +@end + +@implementation CAShapeLayer (WineShapeMaskExtensions) + + - (BOOL) isEmptyShaped + { + return CGRectEqualToRect(CGPathGetBoundingBox(self.path), CGRectZero); + } + +@end + + @interface WineBaseView : NSView @end
@@ -388,8 +404,6 @@ @interface WineWindow () @property (nonatomic) void* surface; @property (nonatomic) pthread_mutex_t* surface_mutex;
-@property (copy, nonatomic) NSBezierPath* shape; -@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 = (CAShapeLayer*)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,8 @@ - (void) checkWineDisplayLink
- (BOOL) isEmptyShaped { - return (self.shapeData.length == sizeof(CGRectZero) && !memcmp(self.shapeData.bytes, &CGRectZero, sizeof(CGRectZero))); + CAShapeLayer* mask = (CAShapeLayer*)[[self contentView] layer].mask; + return ([mask isEmptyShaped]); }
- (BOOL) canProvideSnapshot @@ -2650,8 +2657,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 +3462,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); } });