123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560 |
- // Copyright (c) 2013 GitHub, Inc.
- // Use of this source code is governed by the MIT license that can be
- // found in the LICENSE file.
- #include "atom/browser/native_window_mac.h"
- #include <Quartz/Quartz.h>
- #include <string>
- #include "atom/browser/window_list.h"
- #include "atom/common/color_util.h"
- #include "atom/common/draggable_region.h"
- #include "atom/common/options_switches.h"
- #include "base/mac/mac_util.h"
- #include "base/mac/scoped_cftyperef.h"
- #include "base/strings/sys_string_conversions.h"
- #include "brightray/browser/inspectable_web_contents.h"
- #include "brightray/browser/inspectable_web_contents_view.h"
- #include "brightray/browser/mac/event_dispatching_window.h"
- #include "content/public/browser/browser_accessibility_state.h"
- #include "content/public/browser/web_contents.h"
- #include "content/public/browser/render_view_host.h"
- #include "content/public/browser/render_widget_host_view.h"
- #include "native_mate/dictionary.h"
- #include "skia/ext/skia_utils_mac.h"
- #include "third_party/skia/include/core/SkRegion.h"
- #include "ui/gfx/skia_util.h"
- namespace {
- // Prevents window from resizing during the scope.
- class ScopedDisableResize {
- public:
- ScopedDisableResize() { disable_resize_ = true; }
- ~ScopedDisableResize() { disable_resize_ = false; }
- static bool IsResizeDisabled() { return disable_resize_; }
- private:
- static bool disable_resize_;
- };
- bool ScopedDisableResize::disable_resize_ = false;
- } // namespace
- // This view always takes the size of its superview. It is intended to be used
- // as a NSWindow's contentView. It is needed because NSWindow's implementation
- // explicitly resizes the contentView at inopportune times.
- @interface FullSizeContentView : NSView
- @end
- @implementation FullSizeContentView
- // This method is directly called by NSWindow during a window resize on OSX
- // 10.10.0, beta 2. We must override it to prevent the content view from
- // shrinking.
- - (void)setFrameSize:(NSSize)size {
- if ([self superview])
- size = [[self superview] bounds].size;
- [super setFrameSize:size];
- }
- // The contentView gets moved around during certain full-screen operations.
- // This is less than ideal, and should eventually be removed.
- - (void)viewDidMoveToSuperview {
- [self setFrame:[[self superview] bounds]];
- }
- @end
- @interface AtomNSWindowDelegate : NSObject<NSWindowDelegate> {
- @private
- atom::NativeWindowMac* shell_;
- bool is_zooming_;
- }
- - (id)initWithShell:(atom::NativeWindowMac*)shell;
- @end
- @implementation AtomNSWindowDelegate
- - (id)initWithShell:(atom::NativeWindowMac*)shell {
- if ((self = [super init])) {
- shell_ = shell;
- is_zooming_ = false;
- }
- return self;
- }
- - (void)windowDidChangeOcclusionState:(NSNotification *)notification {
- // notification.object is the window that changed its state.
- // It's safe to use self.window instead if you don't assign one delegate to many windows
- NSWindow *window = notification.object;
- // check occlusion binary flag
- if (window.occlusionState & NSWindowOcclusionStateVisible) {
- // The app is visible
- shell_->NotifyWindowShow();
- } else {
- // The app is not visible
- shell_->NotifyWindowHide();
- }
- }
- // Called when the user clicks the zoom button or selects it from the Window
- // menu to determine the "standard size" of the window.
- - (NSRect)windowWillUseStandardFrame:(NSWindow*)window
- defaultFrame:(NSRect)frame {
- if (!shell_->zoom_to_page_width())
- return frame;
- // If the shift key is down, maximize.
- if ([[NSApp currentEvent] modifierFlags] & NSShiftKeyMask)
- return frame;
- content::WebContents* web_contents = shell_->web_contents();
- if (!web_contents)
- return frame;
- CGFloat page_width = static_cast<CGFloat>(
- web_contents->GetPreferredSize().width());
- NSRect window_frame = [window frame];
- // Never shrink from the current size on zoom.
- CGFloat zoomed_width = std::max(page_width, NSWidth(window_frame));
- // |frame| determines our maximum extents. We need to set the origin of the
- // frame -- and only move it left if necessary.
- if (window_frame.origin.x + zoomed_width > NSMaxX(frame))
- frame.origin.x = NSMaxX(frame) - zoomed_width;
- else
- frame.origin.x = window_frame.origin.x;
- // Set the width. Don't touch y or height.
- frame.size.width = zoomed_width;
- return frame;
- }
- - (void)windowDidBecomeMain:(NSNotification*)notification {
- content::WebContents* web_contents = shell_->web_contents();
- if (!web_contents)
- return;
- web_contents->RestoreFocus();
- content::RenderWidgetHostView* rwhv = web_contents->GetRenderWidgetHostView();
- if (rwhv)
- rwhv->SetActive(true);
- shell_->NotifyWindowFocus();
- }
- - (void)windowDidResignMain:(NSNotification*)notification {
- content::WebContents* web_contents = shell_->web_contents();
- if (!web_contents)
- return;
- web_contents->StoreFocus();
- content::RenderWidgetHostView* rwhv = web_contents->GetRenderWidgetHostView();
- if (rwhv)
- rwhv->SetActive(false);
- shell_->NotifyWindowBlur();
- }
- - (NSSize)windowWillResize:(NSWindow*)sender toSize:(NSSize)frameSize {
- NSSize newSize = frameSize;
- double aspectRatio = shell_->GetAspectRatio();
- if (aspectRatio > 0.0) {
- gfx::Size windowSize = shell_->GetSize();
- gfx::Size contentSize = shell_->GetContentSize();
- gfx::Size extraSize = shell_->GetAspectRatioExtraSize();
- double extraWidthPlusFrame =
- windowSize.width() - contentSize.width() + extraSize.width();
- double extraHeightPlusFrame =
- windowSize.height() - contentSize.height() + extraSize.height();
- newSize.width =
- roundf((frameSize.height - extraHeightPlusFrame) * aspectRatio +
- extraWidthPlusFrame);
- newSize.height =
- roundf((newSize.width - extraWidthPlusFrame) / aspectRatio +
- extraHeightPlusFrame);
- }
- return newSize;
- }
- - (void)windowDidResize:(NSNotification*)notification {
- shell_->UpdateDraggableRegionViews();
- shell_->NotifyWindowResize();
- }
- - (void)windowDidMove:(NSNotification*)notification {
- // TODO(zcbenz): Remove the alias after figuring out a proper
- // way to dispatch move.
- shell_->NotifyWindowMove();
- shell_->NotifyWindowMoved();
- }
- - (void)windowDidMiniaturize:(NSNotification*)notification {
- shell_->NotifyWindowMinimize();
- }
- - (void)windowDidDeminiaturize:(NSNotification*)notification {
- shell_->NotifyWindowRestore();
- }
- - (BOOL)windowShouldZoom:(NSWindow*)window toFrame:(NSRect)newFrame {
- is_zooming_ = true;
- return YES;
- }
- - (void)windowDidEndLiveResize:(NSNotification*)notification {
- if (is_zooming_) {
- if (shell_->IsMaximized())
- shell_->NotifyWindowMaximize();
- else
- shell_->NotifyWindowUnmaximize();
- is_zooming_ = false;
- }
- }
- - (void)windowWillEnterFullScreen:(NSNotification*)notification {
- // Hide the native toolbar before entering fullscreen, so there is no visual
- // artifacts.
- if (base::mac::IsOSYosemiteOrLater() &&
- shell_->title_bar_style() == atom::NativeWindowMac::HIDDEN_INSET) {
- NSWindow* window = shell_->GetNativeWindow();
- [window setToolbar:nil];
- }
- }
- - (void)windowDidEnterFullScreen:(NSNotification*)notification {
- shell_->NotifyWindowEnterFullScreen();
- // For frameless window we don't show set title for normal mode since the
- // titlebar is expected to be empty, but after entering fullscreen mode we
- // have to set one, because title bar is visible here.
- NSWindow* window = shell_->GetNativeWindow();
- if ((shell_->transparent() || !shell_->has_frame()) &&
- base::mac::IsOSYosemiteOrLater() &&
- // FIXME(zcbenz): Showing titlebar for hiddenInset window is weird under
- // fullscreen mode.
- shell_->title_bar_style() != atom::NativeWindowMac::HIDDEN_INSET) {
- [window setTitleVisibility:NSWindowTitleVisible];
- }
- // Restore the native toolbar immediately after entering fullscreen, if we do
- // this before leaving fullscreen, traffic light buttons will be jumping.
- if (base::mac::IsOSYosemiteOrLater() &&
- shell_->title_bar_style() == atom::NativeWindowMac::HIDDEN_INSET) {
- base::scoped_nsobject<NSToolbar> toolbar(
- [[NSToolbar alloc] initWithIdentifier:@"titlebarStylingToolbar"]);
- [toolbar setShowsBaselineSeparator:NO];
- [window setToolbar:toolbar];
- // Set window style to hide the toolbar, otherwise the toolbar will show in
- // fullscreen mode.
- shell_->SetStyleMask(true, NSFullSizeContentViewWindowMask);
- }
- }
- - (void)windowWillExitFullScreen:(NSNotification*)notification {
- // Restore the titlebar visibility.
- NSWindow* window = shell_->GetNativeWindow();
- if ((shell_->transparent() || !shell_->has_frame()) &&
- base::mac::IsOSYosemiteOrLater() &&
- shell_->title_bar_style() != atom::NativeWindowMac::HIDDEN_INSET) {
- [window setTitleVisibility:NSWindowTitleHidden];
- }
- // Turn off the style for toolbar.
- if (base::mac::IsOSYosemiteOrLater() &&
- shell_->title_bar_style() == atom::NativeWindowMac::HIDDEN_INSET) {
- shell_->SetStyleMask(false, NSFullSizeContentViewWindowMask);
- }
- }
- - (void)windowDidExitFullScreen:(NSNotification*)notification {
- shell_->NotifyWindowLeaveFullScreen();
- }
- - (void)windowWillClose:(NSNotification*)notification {
- shell_->NotifyWindowClosed();
- // Clears the delegate when window is going to be closed, since EL Capitan it
- // is possible that the methods of delegate would get called after the window
- // has been closed.
- [shell_->GetNativeWindow() setDelegate:nil];
- }
- - (BOOL)windowShouldClose:(id)window {
- // When user tries to close the window by clicking the close button, we do
- // not close the window immediately, instead we try to close the web page
- // fisrt, and when the web page is closed the window will also be closed.
- shell_->RequestToClosePage();
- return NO;
- }
- - (NSRect)window:(NSWindow*)window
- willPositionSheet:(NSWindow*)sheet usingRect:(NSRect)rect {
- NSView* view = window.contentView;
- rect.origin.x = shell_->GetSheetOffsetX();
- rect.origin.y = view.frame.size.height - shell_->GetSheetOffsetY();
- return rect;
- }
- @end
- @interface AtomPreviewItem : NSObject <QLPreviewItem>
- @property (nonatomic, retain) NSURL* previewItemURL;
- @property (nonatomic, retain) NSString* previewItemTitle;
- - (id)initWithURL:(NSURL*)url title:(NSString*)title;
- @end
- @implementation AtomPreviewItem
- - (id)initWithURL:(NSURL*)url title:(NSString*)title {
- self = [super init];
- if (self) {
- self.previewItemURL = url;
- self.previewItemTitle = title;
- }
- return self;
- }
- @end
- @interface AtomNSWindow : EventDispatchingWindow<QLPreviewPanelDataSource, QLPreviewPanelDelegate> {
- @private
- atom::NativeWindowMac* shell_;
- bool enable_larger_than_screen_;
- CGFloat windowButtonsInterButtonSpacing_;
- }
- @property BOOL acceptsFirstMouse;
- @property BOOL disableAutoHideCursor;
- @property BOOL disableKeyOrMainWindow;
- @property NSPoint windowButtonsOffset;
- @property (nonatomic, retain) AtomPreviewItem* quickLookItem;
- @property (nonatomic, retain) NSView* vibrantView;
- - (void)setShell:(atom::NativeWindowMac*)shell;
- - (void)setEnableLargerThanScreen:(bool)enable;
- - (void)enableWindowButtonsOffset;
- @end
- @implementation AtomNSWindow
- - (void)setShell:(atom::NativeWindowMac*)shell {
- shell_ = shell;
- }
- - (void)setEnableLargerThanScreen:(bool)enable {
- enable_larger_than_screen_ = enable;
- }
- // NSWindow overrides.
- - (void)swipeWithEvent:(NSEvent *)event {
- if (event.deltaY == 1.0) {
- shell_->NotifyWindowSwipe("up");
- } else if (event.deltaX == -1.0) {
- shell_->NotifyWindowSwipe("right");
- } else if (event.deltaY == -1.0) {
- shell_->NotifyWindowSwipe("down");
- } else if (event.deltaX == 1.0) {
- shell_->NotifyWindowSwipe("left");
- }
- }
- - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen*)screen {
- // Resizing is disabled.
- if (ScopedDisableResize::IsResizeDisabled())
- return [self frame];
- // Enable the window to be larger than screen.
- if (enable_larger_than_screen_)
- return frameRect;
- else
- return [super constrainFrameRect:frameRect toScreen:screen];
- }
- - (void)setFrame:(NSRect)windowFrame display:(BOOL)displayViews {
- // constrainFrameRect is not called on hidden windows so disable adjusting
- // the frame directly when resize is disabled
- if (!ScopedDisableResize::IsResizeDisabled())
- [super setFrame:windowFrame display:displayViews];
- }
- - (id)accessibilityAttributeValue:(NSString*)attribute {
- if (![attribute isEqualToString:@"AXChildren"])
- return [super accessibilityAttributeValue:attribute];
- // Filter out objects that aren't the title bar buttons. This has the effect
- // of removing the window title, which VoiceOver already sees.
- // * when VoiceOver is disabled, this causes Cmd+C to be used for TTS but
- // still leaves the buttons available in the accessibility tree.
- // * when VoiceOver is enabled, the full accessibility tree is used.
- // Without removing the title and with VO disabled, the TTS would always read
- // the window title instead of using Cmd+C to get the selected text.
- NSPredicate *predicate = [NSPredicate predicateWithFormat:
- @"(self isKindOfClass: %@) OR (self.className == %@)",
- [NSButtonCell class],
- @"RenderWidgetHostViewCocoa"];
- NSArray *children = [super accessibilityAttributeValue:attribute];
- return [children filteredArrayUsingPredicate:predicate];
- }
- - (BOOL)canBecomeMainWindow {
- return !self.disableKeyOrMainWindow;
- }
- - (BOOL)canBecomeKeyWindow {
- return !self.disableKeyOrMainWindow;
- }
- - (void)enableWindowButtonsOffset {
- auto closeButton = [self standardWindowButton:NSWindowCloseButton];
- auto miniaturizeButton = [self standardWindowButton:NSWindowMiniaturizeButton];
- auto zoomButton = [self standardWindowButton:NSWindowZoomButton];
- [closeButton setPostsFrameChangedNotifications:YES];
- [miniaturizeButton setPostsFrameChangedNotifications:YES];
- [zoomButton setPostsFrameChangedNotifications:YES];
- windowButtonsInterButtonSpacing_ =
- NSMinX([miniaturizeButton frame]) - NSMaxX([closeButton frame]);
- auto center = [NSNotificationCenter defaultCenter];
- [center addObserver:self
- selector:@selector(adjustCloseButton:)
- name:NSViewFrameDidChangeNotification
- object:closeButton];
- [center addObserver:self
- selector:@selector(adjustMiniaturizeButton:)
- name:NSViewFrameDidChangeNotification
- object:miniaturizeButton];
- [center addObserver:self
- selector:@selector(adjustZoomButton:)
- name:NSViewFrameDidChangeNotification
- object:zoomButton];
- }
- - (void)adjustCloseButton:(NSNotification*)notification {
- [self adjustButton:[notification object]
- ofKind:NSWindowCloseButton];
- }
- - (void)adjustMiniaturizeButton:(NSNotification*)notification {
- [self adjustButton:[notification object]
- ofKind:NSWindowMiniaturizeButton];
- }
- - (void)adjustZoomButton:(NSNotification*)notification {
- [self adjustButton:[notification object]
- ofKind:NSWindowZoomButton];
- }
- - (void)adjustButton:(NSButton*)button
- ofKind:(NSWindowButton)kind {
- NSRect buttonFrame = [button frame];
- NSRect frameViewBounds = [[self frameView] bounds];
- NSPoint offset = self.windowButtonsOffset;
- buttonFrame.origin = NSMakePoint(
- offset.x,
- (NSHeight(frameViewBounds) - NSHeight(buttonFrame) - offset.y));
- switch (kind) {
- case NSWindowZoomButton:
- buttonFrame.origin.x += NSWidth(
- [[self standardWindowButton:NSWindowMiniaturizeButton] frame]);
- buttonFrame.origin.x += windowButtonsInterButtonSpacing_;
- // fallthrough
- case NSWindowMiniaturizeButton:
- buttonFrame.origin.x += NSWidth(
- [[self standardWindowButton:NSWindowCloseButton] frame]);
- buttonFrame.origin.x += windowButtonsInterButtonSpacing_;
- // fallthrough
- default:
- break;
- }
- BOOL didPost = [button postsBoundsChangedNotifications];
- [button setPostsFrameChangedNotifications:NO];
- [button setFrame:buttonFrame];
- [button setPostsFrameChangedNotifications:didPost];
- }
- - (NSView*)frameView {
- return [[self contentView] superview];
- }
- // Quicklook methods
- - (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel*)panel {
- return YES;
- }
- - (void)beginPreviewPanelControl:(QLPreviewPanel*)panel {
- panel.delegate = self;
- panel.dataSource = self;
- }
- - (void)endPreviewPanelControl:(QLPreviewPanel*)panel {
- panel.delegate = nil;
- panel.dataSource = nil;
- }
- - (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel*)panel {
- return 1;
- }
- - (id <QLPreviewItem>)previewPanel:(QLPreviewPanel*)panel previewItemAtIndex:(NSInteger)index {
- return [self quickLookItem];
- }
- - (void)previewFileAtPath:(NSString*)path withName:(NSString*) fileName {
- NSURL* url = [[[NSURL alloc] initFileURLWithPath:path] autorelease];
- [self setQuickLookItem:[[[AtomPreviewItem alloc] initWithURL:url title:fileName] autorelease]];
- [[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil];
- }
- @end
- @interface ControlRegionView : NSView
- @end
- @implementation ControlRegionView
- - (BOOL)mouseDownCanMoveWindow {
- return NO;
- }
- - (NSView*)hitTest:(NSPoint)aPoint {
- return nil;
- }
- @end
- @interface NSView (WebContentsView)
- - (void)setMouseDownCanMoveWindow:(BOOL)can_move;
- @end
- @interface AtomProgressBar : NSProgressIndicator
- @end
- @implementation AtomProgressBar
- - (void)drawRect:(NSRect)dirtyRect {
- if (self.style != NSProgressIndicatorBarStyle)
- return;
- // Draw edges of rounded rect.
- NSRect rect = NSInsetRect([self bounds], 1.0, 1.0);
- CGFloat radius = rect.size.height / 2;
- NSBezierPath* bezier_path = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:radius yRadius:radius];
- [bezier_path setLineWidth:2.0];
- [[NSColor grayColor] set];
- [bezier_path stroke];
- // Fill the rounded rect.
- rect = NSInsetRect(rect, 2.0, 2.0);
- radius = rect.size.height / 2;
- bezier_path = [NSBezierPath bezierPathWithRoundedRect:rect xRadius:radius yRadius:radius];
- [bezier_path setLineWidth:1.0];
- [bezier_path addClip];
- // Calculate the progress width.
- rect.size.width = floor(rect.size.width * ([self doubleValue] / [self maxValue]));
- // Fill the progress bar with color blue.
- [[NSColor colorWithSRGBRed:0.2 green:0.6 blue:1 alpha:1] set];
- NSRectFill(rect);
- }
- @end
- namespace mate {
- template<>
- struct Converter<atom::NativeWindowMac::TitleBarStyle> {
- static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
- atom::NativeWindowMac::TitleBarStyle* out) {
- std::string title_bar_style;
- if (!ConvertFromV8(isolate, val, &title_bar_style))
- return false;
- if (title_bar_style == "hidden") {
- *out = atom::NativeWindowMac::HIDDEN;
- } else if (title_bar_style == "hidden-inset" || // Deprecate this after 2.0
- title_bar_style == "hiddenInset") {
- *out = atom::NativeWindowMac::HIDDEN_INSET;
- } else {
- return false;
- }
- return true;
- }
- };
- } // namespace mate
- namespace atom {
- NativeWindowMac::NativeWindowMac(
- brightray::InspectableWebContents* web_contents,
- const mate::Dictionary& options,
- NativeWindow* parent)
- : NativeWindow(web_contents, options, parent),
- is_kiosk_(false),
- was_fullscreen_(false),
- zoom_to_page_width_(false),
- attention_request_id_(0),
- title_bar_style_(NORMAL) {
- int width = 800, height = 600;
- options.Get(options::kWidth, &width);
- options.Get(options::kHeight, &height);
- NSRect main_screen_rect = [[[NSScreen screens] firstObject] frame];
- NSRect cocoa_bounds = NSMakeRect(
- round((NSWidth(main_screen_rect) - width) / 2) ,
- round((NSHeight(main_screen_rect) - height) / 2),
- width,
- height);
- bool resizable = true;
- options.Get(options::kResizable, &resizable);
- bool minimizable = true;
- options.Get(options::kMinimizable, &minimizable);
- bool maximizable = true;
- options.Get(options::kMaximizable, &maximizable);
- bool closable = true;
- options.Get(options::kClosable, &closable);
- options.Get(options::kTitleBarStyle, &title_bar_style_);
- std::string windowType;
- options.Get(options::kType, &windowType);
- bool useStandardWindow = true;
- // eventually deprecate separate "standardWindow" option in favor of
- // standard / textured window types
- options.Get(options::kStandardWindow, &useStandardWindow);
- if (windowType == "textured") {
- useStandardWindow = false;
- }
- NSUInteger styleMask = NSTitledWindowMask;
- if (minimizable) {
- styleMask |= NSMiniaturizableWindowMask;
- }
- if (closable) {
- styleMask |= NSClosableWindowMask;
- }
- if (title_bar_style_ != NORMAL) {
- // The window without titlebar is treated the same with frameless window.
- set_has_frame(false);
- }
- if (!useStandardWindow || transparent() || !has_frame()) {
- styleMask |= NSTexturedBackgroundWindowMask;
- }
- if (resizable) {
- styleMask |= NSResizableWindowMask;
- }
- window_.reset([[AtomNSWindow alloc]
- initWithContentRect:cocoa_bounds
- styleMask:styleMask
- backing:NSBackingStoreBuffered
- defer:YES]);
- [window_ setShell:this];
- [window_ setEnableLargerThanScreen:enable_larger_than_screen()];
- window_delegate_.reset([[AtomNSWindowDelegate alloc] initWithShell:this]);
- [window_ setDelegate:window_delegate_];
- // Only use native parent window for non-modal windows.
- if (parent && !is_modal()) {
- SetParentWindow(parent);
- }
- if (transparent()) {
- // Setting the background color to clear will also hide the shadow.
- [window_ setBackgroundColor:[NSColor clearColor]];
- }
- if (windowType == "desktop") {
- [window_ setLevel:kCGDesktopWindowLevel - 1];
- [window_ setDisableKeyOrMainWindow:YES];
- [window_ setCollectionBehavior:
- (NSWindowCollectionBehaviorCanJoinAllSpaces |
- NSWindowCollectionBehaviorStationary |
- NSWindowCollectionBehaviorIgnoresCycle)];
- }
- bool focusable;
- if (options.Get(options::kFocusable, &focusable) && !focusable)
- [window_ setDisableKeyOrMainWindow:YES];
- if (transparent() || !has_frame()) {
- if (base::mac::IsOSYosemiteOrLater()) {
- // Don't show title bar.
- [window_ setTitleVisibility:NSWindowTitleHidden];
- }
- // Remove non-transparent corners, see http://git.io/vfonD.
- [window_ setOpaque:NO];
- }
- // We will manage window's lifetime ourselves.
- [window_ setReleasedWhenClosed:NO];
- // Hide the title bar.
- if (title_bar_style_ == HIDDEN_INSET) {
- if (base::mac::IsOSYosemiteOrLater()) {
- [window_ setTitlebarAppearsTransparent:YES];
- base::scoped_nsobject<NSToolbar> toolbar(
- [[NSToolbar alloc] initWithIdentifier:@"titlebarStylingToolbar"]);
- [toolbar setShowsBaselineSeparator:NO];
- [window_ setToolbar:toolbar];
- } else {
- [window_ enableWindowButtonsOffset];
- [window_ setWindowButtonsOffset:NSMakePoint(12, 10)];
- }
- }
- // On macOS the initial window size doesn't include window frame.
- bool use_content_size = false;
- options.Get(options::kUseContentSize, &use_content_size);
- if (!has_frame() || !use_content_size)
- SetSize(gfx::Size(width, height));
- options.Get(options::kZoomToPageWidth, &zoom_to_page_width_);
- // Enable the NSView to accept first mouse event.
- bool acceptsFirstMouse = false;
- options.Get(options::kAcceptFirstMouse, &acceptsFirstMouse);
- [window_ setAcceptsFirstMouse:acceptsFirstMouse];
- // Disable auto-hiding cursor.
- bool disableAutoHideCursor = false;
- options.Get(options::kDisableAutoHideCursor, &disableAutoHideCursor);
- [window_ setDisableAutoHideCursor:disableAutoHideCursor];
- NSView* view = inspectable_web_contents()->GetView()->GetNativeView();
- [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
- // Use an NSEvent monitor to listen for the wheel event.
- BOOL __block began = NO;
- wheel_event_monitor_ = [NSEvent
- addLocalMonitorForEventsMatchingMask:NSScrollWheelMask
- handler:^(NSEvent* event) {
- if ([[event window] windowNumber] != [window_ windowNumber])
- return event;
- if (!web_contents)
- return event;
- if (!began && (([event phase] == NSEventPhaseMayBegin) ||
- ([event phase] == NSEventPhaseBegan))) {
- this->NotifyWindowScrollTouchBegin();
- began = YES;
- } else if (began && (([event phase] == NSEventPhaseEnded) ||
- ([event phase] == NSEventPhaseCancelled))) {
- this->NotifyWindowScrollTouchEnd();
- began = NO;
- }
- return event;
- }];
- InstallView();
- std::string type;
- if (options.Get(options::kVibrancyType, &type)) {
- SetVibrancy(type);
- }
- // Set maximizable state last to ensure zoom button does not get reset
- // by calls to other APIs.
- SetMaximizable(maximizable);
- RegisterInputEventObserver(
- web_contents->GetWebContents()->GetRenderViewHost());
- }
- NativeWindowMac::~NativeWindowMac() {
- [NSEvent removeMonitor:wheel_event_monitor_];
- Observe(nullptr);
- }
- void NativeWindowMac::Close() {
- // When this is a sheet showing, performClose won't work.
- if (is_modal() && parent() && IsVisible()) {
- [parent()->GetNativeWindow() endSheet:window_];
- CloseImmediately();
- return;
- }
- if (!IsClosable()) {
- WindowList::WindowCloseCancelled(this);
- return;
- }
- [window_ performClose:nil];
- }
- void NativeWindowMac::CloseImmediately() {
- [window_ close];
- }
- void NativeWindowMac::Focus(bool focus) {
- if (!IsVisible())
- return;
- if (focus) {
- [[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
- [window_ makeKeyAndOrderFront:nil];
- } else {
- [window_ orderBack:nil];
- }
- }
- bool NativeWindowMac::IsFocused() {
- return [window_ isKeyWindow];
- }
- void NativeWindowMac::Show() {
- if (is_modal() && parent()) {
- if ([window_ sheetParent] == nil)
- [parent()->GetNativeWindow() beginSheet:window_
- completionHandler:^(NSModalResponse) {}];
- return;
- }
- // This method is supposed to put focus on window, however if the app does not
- // have focus then "makeKeyAndOrderFront" will only show the window.
- [NSApp activateIgnoringOtherApps:YES];
- [window_ makeKeyAndOrderFront:nil];
- }
- void NativeWindowMac::ShowInactive() {
- [window_ orderFrontRegardless];
- }
- void NativeWindowMac::Hide() {
- if (is_modal() && parent()) {
- [window_ orderOut:nil];
- [parent()->GetNativeWindow() endSheet:window_];
- return;
- }
- [window_ orderOut:nil];
- }
- bool NativeWindowMac::IsVisible() {
- return [window_ isVisible];
- }
- bool NativeWindowMac::IsEnabled() {
- return [window_ attachedSheet] == nil;
- }
- void NativeWindowMac::Maximize() {
- if (IsMaximized())
- return;
- [window_ zoom:nil];
- }
- void NativeWindowMac::Unmaximize() {
- if (!IsMaximized())
- return;
- [window_ zoom:nil];
- }
- bool NativeWindowMac::IsMaximized() {
- if (([window_ styleMask] & NSResizableWindowMask) != 0) {
- return [window_ isZoomed];
- } else {
- NSRect rectScreen = [[NSScreen mainScreen] visibleFrame];
- NSRect rectWindow = [window_ frame];
- return (rectScreen.origin.x == rectWindow.origin.x &&
- rectScreen.origin.y == rectWindow.origin.y &&
- rectScreen.size.width == rectWindow.size.width &&
- rectScreen.size.height == rectWindow.size.height);
- }
- }
- void NativeWindowMac::Minimize() {
- [window_ miniaturize:nil];
- }
- void NativeWindowMac::Restore() {
- [window_ deminiaturize:nil];
- }
- bool NativeWindowMac::IsMinimized() {
- return [window_ isMiniaturized];
- }
- void NativeWindowMac::SetFullScreen(bool fullscreen) {
- if (fullscreen == IsFullscreen())
- return;
- [window_ toggleFullScreen:nil];
- }
- bool NativeWindowMac::IsFullscreen() const {
- return [window_ styleMask] & NSFullScreenWindowMask;
- }
- void NativeWindowMac::SetBounds(const gfx::Rect& bounds, bool animate) {
- // Do nothing if in fullscreen mode.
- if (IsFullscreen())
- return;
- // Check size constraints since setFrame does not check it.
- gfx::Size size = bounds.size();
- size.SetToMax(GetMinimumSize());
- gfx::Size max_size = GetMaximumSize();
- if (!max_size.IsEmpty())
- size.SetToMin(max_size);
- NSRect cocoa_bounds = NSMakeRect(bounds.x(), 0, size.width(), size.height());
- // Flip coordinates based on the primary screen.
- NSScreen* screen = [[NSScreen screens] firstObject];
- cocoa_bounds.origin.y =
- NSHeight([screen frame]) - size.height() - bounds.y();
- [window_ setFrame:cocoa_bounds display:YES animate:animate];
- }
- gfx::Rect NativeWindowMac::GetBounds() {
- NSRect frame = [window_ frame];
- gfx::Rect bounds(frame.origin.x, 0, NSWidth(frame), NSHeight(frame));
- NSScreen* screen = [[NSScreen screens] firstObject];
- bounds.set_y(NSHeight([screen frame]) - NSMaxY(frame));
- return bounds;
- }
- void NativeWindowMac::SetContentSizeConstraints(
- const extensions::SizeConstraints& size_constraints) {
- auto convertSize = [this](const gfx::Size& size) {
- // Our frameless window still has titlebar attached, so setting contentSize
- // will result in actual content size being larger.
- if (!has_frame()) {
- NSRect frame = NSMakeRect(0, 0, size.width(), size.height());
- NSRect content = [window_ contentRectForFrameRect:frame];
- return content.size;
- } else {
- return NSMakeSize(size.width(), size.height());
- }
- };
- NSView* content = [window_ contentView];
- if (size_constraints.HasMinimumSize()) {
- NSSize min_size = convertSize(size_constraints.GetMinimumSize());
- [window_ setContentMinSize:[content convertSize:min_size toView:nil]];
- }
- if (size_constraints.HasMaximumSize()) {
- NSSize max_size = convertSize(size_constraints.GetMaximumSize());
- [window_ setContentMaxSize:[content convertSize:max_size toView:nil]];
- }
- NativeWindow::SetContentSizeConstraints(size_constraints);
- }
- void NativeWindowMac::SetResizable(bool resizable) {
- SetStyleMask(resizable, NSResizableWindowMask);
- }
- bool NativeWindowMac::IsResizable() {
- return [window_ styleMask] & NSResizableWindowMask;
- }
- void NativeWindowMac::SetAspectRatio(double aspect_ratio,
- const gfx::Size& extra_size) {
- NativeWindow::SetAspectRatio(aspect_ratio, extra_size);
- // Reset the behaviour to default if aspect_ratio is set to 0 or less.
- if (aspect_ratio > 0.0)
- [window_ setAspectRatio:NSMakeSize(aspect_ratio, 1.0)];
- else
- [window_ setResizeIncrements:NSMakeSize(1.0, 1.0)];
- }
- void NativeWindowMac::PreviewFile(const std::string& path,
- const std::string& display_name) {
- NSString* path_ns = [NSString stringWithUTF8String:path.c_str()];
- NSString* name_ns = [NSString stringWithUTF8String:display_name.c_str()];
- [window_ previewFileAtPath:path_ns withName:name_ns];
- }
- void NativeWindowMac::CloseFilePreview() {
- if ([QLPreviewPanel sharedPreviewPanelExists]) {
- [[QLPreviewPanel sharedPreviewPanel] close];
- }
- }
- void NativeWindowMac::SetMovable(bool movable) {
- [window_ setMovable:movable];
- }
- bool NativeWindowMac::IsMovable() {
- return [window_ isMovable];
- }
- void NativeWindowMac::SetMinimizable(bool minimizable) {
- SetStyleMask(minimizable, NSMiniaturizableWindowMask);
- }
- bool NativeWindowMac::IsMinimizable() {
- return [window_ styleMask] & NSMiniaturizableWindowMask;
- }
- void NativeWindowMac::SetMaximizable(bool maximizable) {
- [[window_ standardWindowButton:NSWindowZoomButton] setEnabled:maximizable];
- }
- bool NativeWindowMac::IsMaximizable() {
- return [[window_ standardWindowButton:NSWindowZoomButton] isEnabled];
- }
- void NativeWindowMac::SetFullScreenable(bool fullscreenable) {
- SetCollectionBehavior(
- fullscreenable, NSWindowCollectionBehaviorFullScreenPrimary);
- // On EL Capitan this flag is required to hide fullscreen button.
- SetCollectionBehavior(
- !fullscreenable, NSWindowCollectionBehaviorFullScreenAuxiliary);
- }
- bool NativeWindowMac::IsFullScreenable() {
- NSUInteger collectionBehavior = [window_ collectionBehavior];
- return collectionBehavior & NSWindowCollectionBehaviorFullScreenPrimary;
- }
- void NativeWindowMac::SetClosable(bool closable) {
- SetStyleMask(closable, NSClosableWindowMask);
- }
- bool NativeWindowMac::IsClosable() {
- return [window_ styleMask] & NSClosableWindowMask;
- }
- void NativeWindowMac::SetAlwaysOnTop(bool top, const std::string& level) {
- int windowLevel = NSNormalWindowLevel;
- if (top) {
- if (level == "floating") {
- windowLevel = NSFloatingWindowLevel;
- } else if (level == "torn-off-menu") {
- windowLevel = NSTornOffMenuWindowLevel;
- } else if (level == "modal-panel") {
- windowLevel = NSModalPanelWindowLevel;
- } else if (level == "main-menu") {
- windowLevel = NSMainMenuWindowLevel;
- } else if (level == "status") {
- windowLevel = NSStatusWindowLevel;
- } else if (level == "pop-up-menu") {
- windowLevel = NSPopUpMenuWindowLevel;
- } else if (level == "screen-saver") {
- windowLevel = NSScreenSaverWindowLevel;
- } else if (level == "dock") {
- // Deprecated by macOS, but kept for backwards compatibility
- windowLevel = NSDockWindowLevel;
- }
- }
- [window_ setLevel:windowLevel];
- }
- bool NativeWindowMac::IsAlwaysOnTop() {
- return [window_ level] != NSNormalWindowLevel;
- }
- void NativeWindowMac::Center() {
- [window_ center];
- }
- void NativeWindowMac::SetTitle(const std::string& title) {
- // For macOS <= 10.9, the setTitleVisibility API is not available, we have
- // to avoid calling setTitle for frameless window.
- if (!base::mac::IsOSYosemiteOrLater() && (transparent() || !has_frame()))
- return;
- [window_ setTitle:base::SysUTF8ToNSString(title)];
- }
- std::string NativeWindowMac::GetTitle() {
- return base::SysNSStringToUTF8([window_ title]);;
- }
- void NativeWindowMac::FlashFrame(bool flash) {
- if (flash) {
- attention_request_id_ = [NSApp requestUserAttention:NSInformationalRequest];
- } else {
- [NSApp cancelUserAttentionRequest:attention_request_id_];
- attention_request_id_ = 0;
- }
- }
- void NativeWindowMac::SetSkipTaskbar(bool skip) {
- }
- void NativeWindowMac::SetKiosk(bool kiosk) {
- if (kiosk && !is_kiosk_) {
- kiosk_options_ = [NSApp currentSystemPresentationOptions];
- NSApplicationPresentationOptions options =
- NSApplicationPresentationHideDock +
- NSApplicationPresentationHideMenuBar +
- NSApplicationPresentationDisableAppleMenu +
- NSApplicationPresentationDisableProcessSwitching +
- NSApplicationPresentationDisableForceQuit +
- NSApplicationPresentationDisableSessionTermination +
- NSApplicationPresentationDisableHideApplication;
- [NSApp setPresentationOptions:options];
- is_kiosk_ = true;
- was_fullscreen_ = IsFullscreen();
- if (!was_fullscreen_) SetFullScreen(true);
- } else if (!kiosk && is_kiosk_) {
- is_kiosk_ = false;
- if (!was_fullscreen_) SetFullScreen(false);
- [NSApp setPresentationOptions:kiosk_options_];
- }
- }
- bool NativeWindowMac::IsKiosk() {
- return is_kiosk_;
- }
- void NativeWindowMac::SetBackgroundColor(const std::string& color_name) {
- SkColor color = ParseHexColor(color_name);
- base::ScopedCFTypeRef<CGColorRef> cgcolor(
- skia::CGColorCreateFromSkColor(color));
- [[[window_ contentView] layer] setBackgroundColor:cgcolor];
- const auto view = web_contents()->GetRenderWidgetHostView();
- if (view)
- view->SetBackgroundColor(color);
- }
- void NativeWindowMac::SetHasShadow(bool has_shadow) {
- [window_ setHasShadow:has_shadow];
- }
- bool NativeWindowMac::HasShadow() {
- return [window_ hasShadow];
- }
- void NativeWindowMac::SetRepresentedFilename(const std::string& filename) {
- [window_ setRepresentedFilename:base::SysUTF8ToNSString(filename)];
- }
- std::string NativeWindowMac::GetRepresentedFilename() {
- return base::SysNSStringToUTF8([window_ representedFilename]);
- }
- void NativeWindowMac::SetDocumentEdited(bool edited) {
- [window_ setDocumentEdited:edited];
- }
- bool NativeWindowMac::IsDocumentEdited() {
- return [window_ isDocumentEdited];
- }
- void NativeWindowMac::SetIgnoreMouseEvents(bool ignore) {
- [window_ setIgnoresMouseEvents:ignore];
- }
- void NativeWindowMac::SetContentProtection(bool enable) {
- [window_ setSharingType:enable ? NSWindowSharingNone
- : NSWindowSharingReadOnly];
- }
- void NativeWindowMac::SetParentWindow(NativeWindow* parent) {
- if (is_modal())
- return;
- NativeWindow::SetParentWindow(parent);
- // Remove current parent window.
- if ([window_ parentWindow])
- [[window_ parentWindow] removeChildWindow:window_];
- // Set new current window.
- if (parent)
- [parent->GetNativeWindow() addChildWindow:window_ ordered:NSWindowAbove];
- }
- gfx::NativeWindow NativeWindowMac::GetNativeWindow() {
- return window_;
- }
- gfx::AcceleratedWidget NativeWindowMac::GetAcceleratedWidget() {
- return inspectable_web_contents()->GetView()->GetNativeView();
- }
- void NativeWindowMac::SetProgressBar(double progress, const NativeWindow::ProgressState state) {
- NSDockTile* dock_tile = [NSApp dockTile];
- // For the first time API invoked, we need to create a ContentView in DockTile.
- if (dock_tile.contentView == NULL) {
- NSImageView* image_view = [[NSImageView alloc] init];
- [image_view setImage:[NSApp applicationIconImage]];
- [dock_tile setContentView:image_view];
- }
- if ([[dock_tile.contentView subviews] count] == 0) {
- NSProgressIndicator* progress_indicator = [[AtomProgressBar alloc]
- initWithFrame:NSMakeRect(0.0f, 0.0f, dock_tile.size.width, 15.0)];
- [progress_indicator setStyle:NSProgressIndicatorBarStyle];
- [progress_indicator setIndeterminate:NO];
- [progress_indicator setBezeled:YES];
- [progress_indicator setMinValue:0];
- [progress_indicator setMaxValue:1];
- [progress_indicator setHidden:NO];
- [dock_tile.contentView addSubview:progress_indicator];
- }
- NSProgressIndicator* progress_indicator =
- static_cast<NSProgressIndicator*>([[[dock_tile contentView] subviews]
- objectAtIndex:0]);
- if (progress < 0) {
- [progress_indicator setHidden:YES];
- } else if (progress > 1) {
- [progress_indicator setHidden:NO];
- [progress_indicator setIndeterminate:YES];
- [progress_indicator setDoubleValue:1];
- } else {
- [progress_indicator setHidden:NO];
- [progress_indicator setDoubleValue:progress];
- }
- [dock_tile display];
- }
- void NativeWindowMac::SetOverlayIcon(const gfx::Image& overlay,
- const std::string& description) {
- }
- void NativeWindowMac::SetVisibleOnAllWorkspaces(bool visible) {
- SetCollectionBehavior(visible, NSWindowCollectionBehaviorCanJoinAllSpaces);
- }
- bool NativeWindowMac::IsVisibleOnAllWorkspaces() {
- NSUInteger collectionBehavior = [window_ collectionBehavior];
- return collectionBehavior & NSWindowCollectionBehaviorCanJoinAllSpaces;
- }
- void NativeWindowMac::SetAutoHideCursor(bool auto_hide) {
- [window_ setDisableAutoHideCursor:!auto_hide];
- }
- void NativeWindowMac::SetVibrancy(const std::string& type) {
- if (!base::mac::IsOSYosemiteOrLater()) return;
- NSView* vibrant_view = [window_ vibrantView];
- if (type.empty()) {
- if (vibrant_view == nil) return;
- [vibrant_view removeFromSuperview];
- [window_ setVibrantView:nil];
- return;
- }
- NSVisualEffectView* effect_view = (NSVisualEffectView*)vibrant_view;
- if (effect_view == nil) {
- effect_view = [[[NSVisualEffectView alloc]
- initWithFrame: [[window_ contentView] bounds]] autorelease];
- [window_ setVibrantView:(NSView*)effect_view];
- [effect_view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
- [effect_view setBlendingMode:NSVisualEffectBlendingModeBehindWindow];
- [effect_view setState:NSVisualEffectStateActive];
- [[window_ contentView] addSubview:effect_view
- positioned:NSWindowBelow
- relativeTo:nil];
- }
- NSVisualEffectMaterial vibrancyType = NSVisualEffectMaterialLight;
- if (type == "appearance-based") {
- vibrancyType = NSVisualEffectMaterialAppearanceBased;
- } else if (type == "light") {
- vibrancyType = NSVisualEffectMaterialLight;
- } else if (type == "dark") {
- vibrancyType = NSVisualEffectMaterialDark;
- } else if (type == "titlebar") {
- vibrancyType = NSVisualEffectMaterialTitlebar;
- }
- if (base::mac::IsOSElCapitanOrLater()) {
- // TODO(kevinsawicki): Use NSVisualEffectMaterial* constants directly once
- // they are available in the minimum SDK version
- if (type == "selection") {
- // NSVisualEffectMaterialSelection
- vibrancyType = (NSVisualEffectMaterial) 4;
- } else if (type == "menu") {
- // NSVisualEffectMaterialMenu
- vibrancyType = (NSVisualEffectMaterial) 5;
- } else if (type == "popover") {
- // NSVisualEffectMaterialPopover
- vibrancyType = (NSVisualEffectMaterial) 6;
- } else if (type == "sidebar") {
- // NSVisualEffectMaterialSidebar
- vibrancyType = (NSVisualEffectMaterial) 7;
- } else if (type == "medium-light") {
- // NSVisualEffectMaterialMediumLight
- vibrancyType = (NSVisualEffectMaterial) 8;
- } else if (type == "ultra-dark") {
- // NSVisualEffectMaterialUltraDark
- vibrancyType = (NSVisualEffectMaterial) 9;
- }
- }
- [effect_view setMaterial:vibrancyType];
- }
- void NativeWindowMac::OnInputEvent(const blink::WebInputEvent& event) {
- switch (event.type) {
- case blink::WebInputEvent::GestureScrollBegin:
- case blink::WebInputEvent::GestureScrollUpdate:
- case blink::WebInputEvent::GestureScrollEnd:
- this->NotifyWindowScrollTouchEdge();
- break;
- default:
- break;
- }
- }
- void NativeWindowMac::RenderViewHostChanged(
- content::RenderViewHost* old_host,
- content::RenderViewHost* new_host) {
- UnregisterInputEventObserver(old_host);
- RegisterInputEventObserver(new_host);
- }
- std::vector<gfx::Rect> NativeWindowMac::CalculateNonDraggableRegions(
- const std::vector<DraggableRegion>& regions, int width, int height) {
- std::vector<gfx::Rect> result;
- if (regions.empty()) {
- result.push_back(gfx::Rect(0, 0, width, height));
- } else {
- std::unique_ptr<SkRegion> draggable(DraggableRegionsToSkRegion(regions));
- std::unique_ptr<SkRegion> non_draggable(new SkRegion);
- non_draggable->op(0, 0, width, height, SkRegion::kUnion_Op);
- non_draggable->op(*draggable, SkRegion::kDifference_Op);
- for (SkRegion::Iterator it(*non_draggable); !it.done(); it.next()) {
- result.push_back(gfx::SkIRectToRect(it.rect()));
- }
- }
- return result;
- }
- gfx::Rect NativeWindowMac::ContentBoundsToWindowBounds(
- const gfx::Rect& bounds) {
- if (has_frame()) {
- gfx::Rect window_bounds(
- [window_ frameRectForContentRect:bounds.ToCGRect()]);
- int frame_height = window_bounds.height() - bounds.height();
- window_bounds.set_y(window_bounds.y() - frame_height);
- return window_bounds;
- } else {
- return bounds;
- }
- }
- gfx::Rect NativeWindowMac::WindowBoundsToContentBounds(
- const gfx::Rect& bounds) {
- if (has_frame()) {
- gfx::Rect content_bounds(
- [window_ contentRectForFrameRect:bounds.ToCGRect()]);
- int frame_height = bounds.height() - content_bounds.height();
- content_bounds.set_y(content_bounds.y() + frame_height);
- return content_bounds;
- } else {
- return bounds;
- }
- }
- void NativeWindowMac::UpdateDraggableRegions(
- const std::vector<DraggableRegion>& regions) {
- NativeWindow::UpdateDraggableRegions(regions);
- draggable_regions_ = regions;
- UpdateDraggableRegionViews(regions);
- }
- void NativeWindowMac::ShowWindowButton(NSWindowButton button) {
- auto view = [window_ standardWindowButton:button];
- [view.superview addSubview:view positioned:NSWindowAbove relativeTo:nil];
- }
- void NativeWindowMac::InstallView() {
- // Make sure the bottom corner is rounded for non-modal windows: http://crbug.com/396264.
- // But do not enable it on OS X 10.9 for transparent window, otherwise a
- // semi-transparent frame would show.
- if (!(transparent() && base::mac::IsOSMavericks()) && !is_modal())
- [[window_ contentView] setWantsLayer:YES];
- NSView* view = inspectable_web_contents()->GetView()->GetNativeView();
- if (has_frame()) {
- [view setFrame:[[window_ contentView] bounds]];
- [[window_ contentView] addSubview:view];
- } else {
- // In OSX 10.10, adding subviews to the root view for the NSView hierarchy
- // produces warnings. To eliminate the warnings, we resize the contentView
- // to fill the window, and add subviews to that.
- // http://crbug.com/380412
- content_view_.reset([[FullSizeContentView alloc] init]);
- [content_view_
- setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
- [content_view_ setFrame:[[[window_ contentView] superview] bounds]];
- [window_ setContentView:content_view_];
- [view setFrame:[content_view_ bounds]];
- [content_view_ addSubview:view];
- // The fullscreen button should always be hidden for frameless window.
- [[window_ standardWindowButton:NSWindowFullScreenButton] setHidden:YES];
- if (title_bar_style_ != NORMAL) {
- if (base::mac::IsOSMavericks()) {
- ShowWindowButton(NSWindowZoomButton);
- ShowWindowButton(NSWindowMiniaturizeButton);
- ShowWindowButton(NSWindowCloseButton);
- }
- return;
- }
- // Hide the window buttons.
- [[window_ standardWindowButton:NSWindowZoomButton] setHidden:YES];
- [[window_ standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
- [[window_ standardWindowButton:NSWindowCloseButton] setHidden:YES];
- // Some third-party macOS utilities check the zoom button's enabled state to
- // determine whether to show custom UI on hover, so we disable it here to
- // prevent them from doing so in a frameless app window.
- [[window_ standardWindowButton:NSWindowZoomButton] setEnabled:NO];
- }
- }
- void NativeWindowMac::UninstallView() {
- NSView* view = inspectable_web_contents()->GetView()->GetNativeView();
- [view removeFromSuperview];
- }
- void NativeWindowMac::UpdateDraggableRegionViews(
- const std::vector<DraggableRegion>& regions) {
- if (has_frame())
- return;
- // All ControlRegionViews should be added as children of the WebContentsView,
- // because WebContentsView will be removed and re-added when entering and
- // leaving fullscreen mode.
- NSView* webView = web_contents()->GetNativeView();
- NSInteger webViewWidth = NSWidth([webView bounds]);
- NSInteger webViewHeight = NSHeight([webView bounds]);
- if ([webView respondsToSelector:@selector(setMouseDownCanMoveWindow:)]) {
- [webView setMouseDownCanMoveWindow:YES];
- }
- // Remove all ControlRegionViews that are added last time.
- // Note that [webView subviews] returns the view's mutable internal array and
- // it should be copied to avoid mutating the original array while enumerating
- // it.
- base::scoped_nsobject<NSArray> subviews([[webView subviews] copy]);
- for (NSView* subview in subviews.get())
- if ([subview isKindOfClass:[ControlRegionView class]])
- [subview removeFromSuperview];
- // Draggable regions is implemented by having the whole web view draggable
- // (mouseDownCanMoveWindow) and overlaying regions that are not draggable.
- std::vector<gfx::Rect> system_drag_exclude_areas =
- CalculateNonDraggableRegions(regions, webViewWidth, webViewHeight);
- // Create and add a ControlRegionView for each region that needs to be
- // excluded from the dragging.
- for (std::vector<gfx::Rect>::const_iterator iter =
- system_drag_exclude_areas.begin();
- iter != system_drag_exclude_areas.end();
- ++iter) {
- base::scoped_nsobject<NSView> controlRegion(
- [[ControlRegionView alloc] initWithFrame:NSZeroRect]);
- [controlRegion setFrame:NSMakeRect(iter->x(),
- webViewHeight - iter->bottom(),
- iter->width(),
- iter->height())];
- [webView addSubview:controlRegion];
- }
- // AppKit will not update its cache of mouseDownCanMoveWindow unless something
- // changes. Previously we tried adding an NSView and removing it, but for some
- // reason it required reposting the mouse-down event, and didn't always work.
- // Calling the below seems to be an effective solution.
- [window_ setMovableByWindowBackground:NO];
- [window_ setMovableByWindowBackground:YES];
- }
- void NativeWindowMac::SetStyleMask(bool on, NSUInteger flag) {
- // Changing the styleMask of a frameless windows causes it to change size so
- // we explicitly disable resizing while setting it.
- ScopedDisableResize disable_resize;
- bool was_maximizable = IsMaximizable();
- if (on)
- [window_ setStyleMask:[window_ styleMask] | flag];
- else
- [window_ setStyleMask:[window_ styleMask] & (~flag)];
- // Change style mask will make the zoom button revert to default, probably
- // a bug of Cocoa or macOS.
- SetMaximizable(was_maximizable);
- }
- void NativeWindowMac::SetCollectionBehavior(bool on, NSUInteger flag) {
- bool was_maximizable = IsMaximizable();
- if (on)
- [window_ setCollectionBehavior:[window_ collectionBehavior] | flag];
- else
- [window_ setCollectionBehavior:[window_ collectionBehavior] & (~flag)];
- // Change collectionBehavior will make the zoom button revert to default,
- // probably a bug of Cocoa or macOS.
- SetMaximizable(was_maximizable);
- }
- void NativeWindowMac::RegisterInputEventObserver(
- content::RenderViewHost* host) {
- if (host)
- host->GetWidget()->AddInputEventObserver(this);
- }
- void NativeWindowMac::UnregisterInputEventObserver(
- content::RenderViewHost* host) {
- if (host)
- host->GetWidget()->RemoveInputEventObserver(this);
- }
- // static
- NativeWindow* NativeWindow::Create(
- brightray::InspectableWebContents* inspectable_web_contents,
- const mate::Dictionary& options,
- NativeWindow* parent) {
- return new NativeWindowMac(inspectable_web_contents, options, parent);
- }
- } // namespace atom
|