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) { | |
41 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.
| |
42 BOOL view2IsOpaqueView = [view2 isKindOfClass:[OpaqueView class]]; | |
43 if (view1IsOpaqueView && view2IsOpaqueView) | |
44 return NSOrderedSame; | |
45 if (view1IsOpaqueView) | |
46 return NSOrderedDescending; | |
47 if (view2IsOpaqueView) | |
48 return NSOrderedAscending; | |
49 return NSOrderedSame; | |
50 } | |
51 | |
52 void RootDidAddSubview(id self, SEL _cmd, NSView* subview) { | |
53 // Make sure the opaques are on top. | |
54 [self sortSubviewsUsingFunction:OpaqueViewsOnTop context:NULL]; | |
55 } | |
56 | |
57 } // namespace | |
8 | 58 |
9 @implementation UnderlayOpenGLHostingWindow | 59 @implementation UnderlayOpenGLHostingWindow |
10 | 60 |
11 - (void)underlaySurfaceAdded { | 61 + (void)load { |
12 DCHECK_GE(underlaySurfaceCount_, 0); | 62 base::mac::ScopedNSAutoreleasePool pool; |
13 ++underlaySurfaceCount_; | |
14 | 63 |
15 // We're having the OpenGL surface render under the window, so the window | 64 // On 10.8+ the background for textured windows are no longer drawn by |
16 // needs to be not opaque. | 65 // NSGrayFrame, and NSThemeFrame is used instead <http://crbug.com/114745>. |
17 if (underlaySurfaceCount_ == 1) | 66 Class borderViewClass = NSClassFromString( |
18 [self setOpaque:NO]; | 67 base::mac::IsOSMountainLionOrLater() ? @"NSThemeFrame" : @"NSGrayFrame"); |
68 DCHECK(borderViewClass); | |
69 if (!borderViewClass) return; | |
70 | |
71 // Install callback for added views. | |
72 Method m = class_getInstanceMethod([NSView class], @selector(didAddSubview:)); | |
Mark Mentovai
2012/04/10 19:08:30
You can use borderViewClass here instead of [NSVie
| |
73 DCHECK(m); | |
74 if (m) { | |
75 BOOL didAdd = class_addMethod(borderViewClass, | |
76 @selector(didAddSubview:), | |
77 reinterpret_cast<IMP>(&RootDidAddSubview), | |
78 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:
| |
79 DCHECK(didAdd); | |
80 } | |
19 } | 81 } |
20 | 82 |
21 - (void)underlaySurfaceRemoved { | 83 - (id)initWithContentRect:(NSRect)contentRect |
22 --underlaySurfaceCount_; | 84 styleMask:(NSUInteger)windowStyle |
23 DCHECK_GE(underlaySurfaceCount_, 0); | 85 backing:(NSBackingStoreType)bufferingType |
86 defer:(BOOL)deferCreation { | |
87 if ((self = [super initWithContentRect:contentRect | |
88 styleMask:windowStyle | |
89 backing:bufferingType | |
90 defer:deferCreation])) { | |
91 // The invisible opaque area technique only works > 10.5. Fortunately, hole | |
92 // punching is used only when IOSurfaces are used to transport, and that's | |
93 // also only on > 10.5. | |
94 if (base::mac::IsOSSnowLeopardOrLater()) { | |
95 [self setOpaque:NO]; | |
96 [self _setContentHasShadow:NO]; | |
24 | 97 |
25 if (underlaySurfaceCount_ == 0) | 98 NSView* rootView = [[self contentView] superview]; |
26 [self setOpaque:YES]; | 99 NSRect rootBounds = [rootView bounds]; |
100 | |
101 const CGFloat kEdgeInset = 16; | |
102 | |
103 scoped_nsobject<NSView> leftOpaque( | |
104 [[OpaqueView alloc] initWithFrame: | |
105 NSMakeRect(NSMinX(rootBounds), NSMinY(rootBounds) + kEdgeInset, | |
106 1, NSHeight(rootBounds) - 2 * kEdgeInset)]); | |
107 [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.
| |
108 [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.
| |
109 [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.
| |
110 | |
111 scoped_nsobject<NSView> rightOpaque([[OpaqueView alloc] initWithFrame: | |
112 NSMakeRect(NSMaxX(rootBounds) - 1, NSMinY(rootBounds) + kEdgeInset, | |
113 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:
| |
114 [rootView addSubview:rightOpaque]; | |
115 [rightOpaque setAutoresizingMask:NSViewMinXMargin|NSViewHeightSizable]; | |
116 [rightOpaque setAlphaValue:0.002f]; | |
117 } | |
118 } | |
119 | |
120 return self; | |
27 } | 121 } |
28 | 122 |
29 @end | 123 @end |
OLD | NEW |