1// Copyright (c) 2012 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_aura.h"
6
7#include "base/command_line.h"
8#include "chrome/app/chrome_command_ids.h"
9#include "chrome/browser/ui/views/frame/browser_view.h"
10#include "grit/chromium_strings.h"
11#include "grit/generated_resources.h"
12#include "ui/aura/client/aura_constants.h"
13#include "ui/aura/window.h"
14#include "ui/aura/window_observer.h"
15#include "ui/base/hit_test.h"
16#include "ui/base/l10n/l10n_util.h"
17#include "ui/gfx/font.h"
18#include "ui/views/view.h"
19
20#if defined(USE_ASH)
21#include "ash/wm/window_util.h"
22#include "chrome/browser/ui/ash/ash_init.h"
23#endif
24
25#if !defined(OS_CHROMEOS)
26#include "chrome/browser/ui/views/frame/desktop_browser_frame_aura.h"
27#endif
28
29using aura::Window;
30
31////////////////////////////////////////////////////////////////////////////////
32// BrowserFrameAura::WindowPropertyWatcher
33
34class BrowserFrameAura::WindowPropertyWatcher : public aura::WindowObserver {
35 public:
36  explicit WindowPropertyWatcher(BrowserFrameAura* browser_frame_aura,
37                                 BrowserFrame* browser_frame)
38      : browser_frame_aura_(browser_frame_aura),
39        browser_frame_(browser_frame) {}
40
41  virtual void OnWindowPropertyChanged(aura::Window* window,
42                                       const void* key,
43                                       intptr_t old) OVERRIDE {
44    if (key != aura::client::kShowStateKey)
45      return;
46
47    ui::WindowShowState old_state = static_cast<ui::WindowShowState>(old);
48    ui::WindowShowState new_state =
49        window->GetProperty(aura::client::kShowStateKey);
50
51    // Allow the frame to be replaced when entering or exiting the maximized
52    // state.
53    if (browser_frame_->non_client_view() &&
54        browser_frame_aura_->browser_view()->browser()->is_app() &&
55        (old_state == ui::SHOW_STATE_MAXIMIZED ||
56         new_state == ui::SHOW_STATE_MAXIMIZED)) {
57      // Defer frame layout when replacing the frame. Layout will occur when the
58      // window's bounds are updated. The window maximize/restore animations
59      // clone the window's layers and rely on the subsequent layout to set
60      // the layer sizes.
61      // If the window is minimized, the frame view needs to be updated via
62      // an OnBoundsChanged event so that the frame will change its size
63      // properly.
64      browser_frame_->non_client_view()->UpdateFrame(
65          old_state == ui::SHOW_STATE_MINIMIZED);
66    }
67  }
68
69  virtual void OnWindowBoundsChanged(aura::Window* window,
70                                     const gfx::Rect& old_bounds,
71                                     const gfx::Rect& new_bounds) OVERRIDE {
72    // Don't do anything if we don't have our non-client view yet.
73    if (!browser_frame_->non_client_view())
74      return;
75
76    // If the window just moved to the top of the screen, or just moved away
77    // from it, invoke Layout() so the header size can change.
78    if ((old_bounds.y() == 0 && new_bounds.y() != 0) ||
79        (old_bounds.y() != 0 && new_bounds.y() == 0))
80      browser_frame_->non_client_view()->Layout();
81  }
82
83 private:
84  BrowserFrameAura* browser_frame_aura_;
85  BrowserFrame* browser_frame_;
86
87  DISALLOW_COPY_AND_ASSIGN(WindowPropertyWatcher);
88};
89
90///////////////////////////////////////////////////////////////////////////////
91// BrowserFrameAura, public:
92
93// static
94const char BrowserFrameAura::kWindowName[] = "BrowserFrameAura";
95
96BrowserFrameAura::BrowserFrameAura(BrowserFrame* browser_frame,
97                                   BrowserView* browser_view)
98    : views::NativeWidgetAura(browser_frame),
99      browser_view_(browser_view),
100      window_property_watcher_(new WindowPropertyWatcher(this, browser_frame)) {
101  GetNativeWindow()->SetName(kWindowName);
102  GetNativeWindow()->AddObserver(window_property_watcher_.get());
103#if defined(USE_ASH)
104  // Turn on auto window management if we don't need an explicit bounds.
105  // This way the requested bounds are honored.
106  if (!browser_view->browser()->bounds_overridden() &&
107      !browser_view->browser()->is_session_restore())
108    SetWindowAutoManaged();
109#endif
110}
111
112///////////////////////////////////////////////////////////////////////////////
113// BrowserFrameAura, views::NativeWidgetAura overrides:
114
115void BrowserFrameAura::OnWindowDestroying() {
116  // Window is destroyed before our destructor is called, so clean up our
117  // observer here.
118  GetNativeWindow()->RemoveObserver(window_property_watcher_.get());
119  views::NativeWidgetAura::OnWindowDestroying();
120}
121
122void BrowserFrameAura::OnWindowTargetVisibilityChanged(bool visible) {
123  if (visible) {
124    // Once the window has been shown we know the requested bounds
125    // (if provided) have been honored and we can switch on window management.
126    SetWindowAutoManaged();
127  }
128  views::NativeWidgetAura::OnWindowTargetVisibilityChanged(visible);
129}
130
131////////////////////////////////////////////////////////////////////////////////
132// BrowserFrameAura, NativeBrowserFrame implementation:
133
134views::NativeWidget* BrowserFrameAura::AsNativeWidget() {
135  return this;
136}
137
138const views::NativeWidget* BrowserFrameAura::AsNativeWidget() const {
139  return this;
140}
141
142bool BrowserFrameAura::UsesNativeSystemMenu() const {
143  return false;
144}
145
146int BrowserFrameAura::GetMinimizeButtonOffset() const {
147  return 0;
148}
149
150void BrowserFrameAura::TabStripDisplayModeChanged() {
151}
152
153////////////////////////////////////////////////////////////////////////////////
154// BrowserFrame, public:
155
156// static
157const gfx::Font& BrowserFrame::GetTitleFont() {
158  static gfx::Font* title_font = new gfx::Font;
159  return *title_font;
160}
161
162////////////////////////////////////////////////////////////////////////////////
163// NativeBrowserFrame, public:
164
165// static
166NativeBrowserFrame* NativeBrowserFrame::CreateNativeBrowserFrame(
167    BrowserFrame* browser_frame,
168    BrowserView* browser_view) {
169#if !defined(OS_CHROMEOS)
170  if (
171#if defined(USE_ASH)
172      !chrome::ShouldOpenAshOnStartup() &&
173#endif
174      browser_view->browser()->
175          host_desktop_type() == chrome::HOST_DESKTOP_TYPE_NATIVE)
176    return new DesktopBrowserFrameAura(browser_frame, browser_view);
177#endif
178  return new BrowserFrameAura(browser_frame, browser_view);
179}
180
181///////////////////////////////////////////////////////////////////////////////
182// BrowserFrameAura, private:
183
184BrowserFrameAura::~BrowserFrameAura() {
185}
186
187void BrowserFrameAura::SetWindowAutoManaged() {
188#if defined(USE_ASH)
189  if (browser_view_->browser()->type() != Browser::TYPE_POPUP ||
190      browser_view_->browser()->is_app())
191    ash::wm::SetWindowPositionManaged(GetNativeWindow(), true);
192#endif
193}
194