1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/wm/workspace/workspace_window_resizer.h"
7 #include "ash/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"
37 const int kRootHeight = 600;
39 // A simple window delegate that returns the specified min size.
40 class TestWindowDelegate : public aura::test::TestWindowDelegate {
42 TestWindowDelegate() {
44 virtual ~TestWindowDelegate() {}
46 void set_min_size(const gfx::Size& size) {
50 void set_max_size(const gfx::Size& size) {
55 // Overridden from aura::Test::TestWindowDelegate:
56 virtual gfx::Size GetMinimumSize() const OVERRIDE {
60 virtual gfx::Size GetMaximumSize() const OVERRIDE {
67 DISALLOW_COPY_AND_ASSIGN(TestWindowDelegate);
72 class WorkspaceWindowResizerTest : public test::AshTestBase {
74 WorkspaceWindowResizerTest() : workspace_resizer_(NULL) {}
75 virtual ~WorkspaceWindowResizerTest() {}
77 virtual void SetUp() OVERRIDE {
79 UpdateDisplay(base::StringPrintf("800x%d", kRootHeight));
81 aura::Window* root = Shell::GetPrimaryRootWindow();
82 gfx::Rect root_bounds(root->bounds());
84 // RootWindow and Display can't resize on Windows Ash.
85 // http://crbug.com/165962
86 EXPECT_EQ(kRootHeight, root_bounds.height());
88 EXPECT_EQ(800, root_bounds.width());
89 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
90 window_.reset(new aura::Window(&delegate_));
91 window_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
92 window_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
93 ParentWindowInPrimaryRootWindow(window_.get());
96 window2_.reset(new aura::Window(&delegate2_));
97 window2_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
98 window2_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
99 ParentWindowInPrimaryRootWindow(window2_.get());
102 window3_.reset(new aura::Window(&delegate3_));
103 window3_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
104 window3_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
105 ParentWindowInPrimaryRootWindow(window3_.get());
108 window4_.reset(new aura::Window(&delegate4_));
109 window4_->SetType(ui::wm::WINDOW_TYPE_NORMAL);
110 window4_->Init(aura::WINDOW_LAYER_NOT_DRAWN);
111 ParentWindowInPrimaryRootWindow(window4_.get());
115 virtual void TearDown() OVERRIDE {
120 touch_resize_window_.reset();
121 AshTestBase::TearDown();
124 // Returns a string identifying the z-order of each of the known child windows
125 // of |parent|. The returned string constains the id of the known windows and
126 // is ordered from topmost to bottomost windows.
127 std::string WindowOrderAsString(aura::Window* parent) const {
129 const aura::Window::Windows& windows = parent->children();
130 for (aura::Window::Windows::const_reverse_iterator i = windows.rbegin();
131 i != windows.rend(); ++i) {
132 if (*i == window_ || *i == window2_ || *i == window3_) {
135 result += base::IntToString((*i)->id());
142 WindowResizer* CreateResizerForTest(
143 aura::Window* window,
144 const gfx::Point& point_in_parent,
145 int window_component) {
146 WindowResizer* resizer = CreateWindowResizer(
150 aura::client::WINDOW_MOVE_SOURCE_MOUSE).release();
151 workspace_resizer_ = WorkspaceWindowResizer::instance_;
154 WorkspaceWindowResizer* CreateWorkspaceResizerForTest(
155 aura::Window* window,
156 const gfx::Point& point_in_parent,
157 int window_component,
158 aura::client::WindowMoveSource source,
159 const std::vector<aura::Window*>& attached_windows) {
160 wm::WindowState* window_state = wm::GetWindowState(window);
161 window_state->CreateDragDetails(
162 window, point_in_parent, window_component, source);
163 return WorkspaceWindowResizer::Create(window_state, attached_windows);
166 PhantomWindowController* snap_phantom_window_controller() const {
167 return workspace_resizer_->snap_phantom_window_controller_.get();
170 gfx::Point CalculateDragPoint(const WindowResizer& resizer,
173 gfx::Point location = resizer.GetInitialLocation();
174 location.set_x(location.x() + delta_x);
175 location.set_y(location.y() + delta_y);
179 std::vector<aura::Window*> empty_windows() const {
180 return std::vector<aura::Window*>();
183 internal::ShelfLayoutManager* shelf_layout_manager() {
184 return Shell::GetPrimaryRootWindowController()->GetShelfLayoutManager();
187 void InitTouchResizeWindow(const gfx::Rect& bounds, int window_component) {
188 touch_resize_delegate_.set_window_component(window_component);
189 touch_resize_window_.reset(
190 CreateTestWindowInShellWithDelegate(&touch_resize_delegate_, 0,
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,
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_;
211 TestWindowDelegate touch_resize_delegate_;
212 scoped_ptr<aura::Window> touch_resize_window_;
213 WorkspaceWindowResizer* workspace_resizer_;
216 DISALLOW_COPY_AND_ASSIGN(WorkspaceWindowResizerTest);
219 class WorkspaceWindowResizerTestSticky : public WorkspaceWindowResizerTest {
221 WorkspaceWindowResizerTestSticky() {}
222 virtual ~WorkspaceWindowResizerTestSticky() {}
224 virtual void SetUp() OVERRIDE {
225 CommandLine::ForCurrentProcess()->AppendSwitch(
226 ash::switches::kAshEnableStickyEdges);
227 WorkspaceWindowResizerTest::SetUp();
231 DISALLOW_COPY_AND_ASSIGN(WorkspaceWindowResizerTestSticky);
234 // Assertions around attached window resize dragging from the right with 2
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));
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());
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());
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());
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());
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));
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());
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());
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());
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());
302 // Assertions around attached window resize dragging from the right with 3
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));
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());
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());
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());
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());
343 // Assertions around attached window resizing (collapsing and expanding) with
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));
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());
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());
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());
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));
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());
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());
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());
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());
411 // Assertions around attached window resize dragging from the bottom with 2
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));
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());
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());
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());
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());
447 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
448 #define MAYBE_AttachedResize_BOTTOM_3 DISABLED_AttachedResize_BOTTOM_3
450 #define MAYBE_AttachedResize_BOTTOM_3 AttachedResize_BOTTOM_3
453 // Assertions around attached window resize dragging from the bottom with 3
455 TEST_F(WorkspaceWindowResizerTest, MAYBE_AttachedResize_BOTTOM_3) {
456 UpdateDisplay("600x800");
457 aura::Window* root = Shell::GetPrimaryRootWindow();
458 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
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));
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());
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());
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());
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());
498 // Assertions around attached window resizing (collapsing and expanding) with
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));
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());
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());
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());
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));
539 Shell* shell = Shell::GetInstance();
540 aura::test::EventGenerator generator(window_->GetRootWindow());
542 // The cursor should not be locked initially.
543 EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked());
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());
552 // Creating a WorkspaceWindowResizer should not lock the cursor.
553 EXPECT_FALSE(shell->cursor_manager()->IsCursorLocked());
555 // The cursor should be hidden after touching the screen and
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());
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());
568 resizer->RevertDrag();
571 // Assertions around dragging to the left/right edge of the screen.
572 TEST_F(WorkspaceWindowResizerTest, Edge) {
573 if (!SupportsHostWindowResize())
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());
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());
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();
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());
600 // Try the same with the right side.
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());
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());
617 // Test if the restore bounds is correct in multiple displays.
618 if (!SupportsMultipleDisplays())
621 // Restore the window to clear snapped state.
622 window_state->Restore();
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());
632 EXPECT_EQ("800,10 400x60", window_->GetBoundsInScreen().ToString());
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);
639 ScreenUtil::GetDisplayWorkAreaBoundsInParent(window_.get()).bottom();
640 resizer->CompleteDrag();
641 // With the resolution of 500x600 we will hit in this case the 50% screen
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());
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);
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());
664 TEST_F(WorkspaceWindowResizerTest, CancelSnapPhantom) {
665 if (!SupportsMultipleDisplays())
668 UpdateDisplay("800x600,800x600");
669 aura::Window::Windows root_windows = Shell::GetAllRootWindows();
670 ASSERT_EQ(2U, root_windows.size());
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());
677 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
678 window_.get(), gfx::Point(), HTCAPTION));
679 ASSERT_TRUE(resizer.get());
680 EXPECT_FALSE(snap_phantom_window_controller());
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());
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());
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));
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);
710 // 2 should be topmost since it's initially the highest in the stack.
711 EXPECT_EQ("2 1 3", WindowOrderAsString(window_->parent()));
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);
724 // 2 should be topmost since it's initially the highest in the stack.
725 EXPECT_EQ("2 3 1", WindowOrderAsString(window_->parent()));
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));
734 ASSERT_EQ(1, Shell::GetScreen()->GetNumDisplays());
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);
742 kRootHeight - WorkspaceWindowResizer::kMinOnscreenHeight - 10;
743 EXPECT_EQ("100," + base::IntToString(expected_y) + " 300x400",
744 window_->bounds().ToString());
747 // Makes sure we don't allow dragging on the work area with multidisplay.
748 TEST_F(WorkspaceWindowResizerTest, DontDragOffBottomWithMultiDisplay) {
749 if (!SupportsMultipleDisplays())
752 UpdateDisplay("800x600,800x600");
753 ASSERT_EQ(2, Shell::GetScreen()->GetNumDisplays());
755 Shell::GetInstance()->SetDisplayWorkAreaInsets(
756 Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 10, 0));
758 // Positions the secondary display at the bottom the primary display.
759 Shell::GetInstance()->display_manager()->SetLayoutForCurrentDisplays(
760 ash::DisplayLayout(ash::DisplayLayout::BOTTOM, 0));
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();
781 Shell::GetInstance()->SetDisplayWorkAreaInsets(
782 Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 10, 0));
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);
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();
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();
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));
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());
826 TEST_F(WorkspaceWindowResizerTest, ResizeBottomOutsideWorkArea) {
827 Shell::GetInstance()->SetDisplayWorkAreaInsets(
828 Shell::GetPrimaryRootWindow(), gfx::Insets(0, 0, 50, 0));
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());
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());
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) +
870 base::IntToString(window_width - pixels_to_right_border +
871 kMinimumOnScreenArea) +
872 "x380", window_->bounds().ToString());
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;
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);
888 base::IntToString(bottom - kMinimumOnScreenArea) +
890 base::IntToString(height - (delta_to_bottom -
891 kMinimumOnScreenArea)),
892 window_->bounds().ToString());
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
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) +
914 base::IntToString(window_width) +
915 "x380", window_->bounds().ToString());
917 if (!SupportsMultipleDisplays())
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) +
929 base::IntToString(window_width) +
930 "x380", window_->bounds().ToString());
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(
942 window_->bounds().origin() + gfx::Vector2d(50, 0),
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());
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());
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());
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());
987 // And bottom/left should snap too.
989 CalculateDragPoint(*resizer, 7 - 96, 600 - 160 - 112 - 3 - 7), 0);
990 EXPECT_EQ("0,437 320x160", window_->bounds().ToString());
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.
996 CalculateDragPoint(*resizer, -32 - 96, 600 - 160 - 112 - 2 + 32), 0);
997 EXPECT_EQ("-32,470 320x160", window_->bounds().ToString());
999 CalculateDragPoint(*resizer, -33 - 96, 600 - 160 - 112 - 2 + 33), 0);
1000 EXPECT_EQ("-33,471 320x160", window_->bounds().ToString());
1002 // No need to test dragging < 0 as we force that to 0.
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());
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(
1020 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1021 window_.get(), gfx::Point(), HTTOPRIGHT));
1022 ASSERT_TRUE(resizer.get());
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());
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(
1036 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1037 window_.get(), gfx::Point(), HTBOTTOMRIGHT));
1038 ASSERT_TRUE(resizer.get());
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());
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(
1053 scoped_ptr<WindowResizer> resizer(CreateResizerForTest(
1054 window_.get(), gfx::Point(), HTBOTTOMLEFT));
1055 ASSERT_TRUE(resizer.get());
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());
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(
1073 window_->bounds().origin() + gfx::Vector2d(50, 0),
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());
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());
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());
1105 // No need to test dragging < 0 as we force that to 0.
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());
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());
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(
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,
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());
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(
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());
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(
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());
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());
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());
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);
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());
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));
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
1239 resizer->Drag(CalculateDragPoint(*resizer, 119, 145), 0);
1240 EXPECT_EQ("130,160 20x30", window_->bounds().ToString());
1242 // Move |window| one pixel to the right of |window2|. Should snap to left and
1244 resizer->Drag(CalculateDragPoint(*resizer, 164, 145), 0);
1245 EXPECT_EQ("175,160 20x30", window_->bounds().ToString());
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());
1251 // Move |window| one pixel above the bottom of |window2|. Should snap to
1253 resizer->Drag(CalculateDragPoint(*resizer, 142, 169), 0);
1254 EXPECT_EQ("150,180 20x30", window_->bounds().ToString());
1257 // The following variants verify magnetic snapping during resize when dragging a
1259 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOP) {
1260 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1261 window2_->SetBounds(gfx::Rect(99, 179, 10, 20));
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());
1271 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOPLEFT) {
1272 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1273 window2_->SetBounds(gfx::Rect(99, 179, 10, 20));
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();
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();
1296 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_TOPRIGHT) {
1297 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
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();
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();
1321 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_RIGHT) {
1322 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1323 window2_->SetBounds(gfx::Rect(121, 199, 10, 20));
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());
1333 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOMRIGHT) {
1334 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
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();
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();
1358 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOM) {
1359 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
1360 window2_->SetBounds(gfx::Rect(111, 233, 10, 20));
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());
1370 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_BOTTOMLEFT) {
1371 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
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();
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();
1395 TEST_F(WorkspaceWindowResizerTest, MagneticallyResize_LEFT) {
1396 window2_->SetBounds(gfx::Rect(89, 209, 10, 20));
1397 window_->SetBounds(gfx::Rect(100, 200, 20, 30));
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());
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));
1411 std::vector<aura::Window*> no_attached_windows;
1412 // Check that an abort doesn't change anything.
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();
1422 EXPECT_FALSE(wm::GetWindowState(window_.get())->bounds_changed_by_user());
1425 // Check that a completed move / size does change the user coordinates.
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());
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));
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());
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));
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());
1462 // Test that a window with a specified max size can't be snapped.
1463 TEST_F(WorkspaceWindowResizerTest, PhantomSnapMaxSize) {
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));
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();
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));
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());
1489 EXPECT_FALSE(snap_phantom_window_controller());
1490 resizer->RevertDrag();
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));
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();
1507 TEST_F(WorkspaceWindowResizerTest, DontRewardRightmostWindowForOverflows) {
1508 UpdateDisplay("600x800");
1509 aura::Window* root = Shell::GetPrimaryRootWindow();
1510 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
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));
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());
1538 TEST_F(WorkspaceWindowResizerTest, DontExceedMaxWidth) {
1539 UpdateDisplay("600x800");
1540 aura::Window* root = Shell::GetPrimaryRootWindow();
1541 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
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));
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());
1567 TEST_F(WorkspaceWindowResizerTest, DontExceedMaxHeight) {
1568 UpdateDisplay("600x800");
1569 aura::Window* root = Shell::GetPrimaryRootWindow();
1570 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
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));
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());
1597 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
1598 #define MAYBE_DontExceedMinHeight DISABLED_DontExceedMinHeight
1600 #define MAYBE_DontExceedMinHeight DontExceedMinHeight
1603 TEST_F(WorkspaceWindowResizerTest, MAYBE_DontExceedMinHeight) {
1604 UpdateDisplay("600x500");
1605 aura::Window* root = Shell::GetPrimaryRootWindow();
1606 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
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));
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());
1632 TEST_F(WorkspaceWindowResizerTest, DontExpandRightmostPastMaxWidth) {
1633 UpdateDisplay("600x800");
1634 aura::Window* root = Shell::GetPrimaryRootWindow();
1635 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
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));
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());
1658 TEST_F(WorkspaceWindowResizerTest, MoveAttachedWhenGrownToMaxSize) {
1659 UpdateDisplay("600x800");
1660 aura::Window* root = Shell::GetPrimaryRootWindow();
1661 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
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));
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());
1686 // RootWindow and Display can't resize on Windows Ash. http://crbug.com/165962
1687 #define MAYBE_MainWindowHonoursMaxWidth DISABLED_MainWindowHonoursMaxWidth
1689 #define MAYBE_MainWindowHonoursMaxWidth MainWindowHonoursMaxWidth
1692 TEST_F(WorkspaceWindowResizerTest, MAYBE_MainWindowHonoursMaxWidth) {
1693 UpdateDisplay("400x800");
1694 aura::Window* root = Shell::GetPrimaryRootWindow();
1695 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
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));
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());
1719 TEST_F(WorkspaceWindowResizerTest, MainWindowHonoursMinWidth) {
1720 UpdateDisplay("400x800");
1721 aura::Window* root = Shell::GetPrimaryRootWindow();
1722 Shell::GetInstance()->SetDisplayWorkAreaInsets(root, gfx::Insets());
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));
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());
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);
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());
1753 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1754 touch_resize_window_.get());
1756 // Drag out of the right border a bit and check if the border is aligned with
1758 generator.GestureScrollSequence(gfx::Point(715, kRootHeight / 2),
1759 gfx::Point(725, kRootHeight / 2),
1760 base::TimeDelta::FromMilliseconds(10),
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),
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),
1776 EXPECT_EQ(gfx::Rect(100, 100, 700, kRootHeight - 200).ToString(),
1777 touch_resize_window_->bounds().ToString());
1780 TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_LEFT) {
1781 shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);
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());
1787 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1788 touch_resize_window_.get());
1790 // Drag out of the left border a bit and check if the border is aligned with
1792 generator.GestureScrollSequence(gfx::Point(85, kRootHeight / 2),
1793 gfx::Point(75, kRootHeight / 2),
1794 base::TimeDelta::FromMilliseconds(10),
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),
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),
1810 EXPECT_EQ(gfx::Rect(0, 100, 700, kRootHeight - 200).ToString(),
1811 touch_resize_window_->bounds().ToString());
1814 TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_TOP) {
1815 shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);
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());
1821 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1822 touch_resize_window_.get());
1824 // Drag out of the top border a bit and check if the border is aligned with
1826 generator.GestureScrollSequence(gfx::Point(400, 85),
1827 gfx::Point(400, 75),
1828 base::TimeDelta::FromMilliseconds(10),
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),
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),
1844 EXPECT_EQ(gfx::Rect(100, 0, 600, kRootHeight - 100).ToString(),
1845 touch_resize_window_->bounds().ToString());
1848 TEST_F(WorkspaceWindowResizerTest, TouchResizeToEdge_BOTTOM) {
1849 shelf_layout_manager()->SetAutoHideBehavior(SHELF_AUTO_HIDE_ALWAYS_HIDDEN);
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());
1855 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
1856 touch_resize_window_.get());
1858 // Drag out of the bottom border a bit and check if the border is aligned with
1860 generator.GestureScrollSequence(gfx::Point(400, kRootHeight - 85),
1861 gfx::Point(400, kRootHeight - 75),
1862 base::TimeDelta::FromMilliseconds(10),
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),
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),
1878 EXPECT_EQ(gfx::Rect(100, 100, 600, kRootHeight - 100).ToString(),
1879 touch_resize_window_->bounds().ToString());
1882 } // namespace internal