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