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: Ken Thomases <ken@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
5c5eef8d40
commit
fdd7db0593
|
@ -34,6 +34,7 @@ @interface WineWindow : NSPanel <NSWindowDelegate>
|
|||
BOOL fullscreen;
|
||||
BOOL pendingMinimize;
|
||||
BOOL savedVisibleState;
|
||||
BOOL drawnSinceShown;
|
||||
WineWindow* latentParentWindow;
|
||||
NSMutableArray* latentChildWindows;
|
||||
|
||||
|
|
|
@ -317,6 +317,7 @@ @interface WineWindow ()
|
|||
@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 @@ - (void) updateForGLSubviews;
|
|||
- (BOOL) becameEligibleParentOrChild;
|
||||
- (void) becameIneligibleChild;
|
||||
|
||||
- (void) windowDidDrawContent;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
|
@ -383,7 +386,7 @@ - (void) drawRect:(NSRect)rect
|
|||
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 @@ - (void) drawRect:(NSRect)rect
|
|||
CGImageRelease(image);
|
||||
}
|
||||
}
|
||||
|
||||
[window windowDidDrawContent];
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(window.surface_mutex);
|
||||
|
@ -449,7 +454,7 @@ - (void) drawRect:(NSRect)rect
|
|||
// 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 @@ @implementation WineWindow
|
|||
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 @@ + (WineWindow*) createWindowWithFeatures:(const struct macdrv_window_features*)w
|
|||
[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 @@ - (BOOL) addChildWineWindow:(WineWindow*)child assumeVisible:(BOOL)assumeVisible
|
|||
{
|
||||
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 @@ - (void) orderBelow:(WineWindow*)prev orAbove:(WineWindow*)next activate:(BOOL)a
|
|||
// 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 @@ - (void) orderBelow:(WineWindow*)prev orAbove:(WineWindow*)next activate:(BOOL)a
|
|||
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 @@ - (void) doOrderOut
|
|||
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 @@ - (void) displayIfNeeded
|
|||
[self setAutodisplay:NO];
|
||||
}
|
||||
|
||||
- (void) windowDidDrawContent
|
||||
{
|
||||
if (!drawnSinceShown)
|
||||
{
|
||||
drawnSinceShown = YES;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self checkTransparency];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray*) childWineWindows
|
||||
{
|
||||
NSArray* childWindows = self.childWindows;
|
||||
|
|
Loading…
Reference in New Issue