1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
|
// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/app_list/app_list_presenter_impl.h"
#include <memory>
#include <utility>
#include <vector>
#include "ash/app_list/app_list_controller_impl.h"
#include "ash/app_list/app_list_model_provider.h"
#include "ash/app_list/test/app_list_test_helper.h"
#include "ash/app_list/views/app_list_item_view.h"
#include "ash/app_list/views/app_list_view.h"
#include "ash/app_list/views/paged_apps_grid_view.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "chromeos/ash/services/assistant/public/cpp/features.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_occlusion_tracker.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/display/display.h"
#include "ui/events/test/event_generator.h"
namespace ash {
namespace {
int64_t GetPrimaryDisplayId() {
return display::Screen::GetScreen()->GetPrimaryDisplay().id();
}
class AppListPresenterImplTest : public AshTestBase {
public:
AppListPresenterImplTest()
: AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
AppListPresenterImplTest(const AppListPresenterImplTest&) = delete;
AppListPresenterImplTest& operator=(const AppListPresenterImplTest&) = delete;
~AppListPresenterImplTest() override = default;
AppListPresenterImpl* presenter() {
return Shell::Get()->app_list_controller()->fullscreen_presenter();
}
// Enables tablet mode and fast-forwards mock time until window occlusion
// tracking is enabled. See TabletModeController::SuspendOcclusionTracker().
// This is necessary for AppListPresenterImpl::IsAtLeastPartiallyVisible() to
// return correct results.
void EnableTabletMode() {
Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
auto* occlusion_tracker =
aura::Env::GetInstance()->GetWindowOcclusionTracker();
while (occlusion_tracker->IsPaused()) {
task_environment()->FastForwardBy(base::Milliseconds(100));
}
}
// Shows the app list on the primary display.
void ShowAppList() {
presenter()->Show(AppListViewState::kFullscreenAllApps,
GetPrimaryDisplay().id(), base::TimeTicks(),
/*show_source=*/std::nullopt);
}
// Shows the Assistant UI.
void ShowAssistantUI() {
presenter()->ShowEmbeddedAssistantUI(/*show=*/true);
}
bool IsShowingAssistantUI() {
return presenter()->IsShowingEmbeddedAssistantUI();
}
};
// Tests, in tablet mode, that when specific container id widgets are focused,
// that the shelf background type remains in kHomeLauncher and does not change
// to kInApp.
TEST_F(AppListPresenterImplTest,
ShelfBackgroundWithHomeLauncherAndContainerIdsShown) {
// Enter tablet mode to display the home launcher.
EnableTabletMode();
ASSERT_TRUE(presenter()->GetTargetVisibility());
ASSERT_TRUE(presenter()->IsAtLeastPartiallyVisible());
ShelfLayoutManager* shelf_layout_manager =
Shelf::ForWindow(Shell::GetRootWindowForDisplayId(GetPrimaryDisplayId()))
->shelf_layout_manager();
EXPECT_EQ(ShelfBackgroundType::kHomeLauncher,
shelf_layout_manager->shelf_background_type());
HotseatWidget* hotseat = GetPrimaryShelf()->hotseat_widget();
for (int id : AppListPresenterImpl::kIdsOfContainersThatWontHideAppList) {
// Create a widget with a specific container id and make sure that the
// kHomeLauncher background is still shown.
std::unique_ptr<views::Widget> widget = CreateTestWidget(
views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET, nullptr, id);
EXPECT_EQ(ShelfBackgroundType::kHomeLauncher,
shelf_layout_manager->shelf_background_type())
<< " container " << id;
EXPECT_EQ(hotseat->state(), HotseatState::kShownHomeLauncher);
}
}
// Tests that Assistant UI in tablet mode is closed when open another window.
TEST_F(AppListPresenterImplTest, HideAssistantUIOnFocusOut) {
if (ash::assistant::features::IsNewEntryPointEnabled()) {
GTEST_SKIP() << "Assistant is not available if new entry point is enabled. "
"crbug.com/388361414";
}
// Enter tablet mode to display the home launcher.
EnableTabletMode();
EXPECT_TRUE(presenter()->IsVisibleDeprecated());
EXPECT_FALSE(IsShowingAssistantUI());
// Open a window to cover Home Launcher.
std::unique_ptr<aura::Window> window1 = CreateTestWindow();
EXPECT_FALSE(presenter()->IsVisibleDeprecated());
// Open Assistant UI.
ShowAssistantUI();
// Assistant UI is visible but Home Launcher is considered not visible.
EXPECT_TRUE(IsShowingAssistantUI());
EXPECT_FALSE(presenter()->IsVisibleDeprecated());
// Open another window should close Assistant UI.
std::unique_ptr<aura::Window> window2 = CreateTestWindow();
EXPECT_FALSE(IsShowingAssistantUI());
EXPECT_FALSE(presenter()->IsVisibleDeprecated());
}
// Regression test for https://crbug.com/1235056
// Tests that shelf observers are cleared when shelf is destroyed.
TEST_F(AppListPresenterImplTest, ClearShelfObserversOnShelfRemoval) {
// Set up multidisplay, and open the app list on secondary monitor, so app
// list presenter starts observing the shelf state.
UpdateDisplay("600x400,600x400");
// Enter tablet mode, so the test can trigger tablet mode exit later on.
EnableTabletMode();
ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
// Remove the secondary display, and exit tablet mode to trigger app list view
// dismissal. Note that the display will be removed before the app list close
// animation completes.
UpdateDisplay("600x400");
base::RunLoop run_loop;
Shell::Get()
->app_list_controller()
->SetStateTransitionAnimationCallbackForTesting(
base::BindLambdaForTesting([&](AppListViewState state) {
if (state == AppListViewState::kClosed)
run_loop.Quit();
}));
Shell::Get()->tablet_mode_controller()->SetEnabledForTest(false);
run_loop.Run();
// Just verify there was no crash.
}
} // namespace
} // namespace ash
|