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 |