| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ash/common/wm/workspace_controller.h" | 5 #include "ash/common/wm/workspace_controller.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 | 8 |
| 9 #include "ash/common/session/session_controller.h" | 9 #include "ash/common/session/session_controller.h" |
| 10 #include "ash/common/shelf/shelf_layout_manager.h" | 10 #include "ash/common/shelf/shelf_layout_manager.h" |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 #include "ash/shell.h" | 23 #include "ash/shell.h" |
| 24 #include "ash/test/ash_test_base.h" | 24 #include "ash/test/ash_test_base.h" |
| 25 #include "ash/test/shell_test_api.h" | 25 #include "ash/test/shell_test_api.h" |
| 26 #include "ash/wm/window_state_aura.h" | 26 #include "ash/wm/window_state_aura.h" |
| 27 #include "ash/wm/window_util.h" | 27 #include "ash/wm/window_util.h" |
| 28 #include "base/strings/string_number_conversions.h" | 28 #include "base/strings/string_number_conversions.h" |
| 29 #include "ui/aura/client/aura_constants.h" | 29 #include "ui/aura/client/aura_constants.h" |
| 30 #include "ui/aura/test/test_window_delegate.h" | 30 #include "ui/aura/test/test_window_delegate.h" |
| 31 #include "ui/aura/test/test_windows.h" | 31 #include "ui/aura/test/test_windows.h" |
| 32 #include "ui/aura/window.h" | 32 #include "ui/aura/window.h" |
| 33 #include "ui/aura/window_event_dispatcher.h" | |
| 34 #include "ui/base/hit_test.h" | 33 #include "ui/base/hit_test.h" |
| 35 #include "ui/base/ui_base_types.h" | |
| 36 #include "ui/compositor/layer.h" | |
| 37 #include "ui/compositor/scoped_animation_duration_scale_mode.h" | 34 #include "ui/compositor/scoped_animation_duration_scale_mode.h" |
| 38 #include "ui/display/screen.h" | 35 #include "ui/display/screen.h" |
| 39 #include "ui/events/event_utils.h" | 36 #include "ui/events/event_utils.h" |
| 40 #include "ui/events/test/event_generator.h" | 37 #include "ui/events/test/event_generator.h" |
| 41 #include "ui/views/widget/widget.h" | 38 #include "ui/views/widget/widget.h" |
| 42 #include "ui/wm/core/window_animations.h" | |
| 43 #include "ui/wm/core/window_util.h" | 39 #include "ui/wm/core/window_util.h" |
| 44 | 40 |
| 45 using aura::Window; | 41 using aura::Window; |
| 46 | 42 |
| 47 namespace ash { | 43 namespace ash { |
| 48 | 44 |
| 49 // Returns a string containing the names of all the children of |window| (in | 45 // Returns a string containing the names of all the children of |window| (in |
| 50 // order). Each entry is separated by a space. | 46 // order). Each entry is separated by a space. |
| 51 std::string GetWindowNames(const aura::Window* window) { | 47 std::string GetWindowNames(const aura::Window* window) { |
| 52 std::string result; | 48 std::string result; |
| (...skipping 1283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1336 EXPECT_EQ(snapped_bounds, window->bounds()); | 1332 EXPECT_EQ(snapped_bounds, window->bounds()); |
| 1337 EXPECT_TRUE(window_state->bounds_changed_by_user()); | 1333 EXPECT_TRUE(window_state->bounds_changed_by_user()); |
| 1338 | 1334 |
| 1339 // Minimize and Restore |window|, the restored bounds should be equal to the | 1335 // Minimize and Restore |window|, the restored bounds should be equal to the |
| 1340 // bounds of left snapped state. | 1336 // bounds of left snapped state. |
| 1341 window_state->Minimize(); | 1337 window_state->Minimize(); |
| 1342 window_state->Restore(); | 1338 window_state->Restore(); |
| 1343 EXPECT_EQ(snapped_bounds, window->bounds()); | 1339 EXPECT_EQ(snapped_bounds, window->bounds()); |
| 1344 } | 1340 } |
| 1345 | 1341 |
| 1346 namespace { | |
| 1347 | |
| 1348 // Used by DragMaximizedNonTrackedWindow to track how many times the window | |
| 1349 // hierarchy changes affecting the specified window. | |
| 1350 class DragMaximizedNonTrackedWindowObserver : public aura::WindowObserver { | |
| 1351 public: | |
| 1352 DragMaximizedNonTrackedWindowObserver(aura::Window* window) | |
| 1353 : change_count_(0), window_(window) {} | |
| 1354 | |
| 1355 // Number of times OnWindowHierarchyChanged() has been received. | |
| 1356 void clear_change_count() { change_count_ = 0; } | |
| 1357 int change_count() const { return change_count_; } | |
| 1358 | |
| 1359 // aura::WindowObserver overrides: | |
| 1360 // Counts number of times a window is reparented. Ignores reparenting into and | |
| 1361 // from a docked container which is expected when a tab is dragged. | |
| 1362 void OnWindowHierarchyChanged(const HierarchyChangeParams& params) override { | |
| 1363 if (params.target != window_ || | |
| 1364 (params.old_parent->id() == kShellWindowId_DefaultContainer && | |
| 1365 params.new_parent->id() == kShellWindowId_DockedContainer) || | |
| 1366 (params.old_parent->id() == kShellWindowId_DockedContainer && | |
| 1367 params.new_parent->id() == kShellWindowId_DefaultContainer)) { | |
| 1368 return; | |
| 1369 } | |
| 1370 change_count_++; | |
| 1371 } | |
| 1372 | |
| 1373 private: | |
| 1374 int change_count_; | |
| 1375 aura::Window* window_; | |
| 1376 | |
| 1377 DISALLOW_COPY_AND_ASSIGN(DragMaximizedNonTrackedWindowObserver); | |
| 1378 }; | |
| 1379 | |
| 1380 } // namespace | |
| 1381 | |
| 1382 // Verifies that a new maximized window becomes visible after its activation | 1342 // Verifies that a new maximized window becomes visible after its activation |
| 1383 // is requested, even though it does not become activated because a system | 1343 // is requested, even though it does not become activated because a system |
| 1384 // modal window is active. | 1344 // modal window is active. |
| 1385 TEST_F(WorkspaceControllerTest, SwitchFromModal) { | 1345 TEST_F(WorkspaceControllerTest, SwitchFromModal) { |
| 1386 std::unique_ptr<Window> modal_window(CreateTestWindowUnparented()); | 1346 std::unique_ptr<Window> modal_window(CreateTestWindowUnparented()); |
| 1387 modal_window->SetBounds(gfx::Rect(10, 11, 21, 22)); | 1347 modal_window->SetBounds(gfx::Rect(10, 11, 21, 22)); |
| 1388 modal_window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_SYSTEM); | 1348 modal_window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_SYSTEM); |
| 1389 ParentWindowInPrimaryRootWindow(modal_window.get()); | 1349 ParentWindowInPrimaryRootWindow(modal_window.get()); |
| 1390 modal_window->Show(); | 1350 modal_window->Show(); |
| 1391 wm::ActivateWindow(modal_window.get()); | 1351 wm::ActivateWindow(modal_window.get()); |
| 1392 | 1352 |
| 1393 std::unique_ptr<Window> maximized_window(CreateTestWindow()); | 1353 std::unique_ptr<Window> maximized_window(CreateTestWindow()); |
| 1394 maximized_window->SetProperty(aura::client::kShowStateKey, | 1354 maximized_window->SetProperty(aura::client::kShowStateKey, |
| 1395 ui::SHOW_STATE_MAXIMIZED); | 1355 ui::SHOW_STATE_MAXIMIZED); |
| 1396 maximized_window->Show(); | 1356 maximized_window->Show(); |
| 1397 wm::ActivateWindow(maximized_window.get()); | 1357 wm::ActivateWindow(maximized_window.get()); |
| 1398 EXPECT_TRUE(maximized_window->IsVisible()); | 1358 EXPECT_TRUE(maximized_window->IsVisible()); |
| 1399 } | 1359 } |
| 1400 | 1360 |
| 1401 namespace { | |
| 1402 | |
| 1403 // Subclass of WorkspaceControllerTest that runs tests with docked windows | |
| 1404 // enabled and disabled. | |
| 1405 class WorkspaceControllerTestDragging : public WorkspaceControllerTest { | |
| 1406 public: | |
| 1407 WorkspaceControllerTestDragging() {} | |
| 1408 ~WorkspaceControllerTestDragging() override {} | |
| 1409 | |
| 1410 private: | |
| 1411 DISALLOW_COPY_AND_ASSIGN(WorkspaceControllerTestDragging); | |
| 1412 }; | |
| 1413 | |
| 1414 } // namespace | |
| 1415 | |
| 1416 // Verifies that when dragging a window over the shelf overlap is detected | 1361 // Verifies that when dragging a window over the shelf overlap is detected |
| 1417 // during and after the drag. | 1362 // during and after the drag. |
| 1418 TEST_F(WorkspaceControllerTestDragging, DragWindowOverlapShelf) { | 1363 TEST_F(WorkspaceControllerTest, DragWindowOverlapShelf) { |
| 1419 aura::test::TestWindowDelegate delegate; | 1364 aura::test::TestWindowDelegate delegate; |
| 1420 delegate.set_window_component(HTCAPTION); | 1365 delegate.set_window_component(HTCAPTION); |
| 1421 std::unique_ptr<Window> w1(aura::test::CreateTestWindowWithDelegate( | 1366 std::unique_ptr<Window> w1(aura::test::CreateTestWindowWithDelegate( |
| 1422 &delegate, ui::wm::WINDOW_TYPE_NORMAL, gfx::Rect(5, 5, 100, 50), NULL)); | 1367 &delegate, ui::wm::WINDOW_TYPE_NORMAL, gfx::Rect(5, 5, 100, 50), NULL)); |
| 1423 ParentWindowInPrimaryRootWindow(w1.get()); | 1368 ParentWindowInPrimaryRootWindow(w1.get()); |
| 1424 | 1369 |
| 1425 GetPrimaryShelf()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER); | 1370 GetPrimaryShelf()->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_NEVER); |
| 1426 | 1371 |
| 1427 // Drag near the shelf. | 1372 // Drag near the shelf. |
| 1428 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), | 1373 ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), |
| 1429 gfx::Point()); | 1374 gfx::Point()); |
| 1430 generator.MoveMouseTo(10, 10); | 1375 generator.MoveMouseTo(10, 10); |
| 1431 generator.PressLeftButton(); | 1376 generator.PressLeftButton(); |
| 1432 generator.MoveMouseTo(100, shelf_layout_manager()->GetIdealBounds().y() - 70); | 1377 generator.MoveMouseTo(100, shelf_layout_manager()->GetIdealBounds().y() - 70); |
| 1433 | 1378 |
| 1434 // Shelf should not be in overlapped state. | 1379 // Shelf should not be in overlapped state. |
| 1435 EXPECT_FALSE(GetWindowOverlapsShelf()); | 1380 EXPECT_FALSE(GetWindowOverlapsShelf()); |
| 1436 | 1381 |
| 1437 generator.MoveMouseTo(100, shelf_layout_manager()->GetIdealBounds().y() - 20); | 1382 generator.MoveMouseTo(100, shelf_layout_manager()->GetIdealBounds().y() - 20); |
| 1438 | 1383 |
| 1439 // Shelf should detect overlap. Overlap state stays after mouse is released. | 1384 // Shelf should detect overlap. Overlap state stays after mouse is released. |
| 1440 EXPECT_TRUE(GetWindowOverlapsShelf()); | 1385 EXPECT_TRUE(GetWindowOverlapsShelf()); |
| 1441 generator.ReleaseLeftButton(); | 1386 generator.ReleaseLeftButton(); |
| 1442 EXPECT_TRUE(GetWindowOverlapsShelf()); | 1387 EXPECT_TRUE(GetWindowOverlapsShelf()); |
| 1443 } | 1388 } |
| 1444 | 1389 |
| 1445 // Verifies that when dragging a window autohidden shelf stays hidden during | 1390 // Verifies that when dragging a window autohidden shelf stays hidden during |
| 1446 // and after the drag. | 1391 // and after the drag. |
| 1447 TEST_F(WorkspaceControllerTestDragging, DragWindowKeepsShelfAutohidden) { | 1392 TEST_F(WorkspaceControllerTest, DragWindowKeepsShelfAutohidden) { |
| 1448 aura::test::TestWindowDelegate delegate; | 1393 aura::test::TestWindowDelegate delegate; |
| 1449 delegate.set_window_component(HTCAPTION); | 1394 delegate.set_window_component(HTCAPTION); |
| 1450 std::unique_ptr<Window> w1(aura::test::CreateTestWindowWithDelegate( | 1395 std::unique_ptr<Window> w1(aura::test::CreateTestWindowWithDelegate( |
| 1451 &delegate, ui::wm::WINDOW_TYPE_NORMAL, gfx::Rect(5, 5, 100, 50), NULL)); | 1396 &delegate, ui::wm::WINDOW_TYPE_NORMAL, gfx::Rect(5, 5, 100, 50), NULL)); |
| 1452 ParentWindowInPrimaryRootWindow(w1.get()); | 1397 ParentWindowInPrimaryRootWindow(w1.get()); |
| 1453 | 1398 |
| 1454 WmShelf* shelf = GetPrimaryShelf(); | 1399 WmShelf* shelf = GetPrimaryShelf(); |
| 1455 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); | 1400 shelf->SetAutoHideBehavior(SHELF_AUTO_HIDE_BEHAVIOR_ALWAYS); |
| 1456 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState()); | 1401 EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState()); |
| 1457 | 1402 |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1592 ui::ET_TOUCH_PRESSED, location, ui::EventTimeForNow(), | 1537 ui::ET_TOUCH_PRESSED, location, ui::EventTimeForNow(), |
| 1593 ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0)); | 1538 ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0)); |
| 1594 ui::EventTarget* target = targeter->FindTargetForEvent(root, &touch); | 1539 ui::EventTarget* target = targeter->FindTargetForEvent(root, &touch); |
| 1595 if (points[i].is_target_hit) | 1540 if (points[i].is_target_hit) |
| 1596 EXPECT_EQ(window.get(), target); | 1541 EXPECT_EQ(window.get(), target); |
| 1597 else | 1542 else |
| 1598 EXPECT_NE(window.get(), target); | 1543 EXPECT_NE(window.get(), target); |
| 1599 } | 1544 } |
| 1600 } | 1545 } |
| 1601 | 1546 |
| 1602 // Verifies events targeting just outside the window edges for docked windows. | |
| 1603 TEST_F(WorkspaceControllerTest, WindowEdgeHitTestDocked) { | |
| 1604 aura::test::TestWindowDelegate delegate; | |
| 1605 // Make window smaller than the minimum docked area so that the window edges | |
| 1606 // are exposed. | |
| 1607 delegate.set_maximum_size(gfx::Size(180, 200)); | |
| 1608 std::unique_ptr<Window> window(aura::test::CreateTestWindowWithDelegate( | |
| 1609 &delegate, 123, gfx::Rect(20, 10, 100, 50), NULL)); | |
| 1610 ParentWindowInPrimaryRootWindow(window.get()); | |
| 1611 aura::Window* docked_container = Shell::GetContainer( | |
| 1612 window->GetRootWindow(), kShellWindowId_DockedContainer); | |
| 1613 docked_container->AddChild(window.get()); | |
| 1614 window->Show(); | |
| 1615 aura::Window* root = window->GetRootWindow(); | |
| 1616 ui::EventTargeter* targeter = | |
| 1617 root->GetHost()->dispatcher()->GetDefaultEventTargeter(); | |
| 1618 const gfx::Rect bounds = window->bounds(); | |
| 1619 const int kNumPoints = 5; | |
| 1620 struct { | |
| 1621 const char* direction; | |
| 1622 gfx::Point location; | |
| 1623 bool is_target_hit; | |
| 1624 } points[kNumPoints] = { | |
| 1625 {"left", gfx::Point(bounds.x() - 2, bounds.y() + 10), true}, | |
| 1626 {"top", gfx::Point(bounds.x() + 10, bounds.y() - 2), true}, | |
| 1627 {"right", gfx::Point(bounds.right() + 2, bounds.y() + 10), true}, | |
| 1628 {"bottom", gfx::Point(bounds.x() + 10, bounds.bottom() + 2), true}, | |
| 1629 {"outside", gfx::Point(bounds.x() + 10, bounds.y() - 31), false}, | |
| 1630 }; | |
| 1631 for (int i = 0; i < kNumPoints; ++i) { | |
| 1632 SCOPED_TRACE(points[i].direction); | |
| 1633 const gfx::Point& location = points[i].location; | |
| 1634 ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, location, location, | |
| 1635 ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE); | |
| 1636 ui::EventTarget* target = targeter->FindTargetForEvent(root, &mouse); | |
| 1637 if (points[i].is_target_hit) | |
| 1638 EXPECT_EQ(window.get(), target); | |
| 1639 else | |
| 1640 EXPECT_NE(window.get(), target); | |
| 1641 | |
| 1642 ui::TouchEvent touch( | |
| 1643 ui::ET_TOUCH_PRESSED, location, ui::EventTimeForNow(), | |
| 1644 ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0)); | |
| 1645 target = targeter->FindTargetForEvent(root, &touch); | |
| 1646 if (points[i].is_target_hit) | |
| 1647 EXPECT_EQ(window.get(), target); | |
| 1648 else | |
| 1649 EXPECT_NE(window.get(), target); | |
| 1650 } | |
| 1651 } | |
| 1652 | |
| 1653 } // namespace ash | 1547 } // namespace ash |
| OLD | NEW |