 Chromium Code Reviews
 Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #import "ui/base/cocoa/underlay_opengl_hosting_window.h" | 5 #import "ui/base/cocoa/underlay_opengl_hosting_window.h" | 
| 6 | 6 | 
| 7 #import <objc/runtime.h> | |
| 8 | |
| 7 #include "base/logging.h" | 9 #include "base/logging.h" | 
| 10 #include "base/mac/mac_util.h" | |
| 11 #include "base/mac/scoped_nsautorelease_pool.h" | |
| 12 #include "base/memory/scoped_nsobject.h" | |
| 13 | |
| 14 @interface NSWindow (UndocumentedAPI) | |
| 15 // Normally, punching a hole in a window by painting a subview with a | |
| 16 // transparent color causes the shadow for that area to also not be present. | |
| 17 // That feature is "content has shadow", which means that shadows are effective | |
| 18 // even in the content area of the window. If, however, "content has shadow" is | |
| 19 // turned off, then the transparent area of the content casts a shadow. The one | |
| 20 // tricky part is that even if "content has shadow" is turned off, "the content" | |
| 21 // is defined as being the scanline from the leftmost opaque part to the | |
| 22 // rightmost opaque part. Therefore, to force the entire window to have a | |
| 23 // shadow, make sure that for the entire content region, there is an opaque area | |
| 24 // on the right and left edge of the window. | |
| 25 - (void)_setContentHasShadow:(BOOL)shadow; | |
| 26 @end | |
| 27 | |
| 28 @interface OpaqueView : NSView | |
| 29 @end | |
| 30 | |
| 31 @implementation OpaqueView | |
| 32 - (void)drawRect:(NSRect)r { | |
| 33 [[NSColor blackColor] set]; | |
| 34 NSRectFill(r); | |
| 35 } | |
| 36 @end | |
| 37 | |
| 38 namespace { | |
| 39 | |
| 40 NSComparisonResult OpaqueViewsOnTop(id view1, id view2, void* context) { | |
| 
jbates
2012/04/10 17:54:00
If view1 and view2 are both OpaqueView, then:
  Op
 
Avi (use Gerrit)
2012/04/10 18:34:46
Probably a good idea.
 | |
| 41 if ([view1 isKindOfClass:[OpaqueView class]]) | |
| 42 return NSOrderedDescending; | |
| 43 if ([view2 isKindOfClass:[OpaqueView class]]) | |
| 44 return NSOrderedAscending; | |
| 45 return NSOrderedSame; | |
| 46 } | |
| 47 | |
| 48 void RootDidAddSubview(id self, SEL _cmd, NSView* subview) { | |
| 49 // Make sure the opaques are on top. | |
| 50 [self sortSubviewsUsingFunction:OpaqueViewsOnTop context:NULL]; | |
| 51 } | |
| 52 | |
| 53 } // namespace | |
| 8 | 54 | 
| 9 @implementation UnderlayOpenGLHostingWindow | 55 @implementation UnderlayOpenGLHostingWindow | 
| 10 | 56 | 
| 11 - (void)underlaySurfaceAdded { | 57 + (void)load { | 
| 12 DCHECK_GE(underlaySurfaceCount_, 0); | 58 base::mac::ScopedNSAutoreleasePool pool; | 
| 13 ++underlaySurfaceCount_; | |
| 14 | 59 | 
| 15 // We're having the OpenGL surface render under the window, so the window | 60 // On 10.8+ the background for textured windows are no longer drawn by | 
| 16 // needs to be not opaque. | 61 // NSGrayFrame, and NSThemeFrame is used instead <http://crbug.com/114745>. | 
| 17 if (underlaySurfaceCount_ == 1) | 62 Class borderViewClass = NSClassFromString( | 
| 18 [self setOpaque:NO]; | 63 base::mac::IsOSMountainLionOrLater() ? @"NSThemeFrame" : @"NSGrayFrame"); | 
| 64 DCHECK(borderViewClass); | |
| 65 if (!borderViewClass) return; | |
| 66 | |
| 67 // Install callback for added views. | |
| 68 Method m = class_getInstanceMethod([NSView class], @selector(didAddSubview:)); | |
| 69 DCHECK(m); | |
| 70 if (m) { | |
| 71 BOOL didAdd = class_addMethod(borderViewClass, | |
| 72 @selector(didAddSubview:), | |
| 73 reinterpret_cast<IMP>(&RootDidAddSubview), | |
| 74 method_getTypeEncoding(m)); | |
| 75 DCHECK(didAdd); | |
| 76 } | |
| 19 } | 77 } | 
| 20 | 78 | 
| 21 - (void)underlaySurfaceRemoved { | 79 - (id)initWithContentRect:(NSRect)contentRect | 
| 22 --underlaySurfaceCount_; | 80 styleMask:(NSUInteger)windowStyle | 
| 23 DCHECK_GE(underlaySurfaceCount_, 0); | 81 backing:(NSBackingStoreType)bufferingType | 
| 82 defer:(BOOL)deferCreation { | |
| 83 if ((self = [super initWithContentRect:contentRect | |
| 84 styleMask:windowStyle | |
| 85 backing:bufferingType | |
| 86 defer:deferCreation])) { | |
| 87 // The invisible opaque area technique only works > 10.5. Fortunately, hole | |
| 88 // punching is used only when IOSurfaces are used to transport, and that's | |
| 89 // also only on > 10.5. | |
| 90 if (base::mac::IsOSSnowLeopardOrLater()) { | |
| 91 [self setOpaque:NO]; | |
| 92 [self _setContentHasShadow:NO]; | |
| 24 | 93 | 
| 25 if (underlaySurfaceCount_ == 0) | 94 NSView* rootView = [[self contentView] superview]; | 
| 26 [self setOpaque:YES]; | 95 NSRect rootBounds = [rootView bounds]; | 
| 96 | |
| 97 const CGFloat kEdgeInset = 16; | |
| 98 | |
| 99 scoped_nsobject<NSView> leftOpaque( | |
| 100 [[OpaqueView alloc] initWithFrame: | |
| 101 NSMakeRect(NSMinX(rootBounds), NSMinY(rootBounds) + kEdgeInset, | |
| 102 1, NSHeight(rootBounds) - 2 * kEdgeInset)]); | |
| 103 [rootView addSubview:leftOpaque]; | |
| 104 [leftOpaque setAutoresizingMask:NSViewMaxXMargin|NSViewHeightSizable]; | |
| 105 [leftOpaque setAlphaValue:0.002f]; | |
| 
jbates
2012/04/10 17:54:00
Is this chosen on purpose to round to zero when co
 
Avi (use Gerrit)
2012/04/10 18:34:46
You ascribe to me far more cleverness than is dese
 | |
| 106 | |
| 107 scoped_nsobject<NSView> rightOpaque([[OpaqueView alloc] initWithFrame: | |
| 108 NSMakeRect(NSMaxX(rootBounds) - 1, NSMinY(rootBounds) + kEdgeInset, | |
| 109 1, NSHeight(rootBounds) - 2 * kEdgeInset)]); | |
| 110 [rootView addSubview:rightOpaque]; | |
| 111 [rightOpaque setAutoresizingMask:NSViewMinXMargin|NSViewHeightSizable]; | |
| 112 [rightOpaque setAlphaValue:0.002f]; | |
| 113 } | |
| 114 } | |
| 115 | |
| 116 return self; | |
| 27 } | 117 } | 
| 28 | 118 | 
| 29 @end | 119 @end | 
| OLD | NEW |