Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(512)

Side by Side Diff: ash/wm/workspace/snap_sizer.cc

Issue 23431009: Windows docking should get triggered by pressing against the screen edge (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Windows docking should get triggered by pressing against the screen edge Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 // Fill the |usable_width_| list with items from |kIdealWidth| which fit on
flackr 2013/09/06 02:18:43 Looks like an out of date comment, this returns th
varkha 2013/09/09 15:38:42 Done.
42 // the screen and supplement it with the 'half of screen' size. Furthermore, 49 // the screen and supplement it with the 'half of screen' size. Furthermore,
43 // add an entry for 90% of the screen size if it is smaller then the biggest 50 // add an entry for 90% of the screen size if it is smaller then the biggest
44 // value in the |kIdealWidth| list (to get a step between the values). 51 // value in the |kIdealWidth| list (to get a step between the values).
flackr 2013/09/06 02:18:43 Comment |allow_max| and |allow_dock|.
varkha 2013/09/09 15:38:42 Done.
45 std::vector<int> BuildIdealWidthList(aura::Window* window) { 52 std::vector<int> BuildIdealWidthList(aura::Window* window,
53 bool allow_max,
54 bool allow_dock) {
46 std::vector<int> ideal_width_list; 55 std::vector<int> ideal_width_list;
47 gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window)); 56 if (allow_max) {
48 int half_size = work_area.width() / 2; 57 gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window));
49 int maximum_width = (kMinimumScreenPercent * work_area.width()) / 100; 58 int half_size = work_area.width() / 2;
50 for (size_t i = 0; i < arraysize(kIdealWidth); i++) { 59 int maximum_width = (kMinimumScreenPercent * work_area.width()) / 100;
51 if (maximum_width >= kIdealWidth[i]) { 60 for (size_t i = 0; i < arraysize(kIdealWidth); i++) {
52 if (i && !ideal_width_list.size() && maximum_width != kIdealWidth[i]) 61 if (maximum_width >= kIdealWidth[i]) {
53 ideal_width_list.push_back(maximum_width); 62 if (i && !ideal_width_list.size() && maximum_width != kIdealWidth[i])
54 if (half_size > kIdealWidth[i]) 63 ideal_width_list.push_back(maximum_width);
55 ideal_width_list.push_back(half_size); 64 if (half_size > kIdealWidth[i])
56 if (half_size >= kIdealWidth[i]) 65 ideal_width_list.push_back(half_size);
57 half_size = 0; 66 if (half_size >= kIdealWidth[i])
58 ideal_width_list.push_back(kIdealWidth[i]); 67 half_size = 0;
68 ideal_width_list.push_back(kIdealWidth[i]);
69 }
59 } 70 }
71 if (half_size)
72 ideal_width_list.push_back(half_size);
60 } 73 }
61 if (half_size) 74 // if (allow_max) {
62 ideal_width_list.push_back(half_size); 75 // gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window));
76 // ideal_width_list.push_back(work_area.width() / 2);
77 // }
flackr 2013/09/06 02:18:43 Remove commented code.
varkha 2013/09/09 15:38:42 Done.
78
79 if (allow_dock)
80 ideal_width_list.push_back(0);
63 81
64 return ideal_width_list; 82 return ideal_width_list;
65 } 83 }
66 84
67 } // namespace 85 } // namespace
68 86
69 SnapSizer::SnapSizer(aura::Window* window, 87 SnapSizer::SnapSizer(aura::Window* window,
70 const gfx::Point& start, 88 const gfx::Point& start,
71 Edge edge, 89 Edge edge,
72 InputType input_type) 90 InputType input_type)
73 : window_(window), 91 : window_(window),
74 edge_(edge), 92 edge_(edge),
75 time_last_update_(base::TimeTicks::Now()), 93 time_last_update_(base::TimeTicks::Now()),
76 size_index_(0), 94 size_index_(0),
77 resize_disabled_(false), 95 resize_disabled_(false),
78 num_moves_since_adjust_(0), 96 num_moves_since_adjust_(0),
79 last_adjust_x_(start.x()), 97 last_adjust_x_(start.x()),
80 last_update_x_(start.x()), 98 last_update_x_(start.x()),
81 start_x_(start.x()), 99 start_x_(start.x()),
82 input_type_(input_type), 100 input_type_(input_type) {
83 usable_width_(BuildIdealWidthList(window)) { 101 aura::Window* dock_container = Shell::GetContainer(
102 window_->GetRootWindow(), kShellWindowId_DockedContainer);
103 dock_layout_ = static_cast<DockedWindowLayoutManager*>(
104 dock_container->layout_manager());
105 bool allow_dock =
106 input_type_ == internal::SnapSizer::WORKSPACE_DRAG_INPUT &&
107 CanDockWindow(window_, edge_);
108 bool allow_snap =
109 !allow_dock ||
flackr 2013/09/06 02:18:43 nit: Move up to previous line.
varkha 2013/09/09 15:38:42 Done.
110 (wm::CanSnapWindow(window_) &&
111 !dock_layout_->is_dragged_window_docked() &&
112 window->bounds().width() > DockedWindowLayoutManager::kMaxDockWidth &&
113 (window_->type() != aura::client::WINDOW_TYPE_PANEL));
114 usable_width_ = BuildIdealWidthList(window, allow_snap, allow_dock);
flackr 2013/09/06 02:18:43 In BuildIdealWidthList, you call allow_snap allox_
varkha 2013/09/09 15:38:42 Done (renamed allow_max -> allow_snap for consiste
84 DCHECK(!usable_width_.empty()); 115 DCHECK(!usable_width_.empty());
116 UpdateDockedState();
85 target_bounds_ = GetTargetBounds(); 117 target_bounds_ = GetTargetBounds();
86 } 118 }
87 119
88 SnapSizer::~SnapSizer() { 120 SnapSizer::~SnapSizer() {
121 if (dock_layout_->is_dragged_window_docked())
122 dock_layout_->UndockDraggedWindow();
89 } 123 }
90 124
91 void SnapSizer::SnapWindow(aura::Window* window, SnapSizer::Edge edge) { 125 void SnapSizer::SnapWindow(aura::Window* window, SnapSizer::Edge edge) {
92 if (!wm::CanSnapWindow(window)) 126 if (!wm::CanSnapWindow(window))
93 return; 127 return;
94 internal::SnapSizer sizer(window, gfx::Point(), edge, 128 internal::SnapSizer sizer(window, gfx::Point(), edge,
95 internal::SnapSizer::OTHER_INPUT); 129 internal::SnapSizer::OTHER_INPUT);
96 if (wm::IsWindowFullscreen(window) || wm::IsWindowMaximized(window)) { 130 if (wm::IsWindowFullscreen(window) || wm::IsWindowMaximized(window)) {
97 // Before we can set the bounds we need to restore the window. 131 // Before we can set the bounds we need to restore the window.
98 // Restoring the window will set the window to its restored bounds. 132 // Restoring the window will set the window to its restored bounds.
99 // To avoid an unnecessary bounds changes (which may have side effects) 133 // To avoid an unnecessary bounds changes (which may have side effects)
100 // we set the restore bounds to the bounds we want, restore the window, 134 // we set the restore bounds to the bounds we want, restore the window,
101 // then reset the restore bounds. This way no unnecessary bounds 135 // then reset the restore bounds. This way no unnecessary bounds
102 // changes occurs and the original restore bounds is remembered. 136 // changes occurs and the original restore bounds is remembered.
103 gfx::Rect restore = *GetRestoreBoundsInScreen(window); 137 gfx::Rect restore = *GetRestoreBoundsInScreen(window);
104 SetRestoreBoundsInParent(window, sizer.GetSnapBounds(window->bounds())); 138 SetRestoreBoundsInParent(window, sizer.GetSnapBounds(window->bounds()));
105 wm::RestoreWindow(window); 139 wm::RestoreWindow(window);
106 SetRestoreBoundsInScreen(window, restore); 140 SetRestoreBoundsInScreen(window, restore);
107 } else { 141 } else {
108 window->SetBounds(sizer.GetSnapBounds(window->bounds())); 142 window->SetBounds(sizer.GetSnapBounds(window->bounds()));
109 } 143 }
110 } 144 }
111 145
112 void SnapSizer::Update(const gfx::Point& location) { 146 void SnapSizer::Update(const gfx::Point& location) {
147 LOG(INFO) << "Update to " << location.ToString();
148
113 // See description above for details on this behavior. 149 // See description above for details on this behavior.
114 num_moves_since_adjust_++; 150 num_moves_since_adjust_++;
115 if ((base::TimeTicks::Now() - time_last_update_).InMilliseconds() > 151 if ((base::TimeTicks::Now() - time_last_update_).InMilliseconds() >
116 kDelayBeforeIncreaseMS) { 152 kDelayBeforeIncreaseMS) {
117 ChangeBounds(location.x(), 153 ChangeBounds(location.x(),
118 CalculateIncrement(location.x(), last_update_x_)); 154 CalculateIncrement(location.x(), last_update_x_));
119 } else { 155 } else {
120 bool along_edge = AlongEdge(location.x()); 156 bool along_edge = AlongEdge(location.x());
121 int pixels_before_adjust = kPixelsBeforeAdjust; 157 int pixels_before_adjust = kPixelsBeforeAdjust;
122 if (input_type_ == TOUCH_MAXIMIZE_BUTTON_INPUT) { 158 if (input_type_ == TOUCH_MAXIMIZE_BUTTON_INPUT) {
123 const gfx::Rect& workspace_bounds = window_->parent()->bounds(); 159 const gfx::Rect& workspace_bounds = window_->parent()->bounds();
124 if (start_x_ > location.x()) { 160 if (start_x_ > location.x()) {
125 pixels_before_adjust = 161 pixels_before_adjust =
126 std::min(pixels_before_adjust, start_x_ / 10); 162 std::min(pixels_before_adjust, start_x_ / 10);
127 } else { 163 } else {
128 pixels_before_adjust = 164 pixels_before_adjust =
129 std::min(pixels_before_adjust, 165 std::min(pixels_before_adjust,
130 (workspace_bounds.width() - start_x_) / 10); 166 (workspace_bounds.width() - start_x_) / 10);
131 } 167 }
132 } 168 }
133 if (std::abs(location.x() - last_adjust_x_) >= pixels_before_adjust || 169 if (std::abs(location.x() - last_adjust_x_) >= pixels_before_adjust ||
134 (along_edge && num_moves_since_adjust_ >= kMovesBeforeAdjust)) { 170 (along_edge && num_moves_since_adjust_ >= kMovesBeforeAdjust)) {
135 ChangeBounds(location.x(), 171 ChangeBounds(location.x(),
136 CalculateIncrement(location.x(), last_adjust_x_)); 172 CalculateIncrement(location.x(), last_adjust_x_));
137 } 173 }
138 } 174 }
175 UpdateDockedState();
139 last_update_x_ = location.x(); 176 last_update_x_ = location.x();
140 time_last_update_ = base::TimeTicks::Now(); 177 time_last_update_ = base::TimeTicks::Now();
141 } 178 }
142 179
143 gfx::Rect SnapSizer::GetSnapBounds(const gfx::Rect& bounds) { 180 gfx::Rect SnapSizer::GetSnapBounds(const gfx::Rect& bounds) {
144 int current = 0; 181 int current = 0;
145 if (!resize_disabled_) { 182 if (!resize_disabled_) {
146 for (current = usable_width_.size() - 1; current >= 0; current--) { 183 for (current = usable_width_.size() - 1; current >= 0; current--) {
147 gfx::Rect target = GetTargetBoundsForSize(current); 184 gfx::Rect target = GetTargetBoundsForSize(current);
148 if (target == bounds) { 185 if (target == bounds) {
149 ++current; 186 ++current;
150 break; 187 break;
151 } 188 }
152 } 189 }
153 } 190 }
154 return GetTargetBoundsForSize(current % usable_width_.size()); 191 return GetTargetBoundsForSize(current % usable_width_.size());
155 } 192 }
156 193
157 void SnapSizer::SelectDefaultSizeAndDisableResize() { 194 void SnapSizer::SelectDefaultSizeAndDisableResize() {
158 resize_disabled_ = true; 195 resize_disabled_ = true;
159 size_index_ = 0; 196 size_index_ = 0;
197 UpdateDockedState();
160 target_bounds_ = GetTargetBounds(); 198 target_bounds_ = GetTargetBounds();
161 } 199 }
162 200
163 gfx::Rect SnapSizer::GetTargetBoundsForSize(size_t size_index) const { 201 gfx::Rect SnapSizer::GetTargetBoundsForSize(size_t size_index) const {
164 gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window_)); 202 gfx::Rect work_area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window_));
165 int y = work_area.y(); 203 int y = work_area.y();
166 // We don't align to the bottom of the grid as the launcher may not 204 // 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). 205 // necessarily align to the grid (happens when auto-hidden).
168 int max_y = work_area.bottom(); 206 int max_y = work_area.bottom();
169 int width = 0; 207 int width = 0;
170 if (resize_disabled_) { 208 if (resize_disabled_) {
171 // Make sure that we keep the size of the window smaller then a certain 209 // Make sure that we keep the size of the window smaller then a certain
172 // fraction of the screen space. 210 // fraction of the screen space.
173 int minimum_size = (kMinimumScreenPercent * work_area.width()) / 100; 211 int minimum_size = (kMinimumScreenPercent * work_area.width()) / 100;
174 width = std::max(std::min(minimum_size, 1024), work_area.width() / 2); 212 width = std::max(std::min(minimum_size, 1024), work_area.width() / 2);
175 } else { 213 } else {
176 DCHECK(size_index < usable_width_.size()); 214 DCHECK(size_index < usable_width_.size());
177 width = usable_width_[size_index]; 215 width = usable_width_[size_index];
178 } 216 }
179 217
218 if (width == 0) {
219 LOG(INFO) << "snap bounds " << dock_layout_->dragged_bounds().ToString();
220 return ScreenAsh::ConvertRectFromScreen(window_->parent(),
221 dock_layout_->dragged_bounds());
222 }
223
180 if (edge_ == LEFT_EDGE) { 224 if (edge_ == LEFT_EDGE) {
181 int x = work_area.x(); 225 int x = work_area.x();
182 int mid_x = x + width; 226 int mid_x = x + width;
183 return gfx::Rect(x, y, mid_x - x, max_y - y); 227 return gfx::Rect(x, y, mid_x - x, max_y - y);
184 } 228 }
185 int max_x = work_area.right(); 229 int max_x = work_area.right();
186 int x = max_x - width; 230 int x = max_x - width;
187 return gfx::Rect(x , y, max_x - x, max_y - y); 231 return gfx::Rect(x , y, max_x - x, max_y - y);
188 } 232 }
189 233
234 bool SnapSizer::ShouldDockWindow() const {
235 if (!CanDockWindow(window_, edge_))
flackr 2013/09/06 02:18:43 If !CanDockWindow, 0 shouldn't be in the list of u
varkha 2013/09/09 15:38:42 Done.
236 return false;
237 // Avoid returning true when the last step is not docking.
flackr 2013/09/06 02:18:43 This comment is confusing. The last step is the on
varkha 2013/09/09 15:38:42 More to do with how this code was modified. This i
238 // TODO(varkha): use dedicated state.
239 return (usable_width_[size_index_] == 0 &&
240 size_index_ == static_cast<int>(usable_width_.size()) - 1);
flackr 2013/09/06 02:18:43 Shouldn't 0 always be the last element in usable_w
varkha 2013/09/09 15:38:42 Done.
241 }
242
243 // static
244 bool SnapSizer::CanDockWindow(aura::Window* window, SnapSizer::Edge edge) {
245 if (!CommandLine::ForCurrentProcess()->HasSwitch(
246 switches::kAshEnableDockedWindows)) {
247 return false;
248 }
249 // Cannot dock on the other size from an existing dock.
250 aura::Window* dock_container = Shell::GetContainer(
251 window->GetRootWindow(), kShellWindowId_DockedContainer);
252 DockedWindowLayoutManager* dock_layout =
253 static_cast<DockedWindowLayoutManager*>(dock_container->layout_manager());
254 const DockedAlignment alignment = dock_layout->CalculateAlignment();
255 if ((edge == LEFT_EDGE && alignment == DOCKED_ALIGNMENT_RIGHT) ||
256 (edge == RIGHT_EDGE && alignment == DOCKED_ALIGNMENT_LEFT)) {
257 return false;
258 }
259
260 // Do not allow docking on the same side as launcher shelf.
261 Launcher* launcher = Launcher::ForWindow(window);
262 if (!launcher)
263 return true;
264 return (edge == LEFT_EDGE && launcher->alignment() != SHELF_ALIGNMENT_LEFT) ||
265 (edge == RIGHT_EDGE && launcher->alignment() != SHELF_ALIGNMENT_RIGHT);
266
267 }
268
190 int SnapSizer::CalculateIncrement(int x, int reference_x) const { 269 int SnapSizer::CalculateIncrement(int x, int reference_x) const {
191 if (AlongEdge(x)) 270 if (AlongEdge(x))
192 return 1; 271 return 1;
193 if (x == reference_x) 272 if (x == reference_x)
194 return 0; 273 return 0;
195 if (edge_ == LEFT_EDGE) { 274 if (edge_ == LEFT_EDGE) {
196 if (x < reference_x) 275 if (x < reference_x)
197 return 1; 276 return 1;
198 return -1; 277 return -1;
199 } 278 }
(...skipping 12 matching lines...) Expand all
212 } 291 }
213 num_moves_since_adjust_ = 0; 292 num_moves_since_adjust_ = 0;
214 last_adjust_x_ = x; 293 last_adjust_x_ = x;
215 } 294 }
216 295
217 gfx::Rect SnapSizer::GetTargetBounds() const { 296 gfx::Rect SnapSizer::GetTargetBounds() const {
218 return GetTargetBoundsForSize(size_index_); 297 return GetTargetBoundsForSize(size_index_);
219 } 298 }
220 299
221 bool SnapSizer::AlongEdge(int x) const { 300 bool SnapSizer::AlongEdge(int x) const {
222 gfx::Rect area(ScreenAsh::GetDisplayBoundsInParent(window_)); 301 gfx::Rect area(ScreenAsh::GetDisplayWorkAreaBoundsInParent(window_));
223 return (x <= area.x()) || (x >= area.right() - 1); 302 return (x <= area.x()) || (x >= area.right() - 1);
224 } 303 }
225 304
305 void SnapSizer::UpdateDockedState() {
306 if (ShouldDockWindow() &&
307 dock_layout_->GetAlignmentOfWindow(window_) != DOCKED_ALIGNMENT_NONE) {
308 if (!dock_layout_->is_dragged_window_docked()) {
309 LOG(INFO) << "dock";
310 dock_layout_->DockDraggedWindow(window_);
311 }
312 target_bounds_ = GetTargetBounds();
313 } else {
314 if (dock_layout_->is_dragged_window_docked()) {
315 LOG(INFO) << "undock";
316 dock_layout_->UndockDraggedWindow();
317 }
318 }
319 }
320
226 } // namespace internal 321 } // namespace internal
227 } // namespace ash 322 } // namespace ash
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698