This source file includes following definitions.
- browser_
- GetPersistentState
- GetLastActiveWindowState
- GetTargetDisplay
- browser_
- browser_
- GetBrowserWindowBoundsAndShowState
- DetermineWindowBoundsAndShowState
- GetLastActiveWindowBounds
- GetSavedWindowBounds
- GetDefaultWindowBounds
- AdjustBoundsToBeVisibleOnDisplay
- GetTargetDisplay
- GetWindowDefaultShowState
- IsTabbedBrowserInAsh
- IsPopupBrowserInAsh
#include "chrome/browser/ui/window_sizer/window_sizer.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/prefs/pref_service.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/browser_window_state.h"
#include "chrome/browser/ui/host_desktop.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "ui/gfx/screen.h"
#if defined(USE_ASH)
#include "ash/shell.h"
#include "ash/wm/window_positioner.h"
#include "chrome/browser/ui/ash/ash_init.h"
#endif
namespace {
const int kMinVisibleHeight = 30;
const int kMinVisibleWidth = 30;
class DefaultStateProvider : public WindowSizer::StateProvider {
public:
DefaultStateProvider(const std::string& app_name, const Browser* browser)
: app_name_(app_name), browser_(browser) {
}
virtual bool GetPersistentState(
gfx::Rect* bounds,
gfx::Rect* work_area,
ui::WindowShowState* show_state) const OVERRIDE {
DCHECK(bounds);
DCHECK(show_state);
if (!browser_ || !browser_->profile()->GetPrefs())
return false;
std::string window_name(chrome::GetWindowPlacementKey(browser_));
const base::DictionaryValue* wp_pref =
browser_->profile()->GetPrefs()->GetDictionary(window_name.c_str());
int top = 0, left = 0, bottom = 0, right = 0;
bool maximized = false;
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);
if (*show_state == ui::SHOW_STATE_DEFAULT && maximized)
*show_state = ui::SHOW_STATE_MAXIMIZED;
}
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,
ui::WindowShowState* show_state) const OVERRIDE {
DCHECK(show_state);
if (!app_name_.empty())
return false;
BrowserWindow* window = NULL;
if (browser_ && browser_->window()) {
window = browser_->window();
} else {
const BrowserList* native_browser_list =
BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE);
for (BrowserList::const_reverse_iterator it =
native_browser_list->begin_last_active();
it != native_browser_list->end_last_active(); ++it) {
Browser* last_active = *it;
if (last_active && last_active->is_type_tabbed()) {
window = last_active->window();
DCHECK(window);
break;
}
}
}
if (window) {
*bounds = window->GetRestoredBounds();
if (*show_state == ui::SHOW_STATE_DEFAULT && window->IsMaximized())
*show_state = ui::SHOW_STATE_MAXIMIZED;
return true;
}
return false;
}
private:
std::string app_name_;
const Browser* browser_;
DISALLOW_COPY_AND_ASSIGN(DefaultStateProvider);
};
class DefaultTargetDisplayProvider : public WindowSizer::TargetDisplayProvider {
public:
DefaultTargetDisplayProvider() {}
virtual ~DefaultTargetDisplayProvider() {}
virtual gfx::Display GetTargetDisplay(
const gfx::Screen* screen,
const gfx::Rect& bounds) const OVERRIDE {
#if defined(USE_ASH)
if (chrome::ShouldOpenAshOnStartup()) {
aura::Window* target = ash::Shell::GetTargetRootWindow();
return screen->GetDisplayNearestWindow(target);
}
#endif
return screen->GetDisplayMatching(bounds);
}
private:
DISALLOW_COPY_AND_ASSIGN(DefaultTargetDisplayProvider);
};
}
WindowSizer::WindowSizer(
scoped_ptr<StateProvider> state_provider,
scoped_ptr<TargetDisplayProvider> target_display_provider,
const Browser* browser)
: state_provider_(state_provider.Pass()),
target_display_provider_(target_display_provider.Pass()),
screen_(gfx::Screen::GetNativeScreen()),
browser_(browser) {
}
WindowSizer::WindowSizer(
scoped_ptr<StateProvider> state_provider,
scoped_ptr<TargetDisplayProvider> target_display_provider,
gfx::Screen* screen,
const Browser* browser)
: state_provider_(state_provider.Pass()),
target_display_provider_(target_display_provider.Pass()),
screen_(screen),
browser_(browser) {
DCHECK(screen_);
}
WindowSizer::~WindowSizer() {
}
void WindowSizer::GetBrowserWindowBoundsAndShowState(
const std::string& app_name,
const gfx::Rect& specified_bounds,
const Browser* browser,
gfx::Rect* window_bounds,
ui::WindowShowState* show_state) {
scoped_ptr<StateProvider> state_provider(
new DefaultStateProvider(app_name, browser));
scoped_ptr<TargetDisplayProvider> target_display_provider(
new DefaultTargetDisplayProvider);
const WindowSizer sizer(state_provider.Pass(),
target_display_provider.Pass(),
browser);
sizer.DetermineWindowBoundsAndShowState(specified_bounds,
window_bounds,
show_state);
}
void WindowSizer::DetermineWindowBoundsAndShowState(
const gfx::Rect& specified_bounds,
gfx::Rect* bounds,
ui::WindowShowState* show_state) const {
DCHECK(bounds);
DCHECK(show_state);
*show_state = GetWindowDefaultShowState();
*bounds = specified_bounds;
if (bounds->IsEmpty()) {
#if defined(USE_ASH)
if (IsTabbedBrowserInAsh()) {
GetTabbedBrowserBoundsAsh(bounds, show_state);
return;
} else if (browser_ && browser_->host_desktop_type() ==
chrome::HOST_DESKTOP_TYPE_ASH) {
GetSavedWindowBounds(bounds, show_state);
}
#endif
if (GetLastActiveWindowBounds(bounds, show_state))
return;
if (GetSavedWindowBounds(bounds, show_state))
return;
GetDefaultWindowBounds(GetTargetDisplay(gfx::Rect()), bounds);
} else {
#if defined(USE_ASH)
if (IsPopupBrowserInAsh() && bounds->origin().IsOrigin()) {
*bounds = ash::Shell::GetInstance()->window_positioner()->
GetPopupPosition(*bounds);
return;
}
#endif
gfx::Rect work_area = screen_->GetDisplayMatching(*bounds).work_area();
bounds->AdjustToFit(work_area);
}
}
bool WindowSizer::GetLastActiveWindowBounds(
gfx::Rect* bounds,
ui::WindowShowState* show_state) const {
DCHECK(bounds);
DCHECK(show_state);
if (!state_provider_.get() ||
!state_provider_->GetLastActiveWindowState(bounds, show_state))
return false;
gfx::Rect last_window_bounds = *bounds;
bounds->Offset(kWindowTilePixels, kWindowTilePixels);
AdjustBoundsToBeVisibleOnDisplay(screen_->GetDisplayMatching(*bounds),
gfx::Rect(),
bounds);
return true;
}
bool WindowSizer::GetSavedWindowBounds(gfx::Rect* bounds,
ui::WindowShowState* show_state) const {
DCHECK(bounds);
DCHECK(show_state);
gfx::Rect saved_work_area;
if (!state_provider_.get() ||
!state_provider_->GetPersistentState(bounds,
&saved_work_area,
show_state))
return false;
AdjustBoundsToBeVisibleOnDisplay(GetTargetDisplay(*bounds),
saved_work_area,
bounds);
return true;
}
void WindowSizer::GetDefaultWindowBounds(const gfx::Display& display,
gfx::Rect* default_bounds) const {
DCHECK(default_bounds);
#if defined(USE_ASH)
if (chrome::ShouldOpenAshOnStartup()) {
*default_bounds = ash::WindowPositioner::GetDefaultWindowBounds(display);
return;
}
#endif
gfx::Rect work_area = display.work_area();
int default_width = std::min(work_area.width() - 2 * kWindowTilePixels, 1050);
int default_height = work_area.height() - 2 * kWindowTilePixels;
gfx::Rect screen_size = screen_->GetPrimaryDisplay().bounds();
double width_to_height =
static_cast<double>(screen_size.width()) / screen_size.height();
static const int kMinScreenWidthForWindowHalving = 1600;
if (((width_to_height * 10) >= 16) &&
work_area.width() > kMinScreenWidthForWindowHalving) {
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);
}
void WindowSizer::AdjustBoundsToBeVisibleOnDisplay(
const gfx::Display& display,
const gfx::Rect& saved_work_area,
gfx::Rect* bounds) const {
DCHECK(bounds);
if (bounds->IsEmpty()) {
gfx::Rect default_bounds;
GetDefaultWindowBounds(display, &default_bounds);
if (bounds->height() <= 0)
bounds->set_height(default_bounds.height());
if (bounds->width() <= 0)
bounds->set_width(default_bounds.width());
}
bounds->set_height(std::max(kMinVisibleHeight, bounds->height()));
bounds->set_width(std::max(kMinVisibleWidth, bounds->width()));
gfx::Rect work_area = display.work_area();
if (bounds->y() < work_area.y())
bounds->set_y(work_area.y());
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)
bounds->set_height(std::min(work_area.height(), bounds->height()));
if (bounds->x() < work_area.x() || bounds->right() > work_area.right())
bounds->set_x(work_area.x());
if (bounds->y() < work_area.y() || bounds->bottom() > work_area.bottom())
bounds->set_y(work_area.y());
#else
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
}
gfx::Display WindowSizer::GetTargetDisplay(const gfx::Rect& bounds) const {
return target_display_provider_->GetTargetDisplay(screen_, bounds);
}
ui::WindowShowState WindowSizer::GetWindowDefaultShowState() const {
if (!browser_)
return ui::SHOW_STATE_DEFAULT;
bool show_state = !browser_->is_type_tabbed() && !browser_->is_devtools();
#if defined(USE_AURA)
show_state &= !browser_->is_app();
#endif
if (show_state)
return browser_->initial_show_state();
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kStartMaximized))
return ui::SHOW_STATE_MAXIMIZED;
if (browser_->initial_show_state() != ui::SHOW_STATE_DEFAULT)
return browser_->initial_show_state();
return ui::SHOW_STATE_DEFAULT;
}
#if defined(USE_ASH)
bool WindowSizer::IsTabbedBrowserInAsh() const {
return browser_ &&
browser_->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH &&
browser_->is_type_tabbed();
}
bool WindowSizer::IsPopupBrowserInAsh() const {
return browser_ &&
browser_->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_ASH &&
browser_->is_type_popup();
}
#endif