0

I want to have a window which is like QuickTime X window. An all opaque window with rounded corners.

I've obtained it implementing a custom borderless NSWindow with:

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

and a custom NSView with:

- (void)drawRect:(NSRect)rect
{
    NSBezierPath* thePath = [NSBezierPath bezierPath];
    [thePath appendBezierPathWithRoundedRect:rect xRadius:radius yRadius:radius];
    [thePath fill];
}

It works as expected but the window becomes noticeably slow when it gets resized fast.

I've identified that this slowdown is given by -setOpaque:NO; if I remove that line, the window can be resized fast again but corners are obviously no more rounded.

Is there a way to avoid using -setOpaque:NO and still be able to have rounded corners? Maybe one can have a window which is all opaque except for the corners?

The view is a NSOpenGLView so I can leverage on OpenGL if it may helps.

Community
  • 1
  • 1
Andrea3000
  • 1,018
  • 1
  • 11
  • 26

3 Answers3

0

See this Apple developer example: https://developer.apple.com/library/mac/#samplecode/RoundTransparentWindow/Introduction/Intro.html

dorianj
  • 101
  • 3
  • That example set window to transparent with -setOpaque:NO. I'm looking for a solution which lets me round window's corner without setting it transparent – Andrea3000 May 25 '12 at 18:28
0

In Quartz/Core Graphics, opaque rects are faster to composite than non-opaque rects. But an opaque window means you need to draw a rectangle and anything you didn't fill would be black.

If you want a custom window that is not a sharp-edged rectangle, you must set the window to be non-opaque.

Anyway, this is almost certainly, not your main bottleneck.

First thing is to stop doing so much stuff in drawRect: Make that NSBezierPath a property. Only replace it when the rect is actually changing size. Only do that in viewWillDraw: or some earlier point. Maybe one of the view or window resize NSNotifications or a delegate method.

In drawRect: you should do only drawing really, as much as possible. You should only redraw what you need to, as much as possible.

This is still small, and probably not your bottleneck. You'll need to examine the drawing in ALL of the views in your window.

Your window is really the root CGContext (drawing context) that you get access to on OS X. Everything in your context is all of your subviews. Every subview is a potential drawing bottleneck.

An OpenGL view drawing during live resize of the window sounds like a prime candidate. You might throttle frame rates or something during live resize of the view or the window. That should get it a little snappier.

Beyond that, you'll notice from NSWindow and NSView classes that not drawing during live resize IS a performance win.

See the NSView Class documentation and specifically the methods noted under the section Managing Live Resize

  • inLiveResize
  • preservesContentDuringLiveResize
  • getRectsExposedDuringLiveResize:count:
  • rectPreservedDuringLiveResize
  • viewWillStartLiveResize
  • viewDidEndLiveResize

Those last two look like a great place to sandwich some reduction in drawing,

uchuugaka
  • 12,679
  • 6
  • 37
  • 55
-1

Try using the setAlphaValue method of NSWindow.

Suhas
  • 1,500
  • 11
  • 15