1// Copyright 2013 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 "chrome/browser/ui/views/frame/browser_frame_ash.h"
6
7#include "ash/wm/window_properties.h"
8#include "ash/wm/window_state.h"
9#include "ash/wm/window_state_delegate.h"
10#include "ash/wm/window_util.h"
11#include "chrome/browser/ui/browser_commands.h"
12#include "chrome/browser/ui/browser_finder.h"
13#include "chrome/browser/ui/views/frame/browser_shutdown.h"
14#include "chrome/browser/ui/views/frame/browser_view.h"
15#include "ui/aura/client/aura_constants.h"
16#include "ui/aura/window.h"
17#include "ui/aura/window_observer.h"
18#include "ui/views/view.h"
19
20using aura::Window;
21
22namespace {
23
24// BrowserWindowStateDelegate class handles a user's fullscreen
25// request (Shift+F4/F4).
26class BrowserWindowStateDelegate : public ash::wm::WindowStateDelegate {
27 public:
28  explicit BrowserWindowStateDelegate(Browser* browser)
29      : browser_(browser) {
30    DCHECK(browser_);
31  }
32  virtual ~BrowserWindowStateDelegate(){}
33
34  // Overridden from ash::wm::WindowStateDelegate.
35  virtual bool ToggleFullscreen(ash::wm::WindowState* window_state) OVERRIDE {
36    DCHECK(window_state->IsFullscreen() || window_state->CanMaximize());
37    // Windows which cannot be maximized should not be fullscreened.
38    if (!window_state->IsFullscreen() && !window_state->CanMaximize())
39      return true;
40    chrome::ToggleFullscreenMode(browser_);
41    return true;
42  }
43 private:
44  Browser* browser_;  // not owned.
45
46  DISALLOW_COPY_AND_ASSIGN(BrowserWindowStateDelegate);
47};
48
49}  // namespace
50
51///////////////////////////////////////////////////////////////////////////////
52// BrowserFrameAsh, public:
53
54// static
55const char BrowserFrameAsh::kWindowName[] = "BrowserFrameAsh";
56
57BrowserFrameAsh::BrowserFrameAsh(BrowserFrame* browser_frame,
58                                 BrowserView* browser_view)
59    : views::NativeWidgetAura(browser_frame),
60      browser_view_(browser_view) {
61  GetNativeWindow()->SetName(kWindowName);
62  Browser* browser = browser_view->browser();
63  ash::wm::WindowState* window_state =
64      ash::wm::GetWindowState(GetNativeWindow());
65  window_state->SetDelegate(
66      scoped_ptr<ash::wm::WindowStateDelegate>(
67          new BrowserWindowStateDelegate(browser)).Pass());
68
69  // Turn on auto window management if we don't need an explicit bounds.
70  // This way the requested bounds are honored.
71  if (!browser->bounds_overridden() && !browser->is_session_restore())
72    SetWindowAutoManaged();
73#if defined(OS_CHROMEOS)
74  // For legacy reasons v1 apps (like Secure Shell) are allowed to consume keys
75  // like brightness, volume, etc. Otherwise these keys are handled by the
76  // Ash window manager.
77  window_state->set_can_consume_system_keys(browser->is_app());
78#endif  // defined(OS_CHROMEOS)
79}
80
81///////////////////////////////////////////////////////////////////////////////
82// BrowserFrameAsh, views::NativeWidgetAura overrides:
83
84void BrowserFrameAsh::OnWindowDestroying(aura::Window* window) {
85  // Destroy any remaining WebContents early on. Doing so may result in
86  // calling back to one of the Views/LayoutManagers or supporting classes of
87  // BrowserView. By destroying here we ensure all said classes are valid.
88  DestroyBrowserWebContents(browser_view_->browser());
89  NativeWidgetAura::OnWindowDestroying(window);
90}
91
92void BrowserFrameAsh::OnWindowTargetVisibilityChanged(bool visible) {
93  if (visible) {
94    // Once the window has been shown we know the requested bounds
95    // (if provided) have been honored and we can switch on window management.
96    SetWindowAutoManaged();
97  }
98  views::NativeWidgetAura::OnWindowTargetVisibilityChanged(visible);
99}
100
101bool BrowserFrameAsh::ShouldSaveWindowPlacement() const {
102  return NULL == GetWidget()->GetNativeWindow()->GetProperty(
103                     ash::kRestoreBoundsOverrideKey);
104}
105
106void BrowserFrameAsh::GetWindowPlacement(
107    gfx::Rect* bounds,
108    ui::WindowShowState* show_state) const {
109  gfx::Rect* override_bounds = GetWidget()->GetNativeWindow()->GetProperty(
110                                   ash::kRestoreBoundsOverrideKey);
111  if (override_bounds && !override_bounds->IsEmpty()) {
112    *bounds = *override_bounds;
113    *show_state = GetWidget()->GetNativeWindow()->GetProperty(
114                      ash::kRestoreShowStateOverrideKey);
115  } else {
116    *bounds = GetWidget()->GetRestoredBounds();
117    *show_state = GetWidget()->GetNativeWindow()->GetProperty(
118                      aura::client::kShowStateKey);
119  }
120
121  if (*show_state != ui::SHOW_STATE_MAXIMIZED &&
122      *show_state != ui::SHOW_STATE_MINIMIZED) {
123    *show_state = ui::SHOW_STATE_NORMAL;
124  }
125}
126
127////////////////////////////////////////////////////////////////////////////////
128// BrowserFrameAsh, NativeBrowserFrame implementation:
129
130views::NativeWidget* BrowserFrameAsh::AsNativeWidget() {
131  return this;
132}
133
134const views::NativeWidget* BrowserFrameAsh::AsNativeWidget() const {
135  return this;
136}
137
138bool BrowserFrameAsh::UsesNativeSystemMenu() const {
139  return false;
140}
141
142int BrowserFrameAsh::GetMinimizeButtonOffset() const {
143  return 0;
144}
145
146BrowserFrameAsh::~BrowserFrameAsh() {
147}
148
149///////////////////////////////////////////////////////////////////////////////
150// BrowserFrameAsh, private:
151
152void BrowserFrameAsh::SetWindowAutoManaged() {
153  if (!browser_view_->browser()->is_type_popup() ||
154      browser_view_->browser()->is_app()) {
155    ash::wm::GetWindowState(GetNativeWindow())->
156        set_window_position_managed(true);
157  }
158}
159