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.
5 #include "extensions/components/native_app_window/native_app_window_views.h"
7 #include "base/threading/sequenced_worker_pool.h"
8 #include "content/public/browser/render_view_host.h"
9 #include "content/public/browser/render_widget_host_view.h"
10 #include "content/public/browser/web_contents.h"
11 #include "extensions/browser/app_window/app_window.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"
20 #include "ui/aura/window.h"
23 using extensions::AppWindow
;
25 namespace native_app_window
{
27 NativeAppWindowViews::NativeAppWindowViews()
35 void NativeAppWindowViews::Init(AppWindow
* app_window
,
36 const AppWindow::CreateParams
& create_params
) {
37 app_window_
= app_window
;
38 frameless_
= create_params
.frame
== AppWindow::FRAME_NONE
;
39 resizable_
= create_params
.resizable
;
40 size_constraints_
.set_minimum_size(
41 create_params
.GetContentMinimumSize(gfx::Insets()));
42 size_constraints_
.set_maximum_size(
43 create_params
.GetContentMaximumSize(gfx::Insets()));
44 Observe(app_window_
->web_contents());
46 widget_
= new views::Widget
;
47 widget_
->AddObserver(this);
48 InitializeWindow(app_window
, create_params
);
53 NativeAppWindowViews::~NativeAppWindowViews() {
54 web_view_
->SetWebContents(NULL
);
57 void NativeAppWindowViews::OnCanHaveAlphaEnabledChanged() {
58 app_window_
->OnNativeWindowChanged();
61 void NativeAppWindowViews::InitializeWindow(
62 AppWindow
* app_window
,
63 const AppWindow::CreateParams
& create_params
) {
64 // Stub implementation. See also ChromeNativeAppWindowViews.
65 views::Widget::InitParams
init_params(views::Widget::InitParams::TYPE_WINDOW
);
66 init_params
.delegate
= this;
67 init_params
.keep_on_top
= create_params
.always_on_top
;
68 widget_
->Init(init_params
);
69 widget_
->CenterWindow(
70 create_params
.GetInitialWindowBounds(gfx::Insets()).size());
73 // ui::BaseWindow implementation.
75 bool NativeAppWindowViews::IsActive() const {
76 return widget_
->IsActive();
79 bool NativeAppWindowViews::IsMaximized() const {
80 return widget_
->IsMaximized();
83 bool NativeAppWindowViews::IsMinimized() const {
84 return widget_
->IsMinimized();
87 bool NativeAppWindowViews::IsFullscreen() const {
88 return widget_
->IsFullscreen();
91 gfx::NativeWindow
NativeAppWindowViews::GetNativeWindow() const {
92 return widget_
->GetNativeWindow();
95 gfx::Rect
NativeAppWindowViews::GetRestoredBounds() const {
96 return widget_
->GetRestoredBounds();
99 ui::WindowShowState
NativeAppWindowViews::GetRestoredState() const {
100 // Stub implementation. See also ChromeNativeAppWindowViews.
102 return ui::SHOW_STATE_MAXIMIZED
;
104 return ui::SHOW_STATE_FULLSCREEN
;
105 return ui::SHOW_STATE_NORMAL
;
108 gfx::Rect
NativeAppWindowViews::GetBounds() const {
109 return widget_
->GetWindowBoundsInScreen();
112 void NativeAppWindowViews::Show() {
113 if (widget_
->IsVisible()) {
120 void NativeAppWindowViews::ShowInactive() {
121 if (widget_
->IsVisible())
124 widget_
->ShowInactive();
127 void NativeAppWindowViews::Hide() {
131 void NativeAppWindowViews::Close() {
135 void NativeAppWindowViews::Activate() {
139 void NativeAppWindowViews::Deactivate() {
140 widget_
->Deactivate();
143 void NativeAppWindowViews::Maximize() {
147 void NativeAppWindowViews::Minimize() {
151 void NativeAppWindowViews::Restore() {
155 void NativeAppWindowViews::SetBounds(const gfx::Rect
& bounds
) {
156 widget_
->SetBounds(bounds
);
159 void NativeAppWindowViews::FlashFrame(bool flash
) {
160 widget_
->FlashFrame(flash
);
163 bool NativeAppWindowViews::IsAlwaysOnTop() const {
164 // Stub implementation. See also ChromeNativeAppWindowViews.
165 return widget_
->IsAlwaysOnTop();
168 void NativeAppWindowViews::SetAlwaysOnTop(bool always_on_top
) {
169 widget_
->SetAlwaysOnTop(always_on_top
);
172 gfx::NativeView
NativeAppWindowViews::GetHostView() const {
173 return widget_
->GetNativeView();
176 gfx::Point
NativeAppWindowViews::GetDialogPosition(const gfx::Size
& size
) {
177 gfx::Size app_window_size
= widget_
->GetWindowBoundsInScreen().size();
178 return gfx::Point(app_window_size
.width() / 2 - size
.width() / 2,
179 app_window_size
.height() / 2 - size
.height() / 2);
182 gfx::Size
NativeAppWindowViews::GetMaximumDialogSize() {
183 return widget_
->GetWindowBoundsInScreen().size();
186 void NativeAppWindowViews::AddObserver(
187 web_modal::ModalDialogHostObserver
* observer
) {
188 observer_list_
.AddObserver(observer
);
190 void NativeAppWindowViews::RemoveObserver(
191 web_modal::ModalDialogHostObserver
* observer
) {
192 observer_list_
.RemoveObserver(observer
);
195 void NativeAppWindowViews::OnViewWasResized() {
196 FOR_EACH_OBSERVER(web_modal::ModalDialogHostObserver
,
198 OnPositionRequiresUpdate());
201 // WidgetDelegate implementation.
203 void NativeAppWindowViews::OnWidgetMove() {
204 app_window_
->OnNativeWindowChanged();
207 views::View
* NativeAppWindowViews::GetInitiallyFocusedView() {
211 bool NativeAppWindowViews::CanResize() const {
212 return resizable_
&& !size_constraints_
.HasFixedSize() &&
213 !WidgetHasHitTestMask();
216 bool NativeAppWindowViews::CanMaximize() const {
217 return resizable_
&& !size_constraints_
.HasMaximumSize() &&
218 !app_window_
->window_type_is_panel() && !WidgetHasHitTestMask();
221 bool NativeAppWindowViews::CanMinimize() const {
225 base::string16
NativeAppWindowViews::GetWindowTitle() const {
226 return app_window_
->GetTitle();
229 bool NativeAppWindowViews::ShouldShowWindowTitle() const {
230 return app_window_
->window_type() == AppWindow::WINDOW_TYPE_V1_PANEL
;
233 bool NativeAppWindowViews::ShouldShowWindowIcon() const {
234 return app_window_
->window_type() == AppWindow::WINDOW_TYPE_V1_PANEL
;
237 void NativeAppWindowViews::SaveWindowPlacement(const gfx::Rect
& bounds
,
238 ui::WindowShowState show_state
) {
239 views::WidgetDelegate::SaveWindowPlacement(bounds
, show_state
);
240 app_window_
->OnNativeWindowChanged();
243 void NativeAppWindowViews::DeleteDelegate() {
244 widget_
->RemoveObserver(this);
245 app_window_
->OnNativeClose();
248 views::Widget
* NativeAppWindowViews::GetWidget() {
252 const views::Widget
* NativeAppWindowViews::GetWidget() const {
256 views::View
* NativeAppWindowViews::GetContentsView() {
260 bool NativeAppWindowViews::ShouldDescendIntoChildForEventHandling(
261 gfx::NativeView child
,
262 const gfx::Point
& location
) {
263 #if defined(USE_AURA)
264 if (child
->Contains(web_view_
->web_contents()->GetNativeView())) {
265 // App window should claim mouse events that fall within the draggable
267 return !draggable_region_
.get() ||
268 !draggable_region_
->contains(location
.x(), location
.y());
275 // WidgetObserver implementation.
277 void NativeAppWindowViews::OnWidgetVisibilityChanged(views::Widget
* widget
,
279 app_window_
->OnNativeWindowChanged();
282 void NativeAppWindowViews::OnWidgetActivationChanged(views::Widget
* widget
,
284 app_window_
->OnNativeWindowChanged();
286 app_window_
->OnNativeWindowActivated();
289 // WebContentsObserver implementation.
291 void NativeAppWindowViews::RenderViewCreated(
292 content::RenderViewHost
* render_view_host
) {
293 if (app_window_
->requested_alpha_enabled() && CanHaveAlphaEnabled()) {
294 content::RenderWidgetHostView
* view
= render_view_host
->GetView();
296 view
->SetBackgroundColor(SK_ColorTRANSPARENT
);
300 void NativeAppWindowViews::RenderViewHostChanged(
301 content::RenderViewHost
* old_host
,
302 content::RenderViewHost
* new_host
) {
306 // views::View implementation.
308 void NativeAppWindowViews::Layout() {
310 web_view_
->SetBounds(0, 0, width(), height());
314 void NativeAppWindowViews::ViewHierarchyChanged(
315 const ViewHierarchyChangedDetails
& details
) {
316 if (details
.is_add
&& details
.child
== this) {
317 web_view_
= new views::WebView(NULL
);
318 AddChildView(web_view_
);
319 web_view_
->SetWebContents(app_window_
->web_contents());
323 gfx::Size
NativeAppWindowViews::GetMinimumSize() const {
324 return size_constraints_
.GetMinimumSize();
327 gfx::Size
NativeAppWindowViews::GetMaximumSize() const {
328 return size_constraints_
.GetMaximumSize();
331 void NativeAppWindowViews::OnFocus() {
332 web_view_
->RequestFocus();
335 // NativeAppWindow implementation.
337 void NativeAppWindowViews::SetFullscreen(int fullscreen_types
) {
338 // Stub implementation. See also ChromeNativeAppWindowViews.
339 widget_
->SetFullscreen(fullscreen_types
!= AppWindow::FULLSCREEN_TYPE_NONE
);
342 bool NativeAppWindowViews::IsFullscreenOrPending() const {
343 // Stub implementation. See also ChromeNativeAppWindowViews.
344 return widget_
->IsFullscreen();
347 void NativeAppWindowViews::UpdateWindowIcon() {
348 widget_
->UpdateWindowIcon();
351 void NativeAppWindowViews::UpdateWindowTitle() {
352 widget_
->UpdateWindowTitle();
355 void NativeAppWindowViews::UpdateDraggableRegions(
356 const std::vector
<extensions::DraggableRegion
>& regions
) {
357 // Draggable region is not supported for non-frameless window.
361 draggable_region_
.reset(AppWindow::RawDraggableRegionsToSkRegion(regions
));
365 SkRegion
* NativeAppWindowViews::GetDraggableRegion() {
366 return draggable_region_
.get();
369 void NativeAppWindowViews::UpdateShape(scoped_ptr
<SkRegion
> region
) {
370 // Stub implementation. See also ChromeNativeAppWindowViews.
373 void NativeAppWindowViews::SetInterceptAllKeys(bool want_all_keys
) {
374 // Stub implementation. See also ChromeNativeAppWindowViews.
377 void NativeAppWindowViews::HandleKeyboardEvent(
378 const content::NativeWebKeyboardEvent
& event
) {
379 unhandled_keyboard_event_handler_
.HandleKeyboardEvent(event
,
383 bool NativeAppWindowViews::IsFrameless() const {
387 bool NativeAppWindowViews::HasFrameColor() const {
391 SkColor
NativeAppWindowViews::ActiveFrameColor() const {
392 return SK_ColorBLACK
;
395 SkColor
NativeAppWindowViews::InactiveFrameColor() const {
396 return SK_ColorBLACK
;
399 gfx::Insets
NativeAppWindowViews::GetFrameInsets() const {
401 return gfx::Insets();
403 // The pretend client_bounds passed in need to be large enough to ensure that
404 // GetWindowBoundsForClientBounds() doesn't decide that it needs more than
405 // the specified amount of space to fit the window controls in, and return a
406 // number larger than the real frame insets. Most window controls are smaller
407 // than 1000x1000px, so this should be big enough.
408 gfx::Rect client_bounds
= gfx::Rect(1000, 1000);
409 gfx::Rect window_bounds
=
410 widget_
->non_client_view()->GetWindowBoundsForClientBounds(client_bounds
);
411 return window_bounds
.InsetsFrom(client_bounds
);
414 void NativeAppWindowViews::HideWithApp() {
417 void NativeAppWindowViews::ShowWithApp() {
420 gfx::Size
NativeAppWindowViews::GetContentMinimumSize() const {
421 return size_constraints_
.GetMinimumSize();
424 gfx::Size
NativeAppWindowViews::GetContentMaximumSize() const {
425 return size_constraints_
.GetMaximumSize();
428 void NativeAppWindowViews::SetContentSizeConstraints(
429 const gfx::Size
& min_size
,
430 const gfx::Size
& max_size
) {
431 size_constraints_
.set_minimum_size(min_size
);
432 size_constraints_
.set_maximum_size(max_size
);
433 widget_
->OnSizeConstraintsChanged();
436 bool NativeAppWindowViews::CanHaveAlphaEnabled() const {
437 return widget_
->IsTranslucentWindowOpacitySupported();
440 void NativeAppWindowViews::SetVisibleOnAllWorkspaces(bool always_visible
) {
441 widget_
->SetVisibleOnAllWorkspaces(always_visible
);
444 } // namespace native_app_window