Here's another NSWindow
question ... I've got borderless window, transparent, which is created in this way ...
- (id)initWithView:(NSView *)view anchorPoint:(NSPoint)anchorPoint position:(NSPoint)position distance:(CGFloat)distance {
if ( !view ) {
return nil;
}
NSSize size = view.intrinsicContentSize;
NSRect contentRect = NSMakeRect( 0, 0, size.width, size.height );
self = [super initWithContentRect:contentRect
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
if ( !self ) {
return nil;
}
_windowView = view;
_anchorPoint = anchorPoint;
_position = position;
_distance = distance;
[self setContentView:_windowView];
[self setExcludedFromWindowsMenu:YES];
[self setMovableByWindowBackground:NO];
[self setOpaque:NO];
[self setBackgroundColor:[NSColor clearColor]];
[self setHasShadow:YES];
[self useOptimizedDrawing:YES];
[self setReleasedWhenClosed:NO];
[self setFrame:[self windowRectWithSize:contentRect.size] display:YES];
[self setAnchorAttribute:NSLayoutAttributeTop forOrientation:NSLayoutConstraintOrientationVertical];
[self setAnchorAttribute:NSLayoutAttributeCenterX forOrientation:NSLayoutConstraintOrientationHorizontal];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(viewFrameDidChange:)
name:NSViewFrameDidChangeNotification
object:nil];
return self;
}
... and viewFrameDidChange:
is defined as ...
- (void)viewFrameDidChange:(NSNotification *)note {
if ( note.object != self.contentView ) {
return;
}
[self display];
[self setHasShadow:NO];
[self setHasShadow:YES];
}
... this is the only way to have proper NSWindow
shadow. In other words, whenever window size changes, I have to call display
, setHasShadow:NO
and setHasShadow:YES
otherwise the window shadow is crippled - it's not around the whole window - just part of the window, etc.
This does work until I start animating height. If height is animated, shadow is correctly recalculated and displayed, but the whole window & shadow is flickering and it's pretty ugly.
An idea why the shadow is flickering? I tried to replace display
, setHasShadow:NO/YES
with [self invalidateShadow]
, but it doesn't work at all and shadow is displayed in a wrong way.
How one should animate window height with shadow in borderless/transparent window to avoid flickering?
Here's the video of the flickering shadow. http://d.pr/v/lbkQ
The shadow calculation and drawing is a very resource-consuming operation. So I wouldn't recommend you to invalidate and recalculate the shadow each time the frame changes. Besides, NSWindowDelegate has a –windowDidResize:
method, so why using observer?
How do you get your window resized? Maybe adding NSResizableWindowMask
to the window's style mask will do the trick? You should give it a try.
Another suggestion - check that the content of your window resizes correctly along with the window. You set your window to transparent. But if there is no content inside the window, no shadow is displayed. You can also try to add your view as a subview to the existing window's contentView instead of replacing it.
I have almost the same setup in my project and I can tell that window's shadow is displayed correctly when you resize the window.
P.S. A recommendation: do not rely on 'self' in the initialization method of the object. It may be yet not fully ready for use. Init with minimum, adjust the window after it was creater in your controller (for example, you cannot be sure that setFrame:display will do what you expect with correct sizes). The glitch you have might be related to this also.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With