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 const gfx::Screen* screen_; | |
sky
2013/12/07 00:40:28
I don't think you use this.
oshima
2013/12/07 01:01:38
oops, removed.
| |
162 | |
163 DISALLOW_COPY_AND_ASSIGN(DefaultTargetDisplayProvider); | |
164 }; | |
165 | |
166 } // namespace | |
167 | |
138 /////////////////////////////////////////////////////////////////////////////// | 168 /////////////////////////////////////////////////////////////////////////////// |
139 // WindowSizer, public: | 169 // WindowSizer, public: |
140 | 170 |
141 WindowSizer::WindowSizer(StateProvider* state_provider, const Browser* browser) | 171 WindowSizer::WindowSizer(StateProvider* state_provider, |
172 TargetDisplayProvider* target_display_provider, | |
173 const Browser* browser) | |
142 : state_provider_(state_provider), | 174 : state_provider_(state_provider), |
175 target_display_provider_(target_display_provider), | |
143 // TODO(scottmg): NativeScreen is wrong. http://crbug.com/133312 | 176 // TODO(scottmg): NativeScreen is wrong. http://crbug.com/133312 |
144 screen_(gfx::Screen::GetNativeScreen()), | 177 screen_(gfx::Screen::GetNativeScreen()), |
145 browser_(browser) { | 178 browser_(browser) { |
146 } | 179 } |
147 | 180 |
148 WindowSizer::WindowSizer(StateProvider* state_provider, | 181 WindowSizer::WindowSizer(StateProvider* state_provider, |
182 TargetDisplayProvider* target_display_provider, | |
149 gfx::Screen* screen, | 183 gfx::Screen* screen, |
150 const Browser* browser) | 184 const Browser* browser) |
151 : state_provider_(state_provider), | 185 : state_provider_(state_provider), |
186 target_display_provider_(target_display_provider), | |
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 const WindowSizer sizer(new DefaultStateProvider(app_name, browser), |
203 new DefaultTargetDisplayProvider, | |
204 browser); | |
168 sizer.DetermineWindowBoundsAndShowState(specified_bounds, | 205 sizer.DetermineWindowBoundsAndShowState(specified_bounds, |
169 window_bounds, | 206 window_bounds, |
170 show_state); | 207 show_state); |
171 } | 208 } |
172 | 209 |
173 /////////////////////////////////////////////////////////////////////////////// | 210 /////////////////////////////////////////////////////////////////////////////// |
174 // WindowSizer, private: | 211 // WindowSizer, private: |
175 | 212 |
176 void WindowSizer::DetermineWindowBoundsAndShowState( | 213 void WindowSizer::DetermineWindowBoundsAndShowState( |
177 const gfx::Rect& specified_bounds, | 214 const gfx::Rect& specified_bounds, |
(...skipping 11 matching lines...) Expand all Loading... | |
189 GetTabbedBrowserBoundsAsh(bounds, show_state); | 226 GetTabbedBrowserBoundsAsh(bounds, show_state); |
190 return; | 227 return; |
191 } else if (browser_ && browser_->host_desktop_type() == | 228 } else if (browser_ && browser_->host_desktop_type() == |
192 chrome::HOST_DESKTOP_TYPE_ASH) { | 229 chrome::HOST_DESKTOP_TYPE_ASH) { |
193 // In ash, saved show state takes precidence. If you have a | 230 // In ash, saved show state takes precidence. If you have a |
194 // question or an issue, please contact oshima@chromium.org. | 231 // question or an issue, please contact oshima@chromium.org. |
195 GetSavedWindowBounds(bounds, show_state); | 232 GetSavedWindowBounds(bounds, show_state); |
196 } | 233 } |
197 #endif | 234 #endif |
198 // See if there's last active window's placement information. | 235 // See if there's last active window's placement information. |
199 if (GetLastWindowBounds(bounds, show_state)) | 236 if (GetLastActiveWindowBounds(bounds, show_state)) |
200 return; | 237 return; |
201 // See if there's saved placement information. | 238 // See if there's saved placement information. |
202 if (GetSavedWindowBounds(bounds, show_state)) | 239 if (GetSavedWindowBounds(bounds, show_state)) |
203 return; | 240 return; |
204 // No saved placement, figure out some sensible default size based on | 241 // No saved placement, figure out some sensible default size based on |
205 // the user's screen size. | 242 // the user's screen size. |
206 GetDefaultWindowBounds(screen_->GetPrimaryDisplay(), bounds); | 243 GetDefaultWindowBounds(GetTargetDisplay(gfx::Rect()), bounds); |
207 } else { | 244 } else { |
208 #if defined(USE_ASH) | 245 #if defined(USE_ASH) |
209 // In case of a popup with an 'unspecified' location in ash, we are | 246 // 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 | 247 // looking for a good screen location. We are interpreting (0,0) as an |
211 // unspecified location. | 248 // unspecified location. |
212 if (IsPopupBrowserInAsh() && bounds->origin().IsOrigin()) { | 249 if (IsPopupBrowserInAsh() && bounds->origin().IsOrigin()) { |
213 *bounds = ash::Shell::GetInstance()->window_positioner()-> | 250 *bounds = ash::Shell::GetInstance()->window_positioner()-> |
214 GetPopupPosition(*bounds); | 251 GetPopupPosition(*bounds); |
215 return; | 252 return; |
216 } | 253 } |
217 #endif | 254 #endif |
218 // In case that there was a bound given we need to make sure that it is | 255 // In case that there was a bound given we need to make sure that it is |
219 // visible and fits on the screen. | 256 // visible and fits on the screen. |
220 // Find the size of the work area of the monitor that intersects the bounds | 257 // Find the size of the work area of the monitor that intersects the bounds |
221 // of the anchor window. Note: AdjustBoundsToBeVisibleOnMonitorContaining | 258 // of the anchor window. Note: AdjustBoundsToBeVisibleOnMonitorContaining |
222 // does not exactly what we want: It makes only sure that "a minimal part" | 259 // does not exactly what we want: It makes only sure that "a minimal part" |
223 // is visible on the screen. | 260 // is visible on the screen. |
224 gfx::Rect work_area = screen_->GetDisplayMatching(*bounds).work_area(); | 261 gfx::Rect work_area = screen_->GetDisplayMatching(*bounds).work_area(); |
225 // Resize so that it fits. | 262 // Resize so that it fits. |
226 bounds->AdjustToFit(work_area); | 263 bounds->AdjustToFit(work_area); |
227 } | 264 } |
228 } | 265 } |
229 | 266 |
230 bool WindowSizer::GetLastWindowBounds(gfx::Rect* bounds, | 267 bool WindowSizer::GetLastActiveWindowBounds( |
231 ui::WindowShowState* show_state) const { | 268 gfx::Rect* bounds, |
269 ui::WindowShowState* show_state) const { | |
232 DCHECK(bounds); | 270 DCHECK(bounds); |
233 DCHECK(show_state); | 271 DCHECK(show_state); |
234 if (!state_provider_.get() || | 272 if (!state_provider_.get() || |
235 !state_provider_->GetLastActiveWindowState(bounds, show_state)) | 273 !state_provider_->GetLastActiveWindowState(bounds, show_state)) |
236 return false; | 274 return false; |
237 gfx::Rect last_window_bounds = *bounds; | 275 gfx::Rect last_window_bounds = *bounds; |
238 bounds->Offset(kWindowTilePixels, kWindowTilePixels); | 276 bounds->Offset(kWindowTilePixels, kWindowTilePixels); |
239 AdjustBoundsToBeVisibleOnMonitorContaining(last_window_bounds, | 277 AdjustBoundsToBeVisibleOnDisplay(screen_->GetDisplayMatching(*bounds), |
240 gfx::Rect(), | 278 gfx::Rect(), |
241 bounds); | 279 bounds); |
242 return true; | 280 return true; |
243 } | 281 } |
244 | 282 |
245 bool WindowSizer::GetSavedWindowBounds(gfx::Rect* bounds, | 283 bool WindowSizer::GetSavedWindowBounds(gfx::Rect* bounds, |
246 ui::WindowShowState* show_state) const { | 284 ui::WindowShowState* show_state) const { |
247 DCHECK(bounds); | 285 DCHECK(bounds); |
248 DCHECK(show_state); | 286 DCHECK(show_state); |
249 gfx::Rect saved_work_area; | 287 gfx::Rect saved_work_area; |
250 if (!state_provider_.get() || | 288 if (!state_provider_.get() || |
251 !state_provider_->GetPersistentState(bounds, | 289 !state_provider_->GetPersistentState(bounds, |
252 &saved_work_area, | 290 &saved_work_area, |
253 show_state)) | 291 show_state)) |
254 return false; | 292 return false; |
255 AdjustBoundsToBeVisibleOnMonitorContaining(*bounds, saved_work_area, bounds); | 293 AdjustBoundsToBeVisibleOnDisplay(GetTargetDisplay(*bounds), |
294 saved_work_area, | |
295 bounds); | |
256 return true; | 296 return true; |
257 } | 297 } |
258 | 298 |
259 void WindowSizer::GetDefaultWindowBounds(const gfx::Display& display, | 299 void WindowSizer::GetDefaultWindowBounds(const gfx::Display& display, |
260 gfx::Rect* default_bounds) const { | 300 gfx::Rect* default_bounds) const { |
261 DCHECK(default_bounds); | 301 DCHECK(default_bounds); |
262 #if defined(USE_ASH) | 302 #if defined(USE_ASH) |
263 // TODO(beng): insufficient but currently necessary. http://crbug.com/133312 | 303 // TODO(beng): insufficient but currently necessary. http://crbug.com/133312 |
264 if (chrome::ShouldOpenAshOnStartup()) { | 304 if (chrome::ShouldOpenAshOnStartup()) { |
265 *default_bounds = ash::WindowPositioner::GetDefaultWindowBounds( | 305 *default_bounds = ash::WindowPositioner::GetDefaultWindowBounds(display); |
266 display); | |
267 return; | 306 return; |
268 } | 307 } |
269 #endif | 308 #endif |
270 gfx::Rect work_area = display.work_area(); | 309 gfx::Rect work_area = display.work_area(); |
271 | 310 |
272 // The default size is either some reasonably wide width, or if the work | 311 // 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. | 312 // area is narrower, then the work area width less some aesthetic padding. |
274 int default_width = std::min(work_area.width() - 2 * kWindowTilePixels, 1050); | 313 int default_width = std::min(work_area.width() - 2 * kWindowTilePixels, 1050); |
275 int default_height = work_area.height() - 2 * kWindowTilePixels; | 314 int default_height = work_area.height() - 2 * kWindowTilePixels; |
276 | 315 |
(...skipping 13 matching lines...) Expand all Loading... | |
290 // The padding is set so that two windows, side by side have | 329 // The padding is set so that two windows, side by side have |
291 // kWindowTilePixels between screen edge and each other. | 330 // kWindowTilePixels between screen edge and each other. |
292 default_width = static_cast<int>(work_area.width() / 2. - | 331 default_width = static_cast<int>(work_area.width() / 2. - |
293 1.5 * kWindowTilePixels); | 332 1.5 * kWindowTilePixels); |
294 } | 333 } |
295 default_bounds->SetRect(kWindowTilePixels + work_area.x(), | 334 default_bounds->SetRect(kWindowTilePixels + work_area.x(), |
296 kWindowTilePixels + work_area.y(), | 335 kWindowTilePixels + work_area.y(), |
297 default_width, default_height); | 336 default_width, default_height); |
298 } | 337 } |
299 | 338 |
300 void WindowSizer::AdjustBoundsToBeVisibleOnMonitorContaining( | 339 void WindowSizer::AdjustBoundsToBeVisibleOnDisplay( |
301 const gfx::Rect& other_bounds, | 340 const gfx::Display& display, |
302 const gfx::Rect& saved_work_area, | 341 const gfx::Rect& saved_work_area, |
303 gfx::Rect* bounds) const { | 342 gfx::Rect* bounds) const { |
304 DCHECK(bounds); | 343 DCHECK(bounds); |
305 | 344 |
306 // Find the size of the work area of the monitor that intersects the bounds | 345 // If |bounds| is empty, reset to the default size. |
307 // of the anchor window. | 346 if (bounds->IsEmpty()) { |
308 gfx::Display display = screen_->GetDisplayMatching(other_bounds); | 347 gfx::Rect default_bounds; |
309 | 348 GetDefaultWindowBounds(display, &default_bounds); |
310 // If height or width are 0, reset to the default size. | 349 if (bounds->height() <= 0) |
311 gfx::Rect default_bounds; | 350 bounds->set_height(default_bounds.height()); |
312 GetDefaultWindowBounds(display, &default_bounds); | 351 if (bounds->width() <= 0) |
313 if (bounds->height() <= 0) | 352 bounds->set_width(default_bounds.width()); |
314 bounds->set_height(default_bounds.height()); | 353 } |
315 if (bounds->width() <= 0) | |
316 bounds->set_width(default_bounds.width()); | |
317 | 354 |
318 // Ensure the minimum height and width. | 355 // Ensure the minimum height and width. |
319 bounds->set_height(std::max(kMinVisibleHeight, bounds->height())); | 356 bounds->set_height(std::max(kMinVisibleHeight, bounds->height())); |
320 bounds->set_width(std::max(kMinVisibleWidth, bounds->width())); | 357 bounds->set_width(std::max(kMinVisibleWidth, bounds->width())); |
321 | 358 |
322 gfx::Rect work_area = display.work_area(); | 359 gfx::Rect work_area = display.work_area(); |
323 // Ensure that the title bar is not above the work area. | 360 // Ensure that the title bar is not above the work area. |
324 if (bounds->y() < work_area.y()) | 361 if (bounds->y() < work_area.y()) |
325 bounds->set_y(work_area.y()); | 362 bounds->set_y(work_area.y()); |
326 | 363 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
363 // ensure that at least kMinVisibleWidth * kMinVisibleHeight is visible. | 400 // ensure that at least kMinVisibleWidth * kMinVisibleHeight is visible. |
364 const int min_y = work_area.y() + kMinVisibleHeight - bounds->height(); | 401 const int min_y = work_area.y() + kMinVisibleHeight - bounds->height(); |
365 const int min_x = work_area.x() + kMinVisibleWidth - bounds->width(); | 402 const int min_x = work_area.x() + kMinVisibleWidth - bounds->width(); |
366 const int max_y = work_area.bottom() - kMinVisibleHeight; | 403 const int max_y = work_area.bottom() - kMinVisibleHeight; |
367 const int max_x = work_area.right() - kMinVisibleWidth; | 404 const int max_x = work_area.right() - kMinVisibleWidth; |
368 bounds->set_y(std::max(min_y, std::min(max_y, bounds->y()))); | 405 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()))); | 406 bounds->set_x(std::max(min_x, std::min(max_x, bounds->x()))); |
370 #endif // defined(OS_MACOSX) | 407 #endif // defined(OS_MACOSX) |
371 } | 408 } |
372 | 409 |
410 gfx::Display WindowSizer::GetTargetDisplay(const gfx::Rect& bounds) const { | |
411 return target_display_provider_->GetTargetDisplay(screen_, bounds); | |
412 } | |
413 | |
373 ui::WindowShowState WindowSizer::GetWindowDefaultShowState() const { | 414 ui::WindowShowState WindowSizer::GetWindowDefaultShowState() const { |
374 if (!browser_) | 415 if (!browser_) |
375 return ui::SHOW_STATE_DEFAULT; | 416 return ui::SHOW_STATE_DEFAULT; |
376 | 417 |
377 // Only tabbed browsers use the command line or preference state, with the | 418 // Only tabbed browsers use the command line or preference state, with the |
378 // exception of devtools. | 419 // exception of devtools. |
379 bool show_state = !browser_->is_type_tabbed() && !browser_->is_devtools(); | 420 bool show_state = !browser_->is_type_tabbed() && !browser_->is_devtools(); |
380 | 421 |
381 #if defined(USE_AURA) | 422 #if defined(USE_AURA) |
382 // We use the apps save state on aura. | 423 // 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 && | 443 browser_->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH && |
403 browser_->is_type_tabbed(); | 444 browser_->is_type_tabbed(); |
404 } | 445 } |
405 | 446 |
406 bool WindowSizer::IsPopupBrowserInAsh() const { | 447 bool WindowSizer::IsPopupBrowserInAsh() const { |
407 return browser_ && | 448 return browser_ && |
408 browser_->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH && | 449 browser_->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH && |
409 browser_->is_type_popup(); | 450 browser_->is_type_popup(); |
410 } | 451 } |
411 #endif | 452 #endif |
OLD | NEW |