15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/window_sizer/window_sizer.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/compiler_specific.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/browser_process.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_list.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser_window_state.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/host_desktop.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/pref_names.h"
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "ui/base/ui_base_switches.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/screen.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#if defined(USE_ASH)
234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ash/shell.h"
244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ash/wm/window_positioner.h"
25424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "chrome/browser/ui/ash/ash_init.h"
26424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#endif
27424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace {
29a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Minimum height of the visible part of a window.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinVisibleHeight = 30;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Minimum width of the visible part of a window.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinVisibleWidth = 30;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An implementation of WindowSizer::StateProvider that gets the last active
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and persistent state from the browser window and the user's profile.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DefaultStateProvider : public WindowSizer::StateProvider {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DefaultStateProvider(const std::string& app_name, const Browser* browser)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : app_name_(app_name), browser_(browser) {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Overridden from WindowSizer::StateProvider:
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool GetPersistentState(
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Rect* bounds,
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Rect* work_area,
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ui::WindowShowState* show_state) const OVERRIDE {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(bounds);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(show_state);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!browser_ || !browser_->profile()->GetPrefs())
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::DictionaryValue* wp_pref =
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        chrome::GetWindowPlacementDictionaryReadOnly(
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            chrome::GetWindowName(browser_), browser_->profile()->GetPrefs());
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int top = 0, left = 0, bottom = 0, right = 0;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool maximized = false;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool has_prefs = wp_pref &&
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     wp_pref->GetInteger("top", &top) &&
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     wp_pref->GetInteger("left", &left) &&
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     wp_pref->GetInteger("bottom", &bottom) &&
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     wp_pref->GetInteger("right", &right) &&
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     wp_pref->GetBoolean("maximized", &maximized);
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bounds->SetRect(left, top, std::max(0, right - left),
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    std::max(0, bottom - top));
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int work_area_top = 0;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int work_area_left = 0;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int work_area_bottom = 0;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int work_area_right = 0;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (wp_pref) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wp_pref->GetInteger("work_area_top", &work_area_top);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wp_pref->GetInteger("work_area_left", &work_area_left);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wp_pref->GetInteger("work_area_bottom", &work_area_bottom);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wp_pref->GetInteger("work_area_right", &work_area_right);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (*show_state == ui::SHOW_STATE_DEFAULT && maximized)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *show_state = ui::SHOW_STATE_MAXIMIZED;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    work_area->SetRect(work_area_left, work_area_top,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::max(0, work_area_right - work_area_left),
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::max(0, work_area_bottom - work_area_top));
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return has_prefs;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool GetLastActiveWindowState(
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      gfx::Rect* bounds,
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ui::WindowShowState* show_state) const OVERRIDE {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(show_state);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Applications are always restored with the same position.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!app_name_.empty())
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If a reference browser is set, use its window. Otherwise find last
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // active. Panels are never used as reference browsers as panels are
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // specially positioned.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BrowserWindow* window = NULL;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Window may be null if browser is just starting up.
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (browser_ && browser_->window()) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      window = browser_->window();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // This code is only ran on the native desktop (on the ash
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // desktop, GetTabbedBrowserBoundsAsh should take over below
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // before this is reached).  TODO(gab): This code should go in a
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // native desktop specific window sizer as part of fixing
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // crbug.com/175812.
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const BrowserList* native_browser_list =
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_NATIVE);
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      for (BrowserList::const_reverse_iterator it =
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               native_browser_list->begin_last_active();
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           it != native_browser_list->end_last_active(); ++it) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Browser* last_active = *it;
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (last_active && last_active->is_type_tabbed()) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          window = last_active->window();
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DCHECK(window);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          break;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (window) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *bounds = window->GetRestoredBounds();
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (*show_state == ui::SHOW_STATE_DEFAULT && window->IsMaximized())
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *show_state = ui::SHOW_STATE_MAXIMIZED;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string app_name_;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If set, is used as the reference browser for GetLastActiveWindowState.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const Browser* browser_;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DefaultStateProvider);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class DefaultTargetDisplayProvider : public WindowSizer::TargetDisplayProvider {
142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DefaultTargetDisplayProvider() {}
144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual ~DefaultTargetDisplayProvider() {}
145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual gfx::Display GetTargetDisplay(
147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const gfx::Screen* screen,
148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      const gfx::Rect& bounds) const OVERRIDE {
149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#if defined(USE_ASH)
1506d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    bool force_ash = false;
1516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // On Windows check if the browser is launched to serve ASH. If yes then
1526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // we should get the display for the corresponding root window created for
1536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    // ASH. This ensures that the display gets the correct workarea, etc.
154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // If the ASH shell does not exist then the current behavior is to open
155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // browser windows if any on the desktop. Preserve that for now.
156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // TODO(ananta).
157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // This effectively means that the running browser process is in a split
158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // personality mode, part of it running in ASH and the other running in
159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // desktop. This may cause apps and other widgets to not work correctly.
160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Revisit and address.
1616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#if defined(OS_WIN)
162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    force_ash = ash::Shell::HasInstance() &&
1636d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)        CommandLine::ForCurrentProcess()->HasSwitch(switches::kViewerConnect);
1646d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#endif
165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Use the target display on ash.
1666d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (chrome::ShouldOpenAshOnStartup() || force_ash) {
167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      aura::Window* target = ash::Shell::GetTargetRootWindow();
168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      return screen->GetDisplayNearestWindow(target);
169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#endif
171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Find the size of the work area of the monitor that intersects the bounds
172a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // of the anchor window.
173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return screen->GetDisplayMatching(bounds);
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
175a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private:
177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DefaultTargetDisplayProvider);
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}  // namespace
181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WindowSizer, public:
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)WindowSizer::WindowSizer(
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    scoped_ptr<StateProvider> state_provider,
187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    scoped_ptr<TargetDisplayProvider> target_display_provider,
188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const Browser* browser)
189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    : state_provider_(state_provider.Pass()),
190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      target_display_provider_(target_display_provider.Pass()),
191424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // TODO(scottmg): NativeScreen is wrong. http://crbug.com/133312
192424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      screen_(gfx::Screen::GetNativeScreen()),
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_(browser) {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)WindowSizer::WindowSizer(
197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    scoped_ptr<StateProvider> state_provider,
198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    scoped_ptr<TargetDisplayProvider> target_display_provider,
199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    gfx::Screen* screen,
200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const Browser* browser)
201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    : state_provider_(state_provider.Pass()),
202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      target_display_provider_(target_display_provider.Pass()),
203424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      screen_(screen),
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      browser_(browser) {
205424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(screen_);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WindowSizer::~WindowSizer() {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WindowSizer::GetBrowserWindowBoundsAndShowState(
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& app_name,
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& specified_bounds,
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Browser* browser,
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect* window_bounds,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::WindowShowState* show_state) {
218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<StateProvider> state_provider(
219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      new DefaultStateProvider(app_name, browser));
220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<TargetDisplayProvider> target_display_provider(
221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      new DefaultTargetDisplayProvider);
222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const WindowSizer sizer(state_provider.Pass(),
223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                          target_display_provider.Pass(),
224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                          browser);
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sizer.DetermineWindowBoundsAndShowState(specified_bounds,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          window_bounds,
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          show_state);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WindowSizer, private:
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void WindowSizer::DetermineWindowBoundsAndShowState(
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& specified_bounds,
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect* bounds,
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::WindowShowState* show_state) const {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(bounds);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(show_state);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pre-populate the window state with our default.
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *show_state = GetWindowDefaultShowState();
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *bounds = specified_bounds;
242a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(USE_ASH)
244a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // See if ash should decide the window placement.
245a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (GetBrowserBoundsAsh(bounds, show_state))
246a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
248a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
249a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (bounds->IsEmpty()) {
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // See if there's last active window's placement information.
251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (GetLastActiveWindowBounds(bounds, show_state))
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See if there's saved placement information.
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (GetSavedWindowBounds(bounds, show_state))
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
256a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // No saved placement, figure out some sensible default size based on
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // the user's screen size.
259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    GetDefaultWindowBounds(GetTargetDisplay(gfx::Rect()), bounds);
260a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    return;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
262a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
263a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // In case that there was a bound given we need to make sure that it is
264a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // visible and fits on the screen.
265a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Find the size of the work area of the monitor that intersects the bounds
266a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // of the anchor window. Note: AdjustBoundsToBeVisibleOnMonitorContaining
267a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // does not exactly what we want: It makes only sure that "a minimal part"
268a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // is visible on the screen.
269a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  gfx::Rect work_area = screen_->GetDisplayMatching(*bounds).work_area();
270a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Resize so that it fits.
271a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  bounds->AdjustToFit(work_area);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
274a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool WindowSizer::GetLastActiveWindowBounds(
275a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    gfx::Rect* bounds,
276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ui::WindowShowState* show_state) const {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(bounds);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(show_state);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!state_provider_.get() ||
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !state_provider_->GetLastActiveWindowState(bounds, show_state))
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect last_window_bounds = *bounds;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds->Offset(kWindowTilePixels, kWindowTilePixels);
284a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  AdjustBoundsToBeVisibleOnDisplay(screen_->GetDisplayMatching(*bounds),
285a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                   gfx::Rect(),
286a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                   bounds);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool WindowSizer::GetSavedWindowBounds(gfx::Rect* bounds,
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       ui::WindowShowState* show_state) const {
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(bounds);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(show_state);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect saved_work_area;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!state_provider_.get() ||
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !state_provider_->GetPersistentState(bounds,
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           &saved_work_area,
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           show_state))
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
300a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  AdjustBoundsToBeVisibleOnDisplay(GetTargetDisplay(*bounds),
301a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                   saved_work_area,
302a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                   bounds);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void WindowSizer::GetDefaultWindowBounds(const gfx::Display& display,
3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                         gfx::Rect* default_bounds) const {
3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DCHECK(default_bounds);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_ASH)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(beng): insufficient but currently necessary. http://crbug.com/133312
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (chrome::ShouldOpenAshOnStartup()) {
312a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    *default_bounds = ash::WindowPositioner::GetDefaultWindowBounds(display);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  gfx::Rect work_area = display.work_area();
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The default size is either some reasonably wide width, or if the work
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // area is narrower, then the work area width less some aesthetic padding.
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int default_width = std::min(work_area.width() - 2 * kWindowTilePixels, 1050);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int default_height = work_area.height() - 2 * kWindowTilePixels;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For wider aspect ratio displays at higher resolutions, we might size the
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // window narrower to allow two windows to easily be placed side-by-side.
325424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  gfx::Rect screen_size = screen_->GetPrimaryDisplay().bounds();
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double width_to_height =
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static_cast<double>(screen_size.width()) / screen_size.height();
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The least wide a screen can be to qualify for the halving described above.
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kMinScreenWidthForWindowHalving = 1600;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We assume 16:9/10 is a fairly standard indicator of a wide aspect ratio
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // computer display.
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (((width_to_height * 10) >= 16) &&
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      work_area.width() > kMinScreenWidthForWindowHalving) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Halve the work area, subtracting aesthetic padding on either side.
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The padding is set so that two windows, side by side have
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // kWindowTilePixels between screen edge and each other.
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default_width = static_cast<int>(work_area.width() / 2. -
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        1.5 * kWindowTilePixels);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  default_bounds->SetRect(kWindowTilePixels + work_area.x(),
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          kWindowTilePixels + work_area.y(),
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          default_width, default_height);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
346a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void WindowSizer::AdjustBoundsToBeVisibleOnDisplay(
347a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const gfx::Display& display,
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Rect& saved_work_area,
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect* bounds) const {
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(bounds);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
352a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // If |bounds| is empty, reset to the default size.
353a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (bounds->IsEmpty()) {
354a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    gfx::Rect default_bounds;
355a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    GetDefaultWindowBounds(display, &default_bounds);
356a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (bounds->height() <= 0)
357a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      bounds->set_height(default_bounds.height());
358a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (bounds->width() <= 0)
359a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      bounds->set_width(default_bounds.width());
360a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure the minimum height and width.
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds->set_height(std::max(kMinVisibleHeight, bounds->height()));
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds->set_width(std::max(kMinVisibleWidth, bounds->width()));
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  gfx::Rect work_area = display.work_area();
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure that the title bar is not above the work area.
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bounds->y() < work_area.y())
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bounds->set_y(work_area.y());
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reposition and resize the bounds if the saved_work_area is different from
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the current work area and the current work area doesn't completely contain
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the bounds.
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!saved_work_area.IsEmpty() &&
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      saved_work_area != work_area &&
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !work_area.Contains(*bounds)) {
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bounds->set_width(std::min(bounds->width(), work_area.width()));
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bounds->set_height(std::min(bounds->height(), work_area.height()));
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bounds->set_x(
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::max(work_area.x(),
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 std::min(bounds->x(), work_area.right() - bounds->width())));
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bounds->set_y(
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::max(work_area.y(),
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 std::min(bounds->y(), work_area.bottom() - bounds->height())));
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Limit the maximum height.  On the Mac the sizer is on the
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bottom-right of the window, and a window cannot be moved "up"
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // past the menubar.  If the window is too tall you'll never be able
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to shrink it again.  Windows does not have this limitation
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (e.g. can be resized from the top).
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds->set_height(std::min(work_area.height(), bounds->height()));
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On mac, we want to be aggressive about repositioning windows that are
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // partially offscreen.  If the window is partially offscreen horizontally,
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // move it to be flush with the left edge of the work area.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bounds->x() < work_area.x() || bounds->right() > work_area.right())
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bounds->set_x(work_area.x());
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the window is partially offscreen vertically, move it to be flush with
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the top of the work area.
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bounds->y() < work_area.y() || bounds->bottom() > work_area.bottom())
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bounds->set_y(work_area.y());
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On non-Mac platforms, we are less aggressive about repositioning.  Simply
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ensure that at least kMinVisibleWidth * kMinVisibleHeight is visible.
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int min_y = work_area.y() + kMinVisibleHeight - bounds->height();
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int min_x = work_area.x() + kMinVisibleWidth - bounds->width();
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int max_y = work_area.bottom() - kMinVisibleHeight;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int max_x = work_area.right() - kMinVisibleWidth;
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds->set_y(std::max(min_y, std::min(max_y, bounds->y())));
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds->set_x(std::max(min_x, std::min(max_x, bounds->x())));
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_MACOSX)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
417a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)gfx::Display WindowSizer::GetTargetDisplay(const gfx::Rect& bounds) const {
418a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return target_display_provider_->GetTargetDisplay(screen_, bounds);
419a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
420a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ui::WindowShowState WindowSizer::GetWindowDefaultShowState() const {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!browser_)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ui::SHOW_STATE_DEFAULT;
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only tabbed browsers use the command line or preference state, with the
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // exception of devtools.
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool show_state = !browser_->is_type_tabbed() && !browser_->is_devtools();
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(USE_AURA)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We use the apps save state on aura.
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  show_state &= !browser_->is_app();
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (show_state)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return browser_->initial_show_state();
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kStartMaximized))
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ui::SHOW_STATE_MAXIMIZED;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (browser_->initial_show_state() != ui::SHOW_STATE_DEFAULT)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return browser_->initial_show_state();
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise we use the default which can be overridden later on.
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ui::SHOW_STATE_DEFAULT;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
446