I have a Mac OS X (10.9) application with a custom NSView for my main NSWindow's contentView
property. The only thing the custom view does is override drawRect:
so that it's transparent. Transparency is required so that my NSOpenGLView is visible (see below):
/* Transparent NSView Subclass */
- (void)drawRect:(NSRect)dirtyRect
{
NSLog(@"Drawing Rect");
[[NSColor clearColor] set];
NSRectFillUsingOperation(dirtyRect, NSCompositeClear);
}
The contentView
has an NSOpenGLView as a subview, with its surface order set to -1 (it's 'below' the main NSWindow, which is also transparent):
/* NSOpenGLView subclass: */
GLint order = -1;
[self.openGLContext setValues:&order forParameter:NSOpenGLCPSurfaceOrder];
I then instantiate a WebView and place it as a subview of this custom view:
_webview = [[WebView alloc] initWithFrame:frame];
[_webview setMaintainsBackForwardList:NO];
[_webview setTranslatesAutoresizingMaskIntoConstraints:NO];
[_webview setDrawsBackground:NO];
[_window.contentView addSubview:_webview];
The WebView is a small box in the window (on top of the NSOpenGLView) which is used to login to a service. Once login happens it should disappear, showing only the NSOpenGLView.
Here's the problem: when I call [_webview removeFromSuperview];
the contentView
does not redraw; therefore, the WebView is still drawn on the screen (although not responsive to mouse or keyboard). If I use my mouse to resize the window that everything is in, the contentView
redraws (I see the message in the logs) and the WebView's content disappears.
Also, if I don't add the NSOpenGLView as a subview, the WebView goes away as it should.
Shouldn't the contentView
fire a drawRect
after a subview is removed? Even when I used setNeedsDisplay:
or setNeedsLayout:
after removing the WebView the contentView
still didn't redraw.
Apple's advice these days is to use Core Animation layers to put normal views on top of OpenGL views.
I suspect that the content view has redrawn itself. It draws clear. What you're seeing is the OpenGL surface behind it. The nearly-raw-VRAM nature of OpenGL surfaces may mean that the web view that was drawn on top of it actually modified the contents of the surface. So, I recommend that you force the OpenGL view to redraw itself. If it draws in its -drawRect:
, then it should be enough to send it -setNeedsDisplay:
. If you do rendering outside of -drawRect:
by manually making the context current, issuing rendering commands, and then calling -flushBuffer
, then you'll need to do that.