window_sizer_ash.cc revision 58537e28ecd584eab876aee8be7156509866d23a
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/window_sizer/window_sizer.h" 6 7#include "ash/ash_switches.h" 8#include "ash/shell.h" 9#include "ash/wm/mru_window_tracker.h" 10#include "ash/wm/window_util.h" 11#include "ash/wm/workspace/auto_window_management.h" 12#include "base/command_line.h" 13#include "base/compiler_specific.h" 14#include "chrome/browser/ui/browser.h" 15#include "chrome/browser/ui/browser_list.h" 16#include "chrome/browser/ui/browser_window.h" 17#include "ui/aura/root_window.h" 18#include "ui/aura/window.h" 19#include "ui/aura/window_delegate.h" 20#include "ui/gfx/screen.h" 21 22namespace { 23 24// When a window gets opened in default mode and the screen is less than or 25// equal to this width, the window will get opened in maximized mode. This value 26// can be reduced to a "tame" number if the feature is disabled. 27const int kForceMaximizeWidthLimit = 1366; 28const int kForceMaximizeWidthLimitDisabled = 640; 29 30// Check if the given browser is 'valid': It is a tabbed, non minimized 31// window, which intersects with the |bounds_in_screen| area of a given screen. 32bool IsValidBrowser(Browser* browser, const gfx::Rect& bounds_in_screen) { 33 return (browser && browser->window() && 34 !browser->is_type_popup() && 35 !browser->window()->IsMinimized() && 36 browser->window()->GetNativeWindow() && 37 bounds_in_screen.Intersects( 38 browser->window()->GetNativeWindow()->GetBoundsInScreen())); 39} 40 41// Return the number of valid top level windows on the screen defined by 42// the |bounds_in_screen| rectangle. 43int GetNumberOfValidTopLevelBrowserWindows(const gfx::Rect& bounds_in_screen) { 44 int count = 0; 45 const BrowserList* ash_browser_list = 46 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH); 47 for (BrowserList::const_iterator iter = ash_browser_list->begin(); 48 iter != ash_browser_list->end(); 49 ++iter) { 50 if (IsValidBrowser(*iter, bounds_in_screen)) 51 count++; 52 } 53 return count; 54} 55 56// Move the given |bounds_in_screen| on the available |work_area| to the 57// direction. If |move_right| is true, the rectangle gets moved to the right 58// corner. Otherwise to the left side. 59bool MoveRect(const gfx::Rect& work_area, 60 gfx::Rect& bounds_in_screen, 61 bool move_right) { 62 if (move_right) { 63 if (work_area.right() > bounds_in_screen.right()) { 64 bounds_in_screen.set_x(work_area.right() - bounds_in_screen.width()); 65 return true; 66 } 67 } else { 68 if (work_area.x() < bounds_in_screen.x()) { 69 bounds_in_screen.set_x(work_area.x()); 70 return true; 71 } 72 } 73 return false; 74} 75 76} // namespace 77 78// static 79int WindowSizer::GetForceMaximizedWidthLimit() { 80 static int maximum_limit = 0; 81 if (!maximum_limit) { 82 maximum_limit = CommandLine::ForCurrentProcess()->HasSwitch( 83 ash::switches::kAshDisableAutoMaximizing) ? 84 kForceMaximizeWidthLimitDisabled : kForceMaximizeWidthLimit; 85 } 86 return maximum_limit; 87} 88 89void WindowSizer::GetTabbedBrowserBoundsAsh( 90 gfx::Rect* bounds_in_screen, 91 ui::WindowShowState* show_state) const { 92 DCHECK(show_state); 93 DCHECK(bounds_in_screen); 94 DCHECK(!browser_ || browser_->is_type_tabbed()); 95 96 bounds_in_screen->SetRect(0, 0, 0, 0); 97 98 // Experiment: Force the maximize mode for all tabbed windows 99 if (ash::Shell::IsForcedMaximizeMode()) 100 *show_state = ui::SHOW_STATE_MAXIMIZED; 101 102 ui::WindowShowState passed_show_state = *show_state; 103 bool has_saved_bounds = true; 104 if (!GetSavedWindowBounds(bounds_in_screen, show_state)) { 105 has_saved_bounds = false; 106 GetDefaultWindowBoundsAsh(bounds_in_screen); 107 } 108 109 aura::RootWindow* active = ash::Shell::GetActiveRootWindow(); 110 // Always open new window in the active display. 111 gfx::Rect work_area = 112 screen_->GetDisplayMatching(active->GetBoundsInScreen()).work_area(); 113 114 // This is a window / app. See if there is no window and try to place it. 115 int count = GetNumberOfValidTopLevelBrowserWindows(work_area); 116 aura::Window* top_window = ash::GetTopWindowForNewWindow(active); 117 // Our window should not have any impact if we are already on top. 118 if (browser_->window() && 119 top_window == browser_->window()->GetNativeWindow()) 120 top_window = NULL; 121 122 // If there is no valid other window we take the coordinates as is. 123 if ((!count || !top_window)) { 124 if (has_saved_bounds) { 125 // Restore to previous state - if there is one. 126 bounds_in_screen->AdjustToFit(work_area); 127 return; 128 } 129 130 // When using "small screens" we want to always open in full screen mode. 131 if (passed_show_state == ui::SHOW_STATE_DEFAULT && 132 !browser_->is_session_restore() && 133 work_area.width() <= GetForceMaximizedWidthLimit() && 134 (!browser_->window() || !browser_->window()->IsFullscreen())) 135 *show_state = ui::SHOW_STATE_MAXIMIZED; 136 return; 137 } 138 bool maximized = ash::wm::IsWindowMaximized(top_window); 139 // We ignore the saved show state, but look instead for the top level 140 // window's show state. 141 if (passed_show_state == ui::SHOW_STATE_DEFAULT) { 142 *show_state = maximized ? ui::SHOW_STATE_MAXIMIZED : 143 ui::SHOW_STATE_DEFAULT; 144 } 145 146 // Use the size of the other window. The window's bound will be rearranged 147 // in ash::WorkspaceLayoutManager using this location. 148 *bounds_in_screen = top_window->GetBoundsInScreen(); 149} 150 151void WindowSizer::GetDefaultWindowBoundsAsh(gfx::Rect* default_bounds) const { 152 DCHECK(default_bounds); 153 154 gfx::Rect work_area = screen_->GetPrimaryDisplay().work_area(); 155 156 // There should be a 'desktop' border around the window at the left and right 157 // side. 158 int default_width = work_area.width() - 2 * kDesktopBorderSize; 159 // There should also be a 'desktop' border around the window at the top. 160 // Since the workspace excludes the tray area we only need one border size. 161 int default_height = work_area.height() - kDesktopBorderSize; 162 // We align the size to the grid size to avoid any surprise when the 163 // monitor height isn't divide-able by our alignment factor. 164 default_width -= default_width % kDesktopBorderSize; 165 default_height -= default_height % kDesktopBorderSize; 166 int offset_x = kDesktopBorderSize; 167 if (default_width > kMaximumWindowWidth) { 168 // The window should get centered on the screen and not follow the grid. 169 offset_x = (work_area.width() - kMaximumWindowWidth) / 2; 170 default_width = kMaximumWindowWidth; 171 } 172 default_bounds->SetRect(work_area.x() + offset_x, 173 work_area.y() + kDesktopBorderSize, 174 default_width, 175 default_height); 176} 177