Chromium Code Reviews| 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/window.h" | 15 #include "ui/aura/window.h" |
| 16 #include "ui/aura/window_delegate.h" | 16 #include "ui/aura/window_delegate.h" |
| 17 #include "ui/gfx/screen.h" | 17 #include "ui/gfx/screen.h" |
| 18 | 18 |
| 19 namespace { | 19 namespace { |
| 20 | 20 |
| 21 // Check if the window was not created as popup or as panel. | 21 // Check if the window was not created as popup or as panel, it is |
| 22 bool IsValidToplevelWindow(aura::Window* window) { | 22 // on the screen defined by |bounds| and visible. |
| 23 bool IsValidToplevelWindow(aura::Window* window, const gfx::Rect& bounds) { | |
| 23 for (BrowserList::const_iterator iter = BrowserList::begin(); | 24 for (BrowserList::const_iterator iter = BrowserList::begin(); |
| 24 iter != BrowserList::end(); | 25 iter != BrowserList::end(); |
| 25 ++iter) { | 26 ++iter) { |
| 26 Browser* browser = *iter; | 27 Browser* browser = *iter; |
| 27 if (browser && browser->window() && | 28 if (browser && browser->window() && |
| 28 browser->window()->GetNativeWindow() == window) { | 29 browser->window()->GetNativeWindow() == window) { |
| 29 return (!(browser->is_type_popup() || browser->is_type_panel())); | 30 return (!(browser->is_type_popup() || browser->is_type_panel()) && |
| 31 !browser->window()->IsMinimized() && | |
| 32 bounds.Intersects(browser->window()->GetBounds())); | |
| 30 } | 33 } |
| 31 } | 34 } |
| 32 // A window which has no browser associated with it is probably not a window | 35 // A window which has no browser associated with it is probably not a window |
| 33 // of which we want to copy the size from. | 36 // of which we want to copy the size from. |
| 34 return false; | 37 return false; |
| 35 } | 38 } |
| 36 | 39 |
| 37 // Get the first open window in the stack on the screen. | 40 // Get the first open (non minimized) window which is on the screen defined |
| 38 aura::Window* GetTopWindow() { | 41 // by |bounds| and visible. |
| 42 aura::Window* GetTopWindow(const gfx::Rect& bounds) { | |
|
sky
2012/09/13 15:44:51
The coordinates you pass in here are in screen coo
Mr4D (OOO till 08-26)
2012/09/13 16:45:08
Right! Done.
| |
| 39 // Get the active window. | 43 // Get the active window. |
| 40 aura::Window* window = ash::wm::GetActiveWindow(); | 44 aura::Window* window = ash::wm::GetActiveWindow(); |
| 41 if (window && window->type() == aura::client::WINDOW_TYPE_NORMAL && | 45 if (window && window->type() == aura::client::WINDOW_TYPE_NORMAL && |
| 42 window->IsVisible() && IsValidToplevelWindow(window)) | 46 window->IsVisible() && IsValidToplevelWindow(window, bounds)) |
| 43 return window; | 47 return window; |
| 44 | 48 |
| 45 // Get a list of all windows. | 49 // Get a list of all windows. |
| 46 const std::vector<aura::Window*> windows = | 50 const std::vector<aura::Window*> windows = |
| 47 ash::WindowCycleController::BuildWindowList(NULL); | 51 ash::WindowCycleController::BuildWindowList(NULL); |
| 48 | 52 |
| 49 if (windows.empty()) | 53 if (windows.empty()) |
| 50 return NULL; | 54 return NULL; |
| 51 | 55 |
| 52 aura::Window::Windows::const_iterator iter = windows.begin(); | 56 aura::Window::Windows::const_iterator iter = windows.begin(); |
| 53 // Find the index of the current window. | 57 // Find the index of the current window. |
| 54 if (window) | 58 if (window) |
| 55 iter = std::find(windows.begin(), windows.end(), window); | 59 iter = std::find(windows.begin(), windows.end(), window); |
| 56 | 60 |
| 57 int index = (iter == windows.end()) ? 0 : (iter - windows.begin()); | 61 int index = (iter == windows.end()) ? 0 : (iter - windows.begin()); |
| 58 | 62 |
| 59 // Scan the cycle list backwards to see which is the second topmost window | 63 // 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 | 64 // (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 | 65 // suitable window. However - since the list is fairly small this should be |
| 62 // very fast anyways. | 66 // very fast anyways. |
| 63 for (int i = index + windows.size(); i >= 0; i--) { | 67 for (int i = index + windows.size(); i >= 0; i--) { |
| 64 aura::Window* window = windows[i % windows.size()]; | 68 aura::Window* window = windows[i % windows.size()]; |
| 65 if (window && window->type() == aura::client::WINDOW_TYPE_NORMAL && | 69 if (window && window->type() == aura::client::WINDOW_TYPE_NORMAL && |
| 66 window->IsVisible() && IsValidToplevelWindow(window)) | 70 bounds.Intersects(window->bounds()) && |
| 71 window->IsVisible() && IsValidToplevelWindow(window, bounds)) | |
| 67 return window; | 72 return window; |
| 68 } | 73 } |
| 69 return NULL; | 74 return NULL; |
| 70 } | 75 } |
| 71 | 76 |
| 77 // Return the number of valid top level windows on the screen defined by | |
| 78 // the |bounds| rectangle. | |
| 79 int GetNumberOfValidTopLevelWindows(const gfx::Rect& bounds) { | |
|
sky
2012/09/13 15:44:51
This method is named as though it wants all top le
Mr4D (OOO till 08-26)
2012/09/13 16:45:08
Done.
| |
| 80 int count = 0; | |
| 81 for (BrowserList::const_iterator iter = BrowserList::begin(); | |
| 82 iter != BrowserList::end(); | |
| 83 ++iter) { | |
| 84 Browser* browser = *iter; | |
| 85 | |
| 86 if (browser && browser->window() && | |
|
sky
2012/09/13 15:44:51
Can this and IsToplevelWindow share code?
Mr4D (OOO till 08-26)
2012/09/13 16:45:08
Done.
| |
| 87 bounds.Intersects(browser->window()->GetBounds()) && | |
| 88 !browser->window()->IsMinimized() && | |
| 89 !(browser->is_type_popup() || browser->is_type_panel())) | |
| 90 count++; | |
| 91 } | |
| 92 return count; | |
| 93 } | |
| 94 | |
| 95 // Move the given |bounds| on the available |work_area| to the direction. | |
| 96 // If |move_right| is true, the rectangle gets moved to the right corner. | |
| 97 // otherwise to the left side. | |
| 98 bool MoveRect(const gfx::Rect& work_area, gfx::Rect& bounds, bool move_right) { | |
| 99 if (move_right) { | |
| 100 if (work_area.right() > bounds.right()) { | |
| 101 bounds.set_x(work_area.right() - bounds.width()); | |
| 102 return true; | |
| 103 } | |
| 104 } else { | |
| 105 if (work_area.x() < bounds.x()) { | |
| 106 bounds.set_x(work_area.x()); | |
| 107 return true; | |
| 108 } | |
| 109 } | |
| 110 return false; | |
| 111 } | |
| 112 | |
| 72 } // namespace | 113 } // namespace |
| 73 | 114 |
| 74 bool WindowSizer::GetBoundsIgnoringPreviousStateAsh( | 115 bool WindowSizer::GetBoundsOverrideAsh(const gfx::Rect& specified_bounds, |
| 75 const gfx::Rect& specified_bounds, | 116 gfx::Rect* bounds) const { |
| 76 gfx::Rect* bounds) const { | |
| 77 *bounds = specified_bounds; | 117 *bounds = specified_bounds; |
| 78 DCHECK(bounds->IsEmpty()); | 118 DCHECK(bounds->IsEmpty()); |
| 119 | |
| 120 if (!GetSavedWindowBounds(bounds)) | |
| 121 GetDefaultWindowBounds(bounds); | |
| 122 | |
| 79 if (browser_ != NULL && browser_->type() == Browser::TYPE_TABBED) { | 123 if (browser_ != NULL && browser_->type() == Browser::TYPE_TABBED) { |
| 124 gfx::Rect work_area = | |
| 125 monitor_info_provider_->GetMonitorWorkAreaMatching(*bounds); | |
| 80 // This is a window / app. See if there is no window and try to place it. | 126 // This is a window / app. See if there is no window and try to place it. |
| 81 aura::Window* top_window = GetTopWindow(); | 127 int count = GetNumberOfValidTopLevelWindows(work_area); |
| 82 // If there are no windows we have a special case and try to | 128 aura::Window* top_window = GetTopWindow(work_area); |
| 83 // maximize which leaves a 'border' which shows the desktop. | 129 |
| 84 if (top_window == NULL) { | 130 // If there is no valid other window we take the coordinates as is. |
| 85 GetDefaultWindowBounds(bounds); | 131 if (!count || !top_window || ash::wm::IsWindowMaximized(top_window)) |
| 86 } else { | 132 return true; |
| 87 *bounds = top_window->GetBoundsInScreen(); | 133 |
| 88 gfx::Rect work_area = | 134 gfx::Rect other_bounds = top_window->bounds(); |
| 89 monitor_info_provider_->GetMonitorWorkAreaMatching(*bounds); | 135 bool move_right = |
| 90 *bounds = bounds->AdjustToFit(work_area); | 136 other_bounds.CenterPoint().x() < work_area.CenterPoint().x(); |
| 137 | |
| 138 // In case we have only one window, we move the other window fully to the | |
| 139 // "other side" - making room for this new window. | |
| 140 if (count == 1) { | |
| 141 if (MoveRect(work_area, other_bounds, !move_right)) | |
| 142 top_window->SetBounds(other_bounds); | |
| 91 } | 143 } |
| 144 // Use the size of the other window, and mirror the location to the | |
| 145 // opposite side. Then make sure that it is inside our work area | |
| 146 // (if possible). | |
| 147 *bounds = other_bounds; | |
| 148 MoveRect(work_area, *bounds, move_right); | |
| 149 if (bounds->bottom() > work_area.bottom()) | |
| 150 bounds->set_y(std::max(work_area.y(), | |
| 151 work_area.bottom() - bounds->height())); | |
| 92 return true; | 152 return true; |
| 93 // If both fail we will continue the default path. | |
| 94 } | 153 } |
| 95 | 154 |
| 96 return false; | 155 return false; |
| 97 } | 156 } |
| 98 | 157 |
| 99 void WindowSizer::GetDefaultWindowBoundsAsh(gfx::Rect* default_bounds) const { | 158 void WindowSizer::GetDefaultWindowBoundsAsh(gfx::Rect* default_bounds) const { |
| 100 DCHECK(default_bounds); | 159 DCHECK(default_bounds); |
| 101 DCHECK(monitor_info_provider_.get()); | 160 DCHECK(monitor_info_provider_.get()); |
| 102 | 161 |
| 103 gfx::Rect work_area = monitor_info_provider_->GetPrimaryDisplayWorkArea(); | 162 gfx::Rect work_area = monitor_info_provider_->GetPrimaryDisplayWorkArea(); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 116 if (default_width > kMaximumWindowWidth) { | 175 if (default_width > kMaximumWindowWidth) { |
| 117 // The window should get centered on the screen and not follow the grid. | 176 // The window should get centered on the screen and not follow the grid. |
| 118 offset_x = (work_area.width() - kMaximumWindowWidth) / 2; | 177 offset_x = (work_area.width() - kMaximumWindowWidth) / 2; |
| 119 default_width = kMaximumWindowWidth; | 178 default_width = kMaximumWindowWidth; |
| 120 } | 179 } |
| 121 default_bounds->SetRect(work_area.x() + offset_x, | 180 default_bounds->SetRect(work_area.x() + offset_x, |
| 122 work_area.y() + kDesktopBorderSize, | 181 work_area.y() + kDesktopBorderSize, |
| 123 default_width, | 182 default_width, |
| 124 default_height); | 183 default_height); |
| 125 } | 184 } |
| OLD | NEW |