9
votes

I am drawing a custom window by setting a custom content view for the window. When I draw the custom view I give it rounded corners and a nice outline to mimic a proper window.

However, I see another 1 px outline around the window which strays from the edge at the corners. I have found that if I turn off the shadow it goes away, but obviously as this wants to act like a window I need the shadow. Here's what I mean about the 1px outline:

enter image description here

How can I prevent this?


EDIT

Code for drawing the custom window's content view:

    NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:[self bounds] cornerRadius:5];

    NSGradient* aGradient = [[[NSGradient alloc] initWithColorsAndLocations:
                              [NSColor colorWithDeviceRed:0.5569 green:0.5137 blue:0.4588 alpha:1.0000], 0.0,
                              [NSColor colorWithDeviceRed:0.5569 green:0.5137 blue:0.4588 alpha:1.0000], 1.0,
                              nil] autorelease];

    [aGradient drawInBezierPath:path angle:90];

    [path setLineWidth:4];
    [[NSColor colorWithDeviceRed:0.4235 green:0.3922 blue:0.3451 alpha:0.9000] setStroke];
    [path strokeInside];

    [path setLineWidth:3];
    [[NSColor colorWithDeviceRed:0.8431 green:0.8314 blue:0.8078 alpha:1.0000] setStroke];
    [path strokeInside];

    [path setLineWidth:1];
    [[NSColor colorWithDeviceRed:0.4235 green:0.3922 blue:0.3451 alpha:0.9000] setStroke];
    [path strokeInside];
5

5 Answers

3
votes

Don't ask me how I got this, but this will solve your problem.

Define a category for NSWindow with the following content:

@implementation NSWindow(NoShadowRim)

- (id)_shadowRimInfo {
  return @{
    @"kCUIMeasureWindowFrameRimDensity": [NSNumber numberWithInt:0]
  };
}

@end

DISCLAIMER: This overrides the internal method of NSWindow, so use it at your own risk. It may break with any OS X update.

1
votes

You need to tell the window to recompute its shadow by sending it -invalidateShadow.

1
votes

Try:

[[self window] display];
[[self window] setHasShadow:NO];
[[self window] setHasShadow:YES];
0
votes

This line contouring the window area is drawn automatically. I have a window which has this line running accurately around bottom rounded corners. You have to setup the window as non-opaque and the background color to transparent:

  [self setOpaque:NO];
  [self setBackgroundColor:[NSColor clearColor]];

The somewhere in the contentView -drawRect: you do

  [NSGraphicsContext saveGraphicsState];
  [pathWithBottomRoundedCorner addClip];
  // your drawing here...
  [NSGraphicsContext restoreGraphicsState];

That should work.

0
votes

As I understand correctly, shadows are drawn by windows server. When you draw custom NSWindow with rounded corners or other not rectangular shapes, window server don't count those transparent pixels and dont drop shadow under them.

I developed some hack to avoid such behavior. Just drop additional shadow under your path, something like this:

NSShadow *headShadow = [[NSShadow alloc] init];
[headShadow setShadowColor:[NSColor colorWithSRGBRed:0.0 
                                               green:0.0 
                                                blue:0.0 
                                               alpha:0.16]];
[headShadow setShadowBlurRadius:0.0f];
[headShadow setShadowOffset:NSMakeSize(0.0f, 0.0f)];
[headShadow set];

Ideally for perfect result i fink shadow must be equal to window servers.