Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / ash / wm / workspace / workspace_window_resizer_unittest.cc
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.
4
5 #include "ash/wm/workspace/workspace_window_resizer.h"
6
7 #include "ash/ash_constants.h"
8 #include "ash/ash_switches.h"
9 #include "ash/display/display_manager.h"
10 #include "ash/root_window_controller.h"
11 #include "ash/screen_util.h"
12 #include "ash/shelf/shelf_layout_manager.h"
13 #include "ash/shell.h"
14 #include "ash/shell_window_ids.h"
15 #include "ash/test/ash_test_base.h"
16 #include "ash/wm/window_state.h"
17 #include "ash/wm/window_util.h"
18 #include "ash/wm/workspace/phantom_window_controller.h"
19 #include "ash/wm/workspace/snap_sizer.h"
20 #include "ash/wm/workspace_controller.h"
21 #include "base/command_line.h"
22 #include "base/strings/string_number_conversions.h"
23 #include "base/strings/stringprintf.h"
24 #include "ui/aura/client/aura_constants.h"
25 #include "ui/aura/root_window.h"
26 #include "ui/aura/test/event_generator.h"
27 #include "ui/aura/test/test_window_delegate.h"
28 #include "ui/base/hit_test.h"
29 #include "ui/gfx/insets.h"
30 #include "ui/gfx/screen.h"
31 #include "ui/views/widget/widget.h"
32
33 namespace ash {
34 namespace internal {
35 namespace {
36
37 const int kRootHeight = 600;
38
39 // A simple window delegate that returns the specified min size.
40 class TestWindowDelegate : public aura::test::TestWindowDelegate {
41  public:
42   TestWindowDelegate() {
43   }
44   virtual ~TestWindowDelegate() {}
45
46   void set_min_size(const gfx::Size& size) {
47     min_size_ = size;
48   }
49
50   void set_max_size(const gfx::Size& size) {
51     max_size_ = size;
52   }
53
54  private:
55   // Overridden from aura::Test::TestWindowDelegate:
56   virtual gfx::Size GetMinimumSize() const OVERRIDE {
57     return min_size_;
58   }
59
60   virtual gfx::Size GetMaximumSize() const OVERRIDE {
61     return max_size_;
62   }
63
64   gfx::Size min_size_;
65   gfx::Size max_size_;
66
67   DISALLOW_COPY_AND_ASSIGN(TestWindowDelegate);
68 };
69
70 }  // namespace
71
72 class WorkspaceWindowResizerTest : public test::AshTestBase {
73  public:
74   WorkspaceWindowResizerTest() : workspace_resizer_(NULL) {}
75   virtual ~WorkspaceWindowResizerTest() {}
76
77   virtual void SetUp() OVERRIDE {
78     AshTestBase::SetUp();
79     UpdateDisplay(base::StringPrintf("800x%d", kRootHeight));
80
81     aura::Window* root = Shell::GetPrimaryRootWindow();
82     gfx::Rect root_bounds(root->bounds());
83 #if defined(OS_WIN)
84     // RootWindow and Display can't resize on Windows Ash.
85     // http://crbug.com/165962
86     EXPECT_EQ(kRootHeight, root_bounds.height());
87 #endif
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());
94     window_->set_id(1);
95
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());
100     window2_->set_id(2);
101
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());
106     window3_->set_id(3);
107
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());
112     window4_->set_id(4);
113   }
114
115   virtual void TearDown() OVERRIDE {
116     window_.reset();
117     window2_.reset();
118     window3_.reset();
119     window4_.reset();
120     touch_resize_window_.reset();
121     AshTestBase::TearDown();
122   }
123
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 {
128     std::string result;
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_) {
133         if (!result.empty())
134           result += " ";
135         result += base::IntToString((*i)->id());
136       }
137     }
138     return result;
139   }
140
141  protected:
142   WindowResizer* CreateResizerForTest(
143       aura::Window* window,
144       const gfx::Point& point_in_parent,
145       int window_component) {
146     WindowResizer* resizer = CreateWindowResizer(
147         window,
148         point_in_parent,
149         window_component,
150         aura::client::WINDOW_MOVE_SOURCE_MOUSE).release();
151     workspace_resizer_ = WorkspaceWindowResizer::instance_;
152     return resizer;
153   }
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);
164   }
165
166   PhantomWindowController* snap_phantom_window_controller() const {
167     return workspace_resizer_->snap_phantom_window_controller_.get();
168   }
169
170   gfx::Point CalculateDragPoint(const WindowResizer& resizer,
171                                 int delta_x,
172                                 int delta_y) const {
173     gfx::Point location = resizer.GetInitialLocation();
174     location.set_x(location.x() + delta_x);
175     location.set_y(location.y() + delta_y);
176     return location;
177   }
178
179   std::vector<aura::Window*> empty_windows() const {
180     return std::vector<aura::Window*>();
181   }
182
183   internal::ShelfLayoutManager* shelf_layout_manager() {
184     return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
185   }
186
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,
191                                             bounds));
192     gfx::Insets mouse_outer_insets(-ash::kResizeOutsideBoundsSize,
193                                    -ash::kResizeOutsideBoundsSize,
194                                    -ash::kResizeOutsideBoundsSize,
195                                    -ash::kResizeOutsideBoundsSize);
196     gfx::Insets touch_outer_insets = mouse_outer_insets.Scale(
197         ash::kResizeOutsideBoundsScaleForTouch);
198     touch_resize_window_->SetHitTestBoundsOverrideOuter(mouse_outer_insets,
199                                                         touch_outer_insets);
200   }
201
202   TestWindowDelegate delegate_;
203   TestWindowDelegate delegate2_;
204   TestWindowDelegate delegate3_;
205   TestWindowDelegate delegate4_;
206   scoped_ptr<aura::Window> window_;
207   scoped_ptr<aura::Window> window2_;
208   scoped_ptr<aura::Window> window3_;
209   scoped_ptr<aura::Window> window4_;
210
211   TestWindowDelegate touch_resize_delegate_;
212   scoped_ptr<aura::Window> touch_resize_window_;
213   WorkspaceWindowResizer* workspace_resizer_;
214
215  private:
216   DISALLOW_COPY_AND_ASSIGN(WorkspaceWindowResizerTest);
217 };
218
219 class WorkspaceWindowResizerTestSticky : public WorkspaceWindowResizerTest {
220  public:
221   WorkspaceWindowResizerTestSticky() {}
222   virtual ~WorkspaceWindowResizerTestSticky() {}
223
224   virtual void SetUp() OVERRIDE {
225     CommandLine::ForCurrentProcess()->AppendSwitch(
226         ash::switches::kAshEnableStickyEdges);
227     WorkspaceWindowResizerTest::SetUp();
228   }
229
230  private:
231   DISALLOW_COPY_AND_ASSIGN(WorkspaceWindowResizerTestSticky);
232 };
233
234 // Assertions around attached window resize dragging from the right with 2
235 // windows.
236 TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_2) {
237   window_->SetBounds(gfx::Rect(0, 300, 400, 300));
238   window2_->SetBounds(gfx::Rect(400, 200, 100, 200));
239
240   std::vector<aura::Window*> windows;
241   windows.push_back(window2_.get());
242   scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
243       window_.get(), gfx::Point(), HTRIGHT,
244       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
245   ASSERT_TRUE(resizer.get());
246   // Move it 100 to the right, which should expand w1 and push w2.
247   resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0);
248   EXPECT_EQ("0,300 500x300", window_->bounds().ToString());
249   EXPECT_EQ("500,200 100x200", window2_->bounds().ToString());
250
251   // Push off the screen, w2 should be resized to its min.
252   delegate2_.set_min_size(gfx::Size(20, 20));
253   resizer->Drag(CalculateDragPoint(*resizer, 800, 20), 0);
254   EXPECT_EQ("0,300 780x300", window_->bounds().ToString());
255   EXPECT_EQ("780,200 20x200", window2_->bounds().ToString());
256
257   // Move back to 100 and verify w2 gets its original size.
258   resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0);
259   EXPECT_EQ("0,300 500x300", window_->bounds().ToString());
260   EXPECT_EQ("500,200 100x200", window2_->bounds().ToString());
261
262   // Revert and make sure everything moves back.
263   resizer->Drag(CalculateDragPoint(*resizer, 800, 20), 0);
264   resizer->RevertDrag();
265   EXPECT_EQ("0,300 400x300", window_->bounds().ToString());
266   EXPECT_EQ("400,200 100x200", window2_->bounds().ToString());
267 }
268
269 // Assertions around collapsing and expanding.
270 TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_Compress) {
271   window_->SetBounds(gfx::Rect(   0, 300, 400, 300));
272   window2_->SetBounds(gfx::Rect(400, 200, 100, 200));
273
274   std::vector<aura::Window*> windows;
275   windows.push_back(window2_.get());
276   scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
277       window_.get(), gfx::Point(), HTRIGHT,
278       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
279   ASSERT_TRUE(resizer.get());
280   // Move it 100 to the left, which should expand w2 and collapse w1.
281   resizer->Drag(CalculateDragPoint(*resizer, -100, 10), 0);
282   EXPECT_EQ("0,300 300x300", window_->bounds().ToString());
283   EXPECT_EQ("300,200 200x200", window2_->bounds().ToString());
284
285   // Collapse all the way to w1's min.
286   delegate_.set_min_size(gfx::Size(20, 20));
287   resizer->Drag(CalculateDragPoint(*resizer, -800, 20), 0);
288   EXPECT_EQ("0,300 20x300", window_->bounds().ToString());
289   EXPECT_EQ("20,200 480x200", window2_->bounds().ToString());
290
291   // Move 100 to the left.
292   resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0);
293   EXPECT_EQ("0,300 500x300", window_->bounds().ToString());
294   EXPECT_EQ("500,200 100x200", window2_->bounds().ToString());
295
296   // Back to -100.
297   resizer->Drag(CalculateDragPoint(*resizer, -100, 20), 0);
298   EXPECT_EQ("0,300 300x300", window_->bounds().ToString());
299   EXPECT_EQ("300,200 200x200", window2_->bounds().ToString());
300 }
301
302 // Assertions around attached window resize dragging from the right with 3
303 // windows.
304 TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_3) {
305   window_->SetBounds(gfx::Rect( 100, 300, 200, 300));
306   window2_->SetBounds(gfx::Rect(300, 300, 150, 200));
307   window3_->SetBounds(gfx::Rect(450, 300, 100, 200));
308   delegate2_.set_min_size(gfx::Size(52, 50));
309   delegate3_.set_min_size(gfx::Size(38, 50));
310
311   std::vector<aura::Window*> windows;
312   windows.push_back(window2_.get());
313   windows.push_back(window3_.get());
314   scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
315       window_.get(), gfx::Point(), HTRIGHT,
316       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
317   ASSERT_TRUE(resizer.get());
318   // Move it 100 to the right, which should expand w1 and push w2 and w3.
319   resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0);
320   EXPECT_EQ("100,300 300x300", window_->bounds().ToString());
321   EXPECT_EQ("400,300 150x200", window2_->bounds().ToString());
322   EXPECT_EQ("550,300 100x200", window3_->bounds().ToString());
323
324   // Move it 300, things should compress.
325   resizer->Drag(CalculateDragPoint(*resizer, 300, -10), 0);
326   EXPECT_EQ("100,300 500x300", window_->bounds().ToString());
327   EXPECT_EQ("600,300 120x200", window2_->bounds().ToString());
328   EXPECT_EQ("720,300 80x200", window3_->bounds().ToString());
329
330   // Move it so much the last two end up at their min.
331   resizer->Drag(CalculateDragPoint(*resizer, 800, 50), 0);
332   EXPECT_EQ("100,300 610x300", window_->bounds().ToString());
333   EXPECT_EQ("710,300 52x200", window2_->bounds().ToString());
334   EXPECT_EQ("762,300 38x200", window3_->bounds().ToString());
335
336   // Revert and make sure everything moves back.
337   resizer->RevertDrag();
338   EXPECT_EQ("100,300 200x300", window_->bounds().ToString());
339   EXPECT_EQ("300,300 150x200", window2_->bounds().ToString());
340   EXPECT_EQ("450,300 100x200", window3_->bounds().ToString());
341 }
342
343 // Assertions around attached window resizing (collapsing and expanding) with
344 // 3 windows.
345 TEST_F(WorkspaceWindowResizerTest, AttachedResize_RIGHT_3_Compress) {
346   window_->SetBounds(gfx::Rect( 100, 300, 200, 300));
347   window2_->SetBounds(gfx::Rect(300, 300, 200, 200));
348   window3_->SetBounds(gfx::Rect(450, 300, 100, 200));
349   delegate2_.set_min_size(gfx::Size(52, 50));
350   delegate3_.set_min_size(gfx::Size(38, 50));
351
352   std::vector<aura::Window*> windows;
353   windows.push_back(window2_.get());
354   windows.push_back(window3_.get());
355   scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
356       window_.get(), gfx::Point(), HTRIGHT,
357       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
358   ASSERT_TRUE(resizer.get());
359   // Move it -100 to the right, which should collapse w1 and expand w2 and w3.
360   resizer->Drag(CalculateDragPoint(*resizer, -100, -10), 0);
361   EXPECT_EQ("100,300 100x300", window_->bounds().ToString());
362   EXPECT_EQ("200,300 266x200", window2_->bounds().ToString());
363   EXPECT_EQ("466,300 134x200", window3_->bounds().ToString());
364
365   // Move it 100 to the right.
366   resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0);
367   EXPECT_EQ("100,300 300x300", window_->bounds().ToString());
368   EXPECT_EQ("400,300 200x200", window2_->bounds().ToString());
369   EXPECT_EQ("600,300 100x200", window3_->bounds().ToString());
370
371   // 100 to the left again.
372   resizer->Drag(CalculateDragPoint(*resizer, -100, -10), 0);
373   EXPECT_EQ("100,300 100x300", window_->bounds().ToString());
374   EXPECT_EQ("200,300 266x200", window2_->bounds().ToString());
375   EXPECT_EQ("466,300 134x200", window3_->bounds().ToString());
376 }
377
378 // Assertions around collapsing and expanding from the bottom.
379 TEST_F(WorkspaceWindowResizerTest, AttachedResize_BOTTOM_Compress) {
380   window_->SetBounds(gfx::Rect(   0, 100, 400, 300));
381   window2_->SetBounds(gfx::Rect(400, 400, 100, 200));
382
383   std::vector<aura::Window*> windows;
384   windows.push_back(window2_.get());
385   scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
386       window_.get(), gfx::Point(), HTBOTTOM,
387       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
388   ASSERT_TRUE(resizer.get());
389   // Move it up 100, which should expand w2 and collapse w1.
390   resizer->Drag(CalculateDragPoint(*resizer, 10, -100), 0);
391   EXPECT_EQ("0,100 400x200", window_->bounds().ToString());
392   EXPECT_EQ("400,300 100x300", window2_->bounds().ToString());
393
394   // Collapse all the way to w1's min.
395   delegate_.set_min_size(gfx::Size(20, 20));
396   resizer->Drag(CalculateDragPoint(*resizer, 20, -800), 0);
397   EXPECT_EQ("0,100 400x20", window_->bounds().ToString());
398   EXPECT_EQ("400,120 100x480", window2_->bounds().ToString());
399
400   // Move 100 down.
401   resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0);
402   EXPECT_EQ("0,100 400x400", window_->bounds().ToString());
403   EXPECT_EQ("400,500 100x100", window2_->bounds().ToString());
404
405   // Back to -100.
406   resizer->Drag(CalculateDragPoint(*resizer, 20, -100), 0);
407   EXPECT_EQ("0,100 400x200", window_->bounds().ToString());
408   EXPECT_EQ("400,300 100x300", window2_->bounds().ToString());
409 }
410
411 // Assertions around attached window resize dragging from the bottom with 2
412 // windows.
413 TEST_F(WorkspaceWindowResizerTest, AttachedResize_BOTTOM_2) {
414   window_->SetBounds(gfx::Rect( 0,  50, 400, 200));
415   window2_->SetBounds(gfx::Rect(0, 250, 200, 100));
416
417   std::vector<aura::Window*> windows;
418   windows.push_back(window2_.get());
419   scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
420       window_.get(), gfx::Point(), HTBOTTOM,
421       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
422   ASSERT_TRUE(resizer.get());
423   // Move it 100 to the bottom, which should expand w1 and push w2.
424   resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0);
425   EXPECT_EQ("0,50 400x300", window_->bounds().ToString());
426   EXPECT_EQ("0,350 200x100", window2_->bounds().ToString());
427
428   // Push off the screen, w2 should be resized to its min.
429   delegate2_.set_min_size(gfx::Size(20, 20));
430   resizer->Drag(CalculateDragPoint(*resizer, 50, 820), 0);
431   EXPECT_EQ("0,50 400x530", window_->bounds().ToString());
432   EXPECT_EQ("0,580 200x20", window2_->bounds().ToString());
433
434   // Move back to 100 and verify w2 gets its original size.
435   resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0);
436   EXPECT_EQ("0,50 400x300", window_->bounds().ToString());
437   EXPECT_EQ("0,350 200x100", window2_->bounds().ToString());
438
439   // Revert and make sure everything moves back.
440   resizer->Drag(CalculateDragPoint(*resizer, 800, 20), 0);
441   resizer->RevertDrag();
442   EXPECT_EQ("0,50 400x200", window_->bounds().ToString());
443   EXPECT_EQ("0,250 200x100", window2_->bounds().ToString());
444 }
445
446 #if defined(OS_WIN)
447 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
448 #define MAYBE_AttachedResize_BOTTOM_3 DISABLED_AttachedResize_BOTTOM_3
449 #else
450 #define MAYBE_AttachedResize_BOTTOM_3 AttachedResize_BOTTOM_3
451 #endif
452
453 // Assertions around attached window resize dragging from the bottom with 3
454 // windows.
455 TEST_F(WorkspaceWindowResizerTest, MAYBE_AttachedResize_BOTTOM_3) {
456   UpdateDisplay("600x800");
457   aura::Window* root = Shell::GetPrimaryRootWindow();
458   Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
459
460   window_->SetBounds(gfx::Rect( 300, 100, 300, 200));
461   window2_->SetBounds(gfx::Rect(300, 300, 200, 150));
462   window3_->SetBounds(gfx::Rect(300, 450, 200, 100));
463   delegate2_.set_min_size(gfx::Size(50, 52));
464   delegate3_.set_min_size(gfx::Size(50, 38));
465
466   std::vector<aura::Window*> windows;
467   windows.push_back(window2_.get());
468   windows.push_back(window3_.get());
469   scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
470       window_.get(), gfx::Point(), HTBOTTOM,
471       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
472   ASSERT_TRUE(resizer.get());
473   // Move it 100 down, which should expand w1 and push w2 and w3.
474   resizer->Drag(CalculateDragPoint(*resizer, -10, 100), 0);
475   EXPECT_EQ("300,100 300x300", window_->bounds().ToString());
476   EXPECT_EQ("300,400 200x150", window2_->bounds().ToString());
477   EXPECT_EQ("300,550 200x100", window3_->bounds().ToString());
478
479   // Move it 296 things should compress.
480   resizer->Drag(CalculateDragPoint(*resizer, -10, 296), 0);
481   EXPECT_EQ("300,100 300x496", window_->bounds().ToString());
482   EXPECT_EQ("300,596 200x123", window2_->bounds().ToString());
483   EXPECT_EQ("300,719 200x81", window3_->bounds().ToString());
484
485   // Move it so much everything ends up at its min.
486   resizer->Drag(CalculateDragPoint(*resizer, 50, 798), 0);
487   EXPECT_EQ("300,100 300x610", window_->bounds().ToString());
488   EXPECT_EQ("300,710 200x52", window2_->bounds().ToString());
489   EXPECT_EQ("300,762 200x38", window3_->bounds().ToString());
490
491   // Revert and make sure everything moves back.
492   resizer->RevertDrag();
493   EXPECT_EQ("300,100 300x200", window_->bounds().ToString());
494   EXPECT_EQ("300,300 200x150", window2_->bounds().ToString());
495   EXPECT_EQ("300,450 200x100", window3_->bounds().ToString());
496 }
497
498 // Assertions around attached window resizing (collapsing and expanding) with
499 // 3 windows.
500 TEST_F(WorkspaceWindowResizerTest, AttachedResize_BOTTOM_3_Compress) {
501   window_->SetBounds(gfx::Rect(  0,   0, 200, 200));
502   window2_->SetBounds(gfx::Rect(10, 200, 200, 200));
503   window3_->SetBounds(gfx::Rect(20, 400, 100, 100));
504   delegate2_.set_min_size(gfx::Size(52, 50));
505   delegate3_.set_min_size(gfx::Size(38, 50));
506
507   std::vector<aura::Window*> windows;
508   windows.push_back(window2_.get());
509   windows.push_back(window3_.get());
510   scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
511       window_.get(), gfx::Point(), HTBOTTOM,
512       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
513   ASSERT_TRUE(resizer.get());
514   // Move it 100 up, which should collapse w1 and expand w2 and w3.
515   resizer->Drag(CalculateDragPoint(*resizer, -10, -100), 0);
516   EXPECT_EQ("0,0 200x100", window_->bounds().ToString());
517   EXPECT_EQ("10,100 200x266", window2_->bounds().ToString());
518   EXPECT_EQ("20,366 100x134", window3_->bounds().ToString());
519
520   // Move it 100 down.
521   resizer->Drag(CalculateDragPoint(*resizer, 10, 100), 0);
522   EXPECT_EQ("0,0 200x300", window_->bounds().ToString());
523   EXPECT_EQ("10,300 200x200", window2_->bounds().ToString());
524   EXPECT_EQ("20,500 100x100", window3_->bounds().ToString());
525
526   // 100 up again.
527   resizer->Drag(CalculateDragPoint(*resizer, -10, -100), 0);
528   EXPECT_EQ("0,0 200x100", window_->bounds().ToString());
529   EXPECT_EQ("10,100 200x266", window2_->bounds().ToString());
530   EXPECT_EQ("20,366 100x134", window3_->bounds().ToString());
531 }
532
533 // Tests that touch-dragging a window does not lock the mouse cursor
534 // and therefore shows the cursor on a mousemove.
535 TEST_F(WorkspaceWindowResizerTest, MouseMoveWithTouchDrag) {
536   window_->SetBounds(gfx::Rect(0, 300, 400, 300));
537   window2_->SetBounds(gfx::Rect(400, 200, 100, 200));
538
539   Shell* shell = Shell::GetInstance();
540   aura::test::EventGenerator generator(window_->GetRootWindow());
541
542   // The cursor should not be locked initially.
543   EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked());
544
545   std::vector<aura::Window*> windows;
546   windows.push_back(window2_.get());
547   scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
548       window_.get(), gfx::Point(), HTRIGHT,
549       aura::client::WINDOW_MOVE_SOURCE_TOUCH, windows));
550   ASSERT_TRUE(resizer.get());
551
552   // Creating a WorkspaceWindowResizer should not lock the cursor.
553   EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked());
554
555   // The cursor should be hidden after touching the screen and
556   // starting a drag.
557   EXPECT_TRUE(shell->cursor_manager()->IsCursorVisible());
558   generator.PressTouch();
559   resizer->Drag(CalculateDragPoint(*resizer, 100, 10), 0);
560   EXPECT_FALSE(shell->cursor_manager()->IsCursorVisible());
561   EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked());
562
563   // Moving the mouse should show the cursor.
564   generator.MoveMouseBy(1, 1);
565   EXPECT_TRUE(shell->cursor_manager()->IsCursorVisible());
566   EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked());
567
568   resizer->RevertDrag();
569 }
570
571 // Assertions around dragging to the left/right edge of the screen.
572 TEST_F(WorkspaceWindowResizerTest, Edge) {
573   if (!SupportsHostWindowResize())
574     return;
575
576   // Resize host window to force insets update.
577   UpdateDisplay("800x700");
578   // TODO(varkha): Insets are reset after every drag because of
579   // http://crbug.com/292238.
580   // Window is wide enough not to get docked right away.
581   window_->SetBounds(gfx::Rect(20, 30, 400, 60));
582   wm::WindowState* window_state = wm::GetWindowState(window_.get());
583
584   {
585     internal::SnapSizer snap_sizer(window_state, gfx::Point(),
586         internal::SnapSizer::LEFT_EDGE, internal::SnapSizer::OTHER_INPUT);
587     gfx::Rect expected_bounds(snap_sizer.target_bounds());
588
589     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
590         window_.get(), gfx::Point(), HTCAPTION));
591     ASSERT_TRUE(resizer.get());
592     resizer->Drag(CalculateDragPoint(*resizer, 0, 10), 0);
593     resizer->CompleteDrag();
594
595     EXPECT_EQ(expected_bounds.ToString(), window_->bounds().ToString());
596     ASSERT_TRUE(window_state->HasRestoreBounds());
597     EXPECT_EQ("20,30 400x60",
598               window_state->GetRestoreBoundsInScreen().ToString());
599   }
600   // Try the same with the right side.
601   {
602     internal::SnapSizer snap_sizer(window_state, gfx::Point(),
603         internal::SnapSizer::RIGHT_EDGE, internal::SnapSizer::OTHER_INPUT);
604     gfx::Rect expected_bounds(snap_sizer.target_bounds());
605
606     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
607         window_.get(), gfx::Point(), HTCAPTION));
608     ASSERT_TRUE(resizer.get());
609     resizer->Drag(CalculateDragPoint(*resizer, 800, 10), 0);
610     resizer->CompleteDrag();
611     EXPECT_EQ(expected_bounds.ToString(), window_->bounds().ToString());
612     ASSERT_TRUE(window_state->HasRestoreBounds());
613     EXPECT_EQ("20,30 400x60",
614               window_state->GetRestoreBoundsInScreen().ToString());
615   }
616
617   // Test if the restore bounds is correct in multiple displays.
618   if (!SupportsMultipleDisplays())
619     return;
620
621   // Restore the window to clear snapped state.
622   window_state->Restore();
623
624   UpdateDisplay("800x600,500x600");
625   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
626   EXPECT_EQ(root_windows[0], window_->GetRootWindow());
627   // Window is wide enough not to get docked right away.
628   window_->SetBoundsInScreen(gfx::Rect(800, 10, 400, 60),
629                              ScreenUtil::GetSecondaryDisplay());
630   EXPECT_EQ(root_windows[1], window_->GetRootWindow());
631   {
632     EXPECT_EQ("800,10 400x60", window_->GetBoundsInScreen().ToString());
633
634     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
635         window_.get(), gfx::Point(), HTCAPTION));
636     ASSERT_TRUE(resizer.get());
637     resizer->Drag(CalculateDragPoint(*resizer, 499, 0), 0);
638     int bottom =
639         ScreenUtil::GetDisplayWorkAreaBoundsInParent(window_.get()).bottom();
640     resizer->CompleteDrag();
641     // With the resolution of 500x600 we will hit in this case the 50% screen
642     // size setting.
643     // TODO(varkha): Insets are updated because of http://crbug.com/292238
644     EXPECT_EQ("250,0 250x" + base::IntToString(bottom),
645               window_->bounds().ToString());
646     EXPECT_EQ("800,10 400x60",
647               window_state->GetRestoreBoundsInScreen().ToString());
648   }
649 }
650
651 // Check that non resizable windows will not get resized.
652 TEST_F(WorkspaceWindowResizerTest, NonResizableWindows) {
653   window_->SetBounds(gfx::Rect(20, 30, 50, 60));
654   window_->SetProperty(aura::client::kCanResizeKey, false);
655
656   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
657       window_.get(), gfx::Point(), HTCAPTION));
658   ASSERT_TRUE(resizer.get());
659   resizer->Drag(CalculateDragPoint(*resizer, -20, 0), 0);
660   resizer->CompleteDrag();
661   EXPECT_EQ("0,30 50x60", window_->bounds().ToString());
662 }
663
664 TEST_F(WorkspaceWindowResizerTest, CancelSnapPhantom) {
665   if (!SupportsMultipleDisplays())
666     return;
667
668   UpdateDisplay("800x600,800x600");
669   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
670   ASSERT_EQ(2U, root_windows.size());
671
672   window_->SetBoundsInScreen(gfx::Rect(0, 0, 50, 60),
673                              Shell::GetScreen()->GetPrimaryDisplay());
674   EXPECT_EQ(root_windows[0], window_->GetRootWindow());
675   EXPECT_FLOAT_EQ(1.0f, window_->layer()->opacity());
676   {
677     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
678         window_.get(), gfx::Point(), HTCAPTION));
679     ASSERT_TRUE(resizer.get());
680     EXPECT_FALSE(snap_phantom_window_controller());
681
682     // The pointer is on the edge but not shared. The snap phantom window
683     // controller should be non-NULL.
684     resizer->Drag(CalculateDragPoint(*resizer, 799, 0), 0);
685     EXPECT_TRUE(snap_phantom_window_controller());
686
687     // Move the cursor across the edge. Now the snap phantom window controller
688     // should be canceled.
689     resizer->Drag(CalculateDragPoint(*resizer, 800, 0), 0);
690     EXPECT_FALSE(snap_phantom_window_controller());
691   }
692 }
693
694 // Verifies windows are correctly restacked when reordering multiple windows.
695 TEST_F(WorkspaceWindowResizerTest, RestackAttached) {
696   window_->SetBounds(gfx::Rect(   0, 0, 200, 300));
697   window2_->SetBounds(gfx::Rect(200, 0, 100, 200));
698   window3_->SetBounds(gfx::Rect(300, 0, 100, 100));
699
700   {
701     std::vector<aura::Window*> windows;
702     windows.push_back(window2_.get());
703     scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
704         window_.get(), gfx::Point(), HTRIGHT,
705         aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
706     ASSERT_TRUE(resizer.get());
707     // Move it 100 to the right, which should expand w1 and push w2 and w3.
708     resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0);
709
710     // 2 should be topmost since it's initially the highest in the stack.
711     EXPECT_EQ("2 1 3", WindowOrderAsString(window_->parent()));
712   }
713
714   {
715     std::vector<aura::Window*> windows;
716     windows.push_back(window3_.get());
717     scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
718         window2_.get(), gfx::Point(), HTRIGHT,
719         aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
720     ASSERT_TRUE(resizer.get());
721     // Move it 100 to the right, which should expand w1 and push w2 and w3.
722     resizer->Drag(CalculateDragPoint(*resizer, 100, -10), 0);
723
724     // 2 should be topmost since it's initially the highest in the stack.
725     EXPECT_EQ("2 3 1", WindowOrderAsString(window_->parent()));
726   }
727 }
728
729 // Makes sure we don't allow dragging below the work area.
730 TEST_F(WorkspaceWindowResizerTest, DontDragOffBottom) {
731   Shell::GetInstance()->SetDisplayWorkAreaInsets(
732       Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 10, 0));
733
734   ASSERT_EQ(1, Shell::GetScreen()->GetNumDisplays());
735
736   window_->SetBounds(gfx::Rect(100, 200, 300, 400));
737   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
738       window_.get(), gfx::Point(), HTCAPTION));
739   ASSERT_TRUE(resizer.get());
740   resizer->Drag(CalculateDragPoint(*resizer, 0, 600), 0);
741   int expected_y =
742       kRootHeight - WorkspaceWindowResizer::kMinOnscreenHeight - 10;
743   EXPECT_EQ("100," + base::IntToString(expected_y) + " 300x400",
744             window_->bounds().ToString());
745 }
746
747 // Makes sure we don't allow dragging on the work area with multidisplay.
748 TEST_F(WorkspaceWindowResizerTest, DontDragOffBottomWithMultiDisplay) {
749   if (!SupportsMultipleDisplays())
750     return;
751
752   UpdateDisplay("800x600,800x600");
753   ASSERT_EQ(2, Shell::GetScreen()->GetNumDisplays());
754
755   Shell::GetInstance()->SetDisplayWorkAreaInsets(
756       Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 10, 0));
757
758   // Positions the secondary display at the bottom the primary display.
759   Shell::GetInstance()->display_manager()->SetLayoutForCurrentDisplays(
760       ash::DisplayLayout(ash::DisplayLayout::BOTTOM, 0));
761
762   {
763     window_->SetBounds(gfx::Rect(100, 200, 300, 20));
764     DCHECK_LT(window_->bounds().height(),
765               WorkspaceWindowResizer::kMinOnscreenHeight);
766     // Drag down avoiding dragging along the edge as that would side-snap.
767     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
768         window_.get(), gfx::Point(10, 0), HTCAPTION));
769     ASSERT_TRUE(resizer.get());
770     resizer->Drag(CalculateDragPoint(*resizer, 0, 400), 0);
771     int expected_y = kRootHeight - window_->bounds().height() - 10;
772     // When the mouse cursor is in the primary display, the window cannot move
773     // on non-work area but can get all the way towards the bottom,
774     // restricted only by the window height.
775     EXPECT_EQ("100," + base::IntToString(expected_y) + " 300x20",
776               window_->bounds().ToString());
777     // Revert the drag in order to not remember the restore bounds.
778     resizer->RevertDrag();
779   }
780
781   Shell::GetInstance()->SetDisplayWorkAreaInsets(
782       Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 10, 0));
783   {
784     window_->SetBounds(gfx::Rect(100, 200, 300, 400));
785     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
786         window_.get(), gfx::Point(10, 0), HTCAPTION));
787     ASSERT_TRUE(resizer.get());
788     // Drag down avoiding dragging along the edge as that would side-snap.
789     resizer->Drag(CalculateDragPoint(*resizer, 0, 400), 0);
790     int expected_y =
791         kRootHeight - WorkspaceWindowResizer::kMinOnscreenHeight - 10;
792     // When the mouse cursor is in the primary display, the window cannot move
793     // on non-work area with kMinOnscreenHeight margin.
794     EXPECT_EQ("100," + base::IntToString(expected_y) + " 300x400",
795               window_->bounds().ToString());
796     resizer->CompleteDrag();
797   }
798
799   {
800     window_->SetBounds(gfx::Rect(100, 200, 300, 400));
801     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
802         window_.get(), window_->bounds().origin(), HTCAPTION));
803     ASSERT_TRUE(resizer.get());
804     // Drag down avoiding getting stuck against the shelf on the bottom screen.
805     resizer->Drag(CalculateDragPoint(*resizer, 0, 500), 0);
806     // The window can move to the secondary display beyond non-work area of
807     // the primary display.
808     EXPECT_EQ("100,700 300x400", window_->bounds().ToString());
809     resizer->CompleteDrag();
810   }
811 }
812
813 // Makes sure we don't allow dragging off the top of the work area.
814 TEST_F(WorkspaceWindowResizerTest, DontDragOffTop) {
815   Shell::GetInstance()->SetDisplayWorkAreaInsets(
816       Shell::GetPrimaryRootWindow(), gfx::Insets(10, 0, 0, 0));
817
818   window_->SetBounds(gfx::Rect(100, 200, 300, 400));
819   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
820       window_.get(), gfx::Point(), HTCAPTION));
821   ASSERT_TRUE(resizer.get());
822   resizer->Drag(CalculateDragPoint(*resizer, 0, -600), 0);
823   EXPECT_EQ("100,10 300x400", window_->bounds().ToString());
824 }
825
826 TEST_F(WorkspaceWindowResizerTest, ResizeBottomOutsideWorkArea) {
827   Shell::GetInstance()->SetDisplayWorkAreaInsets(
828       Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
829
830   window_->SetBounds(gfx::Rect(100, 200, 300, 380));
831   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
832       window_.get(), gfx::Point(), HTTOP));
833   ASSERT_TRUE(resizer.get());
834   resizer->Drag(CalculateDragPoint(*resizer, 8, 0), 0);
835   EXPECT_EQ("100,200 300x380", window_->bounds().ToString());
836 }
837
838 TEST_F(WorkspaceWindowResizerTest, ResizeWindowOutsideLeftWorkArea) {
839   Shell::GetInstance()->SetDisplayWorkAreaInsets(
840       Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
841   int left = ScreenUtil::GetDisplayWorkAreaBoundsInParent(window_.get()).x();
842   int pixels_to_left_border = 50;
843   int window_width = 300;
844   int window_x = left - window_width + pixels_to_left_border;
845   window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380));
846   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
847       window_.get(), gfx::Point(pixels_to_left_border, 0), HTRIGHT));
848   ASSERT_TRUE(resizer.get());
849   resizer->Drag(CalculateDragPoint(*resizer, -window_width, 0), 0);
850   EXPECT_EQ(base::IntToString(window_x) + ",100 " +
851             base::IntToString(kMinimumOnScreenArea - window_x) +
852             "x380", window_->bounds().ToString());
853 }
854
855 TEST_F(WorkspaceWindowResizerTest, ResizeWindowOutsideRightWorkArea) {
856   Shell::GetInstance()->SetDisplayWorkAreaInsets(
857       Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
858   int right = ScreenUtil::GetDisplayWorkAreaBoundsInParent(
859       window_.get()).right();
860   int pixels_to_right_border = 50;
861   int window_width = 300;
862   int window_x = right - pixels_to_right_border;
863   window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380));
864   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
865       window_.get(), gfx::Point(window_x, 0), HTLEFT));
866   ASSERT_TRUE(resizer.get());
867   resizer->Drag(CalculateDragPoint(*resizer, window_width, 0), 0);
868   EXPECT_EQ(base::IntToString(right - kMinimumOnScreenArea) +
869             ",100 " +
870             base::IntToString(window_width - pixels_to_right_border +
871                               kMinimumOnScreenArea) +
872             "x380", window_->bounds().ToString());
873 }
874
875 TEST_F(WorkspaceWindowResizerTest, ResizeWindowOutsideBottomWorkArea) {
876   Shell::GetInstance()->SetDisplayWorkAreaInsets(
877       Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
878   int bottom = ScreenUtil::GetDisplayWorkAreaBoundsInParent(
879       window_.get()).bottom();
880   int delta_to_bottom = 50;
881   int height = 380;
882   window_->SetBounds(gfx::Rect(100, bottom - delta_to_bottom, 300, height));
883   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
884       window_.get(), gfx::Point(0, bottom - delta_to_bottom), HTTOP));
885   ASSERT_TRUE(resizer.get());
886   resizer->Drag(CalculateDragPoint(*resizer, 0, bottom), 0);
887   EXPECT_EQ("100," +
888             base::IntToString(bottom - kMinimumOnScreenArea) +
889             " 300x" +
890             base::IntToString(height - (delta_to_bottom -
891                                         kMinimumOnScreenArea)),
892             window_->bounds().ToString());
893 }
894
895 // Verifies that 'outside' check of the resizer take into account the extended
896 // desktop in case of repositions.
897 TEST_F(WorkspaceWindowResizerTest, DragWindowOutsideRightToSecondaryDisplay) {
898   // Only primary display.  Changes the window position to fit within the
899   // display.
900   Shell::GetInstance()->SetDisplayWorkAreaInsets(
901       Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
902   int right = ScreenUtil::GetDisplayWorkAreaBoundsInParent(
903       window_.get()).right();
904   int pixels_to_right_border = 50;
905   int window_width = 300;
906   int window_x = right - pixels_to_right_border;
907   window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380));
908   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
909       window_.get(), gfx::Point(window_x, 0), HTCAPTION));
910   ASSERT_TRUE(resizer.get());
911   resizer->Drag(CalculateDragPoint(*resizer, window_width, 0), 0);
912   EXPECT_EQ(base::IntToString(right - kMinimumOnScreenArea) +
913             ",100 " +
914             base::IntToString(window_width) +
915             "x380", window_->bounds().ToString());
916
917   if (!SupportsMultipleDisplays())
918     return;
919
920   // With secondary display.  Operation itself is same but doesn't change
921   // the position because the window is still within the secondary display.
922   UpdateDisplay("1000x600,600x400");
923   Shell::GetInstance()->SetDisplayWorkAreaInsets(
924       Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
925   window_->SetBounds(gfx::Rect(window_x, 100, window_width, 380));
926   resizer->Drag(CalculateDragPoint(*resizer, window_width, 0), 0);
927   EXPECT_EQ(base::IntToString(window_x + window_width) +
928             ",100 " +
929             base::IntToString(window_width) +
930             "x380", window_->bounds().ToString());
931 }
932
933 // Verifies snapping to edges works.
934 TEST_F(WorkspaceWindowResizerTest, SnapToEdge) {
935   Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()->
936       SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
937   window_->SetBounds(gfx::Rect(96, 112, 320, 160));
938   // Click 50px to the right so that the mouse pointer does not leave the
939   // workspace ensuring sticky behavior.
940   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
941       window_.get(),
942       window_->bounds().origin() + gfx::Vector2d(50, 0),
943       HTCAPTION));
944   ASSERT_TRUE(resizer.get());
945   // Move to an x-coordinate of 15, which should not snap.
946   resizer->Drag(CalculateDragPoint(*resizer, 15 - 96, 0), 0);
947   // An x-coordinate of 7 should snap.
948   resizer->Drag(CalculateDragPoint(*resizer, 7 - 96, 0), 0);
949   EXPECT_EQ("0,112 320x160", window_->bounds().ToString());
950   // Move to -15, should still snap to 0.
951   resizer->Drag(CalculateDragPoint(*resizer, -15 - 96, 0), 0);
952   EXPECT_EQ("0,112 320x160", window_->bounds().ToString());
953   // At -32 should move past snap points.
954   resizer->Drag(CalculateDragPoint(*resizer, -32 - 96, 0), 0);
955   EXPECT_EQ("-32,112 320x160", window_->bounds().ToString());
956   resizer->Drag(CalculateDragPoint(*resizer, -33 - 96, 0), 0);
957   EXPECT_EQ("-33,112 320x160", window_->bounds().ToString());
958
959   // Right side should similarly snap.
960   resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 - 15, 0), 0);
961   EXPECT_EQ("465,112 320x160", window_->bounds().ToString());
962   resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 - 7, 0), 0);
963   EXPECT_EQ("480,112 320x160", window_->bounds().ToString());
964   resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 15, 0), 0);
965   EXPECT_EQ("480,112 320x160", window_->bounds().ToString());
966   resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 32, 0), 0);
967   EXPECT_EQ("512,112 320x160", window_->bounds().ToString());
968   resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 33, 0), 0);
969   EXPECT_EQ("513,112 320x160", window_->bounds().ToString());
970
971   // And the bottom should snap too.
972   resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 3 - 7), 0);
973   EXPECT_EQ("96,437 320x160", window_->bounds().ToString());
974   resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 3 + 15), 0);
975   EXPECT_EQ("96,437 320x160", window_->bounds().ToString());
976   resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 32), 0);
977   EXPECT_EQ("96,470 320x160", window_->bounds().ToString());
978   resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 33), 0);
979   EXPECT_EQ("96,471 320x160", window_->bounds().ToString());
980
981   // And the top should snap too.
982   resizer->Drag(CalculateDragPoint(*resizer, 0, -112 + 20), 0);
983   EXPECT_EQ("96,20 320x160", window_->bounds().ToString());
984   resizer->Drag(CalculateDragPoint(*resizer, 0, -112 + 7), 0);
985   EXPECT_EQ("96,0 320x160", window_->bounds().ToString());
986
987   // And bottom/left should snap too.
988   resizer->Drag(
989       CalculateDragPoint(*resizer, 7 - 96, 600 - 160 - 112 - 3 - 7), 0);
990   EXPECT_EQ("0,437 320x160", window_->bounds().ToString());
991   resizer->Drag(
992       CalculateDragPoint(*resizer, -15 - 96, 600 - 160 - 112 - 3 + 15), 0);
993   EXPECT_EQ("0,437 320x160", window_->bounds().ToString());
994   // should move past snap points.
995   resizer->Drag(
996       CalculateDragPoint(*resizer, -32 - 96, 600 - 160 - 112 - 2 + 32), 0);
997   EXPECT_EQ("-32,470 320x160", window_->bounds().ToString());
998   resizer->Drag(
999       CalculateDragPoint(*resizer, -33 - 96, 600 - 160 - 112 - 2 + 33), 0);
1000   EXPECT_EQ("-33,471 320x160", window_->bounds().ToString());
1001
1002   // No need to test dragging < 0 as we force that to 0.
1003 }
1004
1005 // Verifies a resize snap when dragging TOPLEFT.
1006 TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_TOPLEFT) {
1007   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1008   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1009       window_.get(), gfx::Point(), HTTOPLEFT));
1010   ASSERT_TRUE(resizer.get());
1011   resizer->Drag(CalculateDragPoint(*resizer, -98, -199), 0);
1012   EXPECT_EQ("0,0 120x230", window_->bounds().ToString());
1013 }
1014
1015 // Verifies a resize snap when dragging TOPRIGHT.
1016 TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_TOPRIGHT) {
1017   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1018   gfx::Rect work_area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
1019                           window_.get()));
1020   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1021       window_.get(), gfx::Point(), HTTOPRIGHT));
1022   ASSERT_TRUE(resizer.get());
1023   resizer->Drag(
1024       CalculateDragPoint(*resizer, work_area.right() - 120 - 1, -199), 0);
1025   EXPECT_EQ(100, window_->bounds().x());
1026   EXPECT_EQ(work_area.y(), window_->bounds().y());
1027   EXPECT_EQ(work_area.right() - 100, window_->bounds().width());
1028   EXPECT_EQ(230, window_->bounds().height());
1029 }
1030
1031 // Verifies a resize snap when dragging BOTTOMRIGHT.
1032 TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_BOTTOMRIGHT) {
1033   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1034   gfx::Rect work_area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
1035                           window_.get()));
1036   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1037       window_.get(), gfx::Point(), HTBOTTOMRIGHT));
1038   ASSERT_TRUE(resizer.get());
1039   resizer->Drag(
1040       CalculateDragPoint(*resizer, work_area.right() - 120 - 1,
1041                          work_area.bottom() - 220 - 2), 0);
1042   EXPECT_EQ(100, window_->bounds().x());
1043   EXPECT_EQ(200, window_->bounds().y());
1044   EXPECT_EQ(work_area.right() - 100, window_->bounds().width());
1045   EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height());
1046 }
1047
1048 // Verifies a resize snap when dragging BOTTOMLEFT.
1049 TEST_F(WorkspaceWindowResizerTest, SnapToWorkArea_BOTTOMLEFT) {
1050   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1051   gfx::Rect work_area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
1052                           window_.get()));
1053   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1054       window_.get(), gfx::Point(), HTBOTTOMLEFT));
1055   ASSERT_TRUE(resizer.get());
1056   resizer->Drag(
1057       CalculateDragPoint(*resizer, -98, work_area.bottom() - 220 - 2), 0);
1058   EXPECT_EQ(0, window_->bounds().x());
1059   EXPECT_EQ(200, window_->bounds().y());
1060   EXPECT_EQ(120, window_->bounds().width());
1061   EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height());
1062 }
1063
1064 // Verifies sticking to edges works.
1065 TEST_F(WorkspaceWindowResizerTestSticky, StickToEdge) {
1066   Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()->
1067       SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1068   window_->SetBounds(gfx::Rect(96, 112, 320, 160));
1069   // Click 50px to the right so that the mouse pointer does not leave the
1070   // workspace ensuring sticky behavior.
1071   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1072       window_.get(),
1073       window_->bounds().origin() + gfx::Vector2d(50, 0),
1074       HTCAPTION));
1075   ASSERT_TRUE(resizer.get());
1076   // Move to an x-coordinate of 15, which should not stick.
1077   resizer->Drag(CalculateDragPoint(*resizer, 15 - 96, 0), 0);
1078   // Move to -15, should still stick to 0.
1079   resizer->Drag(CalculateDragPoint(*resizer, -15 - 96, 0), 0);
1080   EXPECT_EQ("0,112 320x160", window_->bounds().ToString());
1081   // At -100 should move past edge.
1082   resizer->Drag(CalculateDragPoint(*resizer, -100 - 96, 0), 0);
1083   EXPECT_EQ("-100,112 320x160", window_->bounds().ToString());
1084   resizer->Drag(CalculateDragPoint(*resizer, -101 - 96, 0), 0);
1085   EXPECT_EQ("-101,112 320x160", window_->bounds().ToString());
1086
1087   // Right side should similarly stick.
1088   resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 - 15, 0), 0);
1089   EXPECT_EQ("465,112 320x160", window_->bounds().ToString());
1090   resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 15, 0), 0);
1091   EXPECT_EQ("480,112 320x160", window_->bounds().ToString());
1092   resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 100, 0), 0);
1093   EXPECT_EQ("580,112 320x160", window_->bounds().ToString());
1094   resizer->Drag(CalculateDragPoint(*resizer, 800 - 320 - 96 + 101, 0), 0);
1095   EXPECT_EQ("581,112 320x160", window_->bounds().ToString());
1096
1097   // And the bottom should stick too.
1098   resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 3 + 15), 0);
1099   EXPECT_EQ("96,437 320x160", window_->bounds().ToString());
1100   resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 100), 0);
1101   EXPECT_EQ("96,538 320x160", window_->bounds().ToString());
1102   resizer->Drag(CalculateDragPoint(*resizer, 0, 600 - 160 - 112 - 2 + 101), 0);
1103   EXPECT_EQ("96,539 320x160", window_->bounds().ToString());
1104
1105   // No need to test dragging < 0 as we force that to 0.
1106 }
1107
1108 // Verifies not sticking to edges when a mouse pointer is outside of work area.
1109 TEST_F(WorkspaceWindowResizerTestSticky, NoStickToEdgeWhenOutside) {
1110   Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager()->
1111       SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS);
1112   window_->SetBounds(gfx::Rect(96, 112, 320, 160));
1113   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1114       window_.get(), gfx::Point(), HTCAPTION));
1115   ASSERT_TRUE(resizer.get());
1116   // Move to an x-coordinate of 15, which should not stick.
1117   resizer->Drag(CalculateDragPoint(*resizer, 15 - 96, 0), 0);
1118   // Move to -15, should still stick to 0.
1119   resizer->Drag(CalculateDragPoint(*resizer, -15 - 96, 0), 0);
1120   EXPECT_EQ("-15,112 320x160", window_->bounds().ToString());
1121 }
1122
1123 // Verifies a resize sticks when dragging TOPLEFT.
1124 TEST_F(WorkspaceWindowResizerTestSticky, StickToWorkArea_TOPLEFT) {
1125   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1126   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1127       window_.get(), gfx::Point(), HTTOPLEFT));
1128   ASSERT_TRUE(resizer.get());
1129   resizer->Drag(CalculateDragPoint(*resizer, -15 - 100, -15 -200), 0);
1130   EXPECT_EQ("0,0 120x230", window_->bounds().ToString());
1131 }
1132
1133 // Verifies a resize sticks when dragging TOPRIGHT.
1134 TEST_F(WorkspaceWindowResizerTestSticky, StickToWorkArea_TOPRIGHT) {
1135   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1136   gfx::Rect work_area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
1137                           window_.get()));
1138   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1139       window_.get(), gfx::Point(), HTTOPRIGHT));
1140   ASSERT_TRUE(resizer.get());
1141   resizer->Drag(CalculateDragPoint(*resizer, work_area.right() - 100 + 20,
1142                                    -200 - 15), 0);
1143   EXPECT_EQ(100, window_->bounds().x());
1144   EXPECT_EQ(work_area.y(), window_->bounds().y());
1145   EXPECT_EQ(work_area.right() - 100, window_->bounds().width());
1146   EXPECT_EQ(230, window_->bounds().height());
1147 }
1148
1149 // Verifies a resize snap when dragging BOTTOMRIGHT.
1150 TEST_F(WorkspaceWindowResizerTestSticky, StickToWorkArea_BOTTOMRIGHT) {
1151   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1152   gfx::Rect work_area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
1153                           window_.get()));
1154   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1155       window_.get(), gfx::Point(), HTBOTTOMRIGHT));
1156   ASSERT_TRUE(resizer.get());
1157   resizer->Drag(CalculateDragPoint(*resizer, work_area.right() - 100 - 20 + 15,
1158                                    work_area.bottom() - 200 - 30 + 15), 0);
1159   EXPECT_EQ(100, window_->bounds().x());
1160   EXPECT_EQ(200, window_->bounds().y());
1161   EXPECT_EQ(work_area.right() - 100, window_->bounds().width());
1162   EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height());
1163 }
1164
1165 // Verifies a resize snap when dragging BOTTOMLEFT.
1166 TEST_F(WorkspaceWindowResizerTestSticky, StickToWorkArea_BOTTOMLEFT) {
1167   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1168   gfx::Rect work_area(ScreenUtil::GetDisplayWorkAreaBoundsInParent(
1169                           window_.get()));
1170   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1171       window_.get(), gfx::Point(), HTBOTTOMLEFT));
1172   ASSERT_TRUE(resizer.get());
1173   resizer->Drag(CalculateDragPoint(*resizer, -15 - 100,
1174                                    work_area.bottom() - 200 - 30 + 15), 0);
1175   EXPECT_EQ(0, window_->bounds().x());
1176   EXPECT_EQ(200, window_->bounds().y());
1177   EXPECT_EQ(120, window_->bounds().width());
1178   EXPECT_EQ(work_area.bottom() - 200, window_->bounds().height());
1179 }
1180
1181 TEST_F(WorkspaceWindowResizerTest, CtrlDragResizeToExactPosition) {
1182   window_->SetBounds(gfx::Rect(96, 112, 320, 160));
1183   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1184       window_.get(), gfx::Point(), HTBOTTOMRIGHT));
1185   ASSERT_TRUE(resizer.get());
1186   // Resize the right bottom to add 10 in width, 12 in height.
1187   resizer->Drag(CalculateDragPoint(*resizer, 10, 12), ui::EF_CONTROL_DOWN);
1188   // Both bottom and right sides to resize to exact size requested.
1189   EXPECT_EQ("96,112 330x172", window_->bounds().ToString());
1190 }
1191
1192 // Verifies that a dragged window will restore to its pre-maximized size.
1193 TEST_F(WorkspaceWindowResizerTest, RestoreToPreMaximizeCoordinates) {
1194   window_->SetBounds(gfx::Rect(0, 0, 1000, 1000));
1195   wm::WindowState* window_state = wm::GetWindowState(window_.get());
1196   window_state->SetRestoreBoundsInScreen(gfx::Rect(96, 112, 320, 160));
1197   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1198       window_.get(), gfx::Point(), HTCAPTION));
1199   ASSERT_TRUE(resizer.get());
1200   // Drag the window to new position by adding (10, 10) to original point,
1201   // the window should get restored.
1202   resizer->Drag(CalculateDragPoint(*resizer, 10, 10), 0);
1203   resizer->CompleteDrag();
1204   EXPECT_EQ("10,10 320x160", window_->bounds().ToString());
1205   // The restore rectangle should get cleared as well.
1206   EXPECT_FALSE(window_state->HasRestoreBounds());
1207 }
1208
1209 // Verifies that a dragged window will restore to its pre-maximized size.
1210 TEST_F(WorkspaceWindowResizerTest, RevertResizeOperation) {
1211   const gfx::Rect initial_bounds(0, 0, 200, 400);
1212   window_->SetBounds(initial_bounds);
1213
1214   wm::WindowState* window_state = wm::GetWindowState(window_.get());
1215   window_state->SetRestoreBoundsInScreen(gfx::Rect(96, 112, 320, 160));
1216   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1217       window_.get(), gfx::Point(), HTCAPTION));
1218   ASSERT_TRUE(resizer.get());
1219   // Drag the window to new poistion by adding (180, 16) to original point,
1220   // the window should get restored.
1221   resizer->Drag(CalculateDragPoint(*resizer, 180, 16), 0);
1222   resizer->RevertDrag();
1223   EXPECT_EQ(initial_bounds.ToString(), window_->bounds().ToString());
1224   EXPECT_EQ("96,112 320x160",
1225             window_state->GetRestoreBoundsInScreen().ToString());
1226 }
1227
1228 // Check that only usable sizes get returned by the resizer.
1229 TEST_F(WorkspaceWindowResizerTest, MagneticallyAttach) {
1230   window_->SetBounds(gfx::Rect(10, 10, 20, 30));
1231   window2_->SetBounds(gfx::Rect(150, 160, 25, 20));
1232   window2_->Show();
1233
1234   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1235       window_.get(), gfx::Point(), HTCAPTION));
1236   ASSERT_TRUE(resizer.get());
1237   // Move |window| one pixel to the left of |window2|. Should snap to right and
1238   // top.
1239   resizer->Drag(CalculateDragPoint(*resizer, 119, 145), 0);
1240   EXPECT_EQ("130,160 20x30", window_->bounds().ToString());
1241
1242   // Move |window| one pixel to the right of |window2|. Should snap to left and
1243   // top.
1244   resizer->Drag(CalculateDragPoint(*resizer, 164, 145), 0);
1245   EXPECT_EQ("175,160 20x30", window_->bounds().ToString());
1246
1247   // Move |window| one pixel above |window2|. Should snap to top and left.
1248   resizer->Drag(CalculateDragPoint(*resizer, 142, 119), 0);
1249   EXPECT_EQ("150,130 20x30", window_->bounds().ToString());
1250
1251   // Move |window| one pixel above the bottom of |window2|. Should snap to
1252   // bottom and left.
1253   resizer->Drag(CalculateDragPoint(*resizer, 142, 169), 0);
1254   EXPECT_EQ("150,180 20x30", window_->bounds().ToString());
1255 }
1256
1257 // The following variants verify magnetic snapping during resize when dragging a
1258 // particular edge.
1259 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOP) {
1260   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1261   window2_->SetBounds(gfx::Rect(99, 179, 10, 20));
1262   window2_->Show();
1263
1264   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1265       window_.get(), gfx::Point(), HTTOP));
1266   ASSERT_TRUE(resizer.get());
1267   resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1268   EXPECT_EQ("100,199 20x31", window_->bounds().ToString());
1269 }
1270
1271 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOPLEFT) {
1272   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1273   window2_->SetBounds(gfx::Rect(99, 179, 10, 20));
1274   window2_->Show();
1275
1276   {
1277     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1278         window_.get(), gfx::Point(), HTTOPLEFT));
1279     ASSERT_TRUE(resizer.get());
1280     resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1281     EXPECT_EQ("99,199 21x31", window_->bounds().ToString());
1282     resizer->RevertDrag();
1283   }
1284
1285   {
1286     window2_->SetBounds(gfx::Rect(88, 201, 10, 20));
1287     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1288         window_.get(), gfx::Point(), HTTOPLEFT));
1289     ASSERT_TRUE(resizer.get());
1290     resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1291     EXPECT_EQ("98,201 22x29", window_->bounds().ToString());
1292     resizer->RevertDrag();
1293   }
1294 }
1295
1296 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOPRIGHT) {
1297   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1298   window2_->Show();
1299
1300   {
1301     window2_->SetBounds(gfx::Rect(111, 179, 10, 20));
1302     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1303         window_.get(), gfx::Point(), HTTOPRIGHT));
1304     ASSERT_TRUE(resizer.get());
1305     resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1306     EXPECT_EQ("100,199 21x31", window_->bounds().ToString());
1307     resizer->RevertDrag();
1308   }
1309
1310   {
1311     window2_->SetBounds(gfx::Rect(121, 199, 10, 20));
1312     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1313         window_.get(), gfx::Point(), HTTOPRIGHT));
1314     ASSERT_TRUE(resizer.get());
1315     resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1316     EXPECT_EQ("100,199 21x31", window_->bounds().ToString());
1317     resizer->RevertDrag();
1318   }
1319 }
1320
1321 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_RIGHT) {
1322   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1323   window2_->SetBounds(gfx::Rect(121, 199, 10, 20));
1324   window2_->Show();
1325
1326   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1327       window_.get(), gfx::Point(), HTRIGHT));
1328   ASSERT_TRUE(resizer.get());
1329   resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1330   EXPECT_EQ("100,200 21x30", window_->bounds().ToString());
1331 }
1332
1333 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOMRIGHT) {
1334   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1335   window2_->Show();
1336
1337   {
1338     window2_->SetBounds(gfx::Rect(122, 212, 10, 20));
1339     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1340         window_.get(), gfx::Point(), HTBOTTOMRIGHT));
1341     ASSERT_TRUE(resizer.get());
1342     resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1343     EXPECT_EQ("100,200 22x32", window_->bounds().ToString());
1344     resizer->RevertDrag();
1345   }
1346
1347   {
1348     window2_->SetBounds(gfx::Rect(111, 233, 10, 20));
1349     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1350         window_.get(), gfx::Point(), HTBOTTOMRIGHT));
1351     ASSERT_TRUE(resizer.get());
1352     resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1353     EXPECT_EQ("100,200 21x33", window_->bounds().ToString());
1354     resizer->RevertDrag();
1355   }
1356 }
1357
1358 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOM) {
1359   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1360   window2_->SetBounds(gfx::Rect(111, 233, 10, 20));
1361   window2_->Show();
1362
1363   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1364       window_.get(), gfx::Point(), HTBOTTOM));
1365   ASSERT_TRUE(resizer.get());
1366   resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1367   EXPECT_EQ("100,200 20x33", window_->bounds().ToString());
1368 }
1369
1370 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOMLEFT) {
1371   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1372   window2_->Show();
1373
1374   {
1375     window2_->SetBounds(gfx::Rect(99, 231, 10, 20));
1376     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1377         window_.get(), gfx::Point(), HTBOTTOMLEFT));
1378     ASSERT_TRUE(resizer.get());
1379     resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1380     EXPECT_EQ("99,200 21x31", window_->bounds().ToString());
1381     resizer->RevertDrag();
1382   }
1383
1384   {
1385     window2_->SetBounds(gfx::Rect(89, 209, 10, 20));
1386     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1387         window_.get(), gfx::Point(), HTBOTTOMLEFT));
1388     ASSERT_TRUE(resizer.get());
1389     resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1390     EXPECT_EQ("99,200 21x29", window_->bounds().ToString());
1391     resizer->RevertDrag();
1392   }
1393 }
1394
1395 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_LEFT) {
1396   window2_->SetBounds(gfx::Rect(89, 209, 10, 20));
1397   window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1398   window2_->Show();
1399
1400   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1401       window_.get(), gfx::Point(), HTLEFT));
1402   ASSERT_TRUE(resizer.get());
1403   resizer->Drag(CalculateDragPoint(*resizer, 0, 0), 0);
1404   EXPECT_EQ("99,200 21x30", window_->bounds().ToString());
1405 }
1406
1407 // Test that the user user moved window flag is getting properly set.
1408 TEST_F(WorkspaceWindowResizerTest, CheckUserWindowManagedFlags) {
1409   window_->SetBounds(gfx::Rect( 0,  50, 400, 200));
1410
1411   std::vector<aura::Window*> no_attached_windows;
1412   // Check that an abort doesn't change anything.
1413   {
1414     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1415         window_.get(), gfx::Point(), HTCAPTION));
1416     ASSERT_TRUE(resizer.get());
1417     // Move it 100 to the bottom.
1418     resizer->Drag(CalculateDragPoint(*resizer, 0, 100), 0);
1419     EXPECT_EQ("0,150 400x200", window_->bounds().ToString());
1420     resizer->RevertDrag();
1421
1422     EXPECT_FALSE(wm::GetWindowState(window_.get())->bounds_changed_by_user());
1423   }
1424
1425   // Check that a completed move / size does change the user coordinates.
1426   {
1427     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1428         window_.get(), gfx::Point(), HTCAPTION));
1429     ASSERT_TRUE(resizer.get());
1430     // Move it 100 to the bottom.
1431     resizer->Drag(CalculateDragPoint(*resizer, 0, 100), 0);
1432     EXPECT_EQ("0,150 400x200", window_->bounds().ToString());
1433     resizer->CompleteDrag();
1434     EXPECT_TRUE(wm::GetWindowState(window_.get())->bounds_changed_by_user());
1435   }
1436 }
1437
1438 // Test that a window with a specified max size doesn't exceed it when dragged.
1439 TEST_F(WorkspaceWindowResizerTest, TestMaxSizeEnforced) {
1440   window_->SetBounds(gfx::Rect(0, 0, 400, 300));
1441   delegate_.set_max_size(gfx::Size(401, 301));
1442
1443   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1444       window_.get(), gfx::Point(), HTBOTTOMRIGHT));
1445   resizer->Drag(CalculateDragPoint(*resizer, 2, 2), 0);
1446   EXPECT_EQ(401, window_->bounds().width());
1447   EXPECT_EQ(301, window_->bounds().height());
1448 }
1449
1450 // Test that a window with a specified max width doesn't restrict its height.
1451 TEST_F(WorkspaceWindowResizerTest, TestPartialMaxSizeEnforced) {
1452   window_->SetBounds(gfx::Rect(0, 0, 400, 300));
1453   delegate_.set_max_size(gfx::Size(401, 0));
1454
1455   scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1456       window_.get(), gfx::Point(), HTBOTTOMRIGHT));
1457   resizer->Drag(CalculateDragPoint(*resizer, 2, 2), 0);
1458   EXPECT_EQ(401, window_->bounds().width());
1459   EXPECT_EQ(302, window_->bounds().height());
1460 }
1461
1462 // Test that a window with a specified max size can't be snapped.
1463 TEST_F(WorkspaceWindowResizerTest, PhantomSnapMaxSize) {
1464   {
1465     // With max size not set we get a phantom window controller for dragging off
1466     // the right hand side.
1467     // Make the window wider than maximum docked width.
1468     window_->SetBounds(gfx::Rect(0, 0, 400, 200));
1469
1470     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1471         window_.get(), gfx::Point(), HTCAPTION));
1472     EXPECT_FALSE(snap_phantom_window_controller());
1473     resizer->Drag(CalculateDragPoint(*resizer, 801, 0), 0);
1474     EXPECT_TRUE(snap_phantom_window_controller());
1475     resizer->RevertDrag();
1476   }
1477   {
1478     // With max size defined, we get no phantom window for snapping but we still
1479     // get a phantom window (docking guide).
1480     window_->SetBounds(gfx::Rect(0, 0, 400, 200));
1481     delegate_.set_max_size(gfx::Size(400, 200));
1482
1483     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1484         window_.get(), gfx::Point(), HTCAPTION));
1485     resizer->Drag(CalculateDragPoint(*resizer, 801, 0), 0);
1486     if (switches::UseDockedWindows())
1487       EXPECT_TRUE(snap_phantom_window_controller());
1488     else
1489       EXPECT_FALSE(snap_phantom_window_controller());
1490     resizer->RevertDrag();
1491   }
1492   {
1493     // With max size defined, we get no phantom window for snapping.
1494     window_->SetBounds(gfx::Rect(0, 0, 400, 200));
1495     delegate_.set_max_size(gfx::Size(400, 200));
1496     // With min size defined, we get no phantom window for docking.
1497     delegate_.set_min_size(gfx::Size(400, 200));
1498
1499     scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1500         window_.get(), gfx::Point(), HTCAPTION));
1501     resizer->Drag(CalculateDragPoint(*resizer, 801, 0), 0);
1502     EXPECT_FALSE(snap_phantom_window_controller());
1503     resizer->RevertDrag();
1504   }
1505 }
1506
1507 TEST_F(WorkspaceWindowResizerTest, DontRewardRightmostWindowForOverflows) {
1508   UpdateDisplay("600x800");
1509   aura::Window* root = Shell::GetPrimaryRootWindow();
1510   Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
1511
1512   // Four 100x100 windows flush against eachother, starting at 100,100.
1513   window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
1514   window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
1515   window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
1516   window4_->SetBounds(gfx::Rect(400, 100, 100, 100));
1517   delegate2_.set_max_size(gfx::Size(101, 0));
1518
1519   std::vector<aura::Window*> windows;
1520   windows.push_back(window2_.get());
1521   windows.push_back(window3_.get());
1522   windows.push_back(window4_.get());
1523   scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
1524       window_.get(), gfx::Point(), HTRIGHT,
1525       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
1526   ASSERT_TRUE(resizer.get());
1527   // Move it 51 to the left, which should contract w1 and expand w2-4.
1528   // w2 will hit its max size straight away, and in doing so will leave extra
1529   // pixels that a naive implementation may award to the rightmost window. A
1530   // fair implementation will give 25 pixels to each of the other windows.
1531   resizer->Drag(CalculateDragPoint(*resizer, -51, 0), 0);
1532   EXPECT_EQ("100,100 49x100", window_->bounds().ToString());
1533   EXPECT_EQ("149,100 101x100", window2_->bounds().ToString());
1534   EXPECT_EQ("250,100 125x100", window3_->bounds().ToString());
1535   EXPECT_EQ("375,100 125x100", window4_->bounds().ToString());
1536 }
1537
1538 TEST_F(WorkspaceWindowResizerTest, DontExceedMaxWidth) {
1539   UpdateDisplay("600x800");
1540   aura::Window* root = Shell::GetPrimaryRootWindow();
1541   Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
1542
1543   // Four 100x100 windows flush against eachother, starting at 100,100.
1544   window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
1545   window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
1546   window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
1547   window4_->SetBounds(gfx::Rect(400, 100, 100, 100));
1548   delegate2_.set_max_size(gfx::Size(101, 0));
1549   delegate3_.set_max_size(gfx::Size(101, 0));
1550
1551   std::vector<aura::Window*> windows;
1552   windows.push_back(window2_.get());
1553   windows.push_back(window3_.get());
1554   windows.push_back(window4_.get());
1555   scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
1556       window_.get(), gfx::Point(), HTRIGHT,
1557       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
1558   ASSERT_TRUE(resizer.get());
1559   // Move it 52 to the left, which should contract w1 and expand w2-4.
1560   resizer->Drag(CalculateDragPoint(*resizer, -52, 0), 0);
1561   EXPECT_EQ("100,100 48x100", window_->bounds().ToString());
1562   EXPECT_EQ("148,100 101x100", window2_->bounds().ToString());
1563   EXPECT_EQ("249,100 101x100", window3_->bounds().ToString());
1564   EXPECT_EQ("350,100 150x100", window4_->bounds().ToString());
1565 }
1566
1567 TEST_F(WorkspaceWindowResizerTest, DontExceedMaxHeight) {
1568   UpdateDisplay("600x800");
1569   aura::Window* root = Shell::GetPrimaryRootWindow();
1570   Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
1571
1572   // Four 100x100 windows flush against eachother, starting at 100,100.
1573   window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
1574   window2_->SetBounds(gfx::Rect(100, 200, 100, 100));
1575   window3_->SetBounds(gfx::Rect(100, 300, 100, 100));
1576   window4_->SetBounds(gfx::Rect(100, 400, 100, 100));
1577   delegate2_.set_max_size(gfx::Size(0, 101));
1578   delegate3_.set_max_size(gfx::Size(0, 101));
1579
1580   std::vector<aura::Window*> windows;
1581   windows.push_back(window2_.get());
1582   windows.push_back(window3_.get());
1583   windows.push_back(window4_.get());
1584   scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
1585       window_.get(), gfx::Point(), HTBOTTOM,
1586       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
1587   ASSERT_TRUE(resizer.get());
1588   // Move it 52 up, which should contract w1 and expand w2-4.
1589   resizer->Drag(CalculateDragPoint(*resizer, 0, -52), 0);
1590   EXPECT_EQ("100,100 100x48", window_->bounds().ToString());
1591   EXPECT_EQ("100,148 100x101", window2_->bounds().ToString());
1592   EXPECT_EQ("100,249 100x101", window3_->bounds().ToString());
1593   EXPECT_EQ("100,350 100x150", window4_->bounds().ToString());
1594 }
1595
1596 #if defined(OS_WIN)
1597 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
1598 #define MAYBE_DontExceedMinHeight DISABLED_DontExceedMinHeight
1599 #else
1600 #define MAYBE_DontExceedMinHeight DontExceedMinHeight
1601 #endif
1602
1603 TEST_F(WorkspaceWindowResizerTest, MAYBE_DontExceedMinHeight) {
1604   UpdateDisplay("600x500");
1605   aura::Window* root = Shell::GetPrimaryRootWindow();
1606   Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
1607
1608   // Four 100x100 windows flush against eachother, starting at 100,100.
1609   window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
1610   window2_->SetBounds(gfx::Rect(100, 200, 100, 100));
1611   window3_->SetBounds(gfx::Rect(100, 300, 100, 100));
1612   window4_->SetBounds(gfx::Rect(100, 400, 100, 100));
1613   delegate2_.set_min_size(gfx::Size(0, 99));
1614   delegate3_.set_min_size(gfx::Size(0, 99));
1615
1616   std::vector<aura::Window*> windows;
1617   windows.push_back(window2_.get());
1618   windows.push_back(window3_.get());
1619   windows.push_back(window4_.get());
1620   scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
1621       window_.get(), gfx::Point(), HTBOTTOM,
1622       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
1623   ASSERT_TRUE(resizer.get());
1624   // Move it 52 down, which should expand w1 and contract w2-4.
1625   resizer->Drag(CalculateDragPoint(*resizer, 0, 52), 0);
1626   EXPECT_EQ("100,100 100x152", window_->bounds().ToString());
1627   EXPECT_EQ("100,252 100x99", window2_->bounds().ToString());
1628   EXPECT_EQ("100,351 100x99", window3_->bounds().ToString());
1629   EXPECT_EQ("100,450 100x50", window4_->bounds().ToString());
1630 }
1631
1632 TEST_F(WorkspaceWindowResizerTest, DontExpandRightmostPastMaxWidth) {
1633   UpdateDisplay("600x800");
1634   aura::Window* root = Shell::GetPrimaryRootWindow();
1635   Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
1636
1637   // Three 100x100 windows flush against eachother, starting at 100,100.
1638   window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
1639   window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
1640   window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
1641   delegate3_.set_max_size(gfx::Size(101, 0));
1642
1643   std::vector<aura::Window*> windows;
1644   windows.push_back(window2_.get());
1645   windows.push_back(window3_.get());
1646   windows.push_back(window4_.get());
1647   scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
1648       window_.get(), gfx::Point(), HTRIGHT,
1649       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
1650   ASSERT_TRUE(resizer.get());
1651   // Move it 51 to the left, which should contract w1 and expand w2-3.
1652   resizer->Drag(CalculateDragPoint(*resizer, -51, 0), 0);
1653   EXPECT_EQ("100,100 49x100", window_->bounds().ToString());
1654   EXPECT_EQ("149,100 150x100", window2_->bounds().ToString());
1655   EXPECT_EQ("299,100 101x100", window3_->bounds().ToString());
1656 }
1657
1658 TEST_F(WorkspaceWindowResizerTest, MoveAttachedWhenGrownToMaxSize) {
1659   UpdateDisplay("600x800");
1660   aura::Window* root = Shell::GetPrimaryRootWindow();
1661   Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
1662
1663   // Three 100x100 windows flush against eachother, starting at 100,100.
1664   window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
1665   window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
1666   window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
1667   delegate2_.set_max_size(gfx::Size(101, 0));
1668   delegate3_.set_max_size(gfx::Size(101, 0));
1669
1670   std::vector<aura::Window*> windows;
1671   windows.push_back(window2_.get());
1672   windows.push_back(window3_.get());
1673   windows.push_back(window4_.get());
1674   scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
1675       window_.get(), gfx::Point(), HTRIGHT,
1676       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
1677   ASSERT_TRUE(resizer.get());
1678   // Move it 52 to the left, which should contract w1 and expand and move w2-3.
1679   resizer->Drag(CalculateDragPoint(*resizer, -52, 0), 0);
1680   EXPECT_EQ("100,100 48x100", window_->bounds().ToString());
1681   EXPECT_EQ("148,100 101x100", window2_->bounds().ToString());
1682   EXPECT_EQ("249,100 101x100", window3_->bounds().ToString());
1683 }
1684
1685 #if defined(OS_WIN)
1686 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
1687 #define MAYBE_MainWindowHonoursMaxWidth DISABLED_MainWindowHonoursMaxWidth
1688 #else
1689 #define MAYBE_MainWindowHonoursMaxWidth MainWindowHonoursMaxWidth
1690 #endif
1691
1692 TEST_F(WorkspaceWindowResizerTest, MAYBE_MainWindowHonoursMaxWidth) {
1693   UpdateDisplay("400x800");
1694   aura::Window* root = Shell::GetPrimaryRootWindow();
1695   Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
1696
1697   // Three 100x100 windows flush against eachother, starting at 100,100.
1698   window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
1699   window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
1700   window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
1701   delegate_.set_max_size(gfx::Size(102, 0));
1702
1703   std::vector<aura::Window*> windows;
1704   windows.push_back(window2_.get());
1705   windows.push_back(window3_.get());
1706   windows.push_back(window4_.get());
1707   scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
1708       window_.get(), gfx::Point(), HTRIGHT,
1709       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
1710   ASSERT_TRUE(resizer.get());
1711   // Move it 50 to the right, which should expand w1 and contract w2-3, as they
1712   // won't fit in the root window in their original sizes.
1713   resizer->Drag(CalculateDragPoint(*resizer, 50, 0), 0);
1714   EXPECT_EQ("100,100 102x100", window_->bounds().ToString());
1715   EXPECT_EQ("202,100 99x100", window2_->bounds().ToString());
1716   EXPECT_EQ("301,100 99x100", window3_->bounds().ToString());
1717 }
1718
1719 TEST_F(WorkspaceWindowResizerTest, MainWindowHonoursMinWidth) {
1720   UpdateDisplay("400x800");
1721   aura::Window* root = Shell::GetPrimaryRootWindow();
1722   Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
1723
1724   // Three 100x100 windows flush against eachother, starting at 100,100.
1725   window_->SetBounds(gfx::Rect( 100, 100, 100, 100));
1726   window2_->SetBounds(gfx::Rect(200, 100, 100, 100));
1727   window3_->SetBounds(gfx::Rect(300, 100, 100, 100));
1728   delegate_.set_min_size(gfx::Size(98, 0));
1729
1730   std::vector<aura::Window*> windows;
1731   windows.push_back(window2_.get());
1732   windows.push_back(window3_.get());
1733   scoped_ptr<WorkspaceWindowResizer> resizer(CreateWorkspaceResizerForTest(
1734       window_.get(), gfx::Point(), HTRIGHT,
1735       aura::client::WINDOW_MOVE_SOURCE_MOUSE, windows));
1736   ASSERT_TRUE(resizer.get());
1737   // Move it 50 to the left, which should contract w1 and expand w2-3.
1738   resizer->Drag(CalculateDragPoint(*resizer, -50, 0), 0);
1739   EXPECT_EQ("100,100 98x100", window_->bounds().ToString());
1740   EXPECT_EQ("198,100 101x100", window2_->bounds().ToString());
1741   EXPECT_EQ("299,100 101x100", window3_->bounds().ToString());
1742 }
1743
1744 // The following variants test that windows are resized correctly to the edges
1745 // of the screen using touch, when touch point is off of the window border.
1746 TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_RIGHT) {
1747   shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);
1748
1749   InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTRIGHT);
1750   EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(),
1751             touch_resize_window_->bounds().ToString());
1752
1753   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1754                                        touch_resize_window_.get());
1755
1756   // Drag out of the right border a bit and check if the border is aligned with
1757   // the touch point.
1758   generator.GestureScrollSequence(gfx::Point(715, kRootHeight / 2),
1759                                   gfx::Point(725, kRootHeight / 2),
1760                                   base::TimeDelta::FromMilliseconds(10),
1761                                   5);
1762   EXPECT_EQ(gfx::Rect(100, 100, 625, kRootHeight - 200).ToString(),
1763             touch_resize_window_->bounds().ToString());
1764   // Drag more, but stop before being snapped to the edge.
1765   generator.GestureScrollSequence(gfx::Point(725, kRootHeight / 2),
1766                                   gfx::Point(760, kRootHeight / 2),
1767                                   base::TimeDelta::FromMilliseconds(10),
1768                                   5);
1769   EXPECT_EQ(gfx::Rect(100, 100, 660, kRootHeight - 200).ToString(),
1770             touch_resize_window_->bounds().ToString());
1771   // Drag even more to snap to the edge.
1772   generator.GestureScrollSequence(gfx::Point(760, kRootHeight / 2),
1773                                   gfx::Point(775, kRootHeight / 2),
1774                                   base::TimeDelta::FromMilliseconds(10),
1775                                   5);
1776   EXPECT_EQ(gfx::Rect(100, 100, 700, kRootHeight - 200).ToString(),
1777             touch_resize_window_->bounds().ToString());
1778 }
1779
1780 TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_LEFT) {
1781   shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);
1782
1783   InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTLEFT);
1784   EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(),
1785             touch_resize_window_->bounds().ToString());
1786
1787   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1788                                        touch_resize_window_.get());
1789
1790   // Drag out of the left border a bit and check if the border is aligned with
1791   // the touch point.
1792   generator.GestureScrollSequence(gfx::Point(85, kRootHeight / 2),
1793                                   gfx::Point(75, kRootHeight / 2),
1794                                   base::TimeDelta::FromMilliseconds(10),
1795                                   5);
1796   EXPECT_EQ(gfx::Rect(75, 100, 625, kRootHeight - 200).ToString(),
1797             touch_resize_window_->bounds().ToString());
1798   // Drag more, but stop before being snapped to the edge.
1799   generator.GestureScrollSequence(gfx::Point(75, kRootHeight / 2),
1800                                   gfx::Point(40, kRootHeight / 2),
1801                                   base::TimeDelta::FromMilliseconds(10),
1802                                   5);
1803   EXPECT_EQ(gfx::Rect(40, 100, 660, kRootHeight - 200).ToString(),
1804             touch_resize_window_->bounds().ToString());
1805   // Drag even more to snap to the edge.
1806   generator.GestureScrollSequence(gfx::Point(40, kRootHeight / 2),
1807                                   gfx::Point(25, kRootHeight / 2),
1808                                   base::TimeDelta::FromMilliseconds(10),
1809                                   5);
1810   EXPECT_EQ(gfx::Rect(0, 100, 700, kRootHeight - 200).ToString(),
1811             touch_resize_window_->bounds().ToString());
1812 }
1813
1814 TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_TOP) {
1815   shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);
1816
1817   InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTTOP);
1818   EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(),
1819             touch_resize_window_->bounds().ToString());
1820
1821   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1822                                        touch_resize_window_.get());
1823
1824   // Drag out of the top border a bit and check if the border is aligned with
1825   // the touch point.
1826   generator.GestureScrollSequence(gfx::Point(400, 85),
1827                                   gfx::Point(400, 75),
1828                                   base::TimeDelta::FromMilliseconds(10),
1829                                   5);
1830   EXPECT_EQ(gfx::Rect(100, 75, 600, kRootHeight - 175).ToString(),
1831             touch_resize_window_->bounds().ToString());
1832   // Drag more, but stop before being snapped to the edge.
1833   generator.GestureScrollSequence(gfx::Point(400, 75),
1834                                   gfx::Point(400, 40),
1835                                   base::TimeDelta::FromMilliseconds(10),
1836                                   5);
1837   EXPECT_EQ(gfx::Rect(100, 40, 600, kRootHeight - 140).ToString(),
1838             touch_resize_window_->bounds().ToString());
1839   // Drag even more to snap to the edge.
1840   generator.GestureScrollSequence(gfx::Point(400, 40),
1841                                   gfx::Point(400, 25),
1842                                   base::TimeDelta::FromMilliseconds(10),
1843                                   5);
1844   EXPECT_EQ(gfx::Rect(100, 0, 600, kRootHeight - 100).ToString(),
1845             touch_resize_window_->bounds().ToString());
1846 }
1847
1848 TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_BOTTOM) {
1849   shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);
1850
1851   InitTouchResizeWindow(gfx::Rect(100, 100, 600, kRootHeight - 200), HTBOTTOM);
1852   EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 200).ToString(),
1853             touch_resize_window_->bounds().ToString());
1854
1855   aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1856                                        touch_resize_window_.get());
1857
1858   // Drag out of the bottom border a bit and check if the border is aligned with
1859   // the touch point.
1860   generator.GestureScrollSequence(gfx::Point(400, kRootHeight - 85),
1861                                   gfx::Point(400, kRootHeight - 75),
1862                                   base::TimeDelta::FromMilliseconds(10),
1863                                   5);
1864   EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 175).ToString(),
1865             touch_resize_window_->bounds().ToString());
1866   // Drag more, but stop before being snapped to the edge.
1867   generator.GestureScrollSequence(gfx::Point(400, kRootHeight - 75),
1868                                   gfx::Point(400, kRootHeight - 40),
1869                                   base::TimeDelta::FromMilliseconds(10),
1870                                   5);
1871   EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 140).ToString(),
1872             touch_resize_window_->bounds().ToString());
1873   // Drag even more to snap to the edge.
1874   generator.GestureScrollSequence(gfx::Point(400, kRootHeight - 40),
1875                                   gfx::Point(400, kRootHeight - 25),
1876                                   base::TimeDelta::FromMilliseconds(10),
1877                                   5);
1878   EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 100).ToString(),
1879             touch_resize_window_->bounds().ToString());
1880 }
1881
1882 }  // namespace internal
1883 }  // namespace ash