winemac.drv: Use a mask layer to support window regions.
Signed-off-by: Chip Davis <cdavis@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
a5cf847aa4
commit
01f027b2db
|
@ -51,8 +51,6 @@ @interface WineWindow : NSPanel <NSWindowDelegate>
|
|||
NSRect wineFrame;
|
||||
NSRect roundedWineFrame;
|
||||
|
||||
NSBezierPath* shape;
|
||||
NSData* shapeData;
|
||||
BOOL shapeChangedSinceLastDraw;
|
||||
|
||||
BOOL colorKeyed;
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
@ -2011,7 +2012,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]);
|
||||
}
|
||||
|
||||
|
@ -2033,22 +2034,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
|
||||
|
@ -2245,7 +2251,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
|
||||
|
@ -2648,8 +2655,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])
|
||||
{
|
||||
|
@ -3453,25 +3459,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);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue