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
3 // found in the LICENSE file.
5 #include "ash/wm/workspace/workspace_window_resizer.h"
7 #include "ash/display/display_manager.h"
8 #include "ash/root_window_controller.h"
9 #include "ash/screen_util.h"
10 #include "ash/shelf/shelf_layout_manager.h"
11 #include "ash/shell.h"
12 #include "ash/shell_window_ids.h"
13 #include "ash/test/ash_test_base.h"
14 #include "ash/wm/window_state.h"
15 #include "ash/wm/window_util.h"
16 #include "ash/wm/wm_event.h"
17 #include "ash/wm/workspace/phantom_window_controller.h"
18 #include "ash/wm/workspace_controller.h"
19 #include "base/command_line.h"
20 #include "base/strings/string_number_conversions.h"
21 #include "base/strings/stringprintf.h"
22 #include "ui/aura/client/aura_constants.h"
23 #include "ui/aura/test/test_window_delegate.h"
24 #include "ui/aura/window_event_dispatcher.h"
25 #include "ui/base/hit_test.h"
26 #include "ui/events/gestures/gesture_configuration.h"
27 #include "ui/events/test/event_generator.h"
28 #include "ui/gfx/insets.h"
29 #include "ui/gfx/screen.h"
30 #include "ui/views/widget/widget.h"
35 const int kRootHeight = 600;
37 // A simple window delegate that returns the specified min size.
38 class TestWindowDelegate : public aura::test::TestWindowDelegate {
40 TestWindowDelegate() {
42 virtual ~TestWindowDelegate() {}
44 void set_min_size(const gfx::Size& size) {
48 void set_max_size(const gfx::Size& size) {
53 // Overridden from aura::Test::TestWindowDelegate:
54 virtual gfx::Size GetMinimumSize() const OVERRIDE {
58 virtual gfx::Size GetMaximumSize() const OVERRIDE {
65 DISALLOW_COPY_AND_ASSIGN(TestWindowDelegate);
70 class WorkspaceWindowResizerTest : public test::AshTestBase {
72 WorkspaceWindowResizerTest() : workspace_resizer_(NULL) {}
73 virtual ~WorkspaceWindowResizerTest() {}
75 virtual void SetUp() OVERRIDE {
77 UpdateDisplay(base::StringPrintf("800x%d", kRootHeight));
78 // Ignore the touch slop region.
79 ui::GestureConfiguration::set_max_touch_move_in_pixels_for_click(0);
81 aura::Window* root = Shell::GetPrimaryRootWindow();
82 gfx::Rect root_bounds(root->bounds());
84 // RootWindow and Display can't resize on Windows Ash.
85 // http://crbug.com/165962
86 EXPECT_EQ(kRootHeight, root_bounds.height());
88 EXPECT_EQ(800, root_bounds.width());
89 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
90 window_.reset(new aura::Window(&delegate_));
91 window_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
92 window_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
93 ParentWindowInPrimaryRootWindow(window_.get());
96 window2_.reset(new aura::Window(&delegate2_));
97 window2_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
98 window2_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
99 ParentWindowInPrimaryRootWindow(window2_.get());
102 window3_.reset(new aura::Window(&delegate3_));
103 window3_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
104 window3_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
105 ParentWindowInPrimaryRootWindow(window3_.get());
108 window4_.reset(new aura::Window(&delegate4_));
109 window4_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
110 window4_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
111 ParentWindowInPrimaryRootWindow(window4_.get());
115 virtual void TearDown() OVERRIDE {
120 touch_resize_window_.reset();
121 AshTestBase::TearDown();
124 // Returns a string identifying the z-order of each of the known child windows
125 // of |parent|. The returned string constains the id of the known windows and
126 // is ordered from topmost to bottomost windows.
127 std::string WindowOrderAsString(aura::Window* parent) const {
129 const aura::Window::Windows& windows = parent->children();
130 for (aura::Window::Windows::const_reverse_iterator i = windows.rbegin();
131 i != windows.rend(); ++i) {
132 if (*i == window_ || *i == window2_ || *i == window3_) {
135 result += base::IntToString((*i)->id());
142 WindowResizer* CreateResizerForTest(
143 aura::Window* window,
144 const gfx::Point& point_in_parent,
145 int window_component) {
146 WindowResizer* resizer = CreateWindowResizer(
150 aura::client::WINDOW_MOVE_SOURCE_MOUSE).release();
151 workspace_resizer_ = WorkspaceWindowResizer::GetInstanceForTest();
154 WorkspaceWindowResizer* CreateWorkspaceResizerForTest(
155 aura::Window* window,
156 const gfx::Point& point_in_parent,
157 int window_component,
158 aura::client::WindowMoveSource source,
159 const std::vector<aura::Window*>& attached_windows) {
160 wm::WindowState* window_state = wm::GetWindowState(window);
161 window_state->CreateDragDetails(
162 window, point_in_parent, window_component, source);
163 return WorkspaceWindowResizer::Create(window_state, attached_windows);
166 PhantomWindowController* snap_phantom_window_controller() const {
167 return workspace_resizer_->snap_phantom_window_controller_.get();
170 gfx::Point CalculateDragPoint(const WindowResizer& resizer,
173 gfx::Point location = resizer.GetInitialLocation();
174 location.set_x(location.x() + delta_x);
175 location.set_y(location.y() + delta_y);
179 std::vector<aura::Window*> empty_windows() const {
180 return std::vector<aura::Window*>();
183 ShelfLayoutManager* shelf_layout_manager() {
184 return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
187 void InitTouchResizeWindow(const gfx::Rect& bounds, int window_component) {
188 touch_resize_delegate_.set_window_component(window_component);
189 touch_resize_window_.reset(
190 CreateTestWindowInShellWithDelegate(&touch_resize_delegate_, 0,
194 TestWindowDelegate delegate_;
195 TestWindowDelegate delegate2_;
196 TestWindowDelegate delegate3_;
197 TestWindowDelegate delegate4_;
198 scoped_ptr<aura::Window> window_;
199 scoped_ptr<aura::Window> window2_;
200 scoped_ptr<aura::Window> window3_;
201 scoped_ptr<aura::Window> window4_;
203 TestWindowDelegate touch_resize_delegate_;
204 scoped_ptr<aura::Window> touch_resize_window_;
205 WorkspaceWindowResizer* workspace_resizer_;
208 DISALLOW_COPY_AND_ASSIGN(WorkspaceWindowResizerTest);
211 // Assertions around attached window resize dragging from the right with 2
213 TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_2) {
214 window_->SetBounds(gfx::Rect(0, 300, 400, 300));
215 window2_->SetBounds(gfx::Rect(400, 200, 100, 200));
217 std::vector<aura::Window*> windows;
218 windows.push_back(window2_.get());
219 scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
220 window_.get(), gfx::Point(), HTRIGHT,
221 aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
222 ASSERT_TRUE(resizer.get());
223 // Move it 100 to the right, which should expand w1 and push w2.
224 resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0);
225 EXPECT_EQ("0,300 500x300", window_->bounds().ToString());
226 EXPECT_EQ("500,200 100x200", window2_->bounds().ToString());
228 // Push off the screen, w2 should be resized to its min.
229 delegate2_.set_min_size(gfx::Size(20, 20));
230 resizer->Drag(CalculateDragPoint(*resizer, 800, 20), 0);
231 EXPECT_EQ("0,300 780x300", window_->bounds().ToString());
232 EXPECT_EQ("780,200 20x200", window2_->bounds().ToString());
234 // Move back to 100 and verify w2 gets its original size.
235 resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0);
236 EXPECT_EQ("0,300 500x300", window_->bounds().ToString());
237 EXPECT_EQ("500,200 100x200", window2_->bounds().ToString());
239 // Revert and make sure everything moves back.
240 resizer->Drag(CalculateDragPoint(*resizer, 800, 20), 0);
241 resizer->RevertDrag();
242 EXPECT_EQ("0,300 400x300", window_->bounds().ToString());
243 EXPECT_EQ("400,200 100x200", window2_->bounds().ToString());
246 // Assertions around collapsing and expanding.
247 TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_Compress) {
248 window_->SetBounds(gfx::Rect( 0, 300, 400, 300));
249 window2_->SetBounds(gfx::Rect(400, 200, 100, 200));
251 std::vector<aura::Window*> windows;
252 windows.push_back(window2_.get());
253 scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
254 window_.get(), gfx::Point(), HTRIGHT,
255 aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
256 ASSERT_TRUE(resizer.get());
257 // Move it 100 to the left, which should expand w2 and collapse w1.
258 resizer->Drag(CalculateDragPoint(*resizer, -100, 10), 0);
259 EXPECT_EQ("0,300 300x300", window_->bounds().ToString());
260 EXPECT_EQ("300,200 200x200", window2_->bounds().ToString());
262 // Collapse all the way to w1's min.
263 delegate_.set_min_size(gfx::Size(20, 20));
264 resizer->Drag(CalculateDragPoint(*resizer, -800, 20), 0);
265 EXPECT_EQ("0,300 20x300", window_->bounds().ToString());
266 EXPECT_EQ("20,200 480x200", window2_->bounds().ToString());
268 // Move 100 to the left.
269 resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0);
270 EXPECT_EQ("0,300 500x300", window_->bounds().ToString());
271 EXPECT_EQ("500,200 100x200", window2_->bounds().ToString());
274 resizer->Drag(CalculateDragPoint(*resizer, -100, 20), 0);
275 EXPECT_EQ("0,300 300x300", window_->bounds().ToString());
276 EXPECT_EQ("300,200 200x200", window2_->bounds().ToString());
279 // Assertions around attached window resize dragging from the right with 3
281 TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_3) {
282 window_->SetBounds(gfx::Rect( 100, 300, 200, 300));
283 window2_->SetBounds(gfx::Rect(300, 300, 150, 200));
284 window3_->SetBounds(gfx::Rect(450, 300, 100, 200));
285 delegate2_.set_min_size(gfx::Size(52, 50));
286 delegate3_.set_min_size(gfx::Size(38, 50));
288 std::vector<aura::Window*> windows;
289 windows.push_back(window2_.get());
290 windows.push_back(window3_.get());
291 scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
292 window_.get(), gfx::Point(), HTRIGHT,
293 aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
294 ASSERT_TRUE(resizer.get());
295 // Move it 100 to the right, which should expand w1 and push w2 and w3.
296 resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0);
297 EXPECT_EQ("100,300 300x300", window_->bounds().ToString());
298 EXPECT_EQ("400,300 150x200", window2_->bounds().ToString());
299 EXPECT_EQ("550,300 100x200", window3_->bounds().ToString());
301 // Move it 300, things should compress.
302 resizer->Drag(CalculateDragPoint(*resizer, 300, -10), 0);
303 EXPECT_EQ("100,300 500x300", window_->bounds().ToString());
304 EXPECT_EQ("600,300 120x200", window2_->bounds().ToString());
305 EXPECT_EQ("720,300 80x200", window3_->bounds().ToString());
307 // Move it so much the last two end up at their min.
308 resizer->Drag(CalculateDragPoint(*resizer, 800, 50), 0);
309 EXPECT_EQ("100,300 610x300", window_->bounds().ToString());
310 EXPECT_EQ("710,300 52x200", window2_->bounds().ToString());
311 EXPECT_EQ("762,300 38x200", window3_->bounds().ToString());
313 // Revert and make sure everything moves back.
314 resizer->RevertDrag();
315 EXPECT_EQ("100,300 200x300", window_->bounds().ToString());
316 EXPECT_EQ("300,300 150x200", window2_->bounds().ToString());
317 EXPECT_EQ("450,300 100x200", window3_->bounds().ToString());
320 // Assertions around attached window resizing (collapsing and expanding) with
322 TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_3_Compress) {
323 window_->SetBounds(gfx::Rect( 100, 300, 200, 300));
324 window2_->SetBounds(gfx::Rect(300, 300, 200, 200));
325 window3_->SetBounds(gfx::Rect(450, 300, 100, 200));
326 delegate2_.set_min_size(gfx::Size(52, 50));
327 delegate3_.set_min_size(gfx::Size(38, 50));
329 std::vector<aura::Window*> windows;
330 windows.push_back(window2_.get());
331 windows.push_back(window3_.get());
332 scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
333 window_.get(), gfx::Point(), HTRIGHT,
334 aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
335 ASSERT_TRUE(resizer.get());
336 // Move it -100 to the right, which should collapse w1 and expand w2 and w3.
337 resizer->Drag(CalculateDragPoint(*resizer, -100, -10), 0);
338 EXPECT_EQ("100,300 100x300", window_->bounds().ToString());
339 EXPECT_EQ("200,300 266x200", window2_->bounds().ToString());
340 EXPECT_EQ("466,300 134x200", window3_->bounds().ToString());
342 // Move it 100 to the right.
343 resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0);
344 EXPECT_EQ("100,300 300x300", window_->bounds().ToString());
345 EXPECT_EQ("400,300 200x200", window2_->bounds().ToString());
346 EXPECT_EQ("600,300 100x200", window3_->bounds().ToString());
348 // 100 to the left again.
349 resizer->Drag(CalculateDragPoint(*resizer, -100, -10), 0);
350 EXPECT_EQ("100,300 100x300", window_->bounds().ToString());
351 EXPECT_EQ("200,300 266x200", window2_->bounds().ToString());
352 EXPECT_EQ("466,300 134x200", window3_->bounds().ToString());
355 // Assertions around collapsing and expanding from the bottom.
356 TEST_F(WorkspaceWindowResizerTest, AttachedResize_BOTTOM_Compress) {
357 window_->SetBounds(gfx::Rect( 0, 100, 400, 300));
358 window2_->SetBounds(gfx::Rect(400, 400, 100, 200));
360 std::vector<aura::Window*> windows;
361 windows.push_back(window2_.get());
362 scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
363 window_.get(), gfx::Point(), HTBOTTOM,
364 aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
365 ASSERT_TRUE(resizer.get());
366 // Move it up 100, which should expand w2 and collapse w1.
367 resizer->Drag(CalculateDragPoint(*resizer, 10, -100), 0);
368 EXPECT_EQ("0,100 400x200", window_->bounds().ToString());
369 EXPECT_EQ("400,300 100x300", window2_->bounds().ToString());
371 // Collapse all the way to w1's min.
372 delegate_.set_min_size(gfx::Size(20, 20));
373 resizer->Drag(CalculateDragPoint(*resizer, 20, -800), 0);
374 EXPECT_EQ("0,100 400x20", window_->bounds().ToString());
375 EXPECT_EQ("400,120 100x480", window2_->bounds().ToString());
378 resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0);
379 EXPECT_EQ("0,100 400x400", window_->bounds().ToString());
380 EXPECT_EQ("400,500 100x100", window2_->bounds().ToString());
383 resizer->Drag(CalculateDragPoint(*resizer, 20, -100), 0);
384 EXPECT_EQ("0,100 400x200", window_->bounds().ToString());
385 EXPECT_EQ("400,300 100x300", window2_->bounds().ToString());
388 // Assertions around attached window resize dragging from the bottom with 2
390 TEST_F(WorkspaceWindowResizerTest, AttachedResize_BOTTOM_2) {
391 window_->SetBounds(gfx::Rect( 0, 50, 400, 200));
392 window2_->SetBounds(gfx::Rect(0, 250, 200, 100));
394 std::vector<aura::Window*> windows;
395 windows.push_back(window2_.get());
396 scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
397 window_.get(), gfx::Point(), HTBOTTOM,
398 aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
399 ASSERT_TRUE(resizer.get());
400 // Move it 100 to the bottom, which should expand w1 and push w2.
401 resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0);
402 EXPECT_EQ("0,50 400x300", window_->bounds().ToString());
403 EXPECT_EQ("0,350 200x100", window2_->bounds().ToString());
405 // Push off the screen, w2 should be resized to its min.
406 delegate2_.set_min_size(gfx::Size(20, 20));
407 resizer->Drag(CalculateDragPoint(*resizer, 50, 820), 0);
408 EXPECT_EQ("0,50 400x530", window_->bounds().ToString());
409 EXPECT_EQ("0,580 200x20", window2_->bounds().ToString());
411 // Move back to 100 and verify w2 gets its original size.
412 resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0);
413 EXPECT_EQ("0,50 400x300", window_->bounds().ToString());
414 EXPECT_EQ("0,350 200x100", window2_->bounds().ToString());
416 // Revert and make sure everything moves back.
417 resizer->Drag(CalculateDragPoint(*resizer, 800, 20), 0);
418 resizer->RevertDrag();
419 EXPECT_EQ("0,50 400x200", window_->bounds().ToString());
420 EXPECT_EQ("0,250 200x100", window2_->bounds().ToString());
424 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
425 #define MAYBE_AttachedResize_BOTTOM_3 DISABLED_AttachedResize_BOTTOM_3
427 #define MAYBE_AttachedResize_BOTTOM_3 AttachedResize_BOTTOM_3
430 // Assertions around attached window resize dragging from the bottom with 3
432 TEST_F(WorkspaceWindowResizerTest, MAYBE_AttachedResize_BOTTOM_3) {
433 UpdateDisplay("600x800");
434 aura::Window* root = Shell::GetPrimaryRootWindow();
435 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
437 window_->SetBounds(gfx::Rect( 300, 100, 300, 200));
438 window2_->SetBounds(gfx::Rect(300, 300, 200, 150));
439 window3_->SetBounds(gfx::Rect(300, 450, 200, 100));
440 delegate2_.set_min_size(gfx::Size(50, 52));
441 delegate3_.set_min_size(gfx::Size(50, 38));
443 std::vector<aura::Window*> windows;
444 windows.push_back(window2_.get());
445 windows.push_back(window3_.get());
446 scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
447 window_.get(), gfx::Point(), HTBOTTOM,
448 aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
449 ASSERT_TRUE(resizer.get());
450 // Move it 100 down, which should expand w1 and push w2 and w3.
451 resizer->Drag(CalculateDragPoint(*resizer, -10, 100), 0);
452 EXPECT_EQ("300,100 300x300", window_->bounds().ToString());
453 EXPECT_EQ("300,400 200x150", window2_->bounds().ToString());
454 EXPECT_EQ("300,550 200x100", window3_->bounds().ToString());
456 // Move it 296 things should compress.
457 resizer->Drag(CalculateDragPoint(*resizer, -10, 296), 0);
458 EXPECT_EQ("300,100 300x496", window_->bounds().ToString());
459 EXPECT_EQ("300,596 200x123", window2_->bounds().ToString());
460 EXPECT_EQ("300,719 200x81", window3_->bounds().ToString());
462 // Move it so much everything ends up at its min.
463 resizer->Drag(CalculateDragPoint(*resizer, 50, 798), 0);
464 EXPECT_EQ("300,100 300x610", window_->bounds().ToString());
465 EXPECT_EQ("300,710 200x52", window2_->bounds().ToString());
466 EXPECT_EQ("300,762 200x38", window3_->bounds().ToString());
468 // Revert and make sure everything moves back.
469 resizer->RevertDrag();
470 EXPECT_EQ("300,100 300x200", window_->bounds().ToString());
471 EXPECT_EQ("300,300 200x150", window2_->bounds().ToString());
472 EXPECT_EQ("300,450 200x100", window3_->bounds().ToString());
475 // Assertions around attached window resizing (collapsing and expanding) with
477 TEST_F(WorkspaceWindowResizerTest, AttachedResize_BOTTOM_3_Compress) {
478 window_->SetBounds(gfx::Rect( 0, 0, 200, 200));
479 window2_->SetBounds(gfx::Rect(10, 200, 200, 200));
480 window3_->SetBounds(gfx::Rect(20, 400, 100, 100));
481 delegate2_.set_min_size(gfx::Size(52, 50));
482 delegate3_.set_min_size(gfx::Size(38, 50));
484 std::vector<aura::Window*> windows;
485 windows.push_back(window2_.get());
486 windows.push_back(window3_.get());
487 scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
488 window_.get(), gfx::Point(), HTBOTTOM,
489 aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
490 ASSERT_TRUE(resizer.get());
491 // Move it 100 up, which should collapse w1 and expand w2 and w3.
492 resizer->Drag(CalculateDragPoint(*resizer, -10, -100), 0);
493 EXPECT_EQ("0,0 200x100", window_->bounds().ToString());
494 EXPECT_EQ("10,100 200x266", window2_->bounds().ToString());
495 EXPECT_EQ("20,366 100x134", window3_->bounds().ToString());
498 resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0);
499 EXPECT_EQ("0,0 200x300", window_->bounds().ToString());
500 EXPECT_EQ("10,300 200x200", window2_->bounds().ToString());
501 EXPECT_EQ("20,500 100x100", window3_->bounds().ToString());
504 resizer->Drag(CalculateDragPoint(*resizer, -10, -100), 0);
505 EXPECT_EQ("0,0 200x100", window_->bounds().ToString());
506 EXPECT_EQ("10,100 200x266", window2_->bounds().ToString());
507 EXPECT_EQ("20,366 100x134", window3_->bounds().ToString());
510 // Tests that touch-dragging a window does not lock the mouse cursor
511 // and therefore shows the cursor on a mousemove.
512 TEST_F(WorkspaceWindowResizerTest, MouseMoveWithTouchDrag) {
513 window_->SetBounds(gfx::Rect(0, 300, 400, 300));
514 window2_->SetBounds(gfx::Rect(400, 200, 100, 200));
516 Shell* shell = Shell::GetInstance();
517 ui::test::EventGenerator generator(window_->GetRootWindow());
519 // The cursor should not be locked initially.
520 EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked());
522 std::vector<aura::Window*> windows;
523 windows.push_back(window2_.get());
524 scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
525 window_.get(), gfx::Point(), HTRIGHT,
526 aura::client::WINDOW_MOVE_SOURCE_TOUCH, windows));
527 ASSERT_TRUE(resizer.get());
529 // Creating a WorkspaceWindowResizer should not lock the cursor.
530 EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked());
532 // The cursor should be hidden after touching the screen and
534 EXPECT_TRUE(shell->cursor_manager()->IsCursorVisible());
535 generator.PressTouch();
536 resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0);
537 EXPECT_FALSE(shell->cursor_manager()->IsCursorVisible());
538 EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked());
540 // Moving the mouse should show the cursor.
541 generator.MoveMouseBy(1, 1);
542 EXPECT_TRUE(shell->cursor_manager()->IsCursorVisible());
543 EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked());
545 resizer->RevertDrag();
548 // Assertions around dragging to the left/right edge of the screen.
549 TEST_F(WorkspaceWindowResizerTest, Edge) {
550 if (!SupportsHostWindowResize())
553 // Resize host window to force insets update.
554 UpdateDisplay("800x700");
555 // TODO(varkha): Insets are reset after every drag because of
556 // http://crbug.com/292238.
557 // Window is wide enough not to get docked right away.
558 window_->SetBounds(gfx::Rect(20, 30, 400, 60));
559 window_->SetProperty(aura::client::kCanMaximizeKey, true);
560 wm::WindowState* window_state = wm::GetWindowState(window_.get());
563 gfx::Rect expected_bounds_in_parent(
564 wm::GetDefaultLeftSnappedWindowBoundsInParent(window_.get()));
566 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
567 window_.get(), gfx::Point(), HTCAPTION));
568 ASSERT_TRUE(resizer.get());
569 resizer->Drag(CalculateDragPoint(*resizer, 0, 10), 0);
570 resizer->CompleteDrag();
572 EXPECT_EQ(expected_bounds_in_parent.ToString(),
573 window_->bounds().ToString());
574 ASSERT_TRUE(window_state->HasRestoreBounds());
575 EXPECT_EQ("20,30 400x60",
576 window_state->GetRestoreBoundsInScreen().ToString());
578 // Try the same with the right side.
580 gfx::Rect expected_bounds_in_parent(
581 wm::GetDefaultRightSnappedWindowBoundsInParent(window_.get()));
583 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
584 window_.get(), gfx::Point(), HTCAPTION));
585 ASSERT_TRUE(resizer.get());
586 resizer->Drag(CalculateDragPoint(*resizer, 800, 10), 0);
587 resizer->CompleteDrag();
588 EXPECT_EQ(expected_bounds_in_parent.ToString(),
589 window_->bounds().ToString());
590 ASSERT_TRUE(window_state->HasRestoreBounds());
591 EXPECT_EQ("20,30 400x60",
592 window_state->GetRestoreBoundsInScreen().ToString());
595 // Test if the restore bounds is correct in multiple displays.
596 if (!SupportsMultipleDisplays())
599 // Restore the window to clear snapped state.
600 window_state->Restore();
602 UpdateDisplay("800x600,500x600");
603 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
604 EXPECT_EQ(root_windows[0], window_->GetRootWindow());
605 // Window is wide enough not to get docked right away.
606 window_->SetBoundsInScreen(gfx::Rect(800, 10, 400, 60),
607 ScreenUtil::GetSecondaryDisplay());
608 EXPECT_EQ(root_windows[1], window_->GetRootWindow());
610 EXPECT_EQ("800,10 400x60", window_->GetBoundsInScreen().ToString());
612 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
613 window_.get(), gfx::Point(), HTCAPTION));
614 ASSERT_TRUE(resizer.get());
615 resizer->Drag(CalculateDragPoint(*resizer, 499, 0), 0);
617 ScreenUtil::GetDisplayWorkAreaBoundsInParent(window_.get()).bottom();
618 resizer->CompleteDrag();
619 // With the resolution of 500x600 we will hit in this case the 50% screen
621 // TODO(varkha): Insets are updated because of http://crbug.com/292238
622 EXPECT_EQ("250,0 250x" + base::IntToString(bottom),
623 window_->bounds().ToString());
624 EXPECT_EQ("800,10 400x60",
625 window_state->GetRestoreBoundsInScreen().ToString());
629 // Check that non resizable windows will not get resized.
630 TEST_F(WorkspaceWindowResizerTest, NonResizableWindows) {
631 window_->SetBounds(gfx::Rect(20, 30, 50, 60));
632 window_->SetProperty(aura::client::kCanResizeKey, false);
634 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
635 window_.get(), gfx::Point(), HTCAPTION));
636 ASSERT_TRUE(resizer.get());
637 resizer->Drag(CalculateDragPoint(*resizer, -20, 0), 0);
638 resizer->CompleteDrag();
639 EXPECT_EQ("0,30 50x60", window_->bounds().ToString());
642 TEST_F(WorkspaceWindowResizerTest, CancelSnapPhantom) {
643 if (!SupportsMultipleDisplays())
646 UpdateDisplay("800x600,800x600");
647 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
648 ASSERT_EQ(2U, root_windows.size());
650 window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
651 Shell::GetScreen()->GetPrimaryDisplay());
652 EXPECT_EQ(root_windows[0], window_->GetRootWindow());
653 EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity());
655 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
656 window_.get(), gfx::Point(), HTCAPTION));
657 ASSERT_TRUE(resizer.get());
658 EXPECT_FALSE(snap_phantom_window_controller());
660 // The pointer is on the edge but not shared. The snap phantom window
661 // controller should be non-NULL.
662 resizer->Drag(CalculateDragPoint(*resizer, 799, 0), 0);
663 EXPECT_TRUE(snap_phantom_window_controller());
665 // Move the cursor across the edge. Now the snap phantom window controller
666 // should be canceled.
667 resizer->Drag(CalculateDragPoint(*resizer, 800, 0), 0);
668 EXPECT_FALSE(snap_phantom_window_controller());
672 // Verifies that dragging a snapped window unsnaps it.
673 TEST_F(WorkspaceWindowResizerTest, DragSnapped) {
674 wm::WindowState* window_state = ash::wm::GetWindowState(window_.get());
676 const gfx::Rect kInitialBounds(100, 100, 100, 100);
677 window_->SetBounds(kInitialBounds);
679 const wm::WMEvent snap_event(wm::WM_EVENT_SNAP_LEFT);
680 window_state->OnWMEvent(&snap_event);
681 EXPECT_EQ(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED, window_state->GetStateType());
682 gfx::Rect snapped_bounds = window_->bounds();
683 EXPECT_NE(snapped_bounds.ToString(), kInitialBounds.ToString());
684 EXPECT_EQ(window_state->GetRestoreBoundsInParent().ToString(),
685 kInitialBounds.ToString());
687 // Dragging a side snapped window should unsnap it.
688 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
689 window_.get(), gfx::Point(), HTCAPTION));
690 resizer->Drag(CalculateDragPoint(*resizer, 10, 0), 0);
691 resizer->CompleteDrag();
692 EXPECT_EQ(wm::WINDOW_STATE_TYPE_NORMAL, window_state->GetStateType());
693 EXPECT_EQ("10,0 100x100", window_->bounds().ToString());
694 EXPECT_FALSE(window_state->HasRestoreBounds());
697 // Verifies the behavior of resizing a side snapped window.
698 TEST_F(WorkspaceWindowResizerTest, ResizeSnapped) {
699 wm::WindowState* window_state = ash::wm::GetWindowState(window_.get());
701 const gfx::Rect kInitialBounds(100, 100, 100, 100);
702 window_->SetBounds(kInitialBounds);
705 const wm::WMEvent snap_event(wm::WM_EVENT_SNAP_LEFT);
706 window_state->OnWMEvent(&snap_event);
707 EXPECT_EQ(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED, window_state->GetStateType());
708 gfx::Rect snapped_bounds = window_->bounds();
709 EXPECT_NE(snapped_bounds.ToString(), kInitialBounds.ToString());
710 EXPECT_EQ(window_state->GetRestoreBoundsInParent().ToString(),
711 kInitialBounds.ToString());
714 // 1) Resizing a side snapped window to make it wider should not unsnap the
716 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
717 window_.get(), gfx::Point(), HTRIGHT));
718 resizer->Drag(CalculateDragPoint(*resizer, 10, 0), 0);
719 resizer->CompleteDrag();
720 EXPECT_EQ(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED, window_state->GetStateType());
721 snapped_bounds.Inset(0, 0, -10, 0);
722 EXPECT_EQ(snapped_bounds.ToString(), window_->bounds().ToString());
723 EXPECT_EQ(window_state->GetRestoreBoundsInParent().ToString(),
724 kInitialBounds.ToString());
728 // 2) Resizing a side snapped window vertically and then undoing the change
729 // should not unsnap.
730 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
731 window_.get(), gfx::Point(), HTBOTTOM));
732 resizer->Drag(CalculateDragPoint(*resizer, 0, -30), 0);
733 resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
734 resizer->CompleteDrag();
735 EXPECT_EQ(wm::WINDOW_STATE_TYPE_LEFT_SNAPPED, window_state->GetStateType());
736 EXPECT_EQ(snapped_bounds.ToString(), window_->bounds().ToString());
737 EXPECT_EQ(window_state->GetRestoreBoundsInParent().ToString(),
738 kInitialBounds.ToString());
742 // 3) Resizing a side snapped window vertically and then not undoing the
743 // change should unsnap.
744 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
745 window_.get(), gfx::Point(), HTBOTTOM));
746 resizer->Drag(CalculateDragPoint(*resizer, 0, -10), 0);
747 resizer->CompleteDrag();
748 EXPECT_EQ(wm::WINDOW_STATE_TYPE_NORMAL, window_state->GetStateType());
749 gfx::Rect expected_bounds(snapped_bounds);
750 expected_bounds.Inset(0, 0, 0, 10);
751 EXPECT_EQ(expected_bounds.ToString(), window_->bounds().ToString());
752 EXPECT_FALSE(window_state->HasRestoreBounds());
756 // Verifies windows are correctly restacked when reordering multiple windows.
757 TEST_F(WorkspaceWindowResizerTest, RestackAttached) {
758 window_->SetBounds(gfx::Rect( 0, 0, 200, 300));
759 window2_->SetBounds(gfx::Rect(200, 0, 100, 200));
760 window3_->SetBounds(gfx::Rect(300, 0, 100, 100));
763 std::vector<aura::Window*> windows;
764 windows.push_back(window2_.get());
765 scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
766 window_.get(), gfx::Point(), HTRIGHT,
767 aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
768 ASSERT_TRUE(resizer.get());
769 // Move it 100 to the right, which should expand w1 and push w2 and w3.
770 resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0);
772 // 2 should be topmost since it's initially the highest in the stack.
773 EXPECT_EQ("2 1 3", WindowOrderAsString(window_->parent()));
777 std::vector<aura::Window*> windows;
778 windows.push_back(window3_.get());
779 scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
780 window2_.get(), gfx::Point(), HTRIGHT,
781 aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
782 ASSERT_TRUE(resizer.get());
783 // Move it 100 to the right, which should expand w1 and push w2 and w3.
784 resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0);
786 // 2 should be topmost since it's initially the highest in the stack.
787 EXPECT_EQ("2 3 1", WindowOrderAsString(window_->parent()));
791 // Makes sure we don't allow dragging below the work area.
792 TEST_F(WorkspaceWindowResizerTest, DontDragOffBottom) {
793 Shell::GetInstance()->SetDisplayWorkAreaInsets(
794 Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 10, 0));
796 ASSERT_EQ(1, Shell::GetScreen()->GetNumDisplays());
798 window_->SetBounds(gfx::Rect(100, 200, 300, 400));
799 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
800 window_.get(), gfx::Point(), HTCAPTION));
801 ASSERT_TRUE(resizer.get());
802 resizer->Drag(CalculateDragPoint(*resizer, 0, 600), 0);
804 kRootHeight - WorkspaceWindowResizer::kMinOnscreenHeight - 10;
805 EXPECT_EQ("100," + base::IntToString(expected_y) + " 300x400",
806 window_->bounds().ToString());
809 // Makes sure we don't allow dragging on the work area with multidisplay.
810 TEST_F(WorkspaceWindowResizerTest, DontDragOffBottomWithMultiDisplay) {
811 if (!SupportsMultipleDisplays())
814 UpdateDisplay("800x600,800x600");
815 ASSERT_EQ(2, Shell::GetScreen()->GetNumDisplays());
817 Shell::GetInstance()->SetDisplayWorkAreaInsets(
818 Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 10, 0));
820 // Positions the secondary display at the bottom the primary display.
821 Shell::GetInstance()->display_manager()->SetLayoutForCurrentDisplays(
822 ash::DisplayLayout(ash::DisplayLayout::BOTTOM, 0));
825 window_->SetBounds(gfx::Rect(100, 200, 300, 20));
826 DCHECK_LT(window_->bounds().height(),
827 WorkspaceWindowResizer::kMinOnscreenHeight);
828 // Drag down avoiding dragging along the edge as that would side-snap.
829 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
830 window_.get(), gfx::Point(10, 0), HTCAPTION));
831 ASSERT_TRUE(resizer.get());
832 resizer->Drag(CalculateDragPoint(*resizer, 0, 400), 0);
833 int expected_y = kRootHeight - window_->bounds().height() - 10;
834 // When the mouse cursor is in the primary display, the window cannot move
835 // on non-work area but can get all the way towards the bottom,
836 // restricted only by the window height.
837 EXPECT_EQ("100," + base::IntToString(expected_y) + " 300x20",
838 window_->bounds().ToString());
839 // Revert the drag in order to not remember the restore bounds.
840 resizer->RevertDrag();
843 Shell::GetInstance()->SetDisplayWorkAreaInsets(
844 Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 10, 0));
846 window_->SetBounds(gfx::Rect(100, 200, 300, 400));
847 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
848 window_.get(), gfx::Point(10, 0), HTCAPTION));
849 ASSERT_TRUE(resizer.get());
850 // Drag down avoiding dragging along the edge as that would side-snap.
851 resizer->Drag(CalculateDragPoint(*resizer, 0, 400), 0);
853 kRootHeight - WorkspaceWindowResizer::kMinOnscreenHeight - 10;
854 // When the mouse cursor is in the primary display, the window cannot move
855 // on non-work area with kMinOnscreenHeight margin.
856 EXPECT_EQ("100," + base::IntToString(expected_y) + " 300x400",
857 window_->bounds().ToString());
858 resizer->CompleteDrag();
862 window_->SetBounds(gfx::Rect(100, 200, 300, 400));
863 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
864 window_.get(), window_->bounds().origin(), HTCAPTION));
865 ASSERT_TRUE(resizer.get());
866 // Drag down avoiding getting stuck against the shelf on the bottom screen.
867 resizer->Drag(CalculateDragPoint(*resizer, 0, 500), 0);
868 // The window can move to the secondary display beyond non-work area of
869 // the primary display.
870 EXPECT_EQ("100,700 300x400", window_->bounds().ToString());
871 resizer->CompleteDrag();
875 // Makes sure we don't allow dragging off the top of the work area.
876 TEST_F(WorkspaceWindowResizerTest, DontDragOffTop) {
877 Shell::GetInstance()->SetDisplayWorkAreaInsets(
878 Shell::GetPrimaryRootWindow(), gfx::Insets(10, 0, 0, 0));
880 window_->SetBounds(gfx::Rect(100, 200, 300, 400));
881 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
882 window_.get(), gfx::Point(), HTCAPTION));
883 ASSERT_TRUE(resizer.get());
884 resizer->Drag(CalculateDragPoint(*resizer, 0, -600), 0);
885 EXPECT_EQ("100,10 300x400", window_->bounds().ToString());
888 TEST_F(WorkspaceWindowResizerTest, ResizeBottomOutsideWorkArea) {
889 Shell::GetInstance()->SetDisplayWorkAreaInsets(
890 Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
892 window_->SetBounds(gfx::Rect(100, 200, 300, 380));
893 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
894 window_.get(), gfx::Point(), HTTOP));
895 ASSERT_TRUE(resizer.get());
896 resizer->Drag(CalculateDragPoint(*resizer, 8, 0), 0);
897 EXPECT_EQ("100,200 300x380", window_->bounds().ToString());
900 TEST_F(WorkspaceWindowResizerTest, ResizeWindowOutsideLeftWorkArea) {
901 Shell::GetInstance()->SetDisplayWorkAreaInsets(
902 Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
903 int left = ScreenUtil::GetDisplayWorkAreaBoundsInParent(window_.get()).x();
904 int pixels_to_left_border = 50;
905 int window_width = 300;
906 int window_x = left - window_width + pixels_to_left_border;
907 window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380));
908 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
909 window_.get(), gfx::Point(pixels_to_left_border, 0), HTRIGHT));
910 ASSERT_TRUE(resizer.get());
911 resizer->Drag(CalculateDragPoint(*resizer, -window_width, 0), 0);
912 EXPECT_EQ(base::IntToString(window_x) + ",100 " +
913 base::IntToString(kMinimumOnScreenArea - window_x) +
914 "x380", window_->bounds().ToString());
917 TEST_F(WorkspaceWindowResizerTest, ResizeWindowOutsideRightWorkArea) {
918 Shell::GetInstance()->SetDisplayWorkAreaInsets(
919 Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
920 int right = ScreenUtil::GetDisplayWorkAreaBoundsInParent(
921 window_.get()).right();
922 int pixels_to_right_border = 50;
923 int window_width = 300;
924 int window_x = right - pixels_to_right_border;
925 window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380));
926 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
927 window_.get(), gfx::Point(window_x, 0), HTLEFT));
928 ASSERT_TRUE(resizer.get());
929 resizer->Drag(CalculateDragPoint(*resizer, window_width, 0), 0);
930 EXPECT_EQ(base::IntToString(right - kMinimumOnScreenArea) +
932 base::IntToString(window_width - pixels_to_right_border +
933 kMinimumOnScreenArea) +
934 "x380", window_->bounds().ToString());
937 TEST_F(WorkspaceWindowResizerTest, ResizeWindowOutsideBottomWorkArea) {
938 Shell::GetInstance()->SetDisplayWorkAreaInsets(
939 Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
940 int bottom = ScreenUtil::GetDisplayWorkAreaBoundsInParent(
941 window_.get()).bottom();
942 int delta_to_bottom = 50;
944 window_->SetBounds(gfx::Rect(100, bottom - delta_to_bottom, 300, height));
945 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
946 window_.get(), gfx::Point(0, bottom - delta_to_bottom), HTTOP));
947 ASSERT_TRUE(resizer.get());
948 resizer->Drag(CalculateDragPoint(*resizer, 0, bottom), 0);
950 base::IntToString(bottom - kMinimumOnScreenArea) +
952 base::IntToString(height - (delta_to_bottom -
953 kMinimumOnScreenArea)),
954 window_->bounds().ToString());
957 // Verifies that 'outside' check of the resizer take into account the extended
958 // desktop in case of repositions.
959 TEST_F(WorkspaceWindowResizerTest, DragWindowOutsideRightToSecondaryDisplay) {
960 // Only primary display. Changes the window position to fit within the
962 Shell::GetInstance()->SetDisplayWorkAreaInsets(
963 Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
964 int right = ScreenUtil::GetDisplayWorkAreaBoundsInParent(
965 window_.get()).right();
966 int pixels_to_right_border = 50;
967 int window_width = 300;
968 int window_x = right - pixels_to_right_border;
969 window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380));
970 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
971 window_.get(), gfx::Point(window_x, 0), HTCAPTION));
972 ASSERT_TRUE(resizer.get());
973 resizer->Drag(CalculateDragPoint(*resizer, window_width, 0), 0);
974 EXPECT_EQ(base::IntToString(right - kMinimumOnScreenArea) +
976 base::IntToString(window_width) +
977 "x380", window_->bounds().ToString());
979 if (!SupportsMultipleDisplays())
982 // With secondary display. Operation itself is same but doesn't change
983 // the position because the window is still within the secondary display.
984 UpdateDisplay("1000x600,600x400");
985 Shell::GetInstance()->SetDisplayWorkAreaInsets(
986 Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
987 window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380));
988 resizer->Drag(CalculateDragPoint(*resizer, window_width, 0), 0);
989 EXPECT_EQ(base::IntToString(window_x + window_width) +
991 base::IntToString(window_width) +
992 "x380", window_->bounds().ToString());
995 // Verifies snapping to edges works.
996 TEST_F(WorkspaceWindowResizerTest, SnapToEdge) {
997 Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()->
998 SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
999 window_->SetBounds(gfx::Rect(96, 112, 320, 160));
1000 // Click 50px to the right so that the mouse pointer does not leave the
1001 // workspace ensuring sticky behavior.
1002 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1004 window_->bounds().origin() + gfx::Vector2d(50, 0),
1006 ASSERT_TRUE(resizer.get());
1007 // Move to an x-coordinate of 15, which should not snap.
1008 resizer->Drag(CalculateDragPoint(*resizer, 15 - 96, 0), 0);
1009 // An x-coordinate of 7 should snap.
1010 resizer->Drag(CalculateDragPoint(*resizer, 7 - 96, 0), 0);
1011 EXPECT_EQ("0,112 320x160", window_->bounds().ToString());
1012 // Move to -15, should still snap to 0.
1013 resizer->Drag(CalculateDragPoint(*resizer, -15 - 96, 0), 0);
1014 EXPECT_EQ("0,112 320x160", window_->bounds().ToString());
1015 // At -32 should move past snap points.
1016 resizer->Drag(CalculateDragPoint(*resizer, -32 - 96, 0), 0);
1017 EXPECT_EQ("-32,112 320x160", window_->bounds().ToString());
1018 resizer->Drag(CalculateDragPoint(*resizer, -33 - 96, 0), 0);
1019 EXPECT_EQ("-33,112 320x160", window_->bounds().ToString());
1021 // Right side should similarly snap.
1022 resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 - 15, 0), 0);
1023 EXPECT_EQ("465,112 320x160", window_->bounds().ToString());
1024 resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 - 7, 0), 0);
1025 EXPECT_EQ("480,112 320x160", window_->bounds().ToString());
1026 resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 15, 0), 0);
1027 EXPECT_EQ("480,112 320x160", window_->bounds().ToString());
1028 resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 32, 0), 0);
1029 EXPECT_EQ("512,112 320x160", window_->bounds().ToString());
1030 resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 33, 0), 0);
1031 EXPECT_EQ("513,112 320x160", window_->bounds().ToString());
1033 // And the bottom should snap too.
1034 resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 3 - 7), 0);
1035 EXPECT_EQ("96,437 320x160", window_->bounds().ToString());
1036 resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 3 + 15), 0);
1037 EXPECT_EQ("96,437 320x160", window_->bounds().ToString());
1038 resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 32), 0);
1039 EXPECT_EQ("96,470 320x160", window_->bounds().ToString());
1040 resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 33), 0);
1041 EXPECT_EQ("96,471 320x160", window_->bounds().ToString());
1043 // And the top should snap too.
1044 resizer->Drag(CalculateDragPoint(*resizer, 0, -112 + 20), 0);
1045 EXPECT_EQ("96,20 320x160", window_->bounds().ToString());
1046 resizer->Drag(CalculateDragPoint(*resizer, 0, -112 + 7), 0);
1047 EXPECT_EQ("96,0 320x160", window_->bounds().ToString());
1049 // And bottom/left should snap too.
1051 CalculateDragPoint(*resizer, 7 - 96, 600 - 160 - 112 - 3 - 7), 0);
1052 EXPECT_EQ("0,437 320x160", window_->bounds().ToString());
1054 CalculateDragPoint(*resizer, -15 - 96, 600 - 160 - 112 - 3 + 15), 0);
1055 EXPECT_EQ("0,437 320x160", window_->bounds().ToString());
1056 // should move past snap points.
1058 CalculateDragPoint(*resizer, -32 - 96, 600 - 160 - 112 - 2 + 32), 0);
1059 EXPECT_EQ("-32,470 320x160", window_->bounds().ToString());
1061 CalculateDragPoint(*resizer, -33 - 96, 600 - 160 - 112 - 2 + 33), 0);
1062 EXPECT_EQ("-33,471 320x160", window_->bounds().ToString());
1064 // No need to test dragging < 0 as we force that to 0.
1067 // Verifies a resize snap when dragging TOPLEFT.
1068 TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_TOPLEFT) {
1069 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1070 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1071 window_.get(), gfx::Point(), HTTOPLEFT));
1072 ASSERT_TRUE(resizer.get());
1073 resizer->Drag(CalculateDragPoint(*resizer, -98, -199), 0);
1074 EXPECT_EQ("0,0 120x230", window_->bounds().ToString());
1077 // Verifies a resize snap when dragging TOPRIGHT.
1078 TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_TOPRIGHT) {
1079 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1080 gfx::Rect work_area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
1082 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1083 window_.get(), gfx::Point(), HTTOPRIGHT));
1084 ASSERT_TRUE(resizer.get());
1086 CalculateDragPoint(*resizer, work_area.right() - 120 - 1, -199), 0);
1087 EXPECT_EQ(100, window_->bounds().x());
1088 EXPECT_EQ(work_area.y(), window_->bounds().y());
1089 EXPECT_EQ(work_area.right() - 100, window_->bounds().width());
1090 EXPECT_EQ(230, window_->bounds().height());
1093 // Verifies a resize snap when dragging BOTTOMRIGHT.
1094 TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_BOTTOMRIGHT) {
1095 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1096 gfx::Rect work_area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
1098 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1099 window_.get(), gfx::Point(), HTBOTTOMRIGHT));
1100 ASSERT_TRUE(resizer.get());
1102 CalculateDragPoint(*resizer, work_area.right() - 120 - 1,
1103 work_area.bottom() - 220 - 2), 0);
1104 EXPECT_EQ(100, window_->bounds().x());
1105 EXPECT_EQ(200, window_->bounds().y());
1106 EXPECT_EQ(work_area.right() - 100, window_->bounds().width());
1107 EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height());
1110 // Verifies a resize snap when dragging BOTTOMLEFT.
1111 TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_BOTTOMLEFT) {
1112 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1113 gfx::Rect work_area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
1115 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1116 window_.get(), gfx::Point(), HTBOTTOMLEFT));
1117 ASSERT_TRUE(resizer.get());
1119 CalculateDragPoint(*resizer, -98, work_area.bottom() - 220 - 2), 0);
1120 EXPECT_EQ(0, window_->bounds().x());
1121 EXPECT_EQ(200, window_->bounds().y());
1122 EXPECT_EQ(120, window_->bounds().width());
1123 EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height());
1126 // Verifies window sticks to both window and work area.
1127 TEST_F(WorkspaceWindowResizerTest, StickToBothEdgeAndWindow) {
1128 window_->SetBounds(gfx::Rect(10, 10, 20, 50));
1130 window2_->SetBounds(gfx::Rect(150, 160, 25, 1000));
1133 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1134 window_.get(), gfx::Point(10, 10), HTCAPTION));
1135 ASSERT_TRUE(resizer.get());
1137 // Move |window| one pixel to the left of |window2|. Should snap to right.
1138 resizer->Drag(CalculateDragPoint(*resizer, 119, 145), 0);
1139 gfx::Rect expected(130, 160, 20, 50);
1140 EXPECT_EQ(expected.ToString(), window_->bounds().ToString());
1142 gfx::Rect work_area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
1145 // The initial y position of |window_|.
1147 // The drag position where the window is exactly attached to the bottom.
1148 int attach_y = work_area.bottom() - window_->bounds().height() - initial_y;
1150 // Dragging 10px above should not attach to the bottom.
1151 resizer->Drag(CalculateDragPoint(*resizer, 119, attach_y - 10), 0);
1152 expected.set_y(attach_y + initial_y - 10);
1153 EXPECT_EQ(expected.ToString(), window_->bounds().ToString());
1155 // Stick to the work area.
1156 resizer->Drag(CalculateDragPoint(*resizer, 119, attach_y - 1), 0);
1157 expected.set_y(attach_y + initial_y);
1158 EXPECT_EQ(expected.ToString(), window_->bounds().ToString());
1160 resizer->Drag(CalculateDragPoint(*resizer, 119, attach_y), 0);
1161 expected.set_y(attach_y + initial_y);
1162 EXPECT_EQ(expected.ToString(), window_->bounds().ToString());
1164 resizer->Drag(CalculateDragPoint(*resizer, 119, attach_y + 1), 0);
1165 expected.set_y(attach_y + initial_y);
1166 EXPECT_EQ(expected.ToString(), window_->bounds().ToString());
1168 // Moving down further should move the window.
1169 resizer->Drag(CalculateDragPoint(*resizer, 119, attach_y + 18), 0);
1170 expected.set_y(attach_y + initial_y + 18);
1171 EXPECT_EQ(expected.ToString(), window_->bounds().ToString());
1174 TEST_F(WorkspaceWindowResizerTest, CtrlDragResizeToExactPosition) {
1175 window_->SetBounds(gfx::Rect(96, 112, 320, 160));
1176 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1177 window_.get(), gfx::Point(), HTBOTTOMRIGHT));
1178 ASSERT_TRUE(resizer.get());
1179 // Resize the right bottom to add 10 in width, 12 in height.
1180 resizer->Drag(CalculateDragPoint(*resizer, 10, 12), ui::EF_CONTROL_DOWN);
1181 // Both bottom and right sides to resize to exact size requested.
1182 EXPECT_EQ("96,112 330x172", window_->bounds().ToString());
1185 // Verifies that a dragged, non-snapped window will clear restore bounds.
1186 TEST_F(WorkspaceWindowResizerTest, RestoreClearedOnResize) {
1187 window_->SetBounds(gfx::Rect(10, 10, 100, 100));
1188 wm::WindowState* window_state = wm::GetWindowState(window_.get());
1189 window_state->SetRestoreBoundsInScreen(gfx::Rect(50, 50, 50, 50));
1190 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1191 window_.get(), gfx::Point(), HTBOTTOMRIGHT));
1192 ASSERT_TRUE(resizer.get());
1193 // Drag the window to new position by adding (20, 30) to original point,
1194 // the original restore bound should be cleared.
1195 resizer->Drag(CalculateDragPoint(*resizer, 20, 30), 0);
1196 resizer->CompleteDrag();
1197 EXPECT_EQ("10,10 120x130", window_->bounds().ToString());
1198 EXPECT_FALSE(window_state->HasRestoreBounds());
1201 // Verifies that a dragged window will restore to its pre-maximized size.
1202 TEST_F(WorkspaceWindowResizerTest, RestoreToPreMaximizeCoordinates) {
1203 window_->SetBounds(gfx::Rect(0, 0, 1000, 1000));
1204 wm::WindowState* window_state = wm::GetWindowState(window_.get());
1205 window_state->SetRestoreBoundsInScreen(gfx::Rect(96, 112, 320, 160));
1206 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1207 window_.get(), gfx::Point(), HTCAPTION));
1208 ASSERT_TRUE(resizer.get());
1209 // Drag the window to new position by adding (10, 10) to original point,
1210 // the window should get restored.
1211 resizer->Drag(CalculateDragPoint(*resizer, 10, 10), 0);
1212 resizer->CompleteDrag();
1213 EXPECT_EQ("10,10 320x160", window_->bounds().ToString());
1214 // The restore rectangle should get cleared as well.
1215 EXPECT_FALSE(window_state->HasRestoreBounds());
1218 // Verifies that a dragged window will restore to its pre-maximized size.
1219 TEST_F(WorkspaceWindowResizerTest, RevertResizeOperation) {
1220 const gfx::Rect initial_bounds(0, 0, 200, 400);
1221 window_->SetBounds(initial_bounds);
1223 wm::WindowState* window_state = wm::GetWindowState(window_.get());
1224 window_state->SetRestoreBoundsInScreen(gfx::Rect(96, 112, 320, 160));
1225 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1226 window_.get(), gfx::Point(), HTCAPTION));
1227 ASSERT_TRUE(resizer.get());
1228 // Drag the window to new poistion by adding (180, 16) to original point,
1229 // the window should get restored.
1230 resizer->Drag(CalculateDragPoint(*resizer, 180, 16), 0);
1231 resizer->RevertDrag();
1232 EXPECT_EQ(initial_bounds.ToString(), window_->bounds().ToString());
1233 EXPECT_EQ("96,112 320x160",
1234 window_state->GetRestoreBoundsInScreen().ToString());
1237 // Check that only usable sizes get returned by the resizer.
1238 TEST_F(WorkspaceWindowResizerTest, MagneticallyAttach) {
1239 window_->SetBounds(gfx::Rect(10, 10, 20, 30));
1240 window2_->SetBounds(gfx::Rect(150, 160, 25, 20));
1243 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1244 window_.get(), gfx::Point(), HTCAPTION));
1245 ASSERT_TRUE(resizer.get());
1246 // Move |window| one pixel to the left of |window2|. Should snap to right and
1248 resizer->Drag(CalculateDragPoint(*resizer, 119, 145), 0);
1249 EXPECT_EQ("130,160 20x30", window_->bounds().ToString());
1251 // Move |window| one pixel to the right of |window2|. Should snap to left and
1253 resizer->Drag(CalculateDragPoint(*resizer, 164, 145), 0);
1254 EXPECT_EQ("175,160 20x30", window_->bounds().ToString());
1256 // Move |window| one pixel above |window2|. Should snap to top and left.
1257 resizer->Drag(CalculateDragPoint(*resizer, 142, 119), 0);
1258 EXPECT_EQ("150,130 20x30", window_->bounds().ToString());
1260 // Move |window| one pixel above the bottom of |window2|. Should snap to
1262 resizer->Drag(CalculateDragPoint(*resizer, 142, 169), 0);
1263 EXPECT_EQ("150,180 20x30", window_->bounds().ToString());
1266 // The following variants verify magnetic snapping during resize when dragging a
1268 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOP) {
1269 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1270 window2_->SetBounds(gfx::Rect(99, 179, 10, 20));
1273 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1274 window_.get(), gfx::Point(), HTTOP));
1275 ASSERT_TRUE(resizer.get());
1276 resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1277 EXPECT_EQ("100,199 20x31", window_->bounds().ToString());
1280 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOPLEFT) {
1281 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1282 window2_->SetBounds(gfx::Rect(99, 179, 10, 20));
1286 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1287 window_.get(), gfx::Point(), HTTOPLEFT));
1288 ASSERT_TRUE(resizer.get());
1289 resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1290 EXPECT_EQ("99,199 21x31", window_->bounds().ToString());
1291 resizer->RevertDrag();
1295 window2_->SetBounds(gfx::Rect(88, 201, 10, 20));
1296 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1297 window_.get(), gfx::Point(), HTTOPLEFT));
1298 ASSERT_TRUE(resizer.get());
1299 resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1300 EXPECT_EQ("98,201 22x29", window_->bounds().ToString());
1301 resizer->RevertDrag();
1305 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOPRIGHT) {
1306 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1310 window2_->SetBounds(gfx::Rect(111, 179, 10, 20));
1311 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1312 window_.get(), gfx::Point(), HTTOPRIGHT));
1313 ASSERT_TRUE(resizer.get());
1314 resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1315 EXPECT_EQ("100,199 21x31", window_->bounds().ToString());
1316 resizer->RevertDrag();
1320 window2_->SetBounds(gfx::Rect(121, 199, 10, 20));
1321 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1322 window_.get(), gfx::Point(), HTTOPRIGHT));
1323 ASSERT_TRUE(resizer.get());
1324 resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1325 EXPECT_EQ("100,199 21x31", window_->bounds().ToString());
1326 resizer->RevertDrag();
1330 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_RIGHT) {
1331 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1332 window2_->SetBounds(gfx::Rect(121, 199, 10, 20));
1335 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1336 window_.get(), gfx::Point(), HTRIGHT));
1337 ASSERT_TRUE(resizer.get());
1338 resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1339 EXPECT_EQ("100,200 21x30", window_->bounds().ToString());
1342 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOMRIGHT) {
1343 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1347 window2_->SetBounds(gfx::Rect(122, 212, 10, 20));
1348 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1349 window_.get(), gfx::Point(), HTBOTTOMRIGHT));
1350 ASSERT_TRUE(resizer.get());
1351 resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1352 EXPECT_EQ("100,200 22x32", window_->bounds().ToString());
1353 resizer->RevertDrag();
1357 window2_->SetBounds(gfx::Rect(111, 233, 10, 20));
1358 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1359 window_.get(), gfx::Point(), HTBOTTOMRIGHT));
1360 ASSERT_TRUE(resizer.get());
1361 resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1362 EXPECT_EQ("100,200 21x33", window_->bounds().ToString());
1363 resizer->RevertDrag();
1367 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOM) {
1368 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1369 window2_->SetBounds(gfx::Rect(111, 233, 10, 20));
1372 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1373 window_.get(), gfx::Point(), HTBOTTOM));
1374 ASSERT_TRUE(resizer.get());
1375 resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1376 EXPECT_EQ("100,200 20x33", window_->bounds().ToString());
1379 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOMLEFT) {
1380 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1384 window2_->SetBounds(gfx::Rect(99, 231, 10, 20));
1385 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1386 window_.get(), gfx::Point(), HTBOTTOMLEFT));
1387 ASSERT_TRUE(resizer.get());
1388 resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1389 EXPECT_EQ("99,200 21x31", window_->bounds().ToString());
1390 resizer->RevertDrag();
1394 window2_->SetBounds(gfx::Rect(89, 209, 10, 20));
1395 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1396 window_.get(), gfx::Point(), HTBOTTOMLEFT));
1397 ASSERT_TRUE(resizer.get());
1398 resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1399 EXPECT_EQ("99,200 21x29", window_->bounds().ToString());
1400 resizer->RevertDrag();
1404 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_LEFT) {
1405 window2_->SetBounds(gfx::Rect(89, 209, 10, 20));
1406 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1409 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1410 window_.get(), gfx::Point(), HTLEFT));
1411 ASSERT_TRUE(resizer.get());
1412 resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1413 EXPECT_EQ("99,200 21x30", window_->bounds().ToString());
1416 // Test that the user user moved window flag is getting properly set.
1417 TEST_F(WorkspaceWindowResizerTest, CheckUserWindowManagedFlags) {
1418 window_->SetBounds(gfx::Rect( 0, 50, 400, 200));
1419 window_->SetProperty(aura::client::kCanMaximizeKey, true);
1421 std::vector<aura::Window*> no_attached_windows;
1422 // Check that an abort doesn't change anything.
1424 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1425 window_.get(), gfx::Point(), HTCAPTION));
1426 ASSERT_TRUE(resizer.get());
1427 // Move it 100 to the bottom.
1428 resizer->Drag(CalculateDragPoint(*resizer, 0, 100), 0);
1429 EXPECT_EQ("0,150 400x200", window_->bounds().ToString());
1430 resizer->RevertDrag();
1432 EXPECT_FALSE(wm::GetWindowState(window_.get())->bounds_changed_by_user());
1435 // Check that a completed move / size does change the user coordinates.
1437 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1438 window_.get(), gfx::Point(), HTCAPTION));
1439 ASSERT_TRUE(resizer.get());
1440 // Move it 100 to the bottom.
1441 resizer->Drag(CalculateDragPoint(*resizer, 0, 100), 0);
1442 EXPECT_EQ("0,150 400x200", window_->bounds().ToString());
1443 resizer->CompleteDrag();
1444 EXPECT_TRUE(wm::GetWindowState(window_.get())->bounds_changed_by_user());
1448 // Test that a window with a specified max size doesn't exceed it when dragged.
1449 TEST_F(WorkspaceWindowResizerTest, TestMaxSizeEnforced) {
1450 window_->SetBounds(gfx::Rect(0, 0, 400, 300));
1451 delegate_.set_max_size(gfx::Size(401, 301));
1453 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1454 window_.get(), gfx::Point(), HTBOTTOMRIGHT));
1455 resizer->Drag(CalculateDragPoint(*resizer, 2, 2), 0);
1456 EXPECT_EQ(401, window_->bounds().width());
1457 EXPECT_EQ(301, window_->bounds().height());
1460 // Test that a window with a specified max width doesn't restrict its height.
1461 TEST_F(WorkspaceWindowResizerTest, TestPartialMaxSizeEnforced) {
1462 window_->SetBounds(gfx::Rect(0, 0, 400, 300));
1463 delegate_.set_max_size(gfx::Size(401, 0));
1465 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1466 window_.get(), gfx::Point(), HTBOTTOMRIGHT));
1467 resizer->Drag(CalculateDragPoint(*resizer, 2, 2), 0);
1468 EXPECT_EQ(401, window_->bounds().width());
1469 EXPECT_EQ(302, window_->bounds().height());
1472 // Test that a window with a specified max size can't be snapped.
1473 TEST_F(WorkspaceWindowResizerTest, PhantomSnapMaxSize) {
1475 // With max size not set we get a phantom window controller for dragging off
1476 // the right hand side.
1477 // Make the window wider than maximum docked width.
1478 window_->SetBounds(gfx::Rect(0, 0, 400, 200));
1480 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1481 window_.get(), gfx::Point(), HTCAPTION));
1482 EXPECT_FALSE(snap_phantom_window_controller());
1483 resizer->Drag(CalculateDragPoint(*resizer, 801, 0), 0);
1484 EXPECT_TRUE(snap_phantom_window_controller());
1485 resizer->RevertDrag();
1488 // With max size defined, we get no phantom window for snapping but we still
1489 // get a phantom window (docking guide).
1490 window_->SetBounds(gfx::Rect(0, 0, 400, 200));
1491 delegate_.set_max_size(gfx::Size(400, 200));
1493 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1494 window_.get(), gfx::Point(), HTCAPTION));
1495 resizer->Drag(CalculateDragPoint(*resizer, 801, 0), 0);
1496 EXPECT_TRUE(snap_phantom_window_controller());
1497 resizer->RevertDrag();
1500 // With max size defined, we get no phantom window for snapping.
1501 window_->SetBounds(gfx::Rect(0, 0, 400, 200));
1502 delegate_.set_max_size(gfx::Size(400, 200));
1503 // With min size defined, we get no phantom window for docking.
1504 delegate_.set_min_size(gfx::Size(400, 200));
1506 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1507 window_.get(), gfx::Point(), HTCAPTION));
1508 resizer->Drag(CalculateDragPoint(*resizer, 801, 0), 0);
1509 EXPECT_FALSE(snap_phantom_window_controller());
1510 resizer->RevertDrag();
1514 TEST_F(WorkspaceWindowResizerTest, DontRewardRightmostWindowForOverflows) {
1515 UpdateDisplay("600x800");
1516 aura::Window* root = Shell::GetPrimaryRootWindow();
1517 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
1519 // Four 100x100 windows flush against eachother, starting at 100,100.
1520 window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
1521 window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
1522 window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
1523 window4_->SetBounds(gfx::Rect(400, 100, 100, 100));
1524 delegate2_.set_max_size(gfx::Size(101, 0));
1526 std::vector<aura::Window*> windows;
1527 windows.push_back(window2_.get());
1528 windows.push_back(window3_.get());
1529 windows.push_back(window4_.get());
1530 scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
1531 window_.get(), gfx::Point(), HTRIGHT,
1532 aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
1533 ASSERT_TRUE(resizer.get());
1534 // Move it 51 to the left, which should contract w1 and expand w2-4.
1535 // w2 will hit its max size straight away, and in doing so will leave extra
1536 // pixels that a naive implementation may award to the rightmost window. A
1537 // fair implementation will give 25 pixels to each of the other windows.
1538 resizer->Drag(CalculateDragPoint(*resizer, -51, 0), 0);
1539 EXPECT_EQ("100,100 49x100", window_->bounds().ToString());
1540 EXPECT_EQ("149,100 101x100", window2_->bounds().ToString());
1541 EXPECT_EQ("250,100 125x100", window3_->bounds().ToString());
1542 EXPECT_EQ("375,100 125x100", window4_->bounds().ToString());
1545 TEST_F(WorkspaceWindowResizerTest, DontExceedMaxWidth) {
1546 UpdateDisplay("600x800");
1547 aura::Window* root = Shell::GetPrimaryRootWindow();
1548 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
1550 // Four 100x100 windows flush against eachother, starting at 100,100.
1551 window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
1552 window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
1553 window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
1554 window4_->SetBounds(gfx::Rect(400, 100, 100, 100));
1555 delegate2_.set_max_size(gfx::Size(101, 0));
1556 delegate3_.set_max_size(gfx::Size(101, 0));
1558 std::vector<aura::Window*> windows;
1559 windows.push_back(window2_.get());
1560 windows.push_back(window3_.get());
1561 windows.push_back(window4_.get());
1562 scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
1563 window_.get(), gfx::Point(), HTRIGHT,
1564 aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
1565 ASSERT_TRUE(resizer.get());
1566 // Move it 52 to the left, which should contract w1 and expand w2-4.
1567 resizer->Drag(CalculateDragPoint(*resizer, -52, 0), 0);
1568 EXPECT_EQ("100,100 48x100", window_->bounds().ToString());
1569 EXPECT_EQ("148,100 101x100", window2_->bounds().ToString());
1570 EXPECT_EQ("249,100 101x100", window3_->bounds().ToString());
1571 EXPECT_EQ("350,100 150x100", window4_->bounds().ToString());
1574 TEST_F(WorkspaceWindowResizerTest, DontExceedMaxHeight) {
1575 UpdateDisplay("600x800");
1576 aura::Window* root = Shell::GetPrimaryRootWindow();
1577 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
1579 // Four 100x100 windows flush against eachother, starting at 100,100.
1580 window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
1581 window2_->SetBounds(gfx::Rect(100, 200, 100, 100));
1582 window3_->SetBounds(gfx::Rect(100, 300, 100, 100));
1583 window4_->SetBounds(gfx::Rect(100, 400, 100, 100));
1584 delegate2_.set_max_size(gfx::Size(0, 101));
1585 delegate3_.set_max_size(gfx::Size(0, 101));
1587 std::vector<aura::Window*> windows;
1588 windows.push_back(window2_.get());
1589 windows.push_back(window3_.get());
1590 windows.push_back(window4_.get());
1591 scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
1592 window_.get(), gfx::Point(), HTBOTTOM,
1593 aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
1594 ASSERT_TRUE(resizer.get());
1595 // Move it 52 up, which should contract w1 and expand w2-4.
1596 resizer->Drag(CalculateDragPoint(*resizer, 0, -52), 0);
1597 EXPECT_EQ("100,100 100x48", window_->bounds().ToString());
1598 EXPECT_EQ("100,148 100x101", window2_->bounds().ToString());
1599 EXPECT_EQ("100,249 100x101", window3_->bounds().ToString());
1600 EXPECT_EQ("100,350 100x150", window4_->bounds().ToString());
1604 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
1605 #define MAYBE_DontExceedMinHeight DISABLED_DontExceedMinHeight
1607 #define MAYBE_DontExceedMinHeight DontExceedMinHeight
1610 TEST_F(WorkspaceWindowResizerTest, MAYBE_DontExceedMinHeight) {
1611 UpdateDisplay("600x500");
1612 aura::Window* root = Shell::GetPrimaryRootWindow();
1613 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
1615 // Four 100x100 windows flush against eachother, starting at 100,100.
1616 window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
1617 window2_->SetBounds(gfx::Rect(100, 200, 100, 100));
1618 window3_->SetBounds(gfx::Rect(100, 300, 100, 100));
1619 window4_->SetBounds(gfx::Rect(100, 400, 100, 100));
1620 delegate2_.set_min_size(gfx::Size(0, 99));
1621 delegate3_.set_min_size(gfx::Size(0, 99));
1623 std::vector<aura::Window*> windows;
1624 windows.push_back(window2_.get());
1625 windows.push_back(window3_.get());
1626 windows.push_back(window4_.get());
1627 scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
1628 window_.get(), gfx::Point(), HTBOTTOM,
1629 aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
1630 ASSERT_TRUE(resizer.get());
1631 // Move it 52 down, which should expand w1 and contract w2-4.
1632 resizer->Drag(CalculateDragPoint(*resizer, 0, 52), 0);
1633 EXPECT_EQ("100,100 100x152", window_->bounds().ToString());
1634 EXPECT_EQ("100,252 100x99", window2_->bounds().ToString());
1635 EXPECT_EQ("100,351 100x99", window3_->bounds().ToString());
1636 EXPECT_EQ("100,450 100x50", window4_->bounds().ToString());
1639 TEST_F(WorkspaceWindowResizerTest, DontExpandRightmostPastMaxWidth) {
1640 UpdateDisplay("600x800");
1641 aura::Window* root = Shell::GetPrimaryRootWindow();
1642 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
1644 // Three 100x100 windows flush against eachother, starting at 100,100.
1645 window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
1646 window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
1647 window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
1648 delegate3_.set_max_size(gfx::Size(101, 0));
1650 std::vector<aura::Window*> windows;
1651 windows.push_back(window2_.get());
1652 windows.push_back(window3_.get());
1653 windows.push_back(window4_.get());
1654 scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
1655 window_.get(), gfx::Point(), HTRIGHT,
1656 aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
1657 ASSERT_TRUE(resizer.get());
1658 // Move it 51 to the left, which should contract w1 and expand w2-3.
1659 resizer->Drag(CalculateDragPoint(*resizer, -51, 0), 0);
1660 EXPECT_EQ("100,100 49x100", window_->bounds().ToString());
1661 EXPECT_EQ("149,100 150x100", window2_->bounds().ToString());
1662 EXPECT_EQ("299,100 101x100", window3_->bounds().ToString());
1665 TEST_F(WorkspaceWindowResizerTest, MoveAttachedWhenGrownToMaxSize) {
1666 UpdateDisplay("600x800");
1667 aura::Window* root = Shell::GetPrimaryRootWindow();
1668 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
1670 // Three 100x100 windows flush against eachother, starting at 100,100.
1671 window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
1672 window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
1673 window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
1674 delegate2_.set_max_size(gfx::Size(101, 0));
1675 delegate3_.set_max_size(gfx::Size(101, 0));
1677 std::vector<aura::Window*> windows;
1678 windows.push_back(window2_.get());
1679 windows.push_back(window3_.get());
1680 windows.push_back(window4_.get());
1681 scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
1682 window_.get(), gfx::Point(), HTRIGHT,
1683 aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
1684 ASSERT_TRUE(resizer.get());
1685 // Move it 52 to the left, which should contract w1 and expand and move w2-3.
1686 resizer->Drag(CalculateDragPoint(*resizer, -52, 0), 0);
1687 EXPECT_EQ("100,100 48x100", window_->bounds().ToString());
1688 EXPECT_EQ("148,100 101x100", window2_->bounds().ToString());
1689 EXPECT_EQ("249,100 101x100", window3_->bounds().ToString());
1693 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
1694 #define MAYBE_MainWindowHonoursMaxWidth DISABLED_MainWindowHonoursMaxWidth
1696 #define MAYBE_MainWindowHonoursMaxWidth MainWindowHonoursMaxWidth
1699 TEST_F(WorkspaceWindowResizerTest, MAYBE_MainWindowHonoursMaxWidth) {
1700 UpdateDisplay("400x800");
1701 aura::Window* root = Shell::GetPrimaryRootWindow();
1702 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
1704 // Three 100x100 windows flush against eachother, starting at 100,100.
1705 window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
1706 window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
1707 window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
1708 delegate_.set_max_size(gfx::Size(102, 0));
1710 std::vector<aura::Window*> windows;
1711 windows.push_back(window2_.get());
1712 windows.push_back(window3_.get());
1713 windows.push_back(window4_.get());
1714 scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
1715 window_.get(), gfx::Point(), HTRIGHT,
1716 aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
1717 ASSERT_TRUE(resizer.get());
1718 // Move it 50 to the right, which should expand w1 and contract w2-3, as they
1719 // won't fit in the root window in their original sizes.
1720 resizer->Drag(CalculateDragPoint(*resizer, 50, 0), 0);
1721 EXPECT_EQ("100,100 102x100", window_->bounds().ToString());
1722 EXPECT_EQ("202,100 99x100", window2_->bounds().ToString());
1723 EXPECT_EQ("301,100 99x100", window3_->bounds().ToString());
1726 TEST_F(WorkspaceWindowResizerTest, MainWindowHonoursMinWidth) {
1727 UpdateDisplay("400x800");
1728 aura::Window* root = Shell::GetPrimaryRootWindow();
1729 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
1731 // Three 100x100 windows flush against eachother, starting at 100,100.
1732 window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
1733 window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
1734 window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
1735 delegate_.set_min_size(gfx::Size(98, 0));
1737 std::vector<aura::Window*> windows;
1738 windows.push_back(window2_.get());
1739 windows.push_back(window3_.get());
1740 scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
1741 window_.get(), gfx::Point(), HTRIGHT,
1742 aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
1743 ASSERT_TRUE(resizer.get());
1744 // Move it 50 to the left, which should contract w1 and expand w2-3.
1745 resizer->Drag(CalculateDragPoint(*resizer, -50, 0), 0);
1746 EXPECT_EQ("100,100 98x100", window_->bounds().ToString());
1747 EXPECT_EQ("198,100 101x100", window2_->bounds().ToString());
1748 EXPECT_EQ("299,100 101x100", window3_->bounds().ToString());
1751 // The following variants test that windows are resized correctly to the edges
1752 // of the screen using touch, when touch point is off of the window border.
1753 TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_RIGHT) {
1754 shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);
1756 InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTRIGHT);
1757 EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(),
1758 touch_resize_window_->bounds().ToString());
1760 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1761 touch_resize_window_.get());
1763 // Drag out of the right border a bit and check if the border is aligned with
1765 generator.GestureScrollSequence(gfx::Point(715, kRootHeight / 2),
1766 gfx::Point(725, kRootHeight / 2),
1767 base::TimeDelta::FromMilliseconds(10),
1769 EXPECT_EQ(gfx::Rect(100, 100, 625, kRootHeight - 200).ToString(),
1770 touch_resize_window_->bounds().ToString());
1771 // Drag more, but stop before being snapped to the edge.
1772 generator.GestureScrollSequence(gfx::Point(725, kRootHeight / 2),
1773 gfx::Point(760, kRootHeight / 2),
1774 base::TimeDelta::FromMilliseconds(10),
1776 EXPECT_EQ(gfx::Rect(100, 100, 660, kRootHeight - 200).ToString(),
1777 touch_resize_window_->bounds().ToString());
1778 // Drag even more to snap to the edge.
1779 generator.GestureScrollSequence(gfx::Point(760, kRootHeight / 2),
1780 gfx::Point(775, kRootHeight / 2),
1781 base::TimeDelta::FromMilliseconds(10),
1783 EXPECT_EQ(gfx::Rect(100, 100, 700, kRootHeight - 200).ToString(),
1784 touch_resize_window_->bounds().ToString());
1787 TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_LEFT) {
1788 shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);
1790 InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTLEFT);
1791 EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(),
1792 touch_resize_window_->bounds().ToString());
1794 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1795 touch_resize_window_.get());
1797 // Drag out of the left border a bit and check if the border is aligned with
1799 generator.GestureScrollSequence(gfx::Point(85, kRootHeight / 2),
1800 gfx::Point(75, kRootHeight / 2),
1801 base::TimeDelta::FromMilliseconds(10),
1803 EXPECT_EQ(gfx::Rect(75, 100, 625, kRootHeight - 200).ToString(),
1804 touch_resize_window_->bounds().ToString());
1805 // Drag more, but stop before being snapped to the edge.
1806 generator.GestureScrollSequence(gfx::Point(75, kRootHeight / 2),
1807 gfx::Point(40, kRootHeight / 2),
1808 base::TimeDelta::FromMilliseconds(10),
1810 EXPECT_EQ(gfx::Rect(40, 100, 660, kRootHeight - 200).ToString(),
1811 touch_resize_window_->bounds().ToString());
1812 // Drag even more to snap to the edge.
1813 generator.GestureScrollSequence(gfx::Point(40, kRootHeight / 2),
1814 gfx::Point(25, kRootHeight / 2),
1815 base::TimeDelta::FromMilliseconds(10),
1817 EXPECT_EQ(gfx::Rect(0, 100, 700, kRootHeight - 200).ToString(),
1818 touch_resize_window_->bounds().ToString());
1821 TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_TOP) {
1822 shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);
1824 InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTTOP);
1825 EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(),
1826 touch_resize_window_->bounds().ToString());
1828 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1829 touch_resize_window_.get());
1831 // Drag out of the top border a bit and check if the border is aligned with
1833 generator.GestureScrollSequence(gfx::Point(400, 85),
1834 gfx::Point(400, 75),
1835 base::TimeDelta::FromMilliseconds(10),
1837 EXPECT_EQ(gfx::Rect(100, 75, 600, kRootHeight - 175).ToString(),
1838 touch_resize_window_->bounds().ToString());
1839 // Drag more, but stop before being snapped to the edge.
1840 generator.GestureScrollSequence(gfx::Point(400, 75),
1841 gfx::Point(400, 40),
1842 base::TimeDelta::FromMilliseconds(10),
1844 EXPECT_EQ(gfx::Rect(100, 40, 600, kRootHeight - 140).ToString(),
1845 touch_resize_window_->bounds().ToString());
1846 // Drag even more to snap to the edge.
1847 generator.GestureScrollSequence(gfx::Point(400, 40),
1848 gfx::Point(400, 25),
1849 base::TimeDelta::FromMilliseconds(10),
1851 EXPECT_EQ(gfx::Rect(100, 0, 600, kRootHeight - 100).ToString(),
1852 touch_resize_window_->bounds().ToString());
1855 TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_BOTTOM) {
1856 shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);
1858 InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTBOTTOM);
1859 EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(),
1860 touch_resize_window_->bounds().ToString());
1862 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1863 touch_resize_window_.get());
1865 // Drag out of the bottom border a bit and check if the border is aligned with
1867 generator.GestureScrollSequence(gfx::Point(400, kRootHeight - 85),
1868 gfx::Point(400, kRootHeight - 75),
1869 base::TimeDelta::FromMilliseconds(10),
1871 EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 175).ToString(),
1872 touch_resize_window_->bounds().ToString());
1873 // Drag more, but stop before being snapped to the edge.
1874 generator.GestureScrollSequence(gfx::Point(400, kRootHeight - 75),
1875 gfx::Point(400, kRootHeight - 40),
1876 base::TimeDelta::FromMilliseconds(10),
1878 EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 140).ToString(),
1879 touch_resize_window_->bounds().ToString());
1880 // Drag even more to snap to the edge.
1881 generator.GestureScrollSequence(gfx::Point(400, kRootHeight - 40),
1882 gfx::Point(400, kRootHeight - 25),
1883 base::TimeDelta::FromMilliseconds(10),
1885 EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 100).ToString(),
1886 touch_resize_window_->bounds().ToString());