| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/window_sizer.h" | 5 #include "chrome/browser/window_sizer.h" |
| 6 | 6 |
| 7 #include "chrome/browser/browser.h" | 7 #include "chrome/browser/browser.h" |
| 8 #include "chrome/browser/browser_list.h" | 8 #include "chrome/browser/browser_list.h" |
| 9 #include "chrome/browser/browser_process.h" | 9 #include "chrome/browser/browser_process.h" |
| 10 #include "chrome/browser/browser_window.h" | 10 #include "chrome/browser/browser_window.h" |
| 11 #include "chrome/common/pref_names.h" | 11 #include "chrome/common/pref_names.h" |
| 12 #include "chrome/common/pref_service.h" | 12 #include "chrome/common/pref_service.h" |
| 13 | 13 |
| 14 /////////////////////////////////////////////////////////////////////////////// | 14 /////////////////////////////////////////////////////////////////////////////// |
| 15 // An implementation of WindowSizer::StateProvider that gets the last active | 15 // An implementation of WindowSizer::StateProvider that gets the last active |
| 16 // and persistent state from the browser window and the user's profile. | 16 // and persistent state from the browser window and the user's profile. |
| 17 class DefaultStateProvider : public WindowSizer::StateProvider { | 17 class DefaultStateProvider : public WindowSizer::StateProvider { |
| 18 public: | 18 public: |
| 19 explicit DefaultStateProvider(const std::wstring& app_name, Browser* browser) | 19 explicit DefaultStateProvider(const std::wstring& app_name, Browser* browser) |
| 20 : app_name_(app_name), | 20 : app_name_(app_name), |
| 21 browser_(browser) { | 21 browser_(browser) { |
| 22 } | 22 } |
| 23 | 23 |
| 24 // Overridden from WindowSizer::StateProvider: | 24 // Overridden from WindowSizer::StateProvider: |
| 25 virtual bool GetPersistentState(gfx::Rect* bounds, bool* maximized) const { | 25 virtual bool GetPersistentState(gfx::Rect* bounds, |
| 26 bool* maximized, |
| 27 gfx::Rect* work_area) const { |
| 26 DCHECK(bounds && maximized); | 28 DCHECK(bounds && maximized); |
| 27 | 29 |
| 28 std::wstring key(prefs::kBrowserWindowPlacement); | 30 std::wstring key(prefs::kBrowserWindowPlacement); |
| 29 if (!app_name_.empty()) { | 31 if (!app_name_.empty()) { |
| 30 key.append(L"_"); | 32 key.append(L"_"); |
| 31 key.append(app_name_); | 33 key.append(app_name_); |
| 32 } | 34 } |
| 33 | 35 |
| 34 if (!g_browser_process->local_state()) | 36 if (!g_browser_process->local_state()) |
| 35 return false; | 37 return false; |
| 36 | 38 |
| 37 const DictionaryValue* wp_pref = | 39 const DictionaryValue* wp_pref = |
| 38 g_browser_process->local_state()->GetDictionary(key.c_str()); | 40 g_browser_process->local_state()->GetDictionary(key.c_str()); |
| 39 int top = 0, left = 0, bottom = 0, right = 0; | 41 int top = 0, left = 0, bottom = 0, right = 0; |
| 40 bool has_prefs = | 42 bool has_prefs = |
| 41 wp_pref && | 43 wp_pref && |
| 42 wp_pref->GetInteger(L"top", &top) && | 44 wp_pref->GetInteger(L"top", &top) && |
| 43 wp_pref->GetInteger(L"left", &left) && | 45 wp_pref->GetInteger(L"left", &left) && |
| 44 wp_pref->GetInteger(L"bottom", &bottom) && | 46 wp_pref->GetInteger(L"bottom", &bottom) && |
| 45 wp_pref->GetInteger(L"right", &right) && | 47 wp_pref->GetInteger(L"right", &right) && |
| 46 wp_pref->GetBoolean(L"maximized", maximized); | 48 wp_pref->GetBoolean(L"maximized", maximized); |
| 47 bounds->SetRect(left, top, std::max(0, right - left), | 49 bounds->SetRect(left, top, std::max(0, right - left), |
| 48 std::max(0, bottom - top)); | 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(L"work_area_top", &work_area_top); |
| 58 wp_pref->GetInteger(L"work_area_left", &work_area_left); |
| 59 wp_pref->GetInteger(L"work_area_bottom", &work_area_bottom); |
| 60 wp_pref->GetInteger(L"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 |
| 49 return has_prefs; | 66 return has_prefs; |
| 50 } | 67 } |
| 51 | 68 |
| 52 virtual bool GetLastActiveWindowState(gfx::Rect* bounds) const { | 69 virtual bool GetLastActiveWindowState(gfx::Rect* bounds) const { |
| 53 // Applications are always restored with the same position. | 70 // Applications are always restored with the same position. |
| 54 if (!app_name_.empty()) | 71 if (!app_name_.empty()) |
| 55 return false; | 72 return false; |
| 56 | 73 |
| 57 // If a reference browser is set, use its window. Otherwise find last | 74 // If a reference browser is set, use its window. Otherwise find last |
| 58 // active. | 75 // active. |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 } | 162 } |
| 146 } | 163 } |
| 147 } | 164 } |
| 148 | 165 |
| 149 bool WindowSizer::GetLastWindowBounds(gfx::Rect* bounds) const { | 166 bool WindowSizer::GetLastWindowBounds(gfx::Rect* bounds) const { |
| 150 DCHECK(bounds); | 167 DCHECK(bounds); |
| 151 if (!state_provider_ || !state_provider_->GetLastActiveWindowState(bounds)) | 168 if (!state_provider_ || !state_provider_->GetLastActiveWindowState(bounds)) |
| 152 return false; | 169 return false; |
| 153 gfx::Rect last_window_bounds = *bounds; | 170 gfx::Rect last_window_bounds = *bounds; |
| 154 bounds->Offset(kWindowTilePixels, kWindowTilePixels); | 171 bounds->Offset(kWindowTilePixels, kWindowTilePixels); |
| 155 AdjustBoundsToBeVisibleOnMonitorContaining(last_window_bounds, bounds); | 172 AdjustBoundsToBeVisibleOnMonitorContaining(last_window_bounds, |
| 173 gfx::Rect(), |
| 174 bounds); |
| 156 return true; | 175 return true; |
| 157 } | 176 } |
| 158 | 177 |
| 159 bool WindowSizer::GetSavedWindowBounds(gfx::Rect* bounds, | 178 bool WindowSizer::GetSavedWindowBounds(gfx::Rect* bounds, |
| 160 bool* maximized) const { | 179 bool* maximized) const { |
| 161 DCHECK(bounds && maximized); | 180 DCHECK(bounds && maximized); |
| 181 gfx::Rect saved_work_area; |
| 162 if (!state_provider_ || | 182 if (!state_provider_ || |
| 163 !state_provider_->GetPersistentState(bounds, maximized)) | 183 !state_provider_->GetPersistentState(bounds, maximized, &saved_work_area)) |
| 164 return false; | 184 return false; |
| 165 AdjustBoundsToBeVisibleOnMonitorContaining(*bounds, bounds); | 185 AdjustBoundsToBeVisibleOnMonitorContaining(*bounds, saved_work_area, bounds); |
| 166 return true; | 186 return true; |
| 167 } | 187 } |
| 168 | 188 |
| 169 void WindowSizer::GetDefaultWindowBounds(gfx::Rect* default_bounds) const { | 189 void WindowSizer::GetDefaultWindowBounds(gfx::Rect* default_bounds) const { |
| 170 DCHECK(default_bounds); | 190 DCHECK(default_bounds); |
| 171 DCHECK(monitor_info_provider_); | 191 DCHECK(monitor_info_provider_); |
| 172 | 192 |
| 173 gfx::Rect work_area = monitor_info_provider_->GetPrimaryMonitorWorkArea(); | 193 gfx::Rect work_area = monitor_info_provider_->GetPrimaryMonitorWorkArea(); |
| 174 | 194 |
| 175 // The default size is either some reasonably wide width, or if the work | 195 // The default size is either some reasonably wide width, or if the work |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 } | 246 } |
| 227 | 247 |
| 228 namespace { | 248 namespace { |
| 229 // Minimum height of the visible part of a window. | 249 // Minimum height of the visible part of a window. |
| 230 static const int kMinVisibleHeight = 30; | 250 static const int kMinVisibleHeight = 30; |
| 231 // Minimum width of the visible part of a window. | 251 // Minimum width of the visible part of a window. |
| 232 static const int kMinVisibleWidth = 30; | 252 static const int kMinVisibleWidth = 30; |
| 233 } | 253 } |
| 234 | 254 |
| 235 void WindowSizer::AdjustBoundsToBeVisibleOnMonitorContaining( | 255 void WindowSizer::AdjustBoundsToBeVisibleOnMonitorContaining( |
| 236 const gfx::Rect& other_bounds, gfx::Rect* bounds) const { | 256 const gfx::Rect& other_bounds, |
| 257 const gfx::Rect& saved_work_area, |
| 258 gfx::Rect* bounds) const { |
| 237 DCHECK(bounds); | 259 DCHECK(bounds); |
| 238 DCHECK(monitor_info_provider_); | 260 DCHECK(monitor_info_provider_); |
| 239 | 261 |
| 240 // Find the size of the work area of the monitor that intersects the bounds | 262 // Find the size of the work area of the monitor that intersects the bounds |
| 241 // of the anchor window. | 263 // of the anchor window. |
| 242 gfx::Rect work_area = | 264 gfx::Rect work_area = |
| 243 monitor_info_provider_->GetMonitorWorkAreaMatching(other_bounds); | 265 monitor_info_provider_->GetMonitorWorkAreaMatching(other_bounds); |
| 244 | 266 |
| 245 // If height or width are 0, reset to the default size. | 267 // If height or width are 0, reset to the default size. |
| 246 gfx::Rect default_bounds; | 268 gfx::Rect default_bounds; |
| 247 GetDefaultWindowBounds(&default_bounds); | 269 GetDefaultWindowBounds(&default_bounds); |
| 248 if (bounds->height() <= 0) | 270 if (bounds->height() <= 0) |
| 249 bounds->set_height(default_bounds.height()); | 271 bounds->set_height(default_bounds.height()); |
| 250 if (bounds->width() <= 0) | 272 if (bounds->width() <= 0) |
| 251 bounds->set_width(default_bounds.width()); | 273 bounds->set_width(default_bounds.width()); |
| 252 | 274 |
| 253 // Ensure the minimum height and width. | 275 // Ensure the minimum height and width. |
| 254 bounds->set_height(std::max(kMinVisibleHeight, bounds->height())); | 276 bounds->set_height(std::max(kMinVisibleHeight, bounds->height())); |
| 255 bounds->set_width(std::max(kMinVisibleWidth, bounds->width())); | 277 bounds->set_width(std::max(kMinVisibleWidth, bounds->width())); |
| 256 | 278 |
| 279 // Ensure that the title bar is not above the work area. |
| 280 if (bounds->y() < work_area.y()) |
| 281 bounds->set_y(work_area.y()); |
| 282 |
| 283 // Reposition and resize the bounds if the saved_work_area is different from |
| 284 // the current work area and the current work area doesn't completely contain |
| 285 // the bounds. |
| 286 if (!saved_work_area.IsEmpty() && |
| 287 saved_work_area != work_area && |
| 288 !work_area.Contains(*bounds)) { |
| 289 bounds->set_width(std::min(bounds->width(), work_area.width())); |
| 290 bounds->set_height(std::min(bounds->height(), work_area.height())); |
| 291 bounds->set_x( |
| 292 std::max(work_area.x(), |
| 293 std::min(bounds->x(), work_area.right() - bounds->width()))); |
| 294 bounds->set_y( |
| 295 std::max(work_area.y(), |
| 296 std::min(bounds->y(), work_area.bottom() - bounds->height()))); |
| 297 } |
| 298 |
| 257 #if defined(OS_MACOSX) | 299 #if defined(OS_MACOSX) |
| 258 // Limit the maximum height. On the Mac the sizer is on the | 300 // Limit the maximum height. On the Mac the sizer is on the |
| 259 // bottom-right of the window, and a window cannot be moved "up" | 301 // bottom-right of the window, and a window cannot be moved "up" |
| 260 // past the menubar. If the window is too tall you'll never be able | 302 // past the menubar. If the window is too tall you'll never be able |
| 261 // to shrink it again. Windows does not have this limitation | 303 // to shrink it again. Windows does not have this limitation |
| 262 // (e.g. can be resized from the top). | 304 // (e.g. can be resized from the top). |
| 263 bounds->set_height(std::min(work_area.height(), bounds->height())); | 305 bounds->set_height(std::min(work_area.height(), bounds->height())); |
| 264 #endif // defined(OS_MACOSX) | 306 #endif // defined(OS_MACOSX) |
| 265 | 307 |
| 266 // Ensure at least kMinVisibleWidth * kMinVisibleHeight is visible. | 308 // Ensure at least kMinVisibleWidth * kMinVisibleHeight is visible. |
| 267 const int min_y = work_area.y() + kMinVisibleHeight - bounds->height(); | 309 const int min_y = work_area.y() + kMinVisibleHeight - bounds->height(); |
| 268 const int min_x = work_area.x() + kMinVisibleWidth - bounds->width(); | 310 const int min_x = work_area.x() + kMinVisibleWidth - bounds->width(); |
| 269 const int max_y = work_area.bottom() - kMinVisibleHeight; | 311 const int max_y = work_area.bottom() - kMinVisibleHeight; |
| 270 const int max_x = work_area.right() - kMinVisibleWidth; | 312 const int max_x = work_area.right() - kMinVisibleWidth; |
| 271 bounds->set_y(std::max(min_y, std::min(max_y, bounds->y()))); | 313 bounds->set_y(std::max(min_y, std::min(max_y, bounds->y()))); |
| 272 bounds->set_x(std::max(min_x, std::min(max_x, bounds->x()))); | 314 bounds->set_x(std::max(min_x, std::min(max_x, bounds->x()))); |
| 273 } | 315 } |
| OLD | NEW |