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/window_sizer/window_sizer.h"
6
7#include "ash/shell.h"
8#include "ash/wm/window_positioner.h"
9#include "ash/wm/window_state.h"
10#include "chrome/browser/ui/browser.h"
11#include "chrome/browser/ui/browser_window.h"
12#include "ui/aura/window.h"
13#include "ui/aura/window_event_dispatcher.h"
14#include "ui/gfx/screen.h"
15
16bool WindowSizer::GetBrowserBoundsAsh(gfx::Rect* bounds,
17                                      ui::WindowShowState* show_state) const {
18  if (!browser_ ||
19      browser_->host_desktop_type() != chrome::HOST_DESKTOP_TYPE_ASH)
20    return false;
21
22  bool determined = false;
23  if (bounds->IsEmpty()) {
24    if (browser_->is_type_tabbed()) {
25      GetTabbedBrowserBoundsAsh(bounds, show_state);
26      determined = true;
27    } else if (browser_->is_trusted_source()) {
28      // For trusted popups (v1 apps and system windows), do not use the last
29      // active window bounds, only use saved or default bounds.
30      if (!GetSavedWindowBounds(bounds, show_state))
31        GetDefaultWindowBounds(GetTargetDisplay(gfx::Rect()), bounds);
32      determined = true;
33    } else {
34      // In Ash, prioritize the last saved |show_state|. If you have questions
35      // or comments about this behavior please contact oshima@chromium.org.
36      if (state_provider_) {
37        gfx::Rect ignored_bounds, ignored_work_area;
38        state_provider_->GetPersistentState(&ignored_bounds,
39                                            &ignored_work_area,
40                                            show_state);
41      }
42    }
43  } else if (browser_->is_type_popup() && bounds->origin().IsOrigin()) {
44    // In case of a popup with an 'unspecified' location in ash, we are
45    // looking for a good screen location. We are interpreting (0,0) as an
46    // unspecified location.
47    *bounds = ash::Shell::GetInstance()->window_positioner()->
48        GetPopupPosition(*bounds);
49    determined = true;
50  }
51
52  if (browser_->is_type_tabbed() && *show_state == ui::SHOW_STATE_DEFAULT) {
53    gfx::Display display = screen_->GetDisplayMatching(*bounds);
54    gfx::Rect work_area = display.work_area();
55    bounds->AdjustToFit(work_area);
56    if (*bounds == work_area) {
57      // A |browser_| that occupies the whole work area gets maximized.
58      // |bounds| returned here become the restore bounds once the window
59      // gets maximized after this method returns. Return a sensible default
60      // in order to make restored state visibly different from maximized.
61      *show_state = ui::SHOW_STATE_MAXIMIZED;
62      *bounds = ash::WindowPositioner::GetDefaultWindowBounds(display);
63      determined = true;
64    }
65  }
66  return determined;
67}
68
69void WindowSizer::GetTabbedBrowserBoundsAsh(
70    gfx::Rect* bounds_in_screen,
71    ui::WindowShowState* show_state) const {
72  DCHECK(show_state);
73  DCHECK(bounds_in_screen);
74  DCHECK(browser_->is_type_tabbed());
75  DCHECK(bounds_in_screen->IsEmpty());
76
77  ui::WindowShowState passed_show_state = *show_state;
78
79  bool is_saved_bounds = GetSavedWindowBounds(bounds_in_screen, show_state);
80  gfx::Display display;
81  if (is_saved_bounds) {
82    display = screen_->GetDisplayMatching(*bounds_in_screen);
83  } else {
84    // If there is no saved bounds (hence bounds_in_screen is empty), use the
85    // target display.
86    display = target_display_provider_->GetTargetDisplay(screen_,
87                                                         *bounds_in_screen);
88    *bounds_in_screen = ash::WindowPositioner::GetDefaultWindowBounds(display);
89  }
90
91  if (browser_->is_session_restore()) {
92    // This is a fall-through case when there is no bounds recorded
93    // for restored window, and should not be used except for the case
94    // above.  The regular path is handled in
95    // |WindowSizer::DetermineWindowBoundsAndShowState|.
96
97    // Note: How restore bounds/show state data are passed.
98    // The restore bounds is passed via |Browser::override_bounds()| in
99    // |chrome::GetBrowserWindowBoundsAndShowState()|.
100    // The restore state is passed via |Browser::initial_state()| in
101    // |WindowSizer::GetWindowDefaultShowState|.
102    bounds_in_screen->AdjustToFit(display.work_area());
103    return;
104  }
105
106  // The |browser_window| is non NULL when this is called after
107  // browser's aura window is created.
108  aura::Window* browser_window =
109      browser_->window() ? browser_->window()->GetNativeWindow() : NULL;
110
111  ash::WindowPositioner::GetBoundsAndShowStateForNewWindow(
112      screen_,
113      browser_window,
114      is_saved_bounds,
115      passed_show_state,
116      bounds_in_screen,
117      show_state);
118}
119