Chromium Code Reviews| Index: ui/views/cocoa/bridged_content_view.mm |
| diff --git a/ui/views/cocoa/bridged_content_view.mm b/ui/views/cocoa/bridged_content_view.mm |
| index 56e53abe4eaf4e947ae921953083f16ada4f8924..d03dc78fa7987185a82fc4b9d857066750276962 100644 |
| --- a/ui/views/cocoa/bridged_content_view.mm |
| +++ b/ui/views/cocoa/bridged_content_view.mm |
| @@ -5,6 +5,7 @@ |
| #import "ui/views/cocoa/bridged_content_view.h" |
| #include "base/logging.h" |
| +#import "base/mac/mac_util.h" |
| #import "base/mac/scoped_nsobject.h" |
| #include "base/strings/sys_string_conversions.h" |
| #include "skia/ext/skia_utils_mac.h" |
| @@ -16,6 +17,9 @@ |
| #import "ui/events/keycodes/keyboard_code_conversion_mac.h" |
| #include "ui/gfx/canvas_paint_mac.h" |
| #include "ui/gfx/geometry/rect.h" |
| +#include "ui/gfx/path.h" |
| +#import "ui/gfx/path_mac.h" |
| +#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" |
| #include "ui/strings/grit/ui_strings.h" |
| #include "ui/views/controls/menu/menu_config.h" |
| #include "ui/views/controls/menu/menu_controller.h" |
| @@ -26,6 +30,17 @@ using views::MenuController; |
| namespace { |
| +// Returns true if all four corners of |rect| are contained inside |path|. |
| +bool IsRectInsidePath(NSRect rect, NSBezierPath* path) { |
| + return [path containsPoint:rect.origin] && |
| + [path containsPoint:NSMakePoint(rect.origin.x + rect.size.width, |
| + rect.origin.y)] && |
| + [path containsPoint:NSMakePoint(rect.origin.x, |
| + rect.origin.y + rect.size.height)] && |
| + [path containsPoint:NSMakePoint(rect.origin.x + rect.size.width, |
| + rect.origin.y + rect.size.height)]; |
| +} |
| + |
| // Convert a |point| in |source_window|'s AppKit coordinate system (origin at |
| // the bottom left of the window) to |target_window|'s content rect, with the |
| // origin at the top left of the content area. |
| @@ -165,6 +180,29 @@ bool DispatchEventToMenu(views::Widget* widget, ui::KeyboardCode key_code) { |
| } |
| } |
| +- (void)updateWindowMask { |
| + DCHECK(![self inLiveResize]); |
|
tapted
2016/02/09 06:47:12
add a DCHECK(hostedView_); too. This is to show it
karandeepb
2016/02/10 00:39:44
Done.
|
| + DCHECK(base::mac::IsOSMavericksOrEarlier()); |
| + |
| + views::Widget* widget = hostedView_->GetWidget(); |
| + if (!widget->non_client_view()) |
| + return; |
| + |
| + const NSRect frameRect = [self bounds]; |
| + gfx::Path mask; |
| + widget->non_client_view()->GetWindowMask(gfx::Size(frameRect.size), &mask); |
| + if (mask.isEmpty()) |
| + return; |
| + |
| + windowMask_.reset([gfx::CreateNSBezierPathFromSkPath(mask) retain]); |
| + |
| + // Convert to AppKit coordinate system. |
| + NSAffineTransform* flipTransform = [NSAffineTransform transform]; |
| + [flipTransform translateXBy:0.0 yBy:frameRect.size.height]; |
| + [flipTransform scaleXBy:1.0 yBy:-1.0]; |
| + [windowMask_ transformUsingAffineTransform:flipTransform]; |
| +} |
| + |
| // BridgedContentView private implementation. |
| - (void)handleKeyEvent:(NSEvent*)theEvent { |
| @@ -306,6 +344,17 @@ bool DispatchEventToMenu(views::Widget* widget, ui::KeyboardCode key_code) { |
| hostedView_->SetSize(gfx::Size(newSize.width, newSize.height)); |
| } |
| +- (void)viewDidEndLiveResize { |
| + // We prevent updating the window mask and clipping the border around the |
| + // view, during a live resize. Hence update the window mask and redraw the |
| + // view after resize has completed. |
| + [super viewDidEndLiveResize]; |
|
tapted
2016/02/09 06:47:12
nit: move before comment
karandeepb
2016/02/10 00:39:44
Done.
|
| + if (base::mac::IsOSMavericksOrEarlier()) { |
| + [self updateWindowMask]; |
| + [self setNeedsDisplay:YES]; |
| + } |
| +} |
| + |
| - (void)drawRect:(NSRect)dirtyRect { |
| // Note that BridgedNativeWidget uses -[NSWindow setAutodisplay:NO] to |
| // suppress calls to this when the window is known to be hidden. |
| @@ -320,6 +369,32 @@ bool DispatchEventToMenu(views::Widget* widget, ui::KeyboardCode key_code) { |
| yRadius:radius] fill]; |
| } |
| + // On OS versions earlier than Yosemite, to generate a drop shadow, we set an |
| + // opaque background. This causes windows with non rectangular shapes to have |
| + // square corners. To get around this, fill the path outside the window |
| + // boundary with clearColor and tell Cococa to regenerate drop shadow. See |
| + // crbug.com/543671. |
| + if (windowMask_ && ![self inLiveResize] && |
| + !IsRectInsidePath(dirtyRect, windowMask_)) { |
| + gfx::ScopedNSGraphicsContextSaveGState state; |
|
tapted
2016/02/09 06:47:12
nit: before this, add
DCHECK(base::mac::IsOSMave
karandeepb
2016/02/10 00:39:44
Done.
|
| + |
| + // The outer rectangular path corresponding to the window. |
| + NSBezierPath* outerPath = [NSBezierPath bezierPathWithRect:[self bounds]]; |
| + |
| + [outerPath appendBezierPath:windowMask_]; |
| + [outerPath setWindingRule:NSEvenOddWindingRule]; |
| + [[NSGraphicsContext currentContext] |
| + setCompositingOperation:NSCompositeCopy]; |
| + [[NSColor clearColor] set]; |
| + |
| + // Fill the region between windowMask_ and its outer rectangular path |
| + // with clear color. This causes the window to have the shape described |
| + // by windowMask_. |
| + [outerPath fill]; |
| + // Regerate drop shadow around the window boundary. |
| + [[self window] invalidateShadow]; |
| + } |
| + |
| // If there's a layer, painting occurs in BridgedNativeWidget::OnPaintLayer(). |
| if (hostedView_->GetWidget()->GetLayer()) |
| return; |