• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 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.
4 
5 #include "apps/ui/views/native_app_window_views.h"
6 
7 #include "apps/app_window.h"
8 #include "base/threading/sequenced_worker_pool.h"
9 #include "content/public/browser/render_view_host.h"
10 #include "content/public/browser/render_widget_host_view.h"
11 #include "content/public/browser/web_contents.h"
12 #include "extensions/common/draggable_region.h"
13 #include "third_party/skia/include/core/SkRegion.h"
14 #include "ui/gfx/path.h"
15 #include "ui/views/controls/webview/webview.h"
16 #include "ui/views/widget/widget.h"
17 #include "ui/views/window/non_client_view.h"
18 
19 #if defined(USE_AURA)
20 #include "ui/aura/window.h"
21 #endif
22 
23 namespace apps {
24 
NativeAppWindowViews()25 NativeAppWindowViews::NativeAppWindowViews()
26     : app_window_(NULL),
27       web_view_(NULL),
28       widget_(NULL),
29       frameless_(false),
30       resizable_(false) {}
31 
Init(AppWindow * app_window,const AppWindow::CreateParams & create_params)32 void NativeAppWindowViews::Init(AppWindow* app_window,
33                                 const AppWindow::CreateParams& create_params) {
34   app_window_ = app_window;
35   frameless_ = create_params.frame == AppWindow::FRAME_NONE;
36   resizable_ = create_params.resizable;
37   size_constraints_.set_minimum_size(
38       create_params.GetContentMinimumSize(gfx::Insets()));
39   size_constraints_.set_maximum_size(
40       create_params.GetContentMaximumSize(gfx::Insets()));
41   Observe(app_window_->web_contents());
42 
43   widget_ = new views::Widget;
44   InitializeWindow(app_window, create_params);
45 
46   OnViewWasResized();
47   widget_->AddObserver(this);
48 }
49 
~NativeAppWindowViews()50 NativeAppWindowViews::~NativeAppWindowViews() {
51   web_view_->SetWebContents(NULL);
52 }
53 
OnCanHaveAlphaEnabledChanged()54 void NativeAppWindowViews::OnCanHaveAlphaEnabledChanged() {
55   app_window_->OnNativeWindowChanged();
56 }
57 
InitializeWindow(AppWindow * app_window,const AppWindow::CreateParams & create_params)58 void NativeAppWindowViews::InitializeWindow(
59     AppWindow* app_window,
60     const AppWindow::CreateParams& create_params) {
61   // Stub implementation. See also ChromeNativeAppWindowViews.
62   views::Widget::InitParams init_params(views::Widget::InitParams::TYPE_WINDOW);
63   init_params.delegate = this;
64   init_params.keep_on_top = create_params.always_on_top;
65   widget_->Init(init_params);
66   widget_->CenterWindow(
67       create_params.GetInitialWindowBounds(gfx::Insets()).size());
68 }
69 
70 // ui::BaseWindow implementation.
71 
IsActive() const72 bool NativeAppWindowViews::IsActive() const { return widget_->IsActive(); }
73 
IsMaximized() const74 bool NativeAppWindowViews::IsMaximized() const {
75   return widget_->IsMaximized();
76 }
77 
IsMinimized() const78 bool NativeAppWindowViews::IsMinimized() const {
79   return widget_->IsMinimized();
80 }
81 
IsFullscreen() const82 bool NativeAppWindowViews::IsFullscreen() const {
83   return widget_->IsFullscreen();
84 }
85 
GetNativeWindow()86 gfx::NativeWindow NativeAppWindowViews::GetNativeWindow() {
87   return widget_->GetNativeWindow();
88 }
89 
GetRestoredBounds() const90 gfx::Rect NativeAppWindowViews::GetRestoredBounds() const {
91   return widget_->GetRestoredBounds();
92 }
93 
GetRestoredState() const94 ui::WindowShowState NativeAppWindowViews::GetRestoredState() const {
95   // Stub implementation. See also ChromeNativeAppWindowViews.
96   if (IsMaximized())
97     return ui::SHOW_STATE_MAXIMIZED;
98   if (IsFullscreen())
99     return ui::SHOW_STATE_FULLSCREEN;
100   return ui::SHOW_STATE_NORMAL;
101 }
102 
GetBounds() const103 gfx::Rect NativeAppWindowViews::GetBounds() const {
104   return widget_->GetWindowBoundsInScreen();
105 }
106 
Show()107 void NativeAppWindowViews::Show() {
108   if (widget_->IsVisible()) {
109     widget_->Activate();
110     return;
111   }
112   widget_->Show();
113 }
114 
ShowInactive()115 void NativeAppWindowViews::ShowInactive() {
116   if (widget_->IsVisible())
117     return;
118 
119   widget_->ShowInactive();
120 }
121 
Hide()122 void NativeAppWindowViews::Hide() { widget_->Hide(); }
123 
Close()124 void NativeAppWindowViews::Close() { widget_->Close(); }
125 
Activate()126 void NativeAppWindowViews::Activate() { widget_->Activate(); }
127 
Deactivate()128 void NativeAppWindowViews::Deactivate() { widget_->Deactivate(); }
129 
Maximize()130 void NativeAppWindowViews::Maximize() { widget_->Maximize(); }
131 
Minimize()132 void NativeAppWindowViews::Minimize() { widget_->Minimize(); }
133 
Restore()134 void NativeAppWindowViews::Restore() { widget_->Restore(); }
135 
SetBounds(const gfx::Rect & bounds)136 void NativeAppWindowViews::SetBounds(const gfx::Rect& bounds) {
137   widget_->SetBounds(bounds);
138 }
139 
FlashFrame(bool flash)140 void NativeAppWindowViews::FlashFrame(bool flash) {
141   widget_->FlashFrame(flash);
142 }
143 
IsAlwaysOnTop() const144 bool NativeAppWindowViews::IsAlwaysOnTop() const {
145   // Stub implementation. See also ChromeNativeAppWindowViews.
146   return widget_->IsAlwaysOnTop();
147 }
148 
SetAlwaysOnTop(bool always_on_top)149 void NativeAppWindowViews::SetAlwaysOnTop(bool always_on_top) {
150   widget_->SetAlwaysOnTop(always_on_top);
151 }
152 
GetHostView() const153 gfx::NativeView NativeAppWindowViews::GetHostView() const {
154   return widget_->GetNativeView();
155 }
156 
GetDialogPosition(const gfx::Size & size)157 gfx::Point NativeAppWindowViews::GetDialogPosition(const gfx::Size& size) {
158   gfx::Size app_window_size = widget_->GetWindowBoundsInScreen().size();
159   return gfx::Point(app_window_size.width() / 2 - size.width() / 2,
160                     app_window_size.height() / 2 - size.height() / 2);
161 }
162 
GetMaximumDialogSize()163 gfx::Size NativeAppWindowViews::GetMaximumDialogSize() {
164   return widget_->GetWindowBoundsInScreen().size();
165 }
166 
AddObserver(web_modal::ModalDialogHostObserver * observer)167 void NativeAppWindowViews::AddObserver(
168     web_modal::ModalDialogHostObserver* observer) {
169   observer_list_.AddObserver(observer);
170 }
RemoveObserver(web_modal::ModalDialogHostObserver * observer)171 void NativeAppWindowViews::RemoveObserver(
172     web_modal::ModalDialogHostObserver* observer) {
173   observer_list_.RemoveObserver(observer);
174 }
175 
OnViewWasResized()176 void NativeAppWindowViews::OnViewWasResized() {
177   FOR_EACH_OBSERVER(web_modal::ModalDialogHostObserver,
178                     observer_list_,
179                     OnPositionRequiresUpdate());
180 }
181 
182 // WidgetDelegate implementation.
183 
OnWidgetMove()184 void NativeAppWindowViews::OnWidgetMove() {
185   app_window_->OnNativeWindowChanged();
186 }
187 
GetInitiallyFocusedView()188 views::View* NativeAppWindowViews::GetInitiallyFocusedView() {
189   return web_view_;
190 }
191 
CanResize() const192 bool NativeAppWindowViews::CanResize() const {
193   return resizable_ && !size_constraints_.HasFixedSize();
194 }
195 
CanMaximize() const196 bool NativeAppWindowViews::CanMaximize() const {
197   return resizable_ && !size_constraints_.HasMaximumSize() &&
198          !app_window_->window_type_is_panel();
199 }
200 
GetWindowTitle() const201 base::string16 NativeAppWindowViews::GetWindowTitle() const {
202   return app_window_->GetTitle();
203 }
204 
ShouldShowWindowTitle() const205 bool NativeAppWindowViews::ShouldShowWindowTitle() const {
206   return app_window_->window_type() == AppWindow::WINDOW_TYPE_V1_PANEL;
207 }
208 
ShouldShowWindowIcon() const209 bool NativeAppWindowViews::ShouldShowWindowIcon() const {
210   return app_window_->window_type() == AppWindow::WINDOW_TYPE_V1_PANEL;
211 }
212 
SaveWindowPlacement(const gfx::Rect & bounds,ui::WindowShowState show_state)213 void NativeAppWindowViews::SaveWindowPlacement(const gfx::Rect& bounds,
214                                                ui::WindowShowState show_state) {
215   views::WidgetDelegate::SaveWindowPlacement(bounds, show_state);
216   app_window_->OnNativeWindowChanged();
217 }
218 
DeleteDelegate()219 void NativeAppWindowViews::DeleteDelegate() {
220   widget_->RemoveObserver(this);
221   app_window_->OnNativeClose();
222 }
223 
GetWidget()224 views::Widget* NativeAppWindowViews::GetWidget() { return widget_; }
225 
GetWidget() const226 const views::Widget* NativeAppWindowViews::GetWidget() const { return widget_; }
227 
GetContentsView()228 views::View* NativeAppWindowViews::GetContentsView() {
229   return this;
230 }
231 
ShouldDescendIntoChildForEventHandling(gfx::NativeView child,const gfx::Point & location)232 bool NativeAppWindowViews::ShouldDescendIntoChildForEventHandling(
233     gfx::NativeView child,
234     const gfx::Point& location) {
235 #if defined(USE_AURA)
236   if (child->Contains(web_view_->web_contents()->GetNativeView())) {
237     // App window should claim mouse events that fall within the draggable
238     // region.
239     return !draggable_region_.get() ||
240            !draggable_region_->contains(location.x(), location.y());
241   }
242 #endif
243 
244   return true;
245 }
246 
247 // WidgetObserver implementation.
248 
OnWidgetVisibilityChanged(views::Widget * widget,bool visible)249 void NativeAppWindowViews::OnWidgetVisibilityChanged(views::Widget* widget,
250                                                      bool visible) {
251   app_window_->OnNativeWindowChanged();
252 }
253 
OnWidgetActivationChanged(views::Widget * widget,bool active)254 void NativeAppWindowViews::OnWidgetActivationChanged(views::Widget* widget,
255                                                      bool active) {
256   app_window_->OnNativeWindowChanged();
257   if (active)
258     app_window_->OnNativeWindowActivated();
259 }
260 
261 // WebContentsObserver implementation.
262 
RenderViewCreated(content::RenderViewHost * render_view_host)263 void NativeAppWindowViews::RenderViewCreated(
264     content::RenderViewHost* render_view_host) {
265   if (app_window_->requested_transparent_background() &&
266       CanHaveAlphaEnabled()) {
267     content::RenderWidgetHostView* view = render_view_host->GetView();
268     DCHECK(view);
269     view->SetBackgroundOpaque(false);
270   }
271 }
272 
RenderViewHostChanged(content::RenderViewHost * old_host,content::RenderViewHost * new_host)273 void NativeAppWindowViews::RenderViewHostChanged(
274     content::RenderViewHost* old_host,
275     content::RenderViewHost* new_host) {
276   OnViewWasResized();
277 }
278 
279 // views::View implementation.
280 
Layout()281 void NativeAppWindowViews::Layout() {
282   DCHECK(web_view_);
283   web_view_->SetBounds(0, 0, width(), height());
284   OnViewWasResized();
285 }
286 
ViewHierarchyChanged(const ViewHierarchyChangedDetails & details)287 void NativeAppWindowViews::ViewHierarchyChanged(
288     const ViewHierarchyChangedDetails& details) {
289   if (details.is_add && details.child == this) {
290     web_view_ = new views::WebView(NULL);
291     AddChildView(web_view_);
292     web_view_->SetWebContents(app_window_->web_contents());
293   }
294 }
295 
GetMinimumSize() const296 gfx::Size NativeAppWindowViews::GetMinimumSize() const {
297   return size_constraints_.GetMinimumSize();
298 }
299 
GetMaximumSize() const300 gfx::Size NativeAppWindowViews::GetMaximumSize() const {
301   return size_constraints_.GetMaximumSize();
302 }
303 
OnFocus()304 void NativeAppWindowViews::OnFocus() {
305   web_view_->RequestFocus();
306 }
307 
308 // NativeAppWindow implementation.
309 
SetFullscreen(int fullscreen_types)310 void NativeAppWindowViews::SetFullscreen(int fullscreen_types) {
311   // Stub implementation. See also ChromeNativeAppWindowViews.
312   widget_->SetFullscreen(fullscreen_types != AppWindow::FULLSCREEN_TYPE_NONE);
313 }
314 
IsFullscreenOrPending() const315 bool NativeAppWindowViews::IsFullscreenOrPending() const {
316   // Stub implementation. See also ChromeNativeAppWindowViews.
317   return widget_->IsFullscreen();
318 }
319 
IsDetached() const320 bool NativeAppWindowViews::IsDetached() const {
321   // Stub implementation. See also ChromeNativeAppWindowViews.
322   return false;
323 }
324 
UpdateWindowIcon()325 void NativeAppWindowViews::UpdateWindowIcon() { widget_->UpdateWindowIcon(); }
326 
UpdateWindowTitle()327 void NativeAppWindowViews::UpdateWindowTitle() { widget_->UpdateWindowTitle(); }
328 
UpdateBadgeIcon()329 void NativeAppWindowViews::UpdateBadgeIcon() {
330   // Stub implementation. See also ChromeNativeAppWindowViews.
331 }
332 
UpdateDraggableRegions(const std::vector<extensions::DraggableRegion> & regions)333 void NativeAppWindowViews::UpdateDraggableRegions(
334     const std::vector<extensions::DraggableRegion>& regions) {
335   // Draggable region is not supported for non-frameless window.
336   if (!frameless_)
337     return;
338 
339   draggable_region_.reset(AppWindow::RawDraggableRegionsToSkRegion(regions));
340   OnViewWasResized();
341 }
342 
GetDraggableRegion()343 SkRegion* NativeAppWindowViews::GetDraggableRegion() {
344   return draggable_region_.get();
345 }
346 
UpdateShape(scoped_ptr<SkRegion> region)347 void NativeAppWindowViews::UpdateShape(scoped_ptr<SkRegion> region) {
348   // Stub implementation. See also ChromeNativeAppWindowViews.
349 }
350 
HandleKeyboardEvent(const content::NativeWebKeyboardEvent & event)351 void NativeAppWindowViews::HandleKeyboardEvent(
352     const content::NativeWebKeyboardEvent& event) {
353   unhandled_keyboard_event_handler_.HandleKeyboardEvent(event,
354                                                         GetFocusManager());
355 }
356 
IsFrameless() const357 bool NativeAppWindowViews::IsFrameless() const { return frameless_; }
358 
HasFrameColor() const359 bool NativeAppWindowViews::HasFrameColor() const { return false; }
360 
ActiveFrameColor() const361 SkColor NativeAppWindowViews::ActiveFrameColor() const {
362   return SK_ColorBLACK;
363 }
364 
InactiveFrameColor() const365 SkColor NativeAppWindowViews::InactiveFrameColor() const {
366   return SK_ColorBLACK;
367 }
368 
GetFrameInsets() const369 gfx::Insets NativeAppWindowViews::GetFrameInsets() const {
370   if (frameless_)
371     return gfx::Insets();
372 
373   // The pretend client_bounds passed in need to be large enough to ensure that
374   // GetWindowBoundsForClientBounds() doesn't decide that it needs more than
375   // the specified amount of space to fit the window controls in, and return a
376   // number larger than the real frame insets. Most window controls are smaller
377   // than 1000x1000px, so this should be big enough.
378   gfx::Rect client_bounds = gfx::Rect(1000, 1000);
379   gfx::Rect window_bounds =
380       widget_->non_client_view()->GetWindowBoundsForClientBounds(client_bounds);
381   return window_bounds.InsetsFrom(client_bounds);
382 }
383 
HideWithApp()384 void NativeAppWindowViews::HideWithApp() {}
385 
ShowWithApp()386 void NativeAppWindowViews::ShowWithApp() {}
387 
UpdateShelfMenu()388 void NativeAppWindowViews::UpdateShelfMenu() {}
389 
GetContentMinimumSize() const390 gfx::Size NativeAppWindowViews::GetContentMinimumSize() const {
391   return size_constraints_.GetMinimumSize();
392 }
393 
GetContentMaximumSize() const394 gfx::Size NativeAppWindowViews::GetContentMaximumSize() const {
395   return size_constraints_.GetMaximumSize();
396 }
397 
SetContentSizeConstraints(const gfx::Size & min_size,const gfx::Size & max_size)398 void NativeAppWindowViews::SetContentSizeConstraints(
399     const gfx::Size& min_size, const gfx::Size& max_size) {
400   size_constraints_.set_minimum_size(min_size);
401   size_constraints_.set_maximum_size(max_size);
402 }
403 
CanHaveAlphaEnabled() const404 bool NativeAppWindowViews::CanHaveAlphaEnabled() const {
405   return widget_->IsTranslucentWindowOpacitySupported();
406 }
407 
408 }  // namespace apps
409