NSWindow, strange corner when using Core Animation - cocoa

In my project there is a view with a custom drawRect: method which draws a dark background. When I call [view setWantsLayer:YES] the corner of the window (where view is placed) appears less smooth (image 2) than usual (image 1).
How can I solve this?

You need to set cornerRadius: and enable maskToBounds: for layer like this:
[view setWantsLayer:YES];
[[view layer] setMasksToBounds:YES];
[[view layer] setCornerRadius:10.0];
Result:

Related

Custom NSWindow in 10.9 Doesn't show shadow when SetOpaque:NO

So I have created an NSWindow (with rounded corners), and in 10.10, it has a shadow around it. However when I tested in 10.9, the shadow disappeared. I have set breakpoints at every possible point, and [window hasShadow] is always YES.
If I set [self setOpaque:YES] in the initWithContentRect method of the window, the shadow comes back.
Has anybody seen this before? Or know what could possibly cause this?
It appears the hasShadow property doesn't do anything because if I set it to YES/NO it doesn't change anything. Just setting it opaque/transparent makes the shadow appear/disappear
Thanks in advance!
Here is how I finally managed this.
First of all, this will happen only if you are using layered back views (and this is our case if we want to easily implement rounded corners), in the RoundTransparentWindow Apple sample you can test it, until you not make the CutomView layered you will see the window shadow on 10.9 too, adding [self setWantsLayer:YES]; will kill your shadow.
The key for the solution here is adding all the layered views to a view that has no layer at all and making that view to the window contentView. That new contentView should reimplement only the drawRect: method on the following way:
- (void)drawRect:(NSRect)dirtyRect
{
[NSGraphicsContext saveGraphicsState];
[[NSColor clearColor] set];
NSRectFill(dirtyRect);
NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:[self bounds]
xRadius:cCornerRadius
yRadius:cCornerRadius];
[[NSColor whiteColor] set];
[path fill];
[NSGraphicsContext restoreGraphicsState];
}
"Pre drawing" the rounded corners filled with any NONE transparent color is the key here, it will make the window server use the shadow again even if [self setOpaque:NO]; self.backgroundColor = [NSColor clearColor]; set during the window construction, that, as you found it earlier, made the server to think the window is transparent and does not need shadow.

NSImageView disappears when the parent NSView wants layer (setWantsLayer:YES)

I have a simple custom NSView that has a label and an image. Currently the view works quite well (all the thumbs are instances of my custom view):
However, I want to set the opacity of these thumbnails. Setting viewInstance.layer.opacity doesn't work as the layer is nil. When I use [viewInstance setWantsLayer:YES] first somewhere, and I set the opacity, the opacity of the text changes (it is displayed correctly), but the image view disappears altogether:
I've tried creating a layer first, assigning it, and then calling setWantsLayer: after reading this question: How to add a CALayer to an NSView on Mac OS X but nothing changed:
CALayer *selfLayer = [[CALayer alloc] init];
[selfLayer setFrame:CGRectMake(0, 0, 100, 100)];
[self setLayer:selfLayer];
[self setWantsLayer:YES];
I've tried all combinations of creating a layer and displaying it for the image view too (just calling setWantsLayer:, creating layer and then assigning it, calling display method of it), but still nothing changes:
[self addSubview:self.imageView];
CALayer *imageLayer = [[CALayer alloc] init];
[imageLayer setFrame:CGRectMake(0, 0, 100, 100)];
[self.imageView setLayer:imageLayer];
[self.imageView setWantsLayer:YES];
I've tried adding the image view's layer as a sublayer of the main view and then displaying it:
[self.layer addSublayer:self.imageView.layer];
[self.imageView.layer display];
[self.layer display];
But still, the images won't display, whereas the text always displays correctly. When I comment out the code about assigning and wanting layers, images display again, but obviously, I can't use the layer opacity. I am on OS X Mavericks with OS X SDK 10.8. What am I doing wrong?
UPDATE: I ended up getting rid of NSImageView completely and drawing the NSImage directly into the layer by setting the layer's contents property. However, this is just another approach which solved my problem for this project, it still doesn't answer the original question.
I ended up getting rid of NSImageView completely and drawing the NSImage directly into the layer by setting the layer's contents property. However, this is just another approach which solved my problem for this project, it still doesn't answer the original question.

