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#ifndef CHROME_BROWSER_UI_WINDOW_SIZER_WINDOW_SIZER_H_
6#define CHROME_BROWSER_UI_WINDOW_SIZER_WINDOW_SIZER_H_
7
8#include "base/basictypes.h"
9#include "base/memory/scoped_ptr.h"
10#include "chrome/browser/ui/host_desktop.h"
11#include "ui/base/ui_base_types.h"
12#include "ui/gfx/rect.h"
13
14class Browser;
15
16namespace gfx {
17class Display;
18class Screen;
19}
20
21///////////////////////////////////////////////////////////////////////////////
22// WindowSizer
23//
24//  A class that determines the best new size and position for a window to be
25//  shown at based several factors, including the position and size of the last
26//  window of the same type, the last saved bounds of the window from the
27//  previous session, and default system metrics if neither of the above two
28//  conditions exist. The system has built-in providers for monitor metrics
29//  and persistent storage (using preferences) but can be overrided with mocks
30//  for testing.
31//
32class WindowSizer {
33 public:
34  class StateProvider;
35  class TargetDisplayProvider;
36
37  // WindowSizer owns |state_provider| and |target_display_provider|,
38  // and will use the platforms's gfx::Screen.
39  WindowSizer(scoped_ptr<StateProvider> state_provider,
40              scoped_ptr<TargetDisplayProvider> target_display_provider,
41              const Browser* browser);
42
43  // WindowSizer owns |state_provider| and |target_display_provider|,
44  // and will use the supplied |screen|. Used only for testing.
45  WindowSizer(scoped_ptr<StateProvider> state_provider,
46              scoped_ptr<TargetDisplayProvider> target_display_provider,
47              gfx::Screen* screen,
48              const Browser* browser);
49
50  virtual ~WindowSizer();
51
52  // An interface implemented by an object that can retrieve state from either a
53  // persistent store or an existing window.
54  class StateProvider {
55   public:
56    virtual ~StateProvider() {}
57
58    // Retrieve the persisted bounds of the window. Returns true if there was
59    // persisted data to retrieve state information, false otherwise.
60    // The |show_state| variable will only be touched if there was persisted
61    // data and the |show_state| variable is SHOW_STATE_DEFAULT.
62    virtual bool GetPersistentState(gfx::Rect* bounds,
63                                    gfx::Rect* work_area,
64                                    ui::WindowShowState* show_state) const = 0;
65
66    // Retrieve the bounds of the most recent window of the matching type.
67    // Returns true if there was a last active window to retrieve state
68    // information from, false otherwise.
69    // The |show_state| variable will only be touched if we have found a
70    // suitable window and the |show_state| variable is SHOW_STATE_DEFAULT.
71    virtual bool GetLastActiveWindowState(
72        gfx::Rect* bounds,
73        ui::WindowShowState* show_state) const = 0;
74  };
75
76  // An interface implemented by an object to identify on which
77  // display a new window should be located.
78  class TargetDisplayProvider {
79    public:
80      virtual ~TargetDisplayProvider() {}
81      virtual gfx::Display GetTargetDisplay(const gfx::Screen* screen,
82                                            const gfx::Rect& bounds) const = 0;
83  };
84
85  // Determines the position and size for a window as it is created as well
86  // as the initial state. This function uses several strategies to figure out
87  // optimal size and placement, first looking for an existing active window,
88  // then falling back to persisted data from a previous session, finally
89  // utilizing a default algorithm. If |specified_bounds| are non-empty, this
90  // value is returned instead. For use only in testing.
91  // |show_state| will be overwritten and return the initial visual state of
92  // the window to use.
93  void DetermineWindowBoundsAndShowState(
94      const gfx::Rect& specified_bounds,
95      gfx::Rect* bounds,
96      ui::WindowShowState* show_state) const;
97
98  // Determines the size, position and maximized state for the browser window.
99  // See documentation for DetermineWindowBounds above. Normally,
100  // |window_bounds| is calculated by calling GetLastActiveWindowState(). To
101  // explicitly specify a particular window to base the bounds on, pass in a
102  // non-NULL value for |browser|.
103  static void GetBrowserWindowBoundsAndShowState(
104      const std::string& app_name,
105      const gfx::Rect& specified_bounds,
106      const Browser* browser,
107      gfx::Rect* window_bounds,
108      ui::WindowShowState* show_state);
109
110  // Returns the default origin for popups of the given size.
111  static gfx::Point GetDefaultPopupOrigin(const gfx::Size& size,
112                                          chrome::HostDesktopType type);
113
114  // How much horizontal and vertical offset there is between newly
115  // opened windows.  This value may be different on each platform.
116  static const int kWindowTilePixels;
117
118 private:
119  // The edge of the screen to check for out-of-bounds.
120  enum Edge { TOP, LEFT, BOTTOM, RIGHT };
121
122  // Gets the size and placement of the last active window. Returns true if this
123  // data is valid, false if there is no last window and the application should
124  // restore saved state from preferences using RestoreWindowPosition.
125  // |show_state| will only be changed if it was set to SHOW_STATE_DEFAULT.
126  bool GetLastActiveWindowBounds(gfx::Rect* bounds,
127                                 ui::WindowShowState* show_state) const;
128
129  // Gets the size and placement of the last window in the last session, saved
130  // in local state preferences. Returns true if local state exists containing
131  // this information, false if this information does not exist and a default
132  // size should be used.
133  // |show_state| will only be changed if it was set to SHOW_STATE_DEFAULT.
134  bool GetSavedWindowBounds(gfx::Rect* bounds,
135                            ui::WindowShowState* show_state) const;
136
137  // Gets the default window position and size to be shown on
138  // |display| if there is no last window and no saved window
139  // placement in prefs. This function determines the default size
140  // based on monitor size, etc.
141  void GetDefaultWindowBounds(const gfx::Display& display,
142                              gfx::Rect* default_bounds) const;
143
144  // Adjusts |bounds| to be visible on-screen, biased toward the work area of
145  // the |display|.  Despite the name, this doesn't
146  // guarantee the bounds are fully contained within this display's work rect;
147  // it just tried to ensure the edges are visible on _some_ work rect.
148  // If |saved_work_area| is non-empty, it is used to determine whether the
149  // monitor configuration has changed. If it has, bounds are repositioned and
150  // resized if necessary to make them completely contained in the current work
151  // area.
152  void AdjustBoundsToBeVisibleOnDisplay(
153      const gfx::Display& display,
154      const gfx::Rect& saved_work_area,
155      gfx::Rect* bounds) const;
156
157  // Determine the target display for a new window based on
158  // |bounds|. On ash environment, this returns the display containing
159  // ash's the target root window.
160  gfx::Display GetTargetDisplay(const gfx::Rect& bounds) const;
161
162#if defined(USE_ASH)
163  // Ash specific logic for window placement. Returns true if |bounds| and
164  // |show_state| have been fully determined, otherwise returns false (but
165  // may still affect |show_state|).
166  // If the window is too big to fit in the display work area then the |bounds|
167  // are adjusted to default bounds and the |show_state| is adjusted to
168  // SHOW_STATE_MAXIMIZED.
169  bool GetBrowserBoundsAsh(gfx::Rect* bounds,
170                           ui::WindowShowState* show_state) const;
171
172  // Determines the position and size for a tabbed browser window in
173  // ash as it gets created. This will be called before other standard
174  // placement logic. |show_state| will only be changed
175  // if it was set to SHOW_STATE_DEFAULT.
176  void GetTabbedBrowserBoundsAsh(gfx::Rect* bounds,
177                                 ui::WindowShowState* show_state) const;
178#endif
179
180  // Determine the default show state for the window - not looking at other
181  // windows or at persistent information.
182  ui::WindowShowState GetWindowDefaultShowState() const;
183
184  // Providers for persistent storage and monitor metrics.
185  scoped_ptr<StateProvider> state_provider_;
186  scoped_ptr<TargetDisplayProvider> target_display_provider_;
187  gfx::Screen* screen_;  // not owned.
188
189  // Note that this browser handle might be NULL.
190  const Browser* browser_;
191
192  DISALLOW_COPY_AND_ASSIGN(WindowSizer);
193};
194
195#endif  // CHROME_BROWSER_UI_WINDOW_SIZER_WINDOW_SIZER_H_
196