Commit fdd7db05 authored by Ken Thomases's avatar Ken Thomases Committed by Alexandre Julliard

winemac: Set windows to transparent until they have content to draw, to reduce flicker.

When a window is shown, it may not have drawn its content into the backing surface, yet. Cocoa will draw the window, starting with its standard light gray background and then the content view. However, the content view won't have anything to draw, yet, though, so the window background is not drawn over. A short while later, usually, the app will paint its content into the window backing surface and Cocoa will be told to redraw the window. This works, but the user can often see the flash of the window background color first. This is especially visible for windows with dark content. Part of the fix is to set the window background to transparent until the content view has actually drawn once since the window was shown. That's not sufficient on its own, though. We had disabled Cocoa's automatic display mechanism for windows and put display on a display-link timer. This meant that the window was not actually cleared to its transparent color. When the window was shown, the Window Server displayed a white backing buffer. It is the app process which should fill that backing buffer with clear color but, because we had disabled auto-display, that wasn't getting done at the same time the window was displayed. It was happening some time after. Again, the result was a visible flicker of white. So, we now temporarily re-enable auto-display just before showing a window. Signed-off-by: 's avatarKen Thomases <ken@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 5c5eef8d
......@@ -34,6 +34,7 @@
BOOL fullscreen;
BOOL pendingMinimize;
BOOL savedVisibleState;
BOOL drawnSinceShown;
WineWindow* latentParentWindow;
NSMutableArray* latentChildWindows;
......
......@@ -317,6 +317,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
@property (readwrite, nonatomic) BOOL disabled;
@property (readwrite, nonatomic) BOOL noActivate;
@property (readwrite, nonatomic) BOOL floating;
@property (readwrite, nonatomic) BOOL drawnSinceShown;
@property (readwrite, getter=isFakingClose, nonatomic) BOOL fakingClose;
@property (retain, nonatomic) NSWindow* latentParentWindow;
......@@ -346,6 +347,8 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
- (BOOL) becameEligibleParentOrChild;
- (void) becameIneligibleChild;
- (void) windowDidDrawContent;
@end
......@@ -383,7 +386,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
if ([window contentView] != self)
return;
if (window.shapeChangedSinceLastDraw && window.shape && !window.colorKeyed && !window.usePerPixelAlpha)
if (window.drawnSinceShown && window.shapeChangedSinceLastDraw && window.shape && !window.colorKeyed && !window.usePerPixelAlpha)
{
[[NSColor clearColor] setFill];
NSRectFill(rect);
......@@ -441,6 +444,8 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
CGImageRelease(image);
}
}
[window windowDidDrawContent];
}
pthread_mutex_unlock(window.surface_mutex);
......@@ -449,7 +454,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
// If the window may be transparent, then we have to invalidate the
// shadow every time we draw. Also, if this is the first time we've
// drawn since changing from transparent to opaque.
if (window.colorKeyed || window.usePerPixelAlpha || window.shapeChangedSinceLastDraw)
if (window.drawnSinceShown && (window.colorKeyed || window.usePerPixelAlpha || window.shapeChangedSinceLastDraw))
{
window.shapeChangedSinceLastDraw = FALSE;
[window invalidateShadow];
......@@ -794,6 +799,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
static WineWindow* causing_becomeKeyWindow;
@synthesize disabled, noActivate, floating, fullscreen, fakingClose, latentParentWindow, hwnd, queue;
@synthesize drawnSinceShown;
@synthesize surface, surface_mutex;
@synthesize shape, shapeData, shapeChangedSinceLastDraw;
@synthesize colorKeyed, colorKeyRed, colorKeyGreen, colorKeyBlue;
......@@ -831,7 +837,8 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
[window setAcceptsMouseMovedEvents:YES];
[window setColorSpace:[NSColorSpace genericRGBColorSpace]];
[window setDelegate:window];
[window setAutodisplay:NO];
[window setBackgroundColor:[NSColor clearColor]];
[window setOpaque:NO];
window.hwnd = hwnd;
window.queue = queue;
window->savedContentMinSize = NSZeroSize;
......@@ -1191,6 +1198,8 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
{
if ([self level] > [child level])
[child setLevel:[self level]];
if (![child isVisible])
[child setAutodisplay:YES];
[self addChildWindow:child ordered:NSWindowAbove];
[child checkWineDisplayLink];
[latentChildWindows removeObjectIdenticalTo:child];
......@@ -1455,6 +1464,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
// Then the levels get fixed by -adjustWindowLevels.
if ([self level] != [other level])
[self setLevel:[other level]];
[self setAutodisplay:YES];
[self orderWindow:orderingMode relativeTo:[other windowNumber]];
[self checkWineDisplayLink];
......@@ -1474,6 +1484,7 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
next = [controller frontWineWindow];
if (next && [self level] < [next level])
[self setLevel:[next level]];
[self setAutodisplay:YES];
[self orderFront:nil];
[self checkWineDisplayLink];
needAdjustWindowLevels = TRUE;
......@@ -1530,6 +1541,9 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
else
[self orderOut:nil];
[self checkWineDisplayLink];
[self setBackgroundColor:[NSColor clearColor]];
[self setOpaque:NO];
drawnSinceShown = NO;
savedVisibleState = FALSE;
if (wasVisible && wasOnActiveSpace && fullscreen)
[controller updateFullscreenWindows];
......@@ -2266,6 +2280,17 @@ static CVReturn WineDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTi
[self setAutodisplay:NO];
}
- (void) windowDidDrawContent
{
if (!drawnSinceShown)
{
drawnSinceShown = YES;
dispatch_async(dispatch_get_main_queue(), ^{
[self checkTransparency];
});
}
}
- (NSArray*) childWineWindows
{
NSArray* childWindows = self.childWindows;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment