| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/window_sizer/window_sizer.h" | 5 #include "chrome/browser/ui/window_sizer/window_sizer.h" |
| 6 | 6 |
| 7 #include "ash/shell.h" | 7 #include "ash/shell.h" |
| 8 #include "ash/wm/window_cycle_controller.h" | 8 #include "ash/wm/window_cycle_controller.h" |
| 9 #include "ash/wm/window_util.h" | 9 #include "ash/wm/window_util.h" |
| 10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
| 11 #include "chrome/browser/browser_process.h" | 11 #include "chrome/browser/browser_process.h" |
| 12 #include "chrome/browser/ui/browser.h" | 12 #include "chrome/browser/ui/browser.h" |
| 13 #include "chrome/browser/ui/browser_list.h" | 13 #include "chrome/browser/ui/browser_list.h" |
| 14 #include "chrome/browser/ui/browser_window.h" | 14 #include "chrome/browser/ui/browser_window.h" |
| 15 #include "ui/aura/root_window.h" |
| 15 #include "ui/aura/window.h" | 16 #include "ui/aura/window.h" |
| 16 #include "ui/aura/window_delegate.h" | 17 #include "ui/aura/window_delegate.h" |
| 17 #include "ui/gfx/screen.h" | 18 #include "ui/gfx/screen.h" |
| 18 | 19 |
| 19 namespace { | 20 namespace { |
| 20 | 21 |
| 21 // Check if the window was not created as popup or as panel. | 22 // Check if the given browser is 'valid': It is a tabbed, non minimized |
| 22 bool IsValidToplevelWindow(aura::Window* window) { | 23 // window, which intersects with the |bounds_in_screen| area of a given screen. |
| 24 bool IsValidBrowser(Browser* browser, const gfx::Rect& bounds_in_screen) { |
| 25 return (browser && browser->window() && |
| 26 !(browser->is_type_popup() || browser->is_type_panel()) && |
| 27 !browser->window()->IsMinimized() && |
| 28 browser->window()->GetNativeWindow() && |
| 29 bounds_in_screen.Intersects( |
| 30 browser->window()->GetNativeWindow()->GetBoundsInScreen())); |
| 31 } |
| 32 |
| 33 // Check if the window was not created as popup or as panel, it is |
| 34 // on the screen defined by |bounds_in_screen| and visible. |
| 35 bool IsValidToplevelWindow(aura::Window* window, |
| 36 const gfx::Rect& bounds_in_screen) { |
| 23 for (BrowserList::const_iterator iter = BrowserList::begin(); | 37 for (BrowserList::const_iterator iter = BrowserList::begin(); |
| 24 iter != BrowserList::end(); | 38 iter != BrowserList::end(); |
| 25 ++iter) { | 39 ++iter) { |
| 26 Browser* browser = *iter; | 40 Browser* browser = *iter; |
| 27 if (browser && browser->window() && | 41 if (browser && browser->window() && |
| 28 browser->window()->GetNativeWindow() == window) { | 42 browser->window()->GetNativeWindow() == window) |
| 29 return (!(browser->is_type_popup() || browser->is_type_panel())); | 43 return IsValidBrowser(browser, bounds_in_screen); |
| 30 } | |
| 31 } | 44 } |
| 32 // A window which has no browser associated with it is probably not a window | 45 // A window which has no browser associated with it is probably not a window |
| 33 // of which we want to copy the size from. | 46 // of which we want to copy the size from. |
| 34 return false; | 47 return false; |
| 35 } | 48 } |
| 36 | 49 |
| 37 // Get the first open window in the stack on the screen. | 50 // Get the first open (non minimized) window which is on the screen defined |
| 38 aura::Window* GetTopWindow() { | 51 // by |bounds_in_screen| and visible. |
| 52 aura::Window* GetTopWindow(const gfx::Rect& bounds_in_screen) { |
| 39 // Get the active window. | 53 // Get the active window. |
| 40 aura::Window* window = ash::wm::GetActiveWindow(); | 54 aura::Window* window = ash::wm::GetActiveWindow(); |
| 41 if (window && window->type() == aura::client::WINDOW_TYPE_NORMAL && | 55 if (window && window->type() == aura::client::WINDOW_TYPE_NORMAL && |
| 42 window->IsVisible() && IsValidToplevelWindow(window)) | 56 window->IsVisible() && IsValidToplevelWindow(window, bounds_in_screen)) |
| 43 return window; | 57 return window; |
| 44 | 58 |
| 45 // Get a list of all windows. | 59 // Get a list of all windows. |
| 46 const std::vector<aura::Window*> windows = | 60 const std::vector<aura::Window*> windows = |
| 47 ash::WindowCycleController::BuildWindowList(NULL); | 61 ash::WindowCycleController::BuildWindowList(NULL); |
| 48 | 62 |
| 49 if (windows.empty()) | 63 if (windows.empty()) |
| 50 return NULL; | 64 return NULL; |
| 51 | 65 |
| 52 aura::Window::Windows::const_iterator iter = windows.begin(); | 66 aura::Window::Windows::const_iterator iter = windows.begin(); |
| 53 // Find the index of the current window. | 67 // Find the index of the current window. |
| 54 if (window) | 68 if (window) |
| 55 iter = std::find(windows.begin(), windows.end(), window); | 69 iter = std::find(windows.begin(), windows.end(), window); |
| 56 | 70 |
| 57 int index = (iter == windows.end()) ? 0 : (iter - windows.begin()); | 71 int index = (iter == windows.end()) ? 0 : (iter - windows.begin()); |
| 58 | 72 |
| 59 // Scan the cycle list backwards to see which is the second topmost window | 73 // Scan the cycle list backwards to see which is the second topmost window |
| 60 // (and so on). Note that we might cycle a few indices twice if there is no | 74 // (and so on). Note that we might cycle a few indices twice if there is no |
| 61 // suitable window. However - since the list is fairly small this should be | 75 // suitable window. However - since the list is fairly small this should be |
| 62 // very fast anyways. | 76 // very fast anyways. |
| 63 for (int i = index + windows.size(); i >= 0; i--) { | 77 for (int i = index + windows.size(); i >= 0; i--) { |
| 64 aura::Window* window = windows[i % windows.size()]; | 78 aura::Window* window = windows[i % windows.size()]; |
| 65 if (window && window->type() == aura::client::WINDOW_TYPE_NORMAL && | 79 if (window && window->type() == aura::client::WINDOW_TYPE_NORMAL && |
| 66 window->IsVisible() && IsValidToplevelWindow(window)) | 80 bounds_in_screen.Intersects(window->GetBoundsInScreen()) && |
| 81 window->IsVisible() && IsValidToplevelWindow(window, bounds_in_screen)) |
| 67 return window; | 82 return window; |
| 68 } | 83 } |
| 69 return NULL; | 84 return NULL; |
| 70 } | 85 } |
| 71 | 86 |
| 87 // Return the number of valid top level windows on the screen defined by |
| 88 // the |bounds_in_screen| rectangle. |
| 89 int GetNumberOfValidTopLevelBrowserWindows(const gfx::Rect& bounds_in_screen) { |
| 90 int count = 0; |
| 91 for (BrowserList::const_iterator iter = BrowserList::begin(); |
| 92 iter != BrowserList::end(); |
| 93 ++iter) { |
| 94 if (IsValidBrowser(*iter, bounds_in_screen)) |
| 95 count++; |
| 96 } |
| 97 return count; |
| 98 } |
| 99 |
| 100 // Move the given |bounds_in_screen| on the available |work_area| to the |
| 101 // direction. If |move_right| is true, the rectangle gets moved to the right |
| 102 // corner. Otherwise to the left side. |
| 103 bool MoveRect(const gfx::Rect& work_area, |
| 104 gfx::Rect& bounds_in_screen, |
| 105 bool move_right) { |
| 106 if (move_right) { |
| 107 if (work_area.right() > bounds_in_screen.right()) { |
| 108 bounds_in_screen.set_x(work_area.right() - bounds_in_screen.width()); |
| 109 return true; |
| 110 } |
| 111 } else { |
| 112 if (work_area.x() < bounds_in_screen.x()) { |
| 113 bounds_in_screen.set_x(work_area.x()); |
| 114 return true; |
| 115 } |
| 116 } |
| 117 return false; |
| 118 } |
| 119 |
| 72 } // namespace | 120 } // namespace |
| 73 | 121 |
| 74 bool WindowSizer::GetBoundsIgnoringPreviousStateAsh( | 122 bool WindowSizer::GetBoundsOverrideAsh(const gfx::Rect& specified_bounds, |
| 75 const gfx::Rect& specified_bounds, | 123 gfx::Rect* bounds_in_screen) const { |
| 76 gfx::Rect* bounds) const { | 124 *bounds_in_screen = specified_bounds; |
| 77 *bounds = specified_bounds; | 125 DCHECK(bounds_in_screen->IsEmpty()); |
| 78 DCHECK(bounds->IsEmpty()); | 126 |
| 127 if (!GetSavedWindowBounds(bounds_in_screen)) |
| 128 GetDefaultWindowBounds(bounds_in_screen); |
| 129 |
| 79 if (browser_ != NULL && browser_->type() == Browser::TYPE_TABBED) { | 130 if (browser_ != NULL && browser_->type() == Browser::TYPE_TABBED) { |
| 131 gfx::Rect work_area = |
| 132 monitor_info_provider_->GetMonitorWorkAreaMatching(*bounds_in_screen); |
| 80 // This is a window / app. See if there is no window and try to place it. | 133 // This is a window / app. See if there is no window and try to place it. |
| 81 aura::Window* top_window = GetTopWindow(); | 134 int count = GetNumberOfValidTopLevelBrowserWindows(work_area); |
| 82 // If there are no windows we have a special case and try to | 135 aura::Window* top_window = GetTopWindow(work_area); |
| 83 // maximize which leaves a 'border' which shows the desktop. | 136 |
| 84 if (top_window == NULL) { | 137 // If there is no valid other window we take the coordinates as is. |
| 85 GetDefaultWindowBounds(bounds); | 138 if (!count || !top_window || ash::wm::IsWindowMaximized(top_window)) |
| 86 } else { | 139 return true; |
| 87 *bounds = top_window->GetBoundsInScreen(); | 140 |
| 88 gfx::Rect work_area = | 141 gfx::Rect other_bounds_in_screen = top_window->GetBoundsInScreen(); |
| 89 monitor_info_provider_->GetMonitorWorkAreaMatching(*bounds); | 142 bool move_right = |
| 90 *bounds = bounds->AdjustToFit(work_area); | 143 other_bounds_in_screen.CenterPoint().x() < work_area.CenterPoint().x(); |
| 144 |
| 145 // In case we have only one window, we move the other window fully to the |
| 146 // "other side" - making room for this new window. |
| 147 if (count == 1) { |
| 148 gfx::Display display = |
| 149 gfx::Screen::GetDisplayMatching( |
| 150 top_window->GetRootWindow()->GetBoundsInScreen()); |
| 151 if (MoveRect(work_area, other_bounds_in_screen, !move_right)) |
| 152 top_window->SetBoundsInScreen(other_bounds_in_screen, display); |
| 91 } | 153 } |
| 154 // Use the size of the other window, and mirror the location to the |
| 155 // opposite side. Then make sure that it is inside our work area |
| 156 // (if possible). |
| 157 *bounds_in_screen = other_bounds_in_screen; |
| 158 MoveRect(work_area, *bounds_in_screen, move_right); |
| 159 if (bounds_in_screen->bottom() > work_area.bottom()) |
| 160 bounds_in_screen->set_y(std::max(work_area.y(), |
| 161 work_area.bottom() - bounds_in_screen->height())); |
| 92 return true; | 162 return true; |
| 93 // If both fail we will continue the default path. | |
| 94 } | 163 } |
| 95 | 164 |
| 96 return false; | 165 return false; |
| 97 } | 166 } |
| 98 | 167 |
| 99 void WindowSizer::GetDefaultWindowBoundsAsh(gfx::Rect* default_bounds) const { | 168 void WindowSizer::GetDefaultWindowBoundsAsh(gfx::Rect* default_bounds) const { |
| 100 DCHECK(default_bounds); | 169 DCHECK(default_bounds); |
| 101 DCHECK(monitor_info_provider_.get()); | 170 DCHECK(monitor_info_provider_.get()); |
| 102 | 171 |
| 103 gfx::Rect work_area = monitor_info_provider_->GetPrimaryDisplayWorkArea(); | 172 gfx::Rect work_area = monitor_info_provider_->GetPrimaryDisplayWorkArea(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 116 if (default_width > kMaximumWindowWidth) { | 185 if (default_width > kMaximumWindowWidth) { |
| 117 // The window should get centered on the screen and not follow the grid. | 186 // The window should get centered on the screen and not follow the grid. |
| 118 offset_x = (work_area.width() - kMaximumWindowWidth) / 2; | 187 offset_x = (work_area.width() - kMaximumWindowWidth) / 2; |
| 119 default_width = kMaximumWindowWidth; | 188 default_width = kMaximumWindowWidth; |
| 120 } | 189 } |
| 121 default_bounds->SetRect(work_area.x() + offset_x, | 190 default_bounds->SetRect(work_area.x() + offset_x, |
| 122 work_area.y() + kDesktopBorderSize, | 191 work_area.y() + kDesktopBorderSize, |
| 123 default_width, | 192 default_width, |
| 124 default_height); | 193 default_height); |
| 125 } | 194 } |
| OLD | NEW |