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 "ash/wm/workspace/snap_sizer.h" | 5 #include "ash/wm/workspace/snap_sizer.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 | 8 |
| 9 #include "ash/ash_switches.h" | |
| 10 #include "ash/launcher/launcher.h" | |
| 9 #include "ash/screen_ash.h" | 11 #include "ash/screen_ash.h" |
| 12 #include "ash/shell.h" | |
| 13 #include "ash/shell_window_ids.h" | |
| 14 #include "ash/wm/dock/docked_window_layout_manager.h" | |
| 10 #include "ash/wm/property_util.h" | 15 #include "ash/wm/property_util.h" |
| 16 #include "ash/wm/window_properties.h" | |
| 11 #include "ash/wm/window_resizer.h" | 17 #include "ash/wm/window_resizer.h" |
| 12 #include "ash/wm/window_util.h" | 18 #include "ash/wm/window_util.h" |
| 19 #include "base/command_line.h" | |
| 13 #include "ui/aura/window.h" | 20 #include "ui/aura/window.h" |
| 14 #include "ui/gfx/screen.h" | 21 #include "ui/gfx/screen.h" |
| 15 | 22 |
| 16 namespace ash { | 23 namespace ash { |
| 17 namespace internal { | 24 namespace internal { |
| 18 | 25 |
| 19 namespace { | 26 namespace { |
| 20 | 27 |
| 21 // A list of ideal window width in pixel which will be used to populate the | 28 // A list of ideal window width in pixel which will be used to populate the |
| 22 // |usable_width_| list. | 29 // |usable_width_| list. |
| 23 const int kIdealWidth[] = { 1280, 1024, 768, 640 }; | 30 const int kIdealWidth[] = { 1280, 1024, 768, 640 }; |
| 24 | 31 |
| 25 // Windows are initially snapped to the size in |usable_width_| at index 0. | 32 // Windows are initially snapped to the size in |usable_width_| at index 0. |
| 26 // The index into |usable_width_| is changed if any of the following happen: | 33 // The index into |usable_width_| is changed if any of the following happen: |
| 27 // . The user stops moving the mouse for |kDelayBeforeIncreaseMS| and then | 34 // . The user stops moving the mouse for |kDelayBeforeIncreaseMS| and then |
| 28 // moves the mouse again. | 35 // moves the mouse again. |
| 29 // . The mouse moves |kPixelsBeforeAdjust| horizontal pixels. | 36 // . The mouse moves |kPixelsBeforeAdjust| horizontal pixels. |
| 30 // . The mouse is against the edge of the screen and the mouse is moved | 37 // . The mouse is against the edge of the screen and the mouse is moved |
| 31 // |kMovesBeforeAdjust| times. | 38 // |kMovesBeforeAdjust| times. |
| 32 const int kDelayBeforeIncreaseMS = 500; | 39 const int kDelayBeforeIncreaseMS = 500; |
| 33 const int kMovesBeforeAdjust = 25; | 40 const int kMovesBeforeAdjust = 25; |
| 34 const int kPixelsBeforeAdjust = 100; | 41 const int kPixelsBeforeAdjust = 100; |
| 35 | 42 |
| 36 // When the smallest resolution does not fit on the screen, we take this | 43 // When the smallest resolution does not fit on the screen, we take this |
| 37 // fraction of the available space. | 44 // fraction of the available space. |
| 38 const int kMinimumScreenPercent = 90; | 45 const int kMinimumScreenPercent = 90; |
| 39 | 46 |
| 40 // Create the list of possible width for the current screen configuration: | 47 // Create the list of possible width for the current screen configuration: |
| 41 // Fill the |usable_width_| list with items from |kIdealWidth| which fit on | 48 // Returns a list that for windows that can be snapped (|allow_snap| set) |
| 42 // the screen and supplement it with the 'half of screen' size. Furthermore, | 49 // includes items from |kIdealWidth| which fit on the screen and supplement it |
| 43 // add an entry for 90% of the screen size if it is smaller then the biggest | 50 // with the 'half of screen' size. Furthermore, add an entry for 90% of the |
| 44 // value in the |kIdealWidth| list (to get a step between the values). | 51 // screen size if it is smaller then the biggest value in the |kIdealWidth| |
| 45 std::vector<int> BuildIdealWidthList(aura::Window* window) { | 52 // list (to get a step between the values). |
| 53 // When a window can be docked (|allow_dock| set) a zero-width is added as the | |
| 54 // last value to facilitate showing a docking guide. | |
| 55 std::vector<int> BuildIdealWidthList(aura::Window* window, | |
|
sky
2013/09/11 19:38:40
allow_snap is effectively should this function do
varkha
2013/09/11 20:02:10
What about the docking guide (allow_dock)? There a
varkha
2013/09/12 19:49:23
I have removed docking state updates from the Snap
| |
| 56 bool allow_snap, | |
| 57 bool allow_dock) { | |
| 46 std::vector<int> ideal_width_list; | 58 std::vector<int> ideal_width_list; |
| 47 gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window)); | 59 if (allow_snap) { |
| 48 int half_size = work_area.width() / 2; | 60 gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window)); |
| 49 int maximum_width = (kMinimumScreenPercent * work_area.width()) / 100; | 61 int half_size = work_area.width() / 2; |
| 50 for (size_t i = 0; i < arraysize(kIdealWidth); i++) { | 62 int maximum_width = (kMinimumScreenPercent * work_area.width()) / 100; |
| 51 if (maximum_width >= kIdealWidth[i]) { | 63 for (size_t i = 0; i < arraysize(kIdealWidth); i++) { |
| 52 if (i && !ideal_width_list.size() && maximum_width != kIdealWidth[i]) | 64 if (maximum_width >= kIdealWidth[i]) { |
| 53 ideal_width_list.push_back(maximum_width); | 65 if (i && !ideal_width_list.size() && maximum_width != kIdealWidth[i]) |
| 54 if (half_size > kIdealWidth[i]) | 66 ideal_width_list.push_back(maximum_width); |
| 55 ideal_width_list.push_back(half_size); | 67 if (half_size > kIdealWidth[i]) |
| 56 if (half_size >= kIdealWidth[i]) | 68 ideal_width_list.push_back(half_size); |
| 57 half_size = 0; | 69 if (half_size >= kIdealWidth[i]) |
| 58 ideal_width_list.push_back(kIdealWidth[i]); | 70 half_size = 0; |
| 71 ideal_width_list.push_back(kIdealWidth[i]); | |
| 72 } | |
| 59 } | 73 } |
| 74 if (half_size) | |
| 75 ideal_width_list.push_back(half_size); | |
| 60 } | 76 } |
| 61 if (half_size) | 77 if (allow_dock) |
| 62 ideal_width_list.push_back(half_size); | 78 ideal_width_list.push_back(0); |
| 63 | 79 |
| 64 return ideal_width_list; | 80 return ideal_width_list; |
| 65 } | 81 } |
| 66 | 82 |
| 67 } // namespace | 83 } // namespace |
| 68 | 84 |
| 69 SnapSizer::SnapSizer(aura::Window* window, | 85 SnapSizer::SnapSizer(aura::Window* window, |
| 70 const gfx::Point& start, | 86 const gfx::Point& start, |
| 71 Edge edge, | 87 Edge edge, |
| 72 InputType input_type) | 88 InputType input_type) |
| 73 : window_(window), | 89 : window_(window), |
| 74 edge_(edge), | 90 edge_(edge), |
| 75 time_last_update_(base::TimeTicks::Now()), | 91 time_last_update_(base::TimeTicks::Now()), |
| 76 size_index_(0), | 92 size_index_(0), |
| 77 resize_disabled_(false), | 93 resize_disabled_(false), |
| 78 num_moves_since_adjust_(0), | 94 num_moves_since_adjust_(0), |
| 79 last_adjust_x_(start.x()), | 95 last_adjust_x_(start.x()), |
| 80 last_update_x_(start.x()), | 96 last_update_x_(start.x()), |
| 81 start_x_(start.x()), | 97 start_x_(start.x()), |
| 82 input_type_(input_type), | 98 input_type_(input_type) { |
| 83 usable_width_(BuildIdealWidthList(window)) { | 99 aura::Window* dock_container = Shell::GetContainer( |
| 100 window_->GetRootWindow(), kShellWindowId_DockedContainer); | |
| 101 dock_layout_ = static_cast<DockedWindowLayoutManager*>( | |
| 102 dock_container->layout_manager()); | |
| 103 bool allow_dock = | |
| 104 input_type_ == internal::SnapSizer::WORKSPACE_DRAG_INPUT && | |
| 105 CanDockWindow(window_, edge_); | |
| 106 bool allow_snap = !allow_dock || | |
| 107 (wm::CanSnapWindow(window_) && | |
| 108 !dock_layout_->is_dragged_window_docked() && | |
| 109 window->bounds().width() > DockedWindowLayoutManager::kMaxDockWidth); | |
| 110 usable_width_ = BuildIdealWidthList(window, allow_snap, allow_dock); | |
| 84 DCHECK(!usable_width_.empty()); | 111 DCHECK(!usable_width_.empty()); |
| 112 UpdateDockedState(); | |
| 85 target_bounds_ = GetTargetBounds(); | 113 target_bounds_ = GetTargetBounds(); |
| 86 } | 114 } |
| 87 | 115 |
| 88 SnapSizer::~SnapSizer() { | 116 SnapSizer::~SnapSizer() { |
| 117 // Normally when a drag is completed CompleteDrag will be called making | |
| 118 // the following a no-op. updating state is necessary when a window gets | |
| 119 // snapped in and out during the drag. | |
| 120 if (dock_layout_->is_dragged_window_docked()) | |
| 121 dock_layout_->UndockDraggedWindow(); | |
| 89 } | 122 } |
| 90 | 123 |
| 91 void SnapSizer::SnapWindow(aura::Window* window, SnapSizer::Edge edge) { | 124 void SnapSizer::SnapWindow(aura::Window* window, SnapSizer::Edge edge) { |
| 92 if (!wm::CanSnapWindow(window)) | 125 if (!wm::CanSnapWindow(window)) |
| 93 return; | 126 return; |
| 94 internal::SnapSizer sizer(window, gfx::Point(), edge, | 127 internal::SnapSizer sizer(window, gfx::Point(), edge, |
| 95 internal::SnapSizer::OTHER_INPUT); | 128 internal::SnapSizer::OTHER_INPUT); |
| 96 if (wm::IsWindowFullscreen(window) || wm::IsWindowMaximized(window)) { | 129 if (wm::IsWindowFullscreen(window) || wm::IsWindowMaximized(window)) { |
| 97 // Before we can set the bounds we need to restore the window. | 130 // Before we can set the bounds we need to restore the window. |
| 98 // Restoring the window will set the window to its restored bounds. | 131 // Restoring the window will set the window to its restored bounds. |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 129 std::min(pixels_before_adjust, | 162 std::min(pixels_before_adjust, |
| 130 (workspace_bounds.width() - start_x_) / 10); | 163 (workspace_bounds.width() - start_x_) / 10); |
| 131 } | 164 } |
| 132 } | 165 } |
| 133 if (std::abs(location.x() - last_adjust_x_) >= pixels_before_adjust || | 166 if (std::abs(location.x() - last_adjust_x_) >= pixels_before_adjust || |
| 134 (along_edge && num_moves_since_adjust_ >= kMovesBeforeAdjust)) { | 167 (along_edge && num_moves_since_adjust_ >= kMovesBeforeAdjust)) { |
| 135 ChangeBounds(location.x(), | 168 ChangeBounds(location.x(), |
| 136 CalculateIncrement(location.x(), last_adjust_x_)); | 169 CalculateIncrement(location.x(), last_adjust_x_)); |
| 137 } | 170 } |
| 138 } | 171 } |
| 172 UpdateDockedState(); | |
| 139 last_update_x_ = location.x(); | 173 last_update_x_ = location.x(); |
| 140 time_last_update_ = base::TimeTicks::Now(); | 174 time_last_update_ = base::TimeTicks::Now(); |
| 141 } | 175 } |
| 142 | 176 |
| 143 gfx::Rect SnapSizer::GetSnapBounds(const gfx::Rect& bounds) { | 177 gfx::Rect SnapSizer::GetSnapBounds(const gfx::Rect& bounds) { |
| 144 int current = 0; | 178 int current = 0; |
| 145 if (!resize_disabled_) { | 179 if (!resize_disabled_) { |
| 146 for (current = usable_width_.size() - 1; current >= 0; current--) { | 180 for (current = usable_width_.size() - 1; current >= 0; current--) { |
| 147 gfx::Rect target = GetTargetBoundsForSize(current); | 181 gfx::Rect target = GetTargetBoundsForSize(current); |
| 148 if (target == bounds) { | 182 if (target == bounds) { |
| 149 ++current; | 183 ++current; |
| 150 break; | 184 break; |
| 151 } | 185 } |
| 152 } | 186 } |
| 153 } | 187 } |
| 154 return GetTargetBoundsForSize(current % usable_width_.size()); | 188 return GetTargetBoundsForSize(current % usable_width_.size()); |
| 155 } | 189 } |
| 156 | 190 |
| 157 void SnapSizer::SelectDefaultSizeAndDisableResize() { | 191 void SnapSizer::SelectDefaultSizeAndDisableResize() { |
| 158 resize_disabled_ = true; | 192 resize_disabled_ = true; |
| 159 size_index_ = 0; | 193 size_index_ = 0; |
| 194 UpdateDockedState(); | |
| 160 target_bounds_ = GetTargetBounds(); | 195 target_bounds_ = GetTargetBounds(); |
| 161 } | 196 } |
| 162 | 197 |
| 163 gfx::Rect SnapSizer::GetTargetBoundsForSize(size_t size_index) const { | 198 gfx::Rect SnapSizer::GetTargetBoundsForSize(size_t size_index) const { |
| 164 gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window_)); | 199 gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window_)); |
| 165 int y = work_area.y(); | 200 int y = work_area.y(); |
| 166 // We don't align to the bottom of the grid as the launcher may not | 201 // We don't align to the bottom of the grid as the launcher may not |
| 167 // necessarily align to the grid (happens when auto-hidden). | 202 // necessarily align to the grid (happens when auto-hidden). |
| 168 int max_y = work_area.bottom(); | 203 int max_y = work_area.bottom(); |
| 169 int width = 0; | 204 int width = 0; |
| 170 if (resize_disabled_) { | 205 if (resize_disabled_) { |
| 171 // Make sure that we keep the size of the window smaller then a certain | 206 // Make sure that we keep the size of the window smaller then a certain |
| 172 // fraction of the screen space. | 207 // fraction of the screen space. |
| 173 int minimum_size = (kMinimumScreenPercent * work_area.width()) / 100; | 208 int minimum_size = (kMinimumScreenPercent * work_area.width()) / 100; |
| 174 width = std::max(std::min(minimum_size, 1024), work_area.width() / 2); | 209 width = std::max(std::min(minimum_size, 1024), work_area.width() / 2); |
| 175 } else { | 210 } else { |
| 176 DCHECK(size_index < usable_width_.size()); | 211 DCHECK(size_index < usable_width_.size()); |
| 177 width = usable_width_[size_index]; | 212 width = usable_width_[size_index]; |
| 178 } | 213 } |
| 179 | 214 |
| 215 if (width == 0) { | |
| 216 return ScreenAsh::ConvertRectFromScreen(window_->parent(), | |
| 217 dock_layout_->dragged_bounds()); | |
| 218 } | |
| 219 | |
| 180 if (edge_ == LEFT_EDGE) { | 220 if (edge_ == LEFT_EDGE) { |
| 181 int x = work_area.x(); | 221 int x = work_area.x(); |
| 182 int mid_x = x + width; | 222 int mid_x = x + width; |
| 183 return gfx::Rect(x, y, mid_x - x, max_y - y); | 223 return gfx::Rect(x, y, mid_x - x, max_y - y); |
| 184 } | 224 } |
| 185 int max_x = work_area.right(); | 225 int max_x = work_area.right(); |
| 186 int x = max_x - width; | 226 int x = max_x - width; |
| 187 return gfx::Rect(x , y, max_x - x, max_y - y); | 227 return gfx::Rect(x , y, max_x - x, max_y - y); |
| 188 } | 228 } |
| 189 | 229 |
| 230 bool SnapSizer::ShouldDockWindow() const { | |
| 231 // TODO(varkha): use dedicated state. | |
| 232 return (usable_width_[size_index_] == 0); | |
| 233 } | |
| 234 | |
| 235 // static | |
| 236 bool SnapSizer::CanDockWindow(aura::Window* window, SnapSizer::Edge edge) { | |
| 237 if (!CommandLine::ForCurrentProcess()->HasSwitch( | |
| 238 switches::kAshEnableDockedWindows)) { | |
| 239 return false; | |
| 240 } | |
| 241 // Cannot dock on the other size from an existing dock. | |
| 242 aura::Window* dock_container = Shell::GetContainer( | |
| 243 window->GetRootWindow(), kShellWindowId_DockedContainer); | |
| 244 DockedWindowLayoutManager* dock_layout = | |
| 245 static_cast<DockedWindowLayoutManager*>(dock_container->layout_manager()); | |
| 246 const DockedAlignment alignment = dock_layout->CalculateAlignment(); | |
| 247 if ((edge == LEFT_EDGE && alignment == DOCKED_ALIGNMENT_RIGHT) || | |
| 248 (edge == RIGHT_EDGE && alignment == DOCKED_ALIGNMENT_LEFT)) { | |
| 249 return false; | |
| 250 } | |
| 251 | |
| 252 // Do not allow docking on the same side as launcher shelf. | |
| 253 Launcher* shelf = Launcher::ForWindow(window); | |
| 254 if (shelf && | |
| 255 ((edge == LEFT_EDGE && shelf->alignment() == SHELF_ALIGNMENT_LEFT) || | |
| 256 (edge == RIGHT_EDGE && shelf->alignment() == SHELF_ALIGNMENT_RIGHT))) { | |
| 257 return false; | |
| 258 } | |
| 259 return true; | |
| 260 } | |
| 261 | |
| 190 int SnapSizer::CalculateIncrement(int x, int reference_x) const { | 262 int SnapSizer::CalculateIncrement(int x, int reference_x) const { |
| 191 if (AlongEdge(x)) | 263 if (AlongEdge(x)) |
| 192 return 1; | 264 return 1; |
| 193 if (x == reference_x) | 265 if (x == reference_x) |
| 194 return 0; | 266 return 0; |
| 195 if (edge_ == LEFT_EDGE) { | 267 if (edge_ == LEFT_EDGE) { |
| 196 if (x < reference_x) | 268 if (x < reference_x) |
| 197 return 1; | 269 return 1; |
| 198 return -1; | 270 return -1; |
| 199 } | 271 } |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 212 } | 284 } |
| 213 num_moves_since_adjust_ = 0; | 285 num_moves_since_adjust_ = 0; |
| 214 last_adjust_x_ = x; | 286 last_adjust_x_ = x; |
| 215 } | 287 } |
| 216 | 288 |
| 217 gfx::Rect SnapSizer::GetTargetBounds() const { | 289 gfx::Rect SnapSizer::GetTargetBounds() const { |
| 218 return GetTargetBoundsForSize(size_index_); | 290 return GetTargetBoundsForSize(size_index_); |
| 219 } | 291 } |
| 220 | 292 |
| 221 bool SnapSizer::AlongEdge(int x) const { | 293 bool SnapSizer::AlongEdge(int x) const { |
| 222 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(window_)); | 294 gfx::Rect area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window_)); |
| 223 return (x <= area.x()) || (x >= area.right() - 1); | 295 return (x <= area.x()) || (x >= area.right() - 1); |
| 224 } | 296 } |
| 225 | 297 |
| 298 void SnapSizer::UpdateDockedState() { | |
| 299 if (ShouldDockWindow() && | |
| 300 dock_layout_->GetAlignmentOfWindow(window_) != DOCKED_ALIGNMENT_NONE) { | |
| 301 if (!dock_layout_->is_dragged_window_docked()) | |
| 302 dock_layout_->DockDraggedWindow(window_); | |
| 303 target_bounds_ = GetTargetBounds(); | |
| 304 } else { | |
| 305 if (dock_layout_->is_dragged_window_docked()) | |
| 306 dock_layout_->UndockDraggedWindow(); | |
| 307 } | |
| 308 } | |
| 309 | |
| 226 } // namespace internal | 310 } // namespace internal |
| 227 } // namespace ash | 311 } // namespace ash |
| OLD | NEW |