Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / ui / views / apps / chrome_native_app_window_views_mac.mm
blob5572ab1c96bc5bb8cff055a016beb9d4cb6b440b
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #import "chrome/browser/ui/views/apps/chrome_native_app_window_views_mac.h"
7 #import <Cocoa/Cocoa.h>
9 #import "base/mac/scoped_nsobject.h"
10 #import "base/mac/sdk_forward_declarations.h"
11 #include "chrome/browser/apps/app_shim/extension_app_shim_handler_mac.h"
12 #import "chrome/browser/ui/views/apps/app_window_native_widget_mac.h"
13 #import "chrome/browser/ui/views/apps/native_app_window_frame_view_mac.h"
14 #import "ui/gfx/mac/coordinate_conversion.h"
16 @interface NSView (WebContentsView)
17 - (void)setMouseDownCanMoveWindow:(BOOL)can_move;
18 @end
20 // This observer is used to get NSWindowWillStartLiveResizeNotification. We need
21 // a single hook when animated/user resize begins to save the current bounds.
22 @interface StartResizeNotificationObserver : NSObject {
23  @private
24   // Weak. Owns us.
25   ChromeNativeAppWindowViewsMac* nativeAppWindow_;
27 - (id)initForNativeAppWindow:(ChromeNativeAppWindowViewsMac*)nativeAppWindow;
28 - (void)onWindowWillStartLiveResize:(NSNotification*)notification;
29 - (void)stopObserving;
30 @end
32 @implementation StartResizeNotificationObserver
34 - (id)initForNativeAppWindow:(ChromeNativeAppWindowViewsMac*)nativeAppWindow {
35   if ((self = [super init])) {
36     nativeAppWindow_ = nativeAppWindow;
37     [[NSNotificationCenter defaultCenter]
38         addObserver:self
39            selector:@selector(onWindowWillStartLiveResize:)
40                name:NSWindowWillStartLiveResizeNotification
41              object:static_cast<ui::BaseWindow*>(nativeAppWindow)
42                         ->GetNativeWindow()];
43   }
44   return self;
47 - (void)onWindowWillStartLiveResize:(NSNotification*)notification {
48   nativeAppWindow_->OnWindowWillStartLiveResize();
51 - (void)stopObserving {
52   [[NSNotificationCenter defaultCenter] removeObserver:self];
53   nativeAppWindow_ = nullptr;
56 @end
58 namespace {
60 bool NSWindowIsMaximized(NSWindow* window) {
61   // -[NSWindow isZoomed] only works if the zoom button is enabled.
62   if ([[window standardWindowButton:NSWindowZoomButton] isEnabled])
63     return [window isZoomed];
65   // We don't attempt to distinguish between a window that has been explicitly
66   // maximized versus one that has just been dragged by the user to fill the
67   // screen. This is the same behavior as -[NSWindow isZoomed] above.
68   return NSEqualRects([window frame], [[window screen] visibleFrame]);
71 }  // namespace
73 ChromeNativeAppWindowViewsMac::ChromeNativeAppWindowViewsMac()
74     : is_hidden_with_app_(false) {
77 ChromeNativeAppWindowViewsMac::~ChromeNativeAppWindowViewsMac() {
78   [nswindow_observer_ stopObserving];
81 void ChromeNativeAppWindowViewsMac::OnWindowWillStartLiveResize() {
82   if (!NSWindowIsMaximized(GetNativeWindow())) {
83     bounds_before_maximize_ = [GetNativeWindow() frame];
84   }
87 void ChromeNativeAppWindowViewsMac::OnBeforeWidgetInit(
88     const extensions::AppWindow::CreateParams& create_params,
89     views::Widget::InitParams* init_params,
90     views::Widget* widget) {
91   DCHECK(!init_params->native_widget);
92   init_params->remove_standard_frame = IsFrameless();
93   init_params->native_widget = new AppWindowNativeWidgetMac(widget, this);
94   ChromeNativeAppWindowViews::OnBeforeWidgetInit(create_params, init_params,
95                                                  widget);
98 views::NonClientFrameView*
99 ChromeNativeAppWindowViewsMac::CreateStandardDesktopAppFrame() {
100   return new NativeAppWindowFrameViewMac(widget(), this);
103 views::NonClientFrameView*
104 ChromeNativeAppWindowViewsMac::CreateNonStandardAppFrame() {
105   return new NativeAppWindowFrameViewMac(widget(), this);
108 bool ChromeNativeAppWindowViewsMac::IsMaximized() const {
109   return !IsMinimized() && NSWindowIsMaximized(GetNativeWindow());
112 gfx::Rect ChromeNativeAppWindowViewsMac::GetRestoredBounds() const {
113   if (NSWindowIsMaximized(GetNativeWindow()))
114     return gfx::ScreenRectFromNSRect(bounds_before_maximize_);
116   return ChromeNativeAppWindowViews::GetRestoredBounds();
119 void ChromeNativeAppWindowViewsMac::Show() {
120   UnhideWithoutActivation();
121   ChromeNativeAppWindowViews::Show();
124 void ChromeNativeAppWindowViewsMac::ShowInactive() {
125   if (is_hidden_with_app_)
126     return;
128   ChromeNativeAppWindowViews::ShowInactive();
131 void ChromeNativeAppWindowViewsMac::Activate() {
132   UnhideWithoutActivation();
133   ChromeNativeAppWindowViews::Activate();
136 void ChromeNativeAppWindowViewsMac::Maximize() {
137   if (IsFullscreen())
138     return;
140   NSWindow* window = GetNativeWindow();
141   if (!NSWindowIsMaximized(window))
142     [window setFrame:[[window screen] visibleFrame] display:YES animate:YES];
144   if (IsMinimized())
145     [window deminiaturize:nil];
148 void ChromeNativeAppWindowViewsMac::Restore() {
149   NSWindow* window = GetNativeWindow();
150   if (NSWindowIsMaximized(window))
151     [window setFrame:bounds_before_maximize_ display:YES animate:YES];
153   ChromeNativeAppWindowViews::Restore();
156 void ChromeNativeAppWindowViewsMac::FlashFrame(bool flash) {
157   apps::ExtensionAppShimHandler::RequestUserAttentionForWindow(
158       app_window(), flash ? apps::APP_SHIM_ATTENTION_CRITICAL
159                           : apps::APP_SHIM_ATTENTION_CANCEL);
162 void ChromeNativeAppWindowViewsMac::OnWidgetCreated(views::Widget* widget) {
163   nswindow_observer_.reset(
164       [[StartResizeNotificationObserver alloc] initForNativeAppWindow:this]);
167 void ChromeNativeAppWindowViewsMac::UpdateDraggableRegions(
168     const std::vector<extensions::DraggableRegion>& regions) {
169   ChromeNativeAppWindowViews::UpdateDraggableRegions(regions);
171   NSView* web_contents_view = app_window()->web_contents()->GetNativeView();
172   [web_contents_view setMouseDownCanMoveWindow:YES];
175 void ChromeNativeAppWindowViewsMac::ShowWithApp() {
176   is_hidden_with_app_ = false;
177   if (!app_window()->is_hidden())
178     ShowInactive();
181 void ChromeNativeAppWindowViewsMac::HideWithApp() {
182   is_hidden_with_app_ = true;
183   ChromeNativeAppWindowViews::Hide();
186 void ChromeNativeAppWindowViewsMac::UnhideWithoutActivation() {
187   if (is_hidden_with_app_) {
188     apps::ExtensionAppShimHandler::UnhideWithoutActivationForWindow(
189         app_window());
190     is_hidden_with_app_ = false;
191   }