blob: 05e2f649cbd957591fc8bd09112ecd44a9a96537 [file] [log] [blame]
// Copyright (c) 2012 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/ui/window_sizer/window_sizer.h"
#include "ash/shell.h"
#include "ash/wm/window_positioner.h"
#include "ash/wm/window_state.h"
#include "chrome/browser/ui/ash/ash_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
bool WindowSizer::GetBrowserBoundsAsh(gfx::Rect* bounds,
ui::WindowShowState* show_state) const {
// TODO(crbug.com/764009): Mash support.
if (ash_util::IsRunningInMash() || !browser_)
return false;
bool determined = false;
if (bounds->IsEmpty()) {
if (browser_->is_type_tabbed()) {
GetTabbedBrowserBoundsAsh(bounds, show_state);
determined = true;
} else if (browser_->is_trusted_source()) {
// For trusted popups (v1 apps and system windows), do not use the last
// active window bounds, only use saved or default bounds.
if (!GetSavedWindowBounds(bounds, show_state))
*bounds = GetDefaultWindowBoundsAsh(GetTargetDisplay(gfx::Rect()));
determined = true;
} else {
// In Ash, prioritize the last saved |show_state|. If you have questions
// or comments about this behavior please contact oshima@chromium.org.
if (state_provider_) {
gfx::Rect ignored_bounds, ignored_work_area;
state_provider_->GetPersistentState(&ignored_bounds,
&ignored_work_area,
show_state);
}
}
} else if (browser_->is_type_popup() && bounds->origin().IsOrigin()) {
// In case of a popup with an 'unspecified' location in ash, we are
// looking for a good screen location. We are interpreting (0,0) as an
// unspecified location.
*bounds = ash::Shell::Get()->window_positioner()->GetPopupPosition(
bounds->size());
determined = true;
}
if (browser_->is_type_tabbed() && *show_state == ui::SHOW_STATE_DEFAULT) {
display::Display display = screen_->GetDisplayMatching(*bounds);
gfx::Rect work_area = display.work_area();
bounds->AdjustToFit(work_area);
if (*bounds == work_area) {
// A |browser_| that occupies the whole work area gets maximized.
// |bounds| returned here become the restore bounds once the window
// gets maximized after this method returns. Return a sensible default
// in order to make restored state visibly different from maximized.
*show_state = ui::SHOW_STATE_MAXIMIZED;
*bounds = GetDefaultWindowBoundsAsh(display);
determined = true;
}
}
return determined;
}
void WindowSizer::GetTabbedBrowserBoundsAsh(
gfx::Rect* bounds_in_screen,
ui::WindowShowState* show_state) const {
DCHECK(show_state);
DCHECK(bounds_in_screen);
DCHECK(browser_->is_type_tabbed());
DCHECK(bounds_in_screen->IsEmpty());
ui::WindowShowState passed_show_state = *show_state;
bool is_saved_bounds = GetSavedWindowBounds(bounds_in_screen, show_state);
display::Display display;
if (is_saved_bounds) {
display = screen_->GetDisplayMatching(*bounds_in_screen);
} else {
// If there is no saved bounds (hence bounds_in_screen is empty), use the
// target display.
display = target_display_provider_->GetTargetDisplay(screen_,
*bounds_in_screen);
*bounds_in_screen = GetDefaultWindowBoundsAsh(display);
}
if (browser_->is_session_restore()) {
// This is a fall-through case when there is no bounds recorded
// for restored window, and should not be used except for the case
// above. The regular path is handled in
// |WindowSizer::DetermineWindowBoundsAndShowState|.
// Note: How restore bounds/show state data are passed.
// The restore bounds is passed via |Browser::override_bounds()| in
// |chrome::GetBrowserWindowBoundsAndShowState()|.
// The restore state is passed via |Browser::initial_state()| in
// |WindowSizer::GetWindowDefaultShowState|.
bounds_in_screen->AdjustToFit(display.work_area());
return;
}
// The |browser_window| is non NULL when this is called after
// browser's aura window is created.
aura::Window* browser_window =
browser_->window() ? browser_->window()->GetNativeWindow() : NULL;
ash::WindowPositioner::GetBoundsAndShowStateForNewWindow(
browser_window, is_saved_bounds, passed_show_state, bounds_in_screen,
show_state);
}
gfx::Rect WindowSizer::GetDefaultWindowBoundsAsh(
const display::Display& display) {
const gfx::Rect work_area = display.work_area();
// There should be a 'desktop' border around the window at the left and right
// side.
int default_width = work_area.width() - 2 * kDesktopBorderSize;
// There should also be a 'desktop' border around the window at the top.
// Since the workspace excludes the tray area we only need one border size.
int default_height = work_area.height() - kDesktopBorderSize;
int offset_x = kDesktopBorderSize;
if (default_width > kMaximumWindowWidth) {
// The window should get centered on the screen and not follow the grid.
offset_x = (work_area.width() - kMaximumWindowWidth) / 2;
default_width = kMaximumWindowWidth;
}
return gfx::Rect(work_area.x() + offset_x, work_area.y() + kDesktopBorderSize,
default_width, default_height);
}