Chromium Code Reviews| Index: ui/base/cocoa/underlay_opengl_hosting_window.mm |
| diff --git a/ui/base/cocoa/underlay_opengl_hosting_window.mm b/ui/base/cocoa/underlay_opengl_hosting_window.mm |
| index 95f36af0476b239db0318c4b15cec907344143ea..e26291f10e5c593c486f43d354382be3cbe568c2 100644 |
| --- a/ui/base/cocoa/underlay_opengl_hosting_window.mm |
| +++ b/ui/base/cocoa/underlay_opengl_hosting_window.mm |
| @@ -4,26 +4,120 @@ |
| #import "ui/base/cocoa/underlay_opengl_hosting_window.h" |
| +#import <objc/runtime.h> |
| + |
| #include "base/logging.h" |
| +#include "base/mac/mac_util.h" |
| +#include "base/mac/scoped_nsautorelease_pool.h" |
| +#include "base/memory/scoped_nsobject.h" |
| + |
| +@interface NSWindow (UndocumentedAPI) |
| +// Normally, punching a hole in a window by painting a subview with a |
| +// transparent color causes the shadow for that area to also not be present. |
| +// That feature is "content has shadow", which means that shadows are effective |
| +// even in the content area of the window. If, however, "content has shadow" is |
| +// turned off, then the transparent area of the content casts a shadow. The one |
| +// tricky part is that even if "content has shadow" is turned off, "the content" |
| +// is defined as being the scanline from the leftmost opaque part to the |
| +// rightmost opaque part. Therefore, to force the entire window to have a |
| +// shadow, make sure that for the entire content region, there is an opaque area |
| +// on the right and left edge of the window. |
| +- (void)_setContentHasShadow:(BOOL)shadow; |
| +@end |
| + |
| +@interface OpaqueView : NSView |
| +@end |
| + |
| +@implementation OpaqueView |
| +- (void)drawRect:(NSRect)r { |
| + [[NSColor blackColor] set]; |
| + NSRectFill(r); |
| +} |
| +@end |
| + |
| +namespace { |
| + |
| +NSComparisonResult OpaqueViewsOnTop(id view1, id view2, void* context) { |
| + BOOL view1IsOpaqueView = [view1 isKindOfClass:[OpaqueView class]]; |
|
Mark Mentovai
2012/04/10 19:08:30
Style nit: use_c_plus_plus_naming outside of @inte
Avi (use Gerrit)
2012/04/10 19:42:50
Done.
|
| + BOOL view2IsOpaqueView = [view2 isKindOfClass:[OpaqueView class]]; |
| + if (view1IsOpaqueView && view2IsOpaqueView) |
| + return NSOrderedSame; |
| + if (view1IsOpaqueView) |
| + return NSOrderedDescending; |
| + if (view2IsOpaqueView) |
| + return NSOrderedAscending; |
| + return NSOrderedSame; |
| +} |
| + |
| +void RootDidAddSubview(id self, SEL _cmd, NSView* subview) { |
| + // Make sure the opaques are on top. |
| + [self sortSubviewsUsingFunction:OpaqueViewsOnTop context:NULL]; |
| +} |
| + |
| +} // namespace |
| @implementation UnderlayOpenGLHostingWindow |
| -- (void)underlaySurfaceAdded { |
| - DCHECK_GE(underlaySurfaceCount_, 0); |
| - ++underlaySurfaceCount_; |
| ++ (void)load { |
| + base::mac::ScopedNSAutoreleasePool pool; |
| + |
| + // On 10.8+ the background for textured windows are no longer drawn by |
| + // NSGrayFrame, and NSThemeFrame is used instead <http://crbug.com/114745>. |
| + Class borderViewClass = NSClassFromString( |
| + base::mac::IsOSMountainLionOrLater() ? @"NSThemeFrame" : @"NSGrayFrame"); |
| + DCHECK(borderViewClass); |
| + if (!borderViewClass) return; |
| - // We're having the OpenGL surface render under the window, so the window |
| - // needs to be not opaque. |
| - if (underlaySurfaceCount_ == 1) |
| - [self setOpaque:NO]; |
| + // Install callback for added views. |
| + Method m = class_getInstanceMethod([NSView class], @selector(didAddSubview:)); |
|
Mark Mentovai
2012/04/10 19:08:30
You can use borderViewClass here instead of [NSVie
|
| + DCHECK(m); |
| + if (m) { |
| + BOOL didAdd = class_addMethod(borderViewClass, |
| + @selector(didAddSubview:), |
| + reinterpret_cast<IMP>(&RootDidAddSubview), |
| + method_getTypeEncoding(m)); |
|
Mark Mentovai
2012/04/10 19:08:30
If this is all you’re using m for, it seems like y
Avi (use Gerrit)
2012/04/10 19:42:50
I'm having trouble; how do you paste together the
Mark Mentovai
2012/04/10 19:48:29
Avi wrote:
Avi (use Gerrit)
2012/04/10 20:11:23
Well, sure, but I'm not sure I see the advantage t
Mark Mentovai
2012/04/10 20:19:11
Avi wrote:
|
| + DCHECK(didAdd); |
| + } |
| } |
| -- (void)underlaySurfaceRemoved { |
| - --underlaySurfaceCount_; |
| - DCHECK_GE(underlaySurfaceCount_, 0); |
| +- (id)initWithContentRect:(NSRect)contentRect |
| + styleMask:(NSUInteger)windowStyle |
| + backing:(NSBackingStoreType)bufferingType |
| + defer:(BOOL)deferCreation { |
| + if ((self = [super initWithContentRect:contentRect |
| + styleMask:windowStyle |
| + backing:bufferingType |
| + defer:deferCreation])) { |
| + // The invisible opaque area technique only works > 10.5. Fortunately, hole |
| + // punching is used only when IOSurfaces are used to transport, and that's |
| + // also only on > 10.5. |
| + if (base::mac::IsOSSnowLeopardOrLater()) { |
| + [self setOpaque:NO]; |
| + [self _setContentHasShadow:NO]; |
| + |
| + NSView* rootView = [[self contentView] superview]; |
| + NSRect rootBounds = [rootView bounds]; |
| + |
| + const CGFloat kEdgeInset = 16; |
| + |
| + scoped_nsobject<NSView> leftOpaque( |
| + [[OpaqueView alloc] initWithFrame: |
| + NSMakeRect(NSMinX(rootBounds), NSMinY(rootBounds) + kEdgeInset, |
| + 1, NSHeight(rootBounds) - 2 * kEdgeInset)]); |
| + [rootView addSubview:leftOpaque]; |
|
Mark Mentovai
2012/04/10 19:08:30
Can you wait to add it ’til after the resize mask
Avi (use Gerrit)
2012/04/10 19:42:50
Done.
|
| + [leftOpaque setAutoresizingMask:NSViewMaxXMargin|NSViewHeightSizable]; |
|
Mark Mentovai
2012/04/10 19:08:30
Tiny bit more readable with space around the “or”
Avi (use Gerrit)
2012/04/10 19:42:50
Done.
|
| + [leftOpaque setAlphaValue:0.002f]; |
|
Mark Mentovai
2012/04/10 19:08:30
Want a const CGFloat to store this so you can be s
Avi (use Gerrit)
2012/04/10 19:42:50
Done.
|
| + |
| + scoped_nsobject<NSView> rightOpaque([[OpaqueView alloc] initWithFrame: |
| + NSMakeRect(NSMaxX(rootBounds) - 1, NSMinY(rootBounds) + kEdgeInset, |
| + 1, NSHeight(rootBounds) - 2 * kEdgeInset)]); |
|
Mark Mentovai
2012/04/10 19:08:30
Similarly, you can also keep consts for y and h.
Avi (use Gerrit)
2012/04/10 19:42:50
It's weird to have some of the values from the roo
Mark Mentovai
2012/04/10 19:48:29
Avi wrote:
|
| + [rootView addSubview:rightOpaque]; |
| + [rightOpaque setAutoresizingMask:NSViewMinXMargin|NSViewHeightSizable]; |
| + [rightOpaque setAlphaValue:0.002f]; |
| + } |
| + } |
| - if (underlaySurfaceCount_ == 0) |
| - [self setOpaque:YES]; |
| + return self; |
| } |
| @end |