Index: chrome/browser/window_sizer.cc |
=================================================================== |
--- chrome/browser/window_sizer.cc (revision 68008) |
+++ chrome/browser/window_sizer.cc (working copy) |
@@ -1,336 +0,0 @@ |
-// Copyright (c) 2010 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/window_sizer.h" |
- |
-#include "chrome/browser/browser_list.h" |
-#include "chrome/browser/browser_process.h" |
-#include "chrome/browser/browser_window.h" |
-#include "chrome/browser/prefs/pref_service.h" |
-#include "chrome/browser/ui/browser.h" |
-#include "chrome/common/pref_names.h" |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// An implementation of WindowSizer::StateProvider that gets the last active |
-// and persistent state from the browser window and the user's profile. |
-class DefaultStateProvider : public WindowSizer::StateProvider { |
- public: |
- explicit DefaultStateProvider(const std::string& app_name, Browser* browser) |
- : app_name_(app_name), |
- browser_(browser) { |
- } |
- |
- // Overridden from WindowSizer::StateProvider: |
- virtual bool GetPersistentState(gfx::Rect* bounds, |
- bool* maximized, |
- gfx::Rect* work_area) const { |
- DCHECK(bounds && maximized); |
- |
- std::string key(prefs::kBrowserWindowPlacement); |
- if (!app_name_.empty()) { |
- key.append("_"); |
- key.append(app_name_); |
- } |
- |
- if (!g_browser_process->local_state()) |
- return false; |
- |
- const DictionaryValue* wp_pref = |
- g_browser_process->local_state()->GetDictionary(key.c_str()); |
- int top = 0, left = 0, bottom = 0, right = 0; |
- bool has_prefs = |
- wp_pref && |
- wp_pref->GetInteger("top", &top) && |
- wp_pref->GetInteger("left", &left) && |
- wp_pref->GetInteger("bottom", &bottom) && |
- wp_pref->GetInteger("right", &right) && |
- wp_pref->GetBoolean("maximized", maximized); |
- bounds->SetRect(left, top, std::max(0, right - left), |
- std::max(0, bottom - top)); |
- |
- int work_area_top = 0; |
- int work_area_left = 0; |
- int work_area_bottom = 0; |
- int work_area_right = 0; |
- if (wp_pref) { |
- wp_pref->GetInteger("work_area_top", &work_area_top); |
- wp_pref->GetInteger("work_area_left", &work_area_left); |
- wp_pref->GetInteger("work_area_bottom", &work_area_bottom); |
- wp_pref->GetInteger("work_area_right", &work_area_right); |
- } |
- work_area->SetRect(work_area_left, work_area_top, |
- std::max(0, work_area_right - work_area_left), |
- std::max(0, work_area_bottom - work_area_top)); |
- |
- return has_prefs; |
- } |
- |
- virtual bool GetLastActiveWindowState(gfx::Rect* bounds) const { |
- // Applications are always restored with the same position. |
- if (!app_name_.empty()) |
- return false; |
- |
- // If a reference browser is set, use its window. Otherwise find last |
- // active. |
- BrowserWindow* window = NULL; |
- if (browser_) { |
- window = browser_->window(); |
- DCHECK(window); |
- } else { |
- BrowserList::const_reverse_iterator it = BrowserList::begin_last_active(); |
- BrowserList::const_reverse_iterator end = BrowserList::end_last_active(); |
- for (; (it != end); ++it) { |
- Browser* last_active = *it; |
- if (last_active && last_active->type() == Browser::TYPE_NORMAL) { |
- window = last_active->window(); |
- DCHECK(window); |
- break; |
- } |
- } |
- } |
- |
- if (window) { |
- *bounds = window->GetRestoredBounds(); |
- return true; |
- } |
- |
- return false; |
- } |
- |
- private: |
- std::string app_name_; |
- |
- // If set, is used as the reference browser for GetLastActiveWindowState. |
- Browser* browser_; |
- DISALLOW_COPY_AND_ASSIGN(DefaultStateProvider); |
-}; |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// MonitorInfoProvider, public: |
- |
-WindowSizer::MonitorInfoProvider::MonitorInfoProvider() {} |
- |
-WindowSizer::MonitorInfoProvider::~MonitorInfoProvider() {} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// WindowSizer, public: |
- |
-WindowSizer::WindowSizer( |
- StateProvider* state_provider, |
- MonitorInfoProvider* monitor_info_provider) { |
- Init(state_provider, monitor_info_provider); |
-} |
- |
-WindowSizer::~WindowSizer() { |
- if (state_provider_) |
- delete state_provider_; |
- if (monitor_info_provider_) |
- delete monitor_info_provider_; |
-} |
- |
-// static |
-void WindowSizer::GetBrowserWindowBounds(const std::string& app_name, |
- const gfx::Rect& specified_bounds, |
- Browser* browser, |
- gfx::Rect* window_bounds, |
- bool* maximized) { |
- const WindowSizer sizer(new DefaultStateProvider(app_name, browser), |
- CreateDefaultMonitorInfoProvider()); |
- sizer.DetermineWindowBounds(specified_bounds, window_bounds, maximized); |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// WindowSizer, private: |
- |
-WindowSizer::WindowSizer(const std::string& app_name) { |
- Init(new DefaultStateProvider(app_name, NULL), |
- CreateDefaultMonitorInfoProvider()); |
-} |
- |
-void WindowSizer::Init(StateProvider* state_provider, |
- MonitorInfoProvider* monitor_info_provider) { |
- state_provider_ = state_provider; |
- monitor_info_provider_ = monitor_info_provider; |
-} |
- |
-void WindowSizer::DetermineWindowBounds(const gfx::Rect& specified_bounds, |
- gfx::Rect* bounds, |
- bool* maximized) const { |
- *bounds = specified_bounds; |
- if (bounds->IsEmpty()) { |
- // See if there's saved placement information. |
- if (!GetLastWindowBounds(bounds)) { |
- if (!GetSavedWindowBounds(bounds, maximized)) { |
- // No saved placement, figure out some sensible default size based on |
- // the user's screen size. |
- GetDefaultWindowBounds(bounds); |
- } |
- } |
- } |
-} |
- |
-bool WindowSizer::GetLastWindowBounds(gfx::Rect* bounds) const { |
- DCHECK(bounds); |
- if (!state_provider_ || !state_provider_->GetLastActiveWindowState(bounds)) |
- return false; |
- gfx::Rect last_window_bounds = *bounds; |
- bounds->Offset(kWindowTilePixels, kWindowTilePixels); |
- AdjustBoundsToBeVisibleOnMonitorContaining(last_window_bounds, |
- gfx::Rect(), |
- bounds); |
- return true; |
-} |
- |
-bool WindowSizer::GetSavedWindowBounds(gfx::Rect* bounds, |
- bool* maximized) const { |
- DCHECK(bounds && maximized); |
- gfx::Rect saved_work_area; |
- if (!state_provider_ || |
- !state_provider_->GetPersistentState(bounds, maximized, &saved_work_area)) |
- return false; |
- AdjustBoundsToBeVisibleOnMonitorContaining(*bounds, saved_work_area, bounds); |
- return true; |
-} |
- |
-void WindowSizer::GetDefaultWindowBounds(gfx::Rect* default_bounds) const { |
- DCHECK(default_bounds); |
- DCHECK(monitor_info_provider_); |
- |
- gfx::Rect work_area = monitor_info_provider_->GetPrimaryMonitorWorkArea(); |
- |
- // The default size is either some reasonably wide width, or if the work |
- // area is narrower, then the work area width less some aesthetic padding. |
- int default_width = std::min(work_area.width() - 2 * kWindowTilePixels, 1050); |
- int default_height = work_area.height() - 2 * kWindowTilePixels; |
- |
- // For wider aspect ratio displays at higher resolutions, we might size the |
- // window narrower to allow two windows to easily be placed side-by-side. |
- gfx::Rect screen_size = monitor_info_provider_->GetPrimaryMonitorBounds(); |
- double width_to_height = |
- static_cast<double>(screen_size.width()) / screen_size.height(); |
- |
- // The least wide a screen can be to qualify for the halving described above. |
- static const int kMinScreenWidthForWindowHalving = 1600; |
- // We assume 16:9/10 is a fairly standard indicator of a wide aspect ratio |
- // computer display. |
- if (((width_to_height * 10) >= 16) && |
- work_area.width() > kMinScreenWidthForWindowHalving) { |
- // Halve the work area, subtracting aesthetic padding on either side. |
- // The padding is set so that two windows, side by side have |
- // kWindowTilePixels between screen edge and each other. |
- default_width = static_cast<int>(work_area.width() / 2. - |
- 1.5 * kWindowTilePixels); |
- } |
- default_bounds->SetRect(kWindowTilePixels + work_area.x(), |
- kWindowTilePixels + work_area.y(), |
- default_width, default_height); |
-} |
- |
-bool WindowSizer::PositionIsOffscreen(int position, Edge edge) const { |
- DCHECK(monitor_info_provider_); |
- size_t monitor_count = monitor_info_provider_->GetMonitorCount(); |
- for (size_t i = 0; i < monitor_count; ++i) { |
- gfx::Rect work_area = monitor_info_provider_->GetWorkAreaAt(i); |
- switch (edge) { |
- case TOP: |
- if (position >= work_area.y()) |
- return false; |
- break; |
- case LEFT: |
- if (position >= work_area.x()) |
- return false; |
- break; |
- case BOTTOM: |
- if (position <= work_area.bottom()) |
- return false; |
- break; |
- case RIGHT: |
- if (position <= work_area.right()) |
- return false; |
- break; |
- } |
- } |
- return true; |
-} |
- |
-namespace { |
- // Minimum height of the visible part of a window. |
- static const int kMinVisibleHeight = 30; |
- // Minimum width of the visible part of a window. |
- static const int kMinVisibleWidth = 30; |
-} |
- |
-void WindowSizer::AdjustBoundsToBeVisibleOnMonitorContaining( |
- const gfx::Rect& other_bounds, |
- const gfx::Rect& saved_work_area, |
- gfx::Rect* bounds) const { |
- DCHECK(bounds); |
- DCHECK(monitor_info_provider_); |
- |
- // Find the size of the work area of the monitor that intersects the bounds |
- // of the anchor window. |
- gfx::Rect work_area = |
- monitor_info_provider_->GetMonitorWorkAreaMatching(other_bounds); |
- |
- // If height or width are 0, reset to the default size. |
- gfx::Rect default_bounds; |
- GetDefaultWindowBounds(&default_bounds); |
- if (bounds->height() <= 0) |
- bounds->set_height(default_bounds.height()); |
- if (bounds->width() <= 0) |
- bounds->set_width(default_bounds.width()); |
- |
- // Ensure the minimum height and width. |
- bounds->set_height(std::max(kMinVisibleHeight, bounds->height())); |
- bounds->set_width(std::max(kMinVisibleWidth, bounds->width())); |
- |
- // Ensure that the title bar is not above the work area. |
- if (bounds->y() < work_area.y()) |
- bounds->set_y(work_area.y()); |
- |
- // Reposition and resize the bounds if the saved_work_area is different from |
- // the current work area and the current work area doesn't completely contain |
- // the bounds. |
- if (!saved_work_area.IsEmpty() && |
- saved_work_area != work_area && |
- !work_area.Contains(*bounds)) { |
- bounds->set_width(std::min(bounds->width(), work_area.width())); |
- bounds->set_height(std::min(bounds->height(), work_area.height())); |
- bounds->set_x( |
- std::max(work_area.x(), |
- std::min(bounds->x(), work_area.right() - bounds->width()))); |
- bounds->set_y( |
- std::max(work_area.y(), |
- std::min(bounds->y(), work_area.bottom() - bounds->height()))); |
- } |
- |
-#if defined(OS_MACOSX) |
- // Limit the maximum height. On the Mac the sizer is on the |
- // bottom-right of the window, and a window cannot be moved "up" |
- // past the menubar. If the window is too tall you'll never be able |
- // to shrink it again. Windows does not have this limitation |
- // (e.g. can be resized from the top). |
- bounds->set_height(std::min(work_area.height(), bounds->height())); |
- |
- // On mac, we want to be aggressive about repositioning windows that are |
- // partially offscreen. If the window is partially offscreen horizontally, |
- // move it to be flush with the left edge of the work area. |
- if (bounds->x() < work_area.x() || bounds->right() > work_area.right()) |
- bounds->set_x(work_area.x()); |
- |
- // If the window is partially offscreen vertically, move it to be flush with |
- // the top of the work area. |
- if (bounds->y() < work_area.y() || bounds->bottom() > work_area.bottom()) |
- bounds->set_y(work_area.y()); |
-#else |
- // On non-Mac platforms, we are less aggressive about repositioning. Simply |
- // ensure that at least kMinVisibleWidth * kMinVisibleHeight is visible. |
- const int min_y = work_area.y() + kMinVisibleHeight - bounds->height(); |
- const int min_x = work_area.x() + kMinVisibleWidth - bounds->width(); |
- const int max_y = work_area.bottom() - kMinVisibleHeight; |
- const int max_x = work_area.right() - kMinVisibleWidth; |
- bounds->set_y(std::max(min_y, std::min(max_y, bounds->y()))); |
- bounds->set_x(std::max(min_x, std::min(max_x, bounds->x()))); |
-#endif // defined(OS_MACOSX) |
-} |