From 5d49fc4bee7e214755b71f438f734f2b77566bb2 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 11 Sep 2013 18:10:28 +0800 Subject: [PATCH 1/7] WIP: rounded corner of frameless window. --- browser/native_window_mac.h | 3 ++ browser/native_window_mac.mm | 85 ++++++++++++++++++++++-------------- 2 files changed, 55 insertions(+), 33 deletions(-) diff --git a/browser/native_window_mac.h b/browser/native_window_mac.h index ea359fa101b..ef3ed3a3839 100644 --- a/browser/native_window_mac.h +++ b/browser/native_window_mac.h @@ -63,6 +63,9 @@ class NativeWindowMac : public NativeWindow { // Called to handle a mouse event. void HandleMouseEvent(NSEvent* event); + // Clip web view to rounded corner. + void ClipWebView(); + NSWindow*& window() { return window_; } SkRegion* draggable_region() const { return draggable_region_.get(); } diff --git a/browser/native_window_mac.mm b/browser/native_window_mac.mm index 87fafd69f83..bfa615d6fe4 100644 --- a/browser/native_window_mac.mm +++ b/browser/native_window_mac.mm @@ -28,10 +28,6 @@ - (void)setBottomCornerRounded:(BOOL)rounded; @end -@interface NSView (WebContentsView) -- (void)setMouseDownCanMoveWindow:(BOOL)can_move; -@end - @interface NSView (PrivateMethods) - (CGFloat)roundedCornerRadius; @end @@ -55,6 +51,11 @@ shell_->NotifyWindowBlur(); } +- (void)windowDidResize:(NSNotification*)otification { + if (!shell_->has_frame()) + shell_->ClipWebView(); +} + - (void)windowWillClose:(NSNotification*)notification { shell_->window() = nil; [self autorelease]; @@ -78,7 +79,7 @@ @end @interface AtomNSWindow : AtomEventProcessingWindow { - @private + @protected atom::NativeWindowMac* shell_; } - (void)setShell:(atom::NativeWindowMac*)shell; @@ -113,32 +114,30 @@ NSRectFill(rect); // Set up our clip. - CGFloat cornerRadius = 4.0; - if ([view respondsToSelector:@selector(roundedCornerRadius)]) - cornerRadius = [view roundedCornerRadius]; + CGFloat cornerRadius = 40.0; + // if ([view respondsToSelector:@selector(roundedCornerRadius)]) + // cornerRadius = [view roundedCornerRadius]; [[NSBezierPath bezierPathWithRoundedRect:[view bounds] xRadius:cornerRadius yRadius:cornerRadius] addClip]; - [[NSColor whiteColor] set]; + [[NSColor clearColor] set]; NSRectFill(rect); } -+ (NSRect)frameRectForContentRect:(NSRect)contentRect - styleMask:(NSUInteger)mask { - return contentRect; +- (BOOL)canBecomeKeyWindow { + return YES; } -+ (NSRect)contentRectForFrameRect:(NSRect)frameRect - styleMask:(NSUInteger)mask { - return frameRect; +- (BOOL)hasShadow { + return YES; } -- (NSRect)frameRectForContentRect:(NSRect)contentRect { - return contentRect; +- (void)keyDown:(NSEvent*)event { + [self redispatchKeyEvent:event]; } -- (NSRect)contentRectForFrameRect:(NSRect)frameRect { - return frameRect; +- (void)keyUp:(NSEvent *)event { + [self redispatchKeyEvent:event]; } @end @@ -195,23 +194,29 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents, (NSHeight(main_screen_rect) - height) / 2, width, height); + + AtomNSWindow* atomWindow; NSUInteger style_mask = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask | NSTexturedBackgroundWindowMask; - AtomNSWindow* atom_window = has_frame_ ? - [[AtomNSWindow alloc] - initWithContentRect:cocoa_bounds - styleMask:style_mask - backing:NSBackingStoreBuffered - defer:YES] : - [[AtomFramelessNSWindow alloc] - initWithContentRect:cocoa_bounds - styleMask:style_mask - backing:NSBackingStoreBuffered - defer:YES]; - [atom_window setShell:this]; + if (has_frame_) { + atomWindow = [[AtomNSWindow alloc] + initWithContentRect:cocoa_bounds + styleMask:style_mask + backing:NSBackingStoreBuffered + defer:YES]; + } else { + atomWindow = [[AtomFramelessNSWindow alloc] + initWithContentRect:cocoa_bounds + styleMask:style_mask + backing:NSBackingStoreBuffered + defer:YES]; + [atomWindow setBottomCornerRounded:YES]; + } + + [atomWindow setShell:this]; + window_ = atomWindow; - window_ = atom_window; [window() setDelegate:[[AtomNSWindowDelegate alloc] initWithShell:this]]; // Disable fullscreen button when 'fullscreen' is specified to false. @@ -434,7 +439,7 @@ gfx::NativeWindow NativeWindowMac::GetNativeWindow() { bool NativeWindowMac::IsWithinDraggableRegion(NSPoint point) const { if (!draggable_region_) return false; - NSView* webView = web_contents()->GetView()->GetNativeView(); + NSView* webView = GetWebContents()->GetView()->GetNativeView(); NSInteger webViewHeight = NSHeight([webView bounds]); // |draggable_region_| is stored in local platform-indepdent coordiate system // while |point| is in local Cocoa coordinate system. Do the conversion @@ -491,6 +496,8 @@ void NativeWindowMac::InstallView() { [view setFrame:[frameView bounds]]; [frameView addSubview:view]; + ClipWebView(); + [[window() standardWindowButton:NSWindowZoomButton] setHidden:YES]; [[window() standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES]; [[window() standardWindowButton:NSWindowCloseButton] setHidden:YES]; @@ -503,6 +510,18 @@ void NativeWindowMac::UninstallView() { [view removeFromSuperview]; } +void NativeWindowMac::ClipWebView() { + NSView* view = GetWebContents()->GetView()->GetNativeView(); + + CGFloat cornerRadius = 40.0; + // if ([view respondsToSelector:@selector(roundedCornerRadius)]) + // cornerRadius = [view roundedCornerRadius]; + + view.wantsLayer = YES; + view.layer.masksToBounds = YES; + view.layer.cornerRadius = cornerRadius; +} + void NativeWindowMac::InstallDraggableRegionViews() { DCHECK(!has_frame_); From 8f31bf8615f760c71c80861924b2d488d70a987f Mon Sep 17 00:00:00 2001 From: Steve Smith Date: Wed, 11 Sep 2013 16:23:17 -0400 Subject: [PATCH 2/7] Get radius working with frameless window. Right now it's set as a constant `AtomWindowCornerRadius`, but it could be set to a variable. --- browser/native_window_mac.mm | 51 +++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/browser/native_window_mac.mm b/browser/native_window_mac.mm index bfa615d6fe4..8cc2dcc236d 100644 --- a/browser/native_window_mac.mm +++ b/browser/native_window_mac.mm @@ -78,6 +78,8 @@ @end +static CGFloat const AtomWindowCornerRadius = 5.0; + @interface AtomNSWindow : AtomEventProcessingWindow { @protected atom::NativeWindowMac* shell_; @@ -102,6 +104,24 @@ @end +@interface AtomFramelessView : NSView +@end + +@implementation AtomFramelessView +- (void)drawRect:(NSRect) rect { + NSBezierPath * shadowPath = [NSBezierPath bezierPathWithRoundedRect:NSInsetRect([self bounds], 0.5, 0.5) + xRadius:AtomWindowCornerRadius + yRadius:AtomWindowCornerRadius]; + + [[NSColor blackColor] set]; + [shadowPath fill]; + + [[NSColor colorWithCalibratedRed: 0.0 green: 0.0 blue: 0.0 alpha:0.7] set]; + [shadowPath stroke]; + [shadowPath addClip]; +} +@end + @interface AtomFramelessNSWindow : AtomNSWindow - (void)drawCustomFrameRect:(NSRect)rect forView:(NSView*)view; @end @@ -112,16 +132,6 @@ [[NSBezierPath bezierPathWithRect:rect] addClip]; [[NSColor clearColor] set]; NSRectFill(rect); - - // Set up our clip. - CGFloat cornerRadius = 40.0; - // if ([view respondsToSelector:@selector(roundedCornerRadius)]) - // cornerRadius = [view roundedCornerRadius]; - [[NSBezierPath bezierPathWithRoundedRect:[view bounds] - xRadius:cornerRadius - yRadius:cornerRadius] addClip]; - [[NSColor clearColor] set]; - NSRectFill(rect); } - (BOOL)canBecomeKeyWindow { @@ -208,10 +218,12 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents, } else { atomWindow = [[AtomFramelessNSWindow alloc] initWithContentRect:cocoa_bounds - styleMask:style_mask + styleMask:NSBorderlessWindowMask | NSClosableWindowMask | + NSMiniaturizableWindowMask | NSResizableWindowMask backing:NSBackingStoreBuffered defer:YES]; - [atomWindow setBottomCornerRounded:YES]; + [atomWindow setOpaque:NO]; + [atomWindow setBackgroundColor:[NSColor clearColor]]; } [atomWindow setShell:this]; @@ -412,7 +424,7 @@ void NativeWindowMac::SetKiosk(bool kiosk) { if (kiosk) { NSApplicationPresentationOptions options = NSApplicationPresentationHideDock + - NSApplicationPresentationHideMenuBar + + NSApplicationPresentationHideMenuBar + NSApplicationPresentationDisableAppleMenu + NSApplicationPresentationDisableProcessSwitching + NSApplicationPresentationDisableForceQuit + @@ -494,9 +506,17 @@ void NativeWindowMac::InstallView() { } else { NSView* frameView = [[window() contentView] superview]; [view setFrame:[frameView bounds]]; - [frameView addSubview:view]; + + AtomFramelessView * shadowView = [[AtomFramelessView alloc] initWithFrame: [frameView bounds]]; + + [frameView addSubview:shadowView]; + [shadowView addSubview:view]; + ClipWebView(); + // + // [window() setHasShadow: NO]; + // [window() setHasShadow: YES]; [[window() standardWindowButton:NSWindowZoomButton] setHidden:YES]; [[window() standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES]; @@ -513,13 +533,12 @@ void NativeWindowMac::UninstallView() { void NativeWindowMac::ClipWebView() { NSView* view = GetWebContents()->GetView()->GetNativeView(); - CGFloat cornerRadius = 40.0; // if ([view respondsToSelector:@selector(roundedCornerRadius)]) // cornerRadius = [view roundedCornerRadius]; view.wantsLayer = YES; view.layer.masksToBounds = YES; - view.layer.cornerRadius = cornerRadius; + view.layer.cornerRadius = AtomWindowCornerRadius; } void NativeWindowMac::InstallDraggableRegionViews() { From aabba3c641974d35dd1144a92adde2d544949940 Mon Sep 17 00:00:00 2001 From: Steve Smith Date: Wed, 11 Sep 2013 17:25:42 -0400 Subject: [PATCH 3/7] Fix view autoresizing. --- browser/native_window_mac.mm | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/browser/native_window_mac.mm b/browser/native_window_mac.mm index 8cc2dcc236d..c66a30d11eb 100644 --- a/browser/native_window_mac.mm +++ b/browser/native_window_mac.mm @@ -115,9 +115,6 @@ static CGFloat const AtomWindowCornerRadius = 5.0; [[NSColor blackColor] set]; [shadowPath fill]; - - [[NSColor colorWithCalibratedRed: 0.0 green: 0.0 blue: 0.0 alpha:0.7] set]; - [shadowPath stroke]; [shadowPath addClip]; } @end @@ -505,10 +502,12 @@ void NativeWindowMac::InstallView() { [[window() contentView] addSubview:view]; } else { NSView* frameView = [[window() contentView] superview]; - [view setFrame:[frameView bounds]]; AtomFramelessView * shadowView = [[AtomFramelessView alloc] initWithFrame: [frameView bounds]]; + [shadowView setAutoresizesSubviews:YES]; + [shadowView setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable]; + [view setFrame:[shadowView bounds]]; [frameView addSubview:shadowView]; [shadowView addSubview:view]; From cf4a5662902e3dbae3b3f6a551994a95006f436c Mon Sep 17 00:00:00 2001 From: Steve Smith Date: Wed, 11 Sep 2013 22:02:42 -0400 Subject: [PATCH 4/7] Just round the top also and use a standard window. Using borderless window causes too many issues. Smaller, less window-like shadows being the most annoying. --- browser/native_window_mac.mm | 39 +++++++++--------------------------- 1 file changed, 10 insertions(+), 29 deletions(-) diff --git a/browser/native_window_mac.mm b/browser/native_window_mac.mm index c66a30d11eb..d3d8087e366 100644 --- a/browser/native_window_mac.mm +++ b/browser/native_window_mac.mm @@ -78,7 +78,7 @@ @end -static CGFloat const AtomWindowCornerRadius = 5.0; +static CGFloat const AtomWindowCornerRadius = 4.0; @interface AtomNSWindow : AtomEventProcessingWindow { @protected @@ -104,21 +104,6 @@ static CGFloat const AtomWindowCornerRadius = 5.0; @end -@interface AtomFramelessView : NSView -@end - -@implementation AtomFramelessView -- (void)drawRect:(NSRect) rect { - NSBezierPath * shadowPath = [NSBezierPath bezierPathWithRoundedRect:NSInsetRect([self bounds], 0.5, 0.5) - xRadius:AtomWindowCornerRadius - yRadius:AtomWindowCornerRadius]; - - [[NSColor blackColor] set]; - [shadowPath fill]; - [shadowPath addClip]; -} -@end - @interface AtomFramelessNSWindow : AtomNSWindow - (void)drawCustomFrameRect:(NSRect)rect forView:(NSView*)view; @end @@ -135,6 +120,10 @@ static CGFloat const AtomWindowCornerRadius = 5.0; return YES; } +- (BOOL)canBecomeMainWindow { + return YES; +} + - (BOOL)hasShadow { return YES; } @@ -197,8 +186,8 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents, NSRect main_screen_rect = [[[NSScreen screens] objectAtIndex:0] frame]; NSRect cocoa_bounds = NSMakeRect( - (NSWidth(main_screen_rect) - width) / 2, - (NSHeight(main_screen_rect) - height) / 2, + round((NSWidth(main_screen_rect) - width) / 2) , + round((NSHeight(main_screen_rect) - height) / 2), width, height); @@ -215,7 +204,7 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents, } else { atomWindow = [[AtomFramelessNSWindow alloc] initWithContentRect:cocoa_bounds - styleMask:NSBorderlessWindowMask | NSClosableWindowMask | + styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask backing:NSBackingStoreBuffered defer:YES]; @@ -503,19 +492,11 @@ void NativeWindowMac::InstallView() { } else { NSView* frameView = [[window() contentView] superview]; - AtomFramelessView * shadowView = [[AtomFramelessView alloc] initWithFrame: [frameView bounds]]; - [shadowView setAutoresizesSubviews:YES]; - [shadowView setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable]; - - [view setFrame:[shadowView bounds]]; - [frameView addSubview:shadowView]; - [shadowView addSubview:view]; + [view setFrame:[frameView bounds]]; + [frameView addSubview:view]; ClipWebView(); - // - // [window() setHasShadow: NO]; - // [window() setHasShadow: YES]; [[window() standardWindowButton:NSWindowZoomButton] setHidden:YES]; [[window() standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES]; From 6c098deb57e5f1b3b4e722d8c416374564aa17e0 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Sep 2013 13:00:28 +0800 Subject: [PATCH 5/7] :lipstick: Fix cpplint warnings. --- browser/native_window_win.cc | 2 +- script/cpplint.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/browser/native_window_win.cc b/browser/native_window_win.cc index babb0e58508..c8ac370e0c8 100644 --- a/browser/native_window_win.cc +++ b/browser/native_window_win.cc @@ -397,7 +397,7 @@ views::NonClientFrameView* NativeWindowWin::CreateNonClientFrameView( return new NativeWindowFramelessView(widget, this); } - + void NativeWindowWin::OnViewWasResized() { // Set the window shape of the RWHV. gfx::Size sz = web_view_->size(); diff --git a/script/cpplint.py b/script/cpplint.py index 54c0674c366..2ee68e08d80 100755 --- a/script/cpplint.py +++ b/script/cpplint.py @@ -12,6 +12,7 @@ IGNORE_FILES = [ 'browser/atom_application_delegate_mac.h', 'browser/native_window_mac.h', 'browser/ui/atom_menu_controller_mac.h', + 'browser/ui/cocoa/custom_frame_view.h', 'browser/ui/nsalert_synchronous_sheet_mac.h', 'common/api/api_messages.cc', 'common/api/api_messages.h', From 7a1365673e508fd8e83654b7b11388a0d7cb61eb Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 12 Sep 2013 15:13:56 +0800 Subject: [PATCH 6/7] Remove code which are used for borderless window. --- browser/native_window_mac.mm | 36 +++--------------------------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/browser/native_window_mac.mm b/browser/native_window_mac.mm index d3d8087e366..7c64f87d90f 100644 --- a/browser/native_window_mac.mm +++ b/browser/native_window_mac.mm @@ -24,9 +24,7 @@ #include "content/public/browser/web_contents_view.h" #include "content/public/browser/render_view_host.h" -@interface NSWindow (NSPrivateApis) -- (void)setBottomCornerRounded:(BOOL)rounded; -@end +static const CGFloat kAtomWindowCornerRadius = 4.0; @interface NSView (PrivateMethods) - (CGFloat)roundedCornerRadius; @@ -78,8 +76,6 @@ @end -static CGFloat const AtomWindowCornerRadius = 4.0; - @interface AtomNSWindow : AtomEventProcessingWindow { @protected atom::NativeWindowMac* shell_; @@ -116,26 +112,6 @@ static CGFloat const AtomWindowCornerRadius = 4.0; NSRectFill(rect); } -- (BOOL)canBecomeKeyWindow { - return YES; -} - -- (BOOL)canBecomeMainWindow { - return YES; -} - -- (BOOL)hasShadow { - return YES; -} - -- (void)keyDown:(NSEvent*)event { - [self redispatchKeyEvent:event]; -} - -- (void)keyUp:(NSEvent *)event { - [self redispatchKeyEvent:event]; -} - @end @interface ControlRegionView : NSView { @@ -204,8 +180,7 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents, } else { atomWindow = [[AtomFramelessNSWindow alloc] initWithContentRect:cocoa_bounds - styleMask:NSTitledWindowMask | NSClosableWindowMask | - NSMiniaturizableWindowMask | NSResizableWindowMask + styleMask:style_mask backing:NSBackingStoreBuffered defer:YES]; [atomWindow setOpaque:NO]; @@ -491,11 +466,9 @@ void NativeWindowMac::InstallView() { [[window() contentView] addSubview:view]; } else { NSView* frameView = [[window() contentView] superview]; - [view setFrame:[frameView bounds]]; [frameView addSubview:view]; - ClipWebView(); [[window() standardWindowButton:NSWindowZoomButton] setHidden:YES]; @@ -513,12 +486,9 @@ void NativeWindowMac::UninstallView() { void NativeWindowMac::ClipWebView() { NSView* view = GetWebContents()->GetView()->GetNativeView(); - // if ([view respondsToSelector:@selector(roundedCornerRadius)]) - // cornerRadius = [view roundedCornerRadius]; - view.wantsLayer = YES; view.layer.masksToBounds = YES; - view.layer.cornerRadius = AtomWindowCornerRadius; + view.layer.cornerRadius = kAtomWindowCornerRadius; } void NativeWindowMac::InstallDraggableRegionViews() { From 7a21ae831f98fd909692635076aba9e3c66b719a Mon Sep 17 00:00:00 2001 From: Steve Smith Date: Thu, 12 Sep 2013 11:20:38 -0400 Subject: [PATCH 7/7] Skip the whole AtomFramelessWindow. Just round the web view and set the bounds to the window, not the main view. --- browser/native_window_mac.mm | 40 ++++++++---------------------------- 1 file changed, 8 insertions(+), 32 deletions(-) diff --git a/browser/native_window_mac.mm b/browser/native_window_mac.mm index 7c64f87d90f..23648b79b1c 100644 --- a/browser/native_window_mac.mm +++ b/browser/native_window_mac.mm @@ -100,20 +100,6 @@ static const CGFloat kAtomWindowCornerRadius = 4.0; @end -@interface AtomFramelessNSWindow : AtomNSWindow -- (void)drawCustomFrameRect:(NSRect)rect forView:(NSView*)view; -@end - -@implementation AtomFramelessNSWindow - -- (void)drawCustomFrameRect:(NSRect)rect forView:(NSView*)view { - [[NSBezierPath bezierPathWithRect:rect] addClip]; - [[NSColor clearColor] set]; - NSRectFill(rect); -} - -@end - @interface ControlRegionView : NSView { @private atom::NativeWindowMac* shellWindow_; // Weak; owns self. @@ -168,24 +154,14 @@ NativeWindowMac::NativeWindowMac(content::WebContents* web_contents, height); AtomNSWindow* atomWindow; - NSUInteger style_mask = NSTitledWindowMask | NSClosableWindowMask | - NSMiniaturizableWindowMask | NSResizableWindowMask | - NSTexturedBackgroundWindowMask; - if (has_frame_) { - atomWindow = [[AtomNSWindow alloc] - initWithContentRect:cocoa_bounds - styleMask:style_mask - backing:NSBackingStoreBuffered - defer:YES]; - } else { - atomWindow = [[AtomFramelessNSWindow alloc] - initWithContentRect:cocoa_bounds - styleMask:style_mask - backing:NSBackingStoreBuffered - defer:YES]; - [atomWindow setOpaque:NO]; - [atomWindow setBackgroundColor:[NSColor clearColor]]; - } + + atomWindow = [[AtomNSWindow alloc] + initWithContentRect:cocoa_bounds + styleMask:NSTitledWindowMask | NSClosableWindowMask | + NSMiniaturizableWindowMask | NSResizableWindowMask | + NSTexturedBackgroundWindowMask + backing:NSBackingStoreBuffered + defer:YES]; [atomWindow setShell:this]; window_ = atomWindow;