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