OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/window_sizer/window_sizer.h" | 5 #include "chrome/browser/ui/window_sizer/window_sizer.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
9 #include "base/prefs/pref_service.h" | 9 #include "base/prefs/pref_service.h" |
10 #include "chrome/browser/browser_process.h" | 10 #include "chrome/browser/browser_process.h" |
11 #include "chrome/browser/profiles/profile.h" | 11 #include "chrome/browser/profiles/profile.h" |
12 #include "chrome/browser/ui/browser.h" | 12 #include "chrome/browser/ui/browser.h" |
13 #include "chrome/browser/ui/browser_list.h" | 13 #include "chrome/browser/ui/browser_list.h" |
14 #include "chrome/browser/ui/browser_window.h" | 14 #include "chrome/browser/ui/browser_window.h" |
15 #include "chrome/browser/ui/browser_window_state.h" | 15 #include "chrome/browser/ui/browser_window_state.h" |
16 #include "chrome/browser/ui/host_desktop.h" | 16 #include "chrome/browser/ui/host_desktop.h" |
17 #include "chrome/common/chrome_switches.h" | 17 #include "chrome/common/chrome_switches.h" |
18 #include "chrome/common/pref_names.h" | 18 #include "chrome/common/pref_names.h" |
19 #include "ui/gfx/screen.h" | 19 #include "ui/gfx/screen.h" |
20 | 20 |
21 #if defined(USE_ASH) | 21 #if defined(USE_ASH) |
22 #include "ash/shell.h" | 22 #include "ash/shell.h" |
23 #include "ash/wm/window_positioner.h" | 23 #include "ash/wm/window_positioner.h" |
24 #include "chrome/browser/ui/ash/ash_init.h" | 24 #include "chrome/browser/ui/ash/ash_init.h" |
25 #endif | 25 #endif |
26 | 26 |
| 27 namespace { |
| 28 |
27 // Minimum height of the visible part of a window. | 29 // Minimum height of the visible part of a window. |
28 const int kMinVisibleHeight = 30; | 30 const int kMinVisibleHeight = 30; |
29 // Minimum width of the visible part of a window. | 31 // Minimum width of the visible part of a window. |
30 const int kMinVisibleWidth = 30; | 32 const int kMinVisibleWidth = 30; |
31 | 33 |
32 /////////////////////////////////////////////////////////////////////////////// | 34 /////////////////////////////////////////////////////////////////////////////// |
33 // An implementation of WindowSizer::StateProvider that gets the last active | 35 // An implementation of WindowSizer::StateProvider that gets the last active |
34 // and persistent state from the browser window and the user's profile. | 36 // and persistent state from the browser window and the user's profile. |
35 class DefaultStateProvider : public WindowSizer::StateProvider { | 37 class DefaultStateProvider : public WindowSizer::StateProvider { |
36 public: | 38 public: |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
128 } | 130 } |
129 | 131 |
130 private: | 132 private: |
131 std::string app_name_; | 133 std::string app_name_; |
132 | 134 |
133 // If set, is used as the reference browser for GetLastActiveWindowState. | 135 // If set, is used as the reference browser for GetLastActiveWindowState. |
134 const Browser* browser_; | 136 const Browser* browser_; |
135 DISALLOW_COPY_AND_ASSIGN(DefaultStateProvider); | 137 DISALLOW_COPY_AND_ASSIGN(DefaultStateProvider); |
136 }; | 138 }; |
137 | 139 |
| 140 class DefaultTargetDisplayProvider : public WindowSizer::TargetDisplayProvider { |
| 141 public: |
| 142 DefaultTargetDisplayProvider() {} |
| 143 virtual ~DefaultTargetDisplayProvider() {} |
| 144 |
| 145 virtual gfx::Display GetTargetDisplay( |
| 146 const gfx::Screen* screen, |
| 147 const gfx::Rect& bounds) const OVERRIDE { |
| 148 #if defined(USE_ASH) |
| 149 // Use the target display on ash. |
| 150 if (chrome::ShouldOpenAshOnStartup()) { |
| 151 aura::Window* target = ash::Shell::GetTargetRootWindow(); |
| 152 return screen->GetDisplayNearestWindow(target); |
| 153 } |
| 154 #endif |
| 155 // Find the size of the work area of the monitor that intersects the bounds |
| 156 // of the anchor window. |
| 157 return screen->GetDisplayMatching(bounds); |
| 158 } |
| 159 |
| 160 private: |
| 161 DISALLOW_COPY_AND_ASSIGN(DefaultTargetDisplayProvider); |
| 162 }; |
| 163 |
| 164 } // namespace |
| 165 |
138 /////////////////////////////////////////////////////////////////////////////// | 166 /////////////////////////////////////////////////////////////////////////////// |
139 // WindowSizer, public: | 167 // WindowSizer, public: |
140 | 168 |
141 WindowSizer::WindowSizer(StateProvider* state_provider, const Browser* browser) | 169 WindowSizer::WindowSizer( |
142 : state_provider_(state_provider), | 170 scoped_ptr<StateProvider> state_provider, |
| 171 scoped_ptr<TargetDisplayProvider> target_display_provider, |
| 172 const Browser* browser) |
| 173 : state_provider_(state_provider.Pass()), |
| 174 target_display_provider_(target_display_provider.Pass()), |
143 // TODO(scottmg): NativeScreen is wrong. http://crbug.com/133312 | 175 // TODO(scottmg): NativeScreen is wrong. http://crbug.com/133312 |
144 screen_(gfx::Screen::GetNativeScreen()), | 176 screen_(gfx::Screen::GetNativeScreen()), |
145 browser_(browser) { | 177 browser_(browser) { |
146 } | 178 } |
147 | 179 |
148 WindowSizer::WindowSizer(StateProvider* state_provider, | 180 WindowSizer::WindowSizer( |
149 gfx::Screen* screen, | 181 scoped_ptr<StateProvider> state_provider, |
150 const Browser* browser) | 182 scoped_ptr<TargetDisplayProvider> target_display_provider, |
151 : state_provider_(state_provider), | 183 gfx::Screen* screen, |
| 184 const Browser* browser) |
| 185 : state_provider_(state_provider.Pass()), |
| 186 target_display_provider_(target_display_provider.Pass()), |
152 screen_(screen), | 187 screen_(screen), |
153 browser_(browser) { | 188 browser_(browser) { |
154 DCHECK(screen_); | 189 DCHECK(screen_); |
155 } | 190 } |
156 | 191 |
157 WindowSizer::~WindowSizer() { | 192 WindowSizer::~WindowSizer() { |
158 } | 193 } |
159 | 194 |
160 // static | 195 // static |
161 void WindowSizer::GetBrowserWindowBoundsAndShowState( | 196 void WindowSizer::GetBrowserWindowBoundsAndShowState( |
162 const std::string& app_name, | 197 const std::string& app_name, |
163 const gfx::Rect& specified_bounds, | 198 const gfx::Rect& specified_bounds, |
164 const Browser* browser, | 199 const Browser* browser, |
165 gfx::Rect* window_bounds, | 200 gfx::Rect* window_bounds, |
166 ui::WindowShowState* show_state) { | 201 ui::WindowShowState* show_state) { |
167 const WindowSizer sizer(new DefaultStateProvider(app_name, browser), browser); | 202 scoped_ptr<StateProvider> state_provider( |
| 203 new DefaultStateProvider(app_name, browser)); |
| 204 scoped_ptr<TargetDisplayProvider> target_display_provider( |
| 205 new DefaultTargetDisplayProvider); |
| 206 const WindowSizer sizer(state_provider.Pass(), |
| 207 target_display_provider.Pass(), |
| 208 browser); |
168 sizer.DetermineWindowBoundsAndShowState(specified_bounds, | 209 sizer.DetermineWindowBoundsAndShowState(specified_bounds, |
169 window_bounds, | 210 window_bounds, |
170 show_state); | 211 show_state); |
171 } | 212 } |
172 | 213 |
173 /////////////////////////////////////////////////////////////////////////////// | 214 /////////////////////////////////////////////////////////////////////////////// |
174 // WindowSizer, private: | 215 // WindowSizer, private: |
175 | 216 |
176 void WindowSizer::DetermineWindowBoundsAndShowState( | 217 void WindowSizer::DetermineWindowBoundsAndShowState( |
177 const gfx::Rect& specified_bounds, | 218 const gfx::Rect& specified_bounds, |
(...skipping 11 matching lines...) Expand all Loading... |
189 GetTabbedBrowserBoundsAsh(bounds, show_state); | 230 GetTabbedBrowserBoundsAsh(bounds, show_state); |
190 return; | 231 return; |
191 } else if (browser_ && browser_->host_desktop_type() == | 232 } else if (browser_ && browser_->host_desktop_type() == |
192 chrome::HOST_DESKTOP_TYPE_ASH) { | 233 chrome::HOST_DESKTOP_TYPE_ASH) { |
193 // In ash, saved show state takes precidence. If you have a | 234 // In ash, saved show state takes precidence. If you have a |
194 // question or an issue, please contact oshima@chromium.org. | 235 // question or an issue, please contact oshima@chromium.org. |
195 GetSavedWindowBounds(bounds, show_state); | 236 GetSavedWindowBounds(bounds, show_state); |
196 } | 237 } |
197 #endif | 238 #endif |
198 // See if there's last active window's placement information. | 239 // See if there's last active window's placement information. |
199 if (GetLastWindowBounds(bounds, show_state)) | 240 if (GetLastActiveWindowBounds(bounds, show_state)) |
200 return; | 241 return; |
201 // See if there's saved placement information. | 242 // See if there's saved placement information. |
202 if (GetSavedWindowBounds(bounds, show_state)) | 243 if (GetSavedWindowBounds(bounds, show_state)) |
203 return; | 244 return; |
204 // No saved placement, figure out some sensible default size based on | 245 // No saved placement, figure out some sensible default size based on |
205 // the user's screen size. | 246 // the user's screen size. |
206 GetDefaultWindowBounds(screen_->GetPrimaryDisplay(), bounds); | 247 GetDefaultWindowBounds(GetTargetDisplay(gfx::Rect()), bounds); |
207 } else { | 248 } else { |
208 #if defined(USE_ASH) | 249 #if defined(USE_ASH) |
209 // In case of a popup with an 'unspecified' location in ash, we are | 250 // In case of a popup with an 'unspecified' location in ash, we are |
210 // looking for a good screen location. We are interpreting (0,0) as an | 251 // looking for a good screen location. We are interpreting (0,0) as an |
211 // unspecified location. | 252 // unspecified location. |
212 if (IsPopupBrowserInAsh() && bounds->origin().IsOrigin()) { | 253 if (IsPopupBrowserInAsh() && bounds->origin().IsOrigin()) { |
213 *bounds = ash::Shell::GetInstance()->window_positioner()-> | 254 *bounds = ash::Shell::GetInstance()->window_positioner()-> |
214 GetPopupPosition(*bounds); | 255 GetPopupPosition(*bounds); |
215 return; | 256 return; |
216 } | 257 } |
217 #endif | 258 #endif |
218 // In case that there was a bound given we need to make sure that it is | 259 // In case that there was a bound given we need to make sure that it is |
219 // visible and fits on the screen. | 260 // visible and fits on the screen. |
220 // Find the size of the work area of the monitor that intersects the bounds | 261 // Find the size of the work area of the monitor that intersects the bounds |
221 // of the anchor window. Note: AdjustBoundsToBeVisibleOnMonitorContaining | 262 // of the anchor window. Note: AdjustBoundsToBeVisibleOnMonitorContaining |
222 // does not exactly what we want: It makes only sure that "a minimal part" | 263 // does not exactly what we want: It makes only sure that "a minimal part" |
223 // is visible on the screen. | 264 // is visible on the screen. |
224 gfx::Rect work_area = screen_->GetDisplayMatching(*bounds).work_area(); | 265 gfx::Rect work_area = screen_->GetDisplayMatching(*bounds).work_area(); |
225 // Resize so that it fits. | 266 // Resize so that it fits. |
226 bounds->AdjustToFit(work_area); | 267 bounds->AdjustToFit(work_area); |
227 } | 268 } |
228 } | 269 } |
229 | 270 |
230 bool WindowSizer::GetLastWindowBounds(gfx::Rect* bounds, | 271 bool WindowSizer::GetLastActiveWindowBounds( |
231 ui::WindowShowState* show_state) const { | 272 gfx::Rect* bounds, |
| 273 ui::WindowShowState* show_state) const { |
232 DCHECK(bounds); | 274 DCHECK(bounds); |
233 DCHECK(show_state); | 275 DCHECK(show_state); |
234 if (!state_provider_.get() || | 276 if (!state_provider_.get() || |
235 !state_provider_->GetLastActiveWindowState(bounds, show_state)) | 277 !state_provider_->GetLastActiveWindowState(bounds, show_state)) |
236 return false; | 278 return false; |
237 gfx::Rect last_window_bounds = *bounds; | 279 gfx::Rect last_window_bounds = *bounds; |
238 bounds->Offset(kWindowTilePixels, kWindowTilePixels); | 280 bounds->Offset(kWindowTilePixels, kWindowTilePixels); |
239 AdjustBoundsToBeVisibleOnMonitorContaining(last_window_bounds, | 281 AdjustBoundsToBeVisibleOnDisplay(screen_->GetDisplayMatching(*bounds), |
240 gfx::Rect(), | 282 gfx::Rect(), |
241 bounds); | 283 bounds); |
242 return true; | 284 return true; |
243 } | 285 } |
244 | 286 |
245 bool WindowSizer::GetSavedWindowBounds(gfx::Rect* bounds, | 287 bool WindowSizer::GetSavedWindowBounds(gfx::Rect* bounds, |
246 ui::WindowShowState* show_state) const { | 288 ui::WindowShowState* show_state) const { |
247 DCHECK(bounds); | 289 DCHECK(bounds); |
248 DCHECK(show_state); | 290 DCHECK(show_state); |
249 gfx::Rect saved_work_area; | 291 gfx::Rect saved_work_area; |
250 if (!state_provider_.get() || | 292 if (!state_provider_.get() || |
251 !state_provider_->GetPersistentState(bounds, | 293 !state_provider_->GetPersistentState(bounds, |
252 &saved_work_area, | 294 &saved_work_area, |
253 show_state)) | 295 show_state)) |
254 return false; | 296 return false; |
255 AdjustBoundsToBeVisibleOnMonitorContaining(*bounds, saved_work_area, bounds); | 297 AdjustBoundsToBeVisibleOnDisplay(GetTargetDisplay(*bounds), |
| 298 saved_work_area, |
| 299 bounds); |
256 return true; | 300 return true; |
257 } | 301 } |
258 | 302 |
259 void WindowSizer::GetDefaultWindowBounds(const gfx::Display& display, | 303 void WindowSizer::GetDefaultWindowBounds(const gfx::Display& display, |
260 gfx::Rect* default_bounds) const { | 304 gfx::Rect* default_bounds) const { |
261 DCHECK(default_bounds); | 305 DCHECK(default_bounds); |
262 #if defined(USE_ASH) | 306 #if defined(USE_ASH) |
263 // TODO(beng): insufficient but currently necessary. http://crbug.com/133312 | 307 // TODO(beng): insufficient but currently necessary. http://crbug.com/133312 |
264 if (chrome::ShouldOpenAshOnStartup()) { | 308 if (chrome::ShouldOpenAshOnStartup()) { |
265 *default_bounds = ash::WindowPositioner::GetDefaultWindowBounds( | 309 *default_bounds = ash::WindowPositioner::GetDefaultWindowBounds(display); |
266 display); | |
267 return; | 310 return; |
268 } | 311 } |
269 #endif | 312 #endif |
270 gfx::Rect work_area = display.work_area(); | 313 gfx::Rect work_area = display.work_area(); |
271 | 314 |
272 // The default size is either some reasonably wide width, or if the work | 315 // The default size is either some reasonably wide width, or if the work |
273 // area is narrower, then the work area width less some aesthetic padding. | 316 // area is narrower, then the work area width less some aesthetic padding. |
274 int default_width = std::min(work_area.width() - 2 * kWindowTilePixels, 1050); | 317 int default_width = std::min(work_area.width() - 2 * kWindowTilePixels, 1050); |
275 int default_height = work_area.height() - 2 * kWindowTilePixels; | 318 int default_height = work_area.height() - 2 * kWindowTilePixels; |
276 | 319 |
(...skipping 13 matching lines...) Expand all Loading... |
290 // The padding is set so that two windows, side by side have | 333 // The padding is set so that two windows, side by side have |
291 // kWindowTilePixels between screen edge and each other. | 334 // kWindowTilePixels between screen edge and each other. |
292 default_width = static_cast<int>(work_area.width() / 2. - | 335 default_width = static_cast<int>(work_area.width() / 2. - |
293 1.5 * kWindowTilePixels); | 336 1.5 * kWindowTilePixels); |
294 } | 337 } |
295 default_bounds->SetRect(kWindowTilePixels + work_area.x(), | 338 default_bounds->SetRect(kWindowTilePixels + work_area.x(), |
296 kWindowTilePixels + work_area.y(), | 339 kWindowTilePixels + work_area.y(), |
297 default_width, default_height); | 340 default_width, default_height); |
298 } | 341 } |
299 | 342 |
300 void WindowSizer::AdjustBoundsToBeVisibleOnMonitorContaining( | 343 void WindowSizer::AdjustBoundsToBeVisibleOnDisplay( |
301 const gfx::Rect& other_bounds, | 344 const gfx::Display& display, |
302 const gfx::Rect& saved_work_area, | 345 const gfx::Rect& saved_work_area, |
303 gfx::Rect* bounds) const { | 346 gfx::Rect* bounds) const { |
304 DCHECK(bounds); | 347 DCHECK(bounds); |
305 | 348 |
306 // Find the size of the work area of the monitor that intersects the bounds | 349 // If |bounds| is empty, reset to the default size. |
307 // of the anchor window. | 350 if (bounds->IsEmpty()) { |
308 gfx::Display display = screen_->GetDisplayMatching(other_bounds); | 351 gfx::Rect default_bounds; |
309 | 352 GetDefaultWindowBounds(display, &default_bounds); |
310 // If height or width are 0, reset to the default size. | 353 if (bounds->height() <= 0) |
311 gfx::Rect default_bounds; | 354 bounds->set_height(default_bounds.height()); |
312 GetDefaultWindowBounds(display, &default_bounds); | 355 if (bounds->width() <= 0) |
313 if (bounds->height() <= 0) | 356 bounds->set_width(default_bounds.width()); |
314 bounds->set_height(default_bounds.height()); | 357 } |
315 if (bounds->width() <= 0) | |
316 bounds->set_width(default_bounds.width()); | |
317 | 358 |
318 // Ensure the minimum height and width. | 359 // Ensure the minimum height and width. |
319 bounds->set_height(std::max(kMinVisibleHeight, bounds->height())); | 360 bounds->set_height(std::max(kMinVisibleHeight, bounds->height())); |
320 bounds->set_width(std::max(kMinVisibleWidth, bounds->width())); | 361 bounds->set_width(std::max(kMinVisibleWidth, bounds->width())); |
321 | 362 |
322 gfx::Rect work_area = display.work_area(); | 363 gfx::Rect work_area = display.work_area(); |
323 // Ensure that the title bar is not above the work area. | 364 // Ensure that the title bar is not above the work area. |
324 if (bounds->y() < work_area.y()) | 365 if (bounds->y() < work_area.y()) |
325 bounds->set_y(work_area.y()); | 366 bounds->set_y(work_area.y()); |
326 | 367 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 // ensure that at least kMinVisibleWidth * kMinVisibleHeight is visible. | 404 // ensure that at least kMinVisibleWidth * kMinVisibleHeight is visible. |
364 const int min_y = work_area.y() + kMinVisibleHeight - bounds->height(); | 405 const int min_y = work_area.y() + kMinVisibleHeight - bounds->height(); |
365 const int min_x = work_area.x() + kMinVisibleWidth - bounds->width(); | 406 const int min_x = work_area.x() + kMinVisibleWidth - bounds->width(); |
366 const int max_y = work_area.bottom() - kMinVisibleHeight; | 407 const int max_y = work_area.bottom() - kMinVisibleHeight; |
367 const int max_x = work_area.right() - kMinVisibleWidth; | 408 const int max_x = work_area.right() - kMinVisibleWidth; |
368 bounds->set_y(std::max(min_y, std::min(max_y, bounds->y()))); | 409 bounds->set_y(std::max(min_y, std::min(max_y, bounds->y()))); |
369 bounds->set_x(std::max(min_x, std::min(max_x, bounds->x()))); | 410 bounds->set_x(std::max(min_x, std::min(max_x, bounds->x()))); |
370 #endif // defined(OS_MACOSX) | 411 #endif // defined(OS_MACOSX) |
371 } | 412 } |
372 | 413 |
| 414 gfx::Display WindowSizer::GetTargetDisplay(const gfx::Rect& bounds) const { |
| 415 return target_display_provider_->GetTargetDisplay(screen_, bounds); |
| 416 } |
| 417 |
373 ui::WindowShowState WindowSizer::GetWindowDefaultShowState() const { | 418 ui::WindowShowState WindowSizer::GetWindowDefaultShowState() const { |
374 if (!browser_) | 419 if (!browser_) |
375 return ui::SHOW_STATE_DEFAULT; | 420 return ui::SHOW_STATE_DEFAULT; |
376 | 421 |
377 // Only tabbed browsers use the command line or preference state, with the | 422 // Only tabbed browsers use the command line or preference state, with the |
378 // exception of devtools. | 423 // exception of devtools. |
379 bool show_state = !browser_->is_type_tabbed() && !browser_->is_devtools(); | 424 bool show_state = !browser_->is_type_tabbed() && !browser_->is_devtools(); |
380 | 425 |
381 #if defined(USE_AURA) | 426 #if defined(USE_AURA) |
382 // We use the apps save state on aura. | 427 // We use the apps save state on aura. |
(...skipping 19 matching lines...) Expand all Loading... |
402 browser_->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH && | 447 browser_->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH && |
403 browser_->is_type_tabbed(); | 448 browser_->is_type_tabbed(); |
404 } | 449 } |
405 | 450 |
406 bool WindowSizer::IsPopupBrowserInAsh() const { | 451 bool WindowSizer::IsPopupBrowserInAsh() const { |
407 return browser_ && | 452 return browser_ && |
408 browser_->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH && | 453 browser_->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH && |
409 browser_->is_type_popup(); | 454 browser_->is_type_popup(); |
410 } | 455 } |
411 #endif | 456 #endif |
OLD | NEW |