Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: chrome/browser/ui/window_sizer.cc

Issue 10704022: browser: Move window sizer to subdir. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/ui/window_sizer.h ('k') | chrome/browser/ui/window_sizer/window_sizer.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.h"
6
7 #include "base/compiler_specific.h"
8 #include "chrome/browser/browser_process.h"
9 #include "chrome/browser/prefs/pref_service.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/ui/ash/ash_init.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/browser_list.h"
14 #include "chrome/browser/ui/browser_window.h"
15 #include "chrome/browser/ui/browser_window_state.h"
16 #include "chrome/common/pref_names.h"
17 #include "ui/gfx/screen.h"
18
19 // Minimum height of the visible part of a window.
20 const int kMinVisibleHeight = 30;
21 // Minimum width of the visible part of a window.
22 const int kMinVisibleWidth = 30;
23
24 class DefaultMonitorInfoProvider : public MonitorInfoProvider {
25 public:
26 // Overridden from MonitorInfoProvider:
27 virtual gfx::Rect GetPrimaryDisplayWorkArea() const OVERRIDE {
28 return gfx::Screen::GetPrimaryDisplay().work_area();
29 }
30 virtual gfx::Rect GetPrimaryDisplayBounds() const OVERRIDE {
31 return gfx::Screen::GetPrimaryDisplay().bounds();
32 }
33 virtual gfx::Rect GetMonitorWorkAreaMatching(
34 const gfx::Rect& match_rect) const OVERRIDE {
35 return gfx::Screen::GetDisplayMatching(match_rect).work_area();
36 }
37 };
38
39 ///////////////////////////////////////////////////////////////////////////////
40 // An implementation of WindowSizer::StateProvider that gets the last active
41 // and persistent state from the browser window and the user's profile.
42 class DefaultStateProvider : public WindowSizer::StateProvider {
43 public:
44 DefaultStateProvider(const std::string& app_name, const Browser* browser)
45 : app_name_(app_name), browser_(browser) {
46 }
47
48 // Overridden from WindowSizer::StateProvider:
49 virtual bool GetPersistentState(gfx::Rect* bounds,
50 gfx::Rect* work_area) const {
51 DCHECK(bounds);
52
53 if (!browser_ || !browser_->profile()->GetPrefs())
54 return false;
55
56 std::string window_name(chrome::GetWindowPlacementKey(browser_));
57 const DictionaryValue* wp_pref =
58 browser_->profile()->GetPrefs()->GetDictionary(window_name.c_str());
59 int top = 0, left = 0, bottom = 0, right = 0;
60 bool has_prefs = wp_pref &&
61 wp_pref->GetInteger("top", &top) &&
62 wp_pref->GetInteger("left", &left) &&
63 wp_pref->GetInteger("bottom", &bottom) &&
64 wp_pref->GetInteger("right", &right);
65 bounds->SetRect(left, top, std::max(0, right - left),
66 std::max(0, bottom - top));
67
68 int work_area_top = 0;
69 int work_area_left = 0;
70 int work_area_bottom = 0;
71 int work_area_right = 0;
72 if (wp_pref) {
73 wp_pref->GetInteger("work_area_top", &work_area_top);
74 wp_pref->GetInteger("work_area_left", &work_area_left);
75 wp_pref->GetInteger("work_area_bottom", &work_area_bottom);
76 wp_pref->GetInteger("work_area_right", &work_area_right);
77 }
78 work_area->SetRect(work_area_left, work_area_top,
79 std::max(0, work_area_right - work_area_left),
80 std::max(0, work_area_bottom - work_area_top));
81
82 return has_prefs;
83 }
84
85 virtual bool GetLastActiveWindowState(gfx::Rect* bounds) const {
86 // Applications are always restored with the same position.
87 if (!app_name_.empty())
88 return false;
89
90 // If a reference browser is set, use its window. Otherwise find last
91 // active. Panels are never used as reference browsers as panels are
92 // specially positioned.
93 BrowserWindow* window = NULL;
94 // Window may be null if browser is just starting up.
95 if (browser_ && browser_->window() && !browser_->window()->IsPanel()) {
96 window = browser_->window();
97 } else {
98 BrowserList::const_reverse_iterator it = BrowserList::begin_last_active();
99 BrowserList::const_reverse_iterator end = BrowserList::end_last_active();
100 for (; (it != end); ++it) {
101 Browser* last_active = *it;
102 if (last_active && last_active->is_type_tabbed()) {
103 window = last_active->window();
104 DCHECK(window);
105 break;
106 }
107 }
108 }
109
110 if (window) {
111 *bounds = window->GetRestoredBounds();
112 return true;
113 }
114
115 return false;
116 }
117
118 private:
119 std::string app_name_;
120
121 // If set, is used as the reference browser for GetLastActiveWindowState.
122 const Browser* browser_;
123 DISALLOW_COPY_AND_ASSIGN(DefaultStateProvider);
124 };
125
126 ///////////////////////////////////////////////////////////////////////////////
127 // WindowSizer, public:
128
129 // The number of pixels which are kept free top, left and right when a window
130 // gets positioned to its default location.
131 const int WindowSizer::kDesktopBorderSize = 16;
132
133 WindowSizer::WindowSizer(StateProvider* state_provider, const Browser* browser)
134 : state_provider_(state_provider),
135 monitor_info_provider_(new DefaultMonitorInfoProvider),
136 browser_(browser) {
137 }
138
139 WindowSizer::WindowSizer(StateProvider* state_provider,
140 MonitorInfoProvider* monitor_info_provider,
141 const Browser* browser)
142 : state_provider_(state_provider),
143 monitor_info_provider_(monitor_info_provider),
144 browser_(browser) {
145 }
146
147 WindowSizer::~WindowSizer() {
148 }
149
150 // static
151 void WindowSizer::GetBrowserWindowBounds(const std::string& app_name,
152 const gfx::Rect& specified_bounds,
153 const Browser* browser,
154 gfx::Rect* window_bounds) {
155 const WindowSizer sizer(new DefaultStateProvider(app_name, browser), browser);
156 sizer.DetermineWindowBounds(specified_bounds, window_bounds);
157 }
158
159 ///////////////////////////////////////////////////////////////////////////////
160 // WindowSizer, private:
161
162 void WindowSizer::DetermineWindowBounds(const gfx::Rect& specified_bounds,
163 gfx::Rect* bounds) const {
164 *bounds = specified_bounds;
165 if (bounds->IsEmpty()) {
166 if (GetBoundsIgnoringPreviousState(specified_bounds, bounds))
167 return;
168 // See if there's saved placement information.
169 if (!GetLastWindowBounds(bounds)) {
170 if (!GetSavedWindowBounds(bounds)) {
171 // No saved placement, figure out some sensible default size based on
172 // the user's screen size.
173 GetDefaultWindowBounds(bounds);
174 }
175 }
176 } else {
177 // In case that there was a bound given we need to make sure that it is
178 // visible and fits on the screen.
179 // Find the size of the work area of the monitor that intersects the bounds
180 // of the anchor window. Note: AdjustBoundsToBeVisibleOnMonitorContaining
181 // does not exactly what we want: It makes only sure that "a minimal part"
182 // is visible on the screen.
183 gfx::Rect work_area =
184 monitor_info_provider_->GetMonitorWorkAreaMatching(*bounds);
185 // Resize so that it fits.
186 *bounds = bounds->AdjustToFit(work_area);
187 }
188 }
189
190 bool WindowSizer::GetLastWindowBounds(gfx::Rect* bounds) const {
191 DCHECK(bounds);
192 if (!state_provider_.get() ||
193 !state_provider_->GetLastActiveWindowState(bounds))
194 return false;
195 gfx::Rect last_window_bounds = *bounds;
196 bounds->Offset(kWindowTilePixels, kWindowTilePixels);
197 AdjustBoundsToBeVisibleOnMonitorContaining(last_window_bounds,
198 gfx::Rect(),
199 bounds);
200 return true;
201 }
202
203 bool WindowSizer::GetSavedWindowBounds(gfx::Rect* bounds) const {
204 DCHECK(bounds);
205 gfx::Rect saved_work_area;
206 if (!state_provider_.get() ||
207 !state_provider_->GetPersistentState(bounds, &saved_work_area))
208 return false;
209 AdjustBoundsToBeVisibleOnMonitorContaining(*bounds, saved_work_area, bounds);
210 return true;
211 }
212
213 void WindowSizer::GetDefaultWindowBounds(gfx::Rect* default_bounds) const {
214 #if defined(USE_ASH)
215 // TODO(beng): insufficient but currently necessary. http://crbug.com/133312
216 if (chrome::ShouldOpenAshOnStartup()) {
217 GetDefaultWindowBoundsAsh(default_bounds);
218 return;
219 }
220 #endif
221 DCHECK(default_bounds);
222 DCHECK(monitor_info_provider_.get());
223
224 gfx::Rect work_area = monitor_info_provider_->GetPrimaryDisplayWorkArea();
225
226 // The default size is either some reasonably wide width, or if the work
227 // area is narrower, then the work area width less some aesthetic padding.
228 int default_width = std::min(work_area.width() - 2 * kWindowTilePixels, 1050);
229 int default_height = work_area.height() - 2 * kWindowTilePixels;
230
231 // For wider aspect ratio displays at higher resolutions, we might size the
232 // window narrower to allow two windows to easily be placed side-by-side.
233 gfx::Rect screen_size = monitor_info_provider_->GetPrimaryDisplayBounds();
234 double width_to_height =
235 static_cast<double>(screen_size.width()) / screen_size.height();
236
237 // The least wide a screen can be to qualify for the halving described above.
238 static const int kMinScreenWidthForWindowHalving = 1600;
239 // We assume 16:9/10 is a fairly standard indicator of a wide aspect ratio
240 // computer display.
241 if (((width_to_height * 10) >= 16) &&
242 work_area.width() > kMinScreenWidthForWindowHalving) {
243 // Halve the work area, subtracting aesthetic padding on either side.
244 // The padding is set so that two windows, side by side have
245 // kWindowTilePixels between screen edge and each other.
246 default_width = static_cast<int>(work_area.width() / 2. -
247 1.5 * kWindowTilePixels);
248 }
249 default_bounds->SetRect(kWindowTilePixels + work_area.x(),
250 kWindowTilePixels + work_area.y(),
251 default_width, default_height);
252 }
253
254 void WindowSizer::AdjustBoundsToBeVisibleOnMonitorContaining(
255 const gfx::Rect& other_bounds,
256 const gfx::Rect& saved_work_area,
257 gfx::Rect* bounds) const {
258 DCHECK(bounds);
259 DCHECK(monitor_info_provider_.get());
260
261 // Find the size of the work area of the monitor that intersects the bounds
262 // of the anchor window.
263 gfx::Rect work_area =
264 monitor_info_provider_->GetMonitorWorkAreaMatching(other_bounds);
265
266 // If height or width are 0, reset to the default size.
267 gfx::Rect default_bounds;
268 GetDefaultWindowBounds(&default_bounds);
269 if (bounds->height() <= 0)
270 bounds->set_height(default_bounds.height());
271 if (bounds->width() <= 0)
272 bounds->set_width(default_bounds.width());
273
274 // Ensure the minimum height and width.
275 bounds->set_height(std::max(kMinVisibleHeight, bounds->height()));
276 bounds->set_width(std::max(kMinVisibleWidth, bounds->width()));
277
278 // Ensure that the title bar is not above the work area.
279 if (bounds->y() < work_area.y())
280 bounds->set_y(work_area.y());
281
282 // Reposition and resize the bounds if the saved_work_area is different from
283 // the current work area and the current work area doesn't completely contain
284 // the bounds.
285 if (!saved_work_area.IsEmpty() &&
286 saved_work_area != work_area &&
287 !work_area.Contains(*bounds)) {
288 bounds->set_width(std::min(bounds->width(), work_area.width()));
289 bounds->set_height(std::min(bounds->height(), work_area.height()));
290 bounds->set_x(
291 std::max(work_area.x(),
292 std::min(bounds->x(), work_area.right() - bounds->width())));
293 bounds->set_y(
294 std::max(work_area.y(),
295 std::min(bounds->y(), work_area.bottom() - bounds->height())));
296 }
297
298 #if defined(OS_MACOSX)
299 // Limit the maximum height. On the Mac the sizer is on the
300 // bottom-right of the window, and a window cannot be moved "up"
301 // past the menubar. If the window is too tall you'll never be able
302 // to shrink it again. Windows does not have this limitation
303 // (e.g. can be resized from the top).
304 bounds->set_height(std::min(work_area.height(), bounds->height()));
305
306 // On mac, we want to be aggressive about repositioning windows that are
307 // partially offscreen. If the window is partially offscreen horizontally,
308 // move it to be flush with the left edge of the work area.
309 if (bounds->x() < work_area.x() || bounds->right() > work_area.right())
310 bounds->set_x(work_area.x());
311
312 // If the window is partially offscreen vertically, move it to be flush with
313 // the top of the work area.
314 if (bounds->y() < work_area.y() || bounds->bottom() > work_area.bottom())
315 bounds->set_y(work_area.y());
316 #else
317 // On non-Mac platforms, we are less aggressive about repositioning. Simply
318 // ensure that at least kMinVisibleWidth * kMinVisibleHeight is visible.
319 const int min_y = work_area.y() + kMinVisibleHeight - bounds->height();
320 const int min_x = work_area.x() + kMinVisibleWidth - bounds->width();
321 const int max_y = work_area.bottom() - kMinVisibleHeight;
322 const int max_x = work_area.right() - kMinVisibleWidth;
323 bounds->set_y(std::max(min_y, std::min(max_y, bounds->y())));
324 bounds->set_x(std::max(min_x, std::min(max_x, bounds->x())));
325 #endif // defined(OS_MACOSX)
326 }
327
328 bool WindowSizer::GetBoundsIgnoringPreviousState(
329 const gfx::Rect& specified_bounds,
330 gfx::Rect* bounds) const {
331 #if defined(USE_ASH)
332 // TODO(beng): insufficient but currently necessary. http://crbug.com/133312
333 if (chrome::ShouldOpenAshOnStartup())
334 return GetBoundsIgnoringPreviousStateAsh(specified_bounds, bounds);
335 #endif
336 return false;
337 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/window_sizer.h ('k') | chrome/browser/ui/window_sizer/window_sizer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698