// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "ash/shell.h" #include "ash/shell_window_ids.h" #include "ash/test/ash_test_base.h" #include "ash/test/test_shell_delegate.h" #include "ash/wm/window_util.h" #include "base/command_line.h" #include "base/memory/scoped_ptr.h" #include "ui/app_list/app_list_switches.h" #include "ui/app_list/views/app_list_view.h" #include "ui/aura/test/test_windows.h" #include "ui/aura/window.h" #include "ui/events/test/event_generator.h" namespace ash { namespace { const int kMinimalCenteredAppListMargin = 10; } // The parameter is true to test the centered app list, false for normal. // (The test name ends in "/0" for normal, "/1" for centered.) class AppListControllerTest : public test::AshTestBase, public ::testing::WithParamInterface { public: AppListControllerTest(); virtual ~AppListControllerTest(); void SetUp() override; bool IsCentered() const; }; AppListControllerTest::AppListControllerTest() { } AppListControllerTest::~AppListControllerTest() { } void AppListControllerTest::SetUp() { AshTestBase::SetUp(); if (IsCentered()) { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); command_line->AppendSwitch(app_list::switches::kEnableCenteredAppList); } // Make the display big enough to hold the experimental app list. UpdateDisplay("1024x768"); } bool AppListControllerTest::IsCentered() const { return GetParam(); } // Tests that app launcher hides when focus moves to a normal window. TEST_P(AppListControllerTest, HideOnFocusOut) { Shell::GetInstance()->ShowAppList(NULL); EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility()); scoped_ptr window(CreateTestWindowInShellWithId(0)); wm::ActivateWindow(window.get()); EXPECT_FALSE(Shell::GetInstance()->GetAppListTargetVisibility()); } // Tests that app launcher remains visible when focus is moved to a different // window in kShellWindowId_AppListContainer. TEST_P(AppListControllerTest, RemainVisibleWhenFocusingToApplistContainer) { Shell::GetInstance()->ShowAppList(NULL); EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility()); aura::Window* applist_container = Shell::GetContainer( Shell::GetPrimaryRootWindow(), kShellWindowId_AppListContainer); scoped_ptr window( aura::test::CreateTestWindowWithId(0, applist_container)); wm::ActivateWindow(window.get()); EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility()); } // Tests that clicking outside the app-list bubble closes it. TEST_P(AppListControllerTest, ClickOutsideBubbleClosesBubble) { Shell* shell = Shell::GetInstance(); shell->ShowAppList(NULL); aura::Window* app_window = shell->GetAppListWindow(); ASSERT_TRUE(app_window); ui::test::EventGenerator generator(shell->GetPrimaryRootWindow(), app_window); // Click on the bubble itself. The bubble should remain visible. generator.ClickLeftButton(); EXPECT_TRUE(shell->GetAppListTargetVisibility()); // Click outside the bubble. This should close it. gfx::Rect app_window_bounds = app_window->GetBoundsInRootWindow(); gfx::Point point_outside = gfx::Point(app_window_bounds.right(), app_window_bounds.y()) + gfx::Vector2d(10, 0); EXPECT_TRUE(shell->GetPrimaryRootWindow()->bounds().Contains(point_outside)); generator.MoveMouseToInHost(point_outside); generator.ClickLeftButton(); EXPECT_FALSE(shell->GetAppListTargetVisibility()); } // Tests that clicking outside the app-list bubble closes it. TEST_P(AppListControllerTest, TapOutsideBubbleClosesBubble) { Shell* shell = Shell::GetInstance(); shell->ShowAppList(NULL); aura::Window* app_window = shell->GetAppListWindow(); ASSERT_TRUE(app_window); gfx::Rect app_window_bounds = app_window->GetBoundsInRootWindow(); ui::test::EventGenerator generator(shell->GetPrimaryRootWindow()); // Click on the bubble itself. The bubble should remain visible. generator.GestureTapAt(app_window_bounds.CenterPoint()); EXPECT_TRUE(shell->GetAppListTargetVisibility()); // Click outside the bubble. This should close it. gfx::Point point_outside = gfx::Point(app_window_bounds.right(), app_window_bounds.y()) + gfx::Vector2d(10, 0); EXPECT_TRUE(shell->GetPrimaryRootWindow()->bounds().Contains(point_outside)); generator.GestureTapAt(point_outside); EXPECT_FALSE(shell->GetAppListTargetVisibility()); } // Tests opening the app launcher on a non-primary display, then deleting the // display. TEST_P(AppListControllerTest, NonPrimaryDisplay) { if (!SupportsMultipleDisplays()) return; // Set up a screen with two displays (horizontally adjacent). UpdateDisplay("1024x768,1024x768"); aura::Window::Windows root_windows = Shell::GetAllRootWindows(); ASSERT_EQ(2u, root_windows.size()); aura::Window* secondary_window = root_windows[1]; EXPECT_EQ("1024,0 1024x768", secondary_window->GetBoundsInScreen().ToString()); Shell::GetInstance()->ShowAppList(secondary_window); EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility()); // Remove the secondary display. Shouldn't crash (http://crbug.com/368990). UpdateDisplay("1024x768"); // Updating the displays should close the app list. EXPECT_FALSE(Shell::GetInstance()->GetAppListTargetVisibility()); } // Tests opening the app launcher on a tiny display that is too small to contain // it. TEST_P(AppListControllerTest, TinyDisplay) { // Don't test this for the non-centered app list case; it isn't designed for // small displays. The most common case of a small display --- when the // virtual keyboard is open --- switches into the centered app list mode, so // we just want to run this test in that case. if (!IsCentered()) return; // UpdateDisplay is not supported in this case, so just skip the test. if (!SupportsHostWindowResize()) return; // Set up a screen with a tiny display (height smaller than the app list). UpdateDisplay("400x300"); Shell::GetInstance()->ShowAppList(NULL); EXPECT_TRUE(Shell::GetInstance()->GetAppListTargetVisibility()); // The top of the app list should be on-screen (even if the bottom is not). // We need to manually calculate the Y coordinate of the top of the app list // from the anchor (center) and height. There isn't a bounds rect that gives // the actual app list position (the widget bounds include the bubble border // which is much bigger than the actual app list size). app_list::AppListView* app_list = Shell::GetInstance()->GetAppListView(); int app_list_view_top = app_list->anchor_rect().y() - app_list->bounds().height() / 2; EXPECT_GE(app_list_view_top, kMinimalCenteredAppListMargin); } INSTANTIATE_TEST_CASE_P(AppListControllerTestInstance, AppListControllerTest, ::testing::Bool()); } // namespace ash