Autolayout NSImageView in NSView - scale size. Programmatically set NSLayoutConstraint

I have an NSImageView in a NSView set up in IB. The NSImageView is exactly the same size as the NSView.
Everything works fine and the NSImageView have the same size as the NSView when resizing the window.
BUT, now I've added an animation (move from A to B) to the NSImageView and that will mess up the constraints that's been set up in IB. So I have to do this programmatically.
How could I programmatically set NSLayoutConstraint to have my NSImageView have the same size as my NSImageView (the superview)?
UPDATE:
Just to give you guys some more information. My app uses a split view (three views) and instead of adding the NSImageView in IB I now add it programmatically. I add my new view (which shall be scalable to it's parent view) to the third view in the split view.
Do you think the split view is causing these issues?
UPDATE 2:
Ok, I'm closer to fixing this. I removed the NSImageView from the view, and added a NSView instead. The NSView scaled fine, but as soon as I added the NSImageView it stopped working in the way that the NSImageView won't scale after resizing the window.
In other words, the problem lies in the NSImageView itself. It won't scale after resizing the window...
SOLVED
I solved it by using PDF View instead of image view (it was a PDF I wanted to show). I set the autoScales property to YES on the PDF View.
I assume you already have references to the views in the example below:
NSView * parentView;
NSImageView * imageView;
[imageView setTranslatesAutoresizingMaskIntoConstraints:NO]; //Required to opt-in to autolayout
[parentView addSubview:imageView]; //Subview must exist before adding constraint.
NSDictionary * views = NSDictionaryOfVariableBindings(imageView);
[parentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[imageView]|"
options:0
metrics:nil
views:views]];
[parentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[imageView]|"
options:0
metrics:nil
views:views]];

Cocoa: [self.view setWantsLayer:YES] brings that view above other subviews?

Simply, I have an NSView with a bunch of subviews. In the awakeFromNib method (inside the view's controller), I decided to add the following:
[_backgroundImageView setWantsLayer:YES];
[[_backgroundImageView layer] setShadowOpacity:1.0f];
[[_backgroundImageView layer] setShadowOffset:NSMakeSize(-3, -3)];
The backgroundImageView is at the back of all the subviews. But, when I added the previous code, it draws the shadow correctly, but also draws the backgroundImageView above all other layers. Why? How I can Fix that?
You need setWantsLayer:YES in code for the superview.
Turn's out I should enable the layer for the superview (self.view), too. Not only that, but I should tighten up the imageView's frame, or else it will be scaled "axis independently" even though it is set to "Proportional up or down".

Gray border when using NSBorderlessWindowMask

Whenever I try to create a custom window using NSBorderlessWindowMask and set an NSView (for example an NSImageView) as its contentView, I get a 1px gray border around the NSView and I don't seem to be able to get rid of it.
I have followed several approaches including Apple's RoundTransparentWindow sample code as well as several suggestions on StackOverflow.
I suspect the gray border is either coming from the window itself or the NSView.
Have any of you experienced this problem or do you have a possible solution?
The code is fairly straightforward. This is the init method of the custom window:
- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag {
self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:YES];
if (self != nil) {
[self setAlphaValue:1.0];
[self setBackgroundColor:[NSColor clearColor]];
[self setOpaque:NO];
}
return self;
}
To test this, in IB I place an NSImageView in that custom window WITHOUT border and yet the image in the NSImageView has a border. The same goes for other NSView subclasses, such as NSTextField, NSTableView.
In addition, I also noticed that the same is happening with the sample application (RoundTransparentWindow) of Apple. Is it even possible to draw an NSView in a custom window without a 1px border?
Thanks
Are you sure this happens when you use a regular NSView with no drawing? I bet not. Other controls (like NSImageView)have borders. Maybe you should double check to make sure they're turned off whe possible.
Update - How do you get your view into your window? You don't include that code. I created a basic test project (download it here) with an image well and it works just fine. See for yourself.

Resources