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

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

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

Powered by Google App Engine
This is Rietveld 408576698