Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(305)

Unified Diff: ui/base/cocoa/underlay_opengl_hosting_window.mm

Issue 10037008: Fix window shadows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ui/base/cocoa/underlay_opengl_hosting_window.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..d663a6ff58c06817218f7154900078d186965120 100644
--- a/ui/base/cocoa/underlay_opengl_hosting_window.mm
+++ b/ui/base/cocoa/underlay_opengl_hosting_window.mm
@@ -4,26 +4,116 @@
#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) {
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.
+ if ([view1 isKindOfClass:[OpaqueView class]])
+ return NSOrderedDescending;
+ if ([view2 isKindOfClass:[OpaqueView class]])
+ 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:));
+ DCHECK(m);
+ if (m) {
+ BOOL didAdd = class_addMethod(borderViewClass,
+ @selector(didAddSubview:),
+ reinterpret_cast<IMP>(&RootDidAddSubview),
+ method_getTypeEncoding(m));
+ 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];
+ [leftOpaque setAutoresizingMask:NSViewMaxXMargin|NSViewHeightSizable];
+ [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
+
+ scoped_nsobject<NSView> rightOpaque([[OpaqueView alloc] initWithFrame:
+ NSMakeRect(NSMaxX(rootBounds) - 1, NSMinY(rootBounds) + kEdgeInset,
+ 1, NSHeight(rootBounds) - 2 * kEdgeInset)]);
+ [rootView addSubview:rightOpaque];
+ [rightOpaque setAutoresizingMask:NSViewMinXMargin|NSViewHeightSizable];
+ [rightOpaque setAlphaValue:0.002f];
+ }
+ }
- if (underlaySurfaceCount_ == 0)
- [self setOpaque:YES];
+ return self;
}
@end
« no previous file with comments | « ui/base/cocoa/underlay_opengl_hosting_window.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698