
This helps distinguish it from the bubble_presenter_ for AppListBubble. Convert from embedded object to std::unique_ptr<> so we can forward declare it and skip including a large header. This requires moving the call to AppListPresenterImpl::Dismiss() out of ~AppListPresenterImpl() into ~AppListControllerImpl(). That functions calls back into the controller and accesses fullscreen_presenter_ during shutdown. Also fix various include-what-you-use issues. Bug: 1204554 Test: ash_unittests, both regular and ASAN Change-Id: I7756c3f757820a3de2646c70f52bf1a47d965459 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2921960 Reviewed-by: Alex Newcomer <newcomer@chromium.org> Commit-Queue: James Cook <jamescook@chromium.org> Cr-Commit-Position: refs/heads/master@{#887353}
293 lines
9.5 KiB
C++
293 lines
9.5 KiB
C++
// Copyright (c) 2012 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/public/cpp/test/shell_test_api.h"
|
|
|
|
#include <memory>
|
|
#include <utility>
|
|
|
|
#include "ash/accelerators/accelerator_commands.h"
|
|
#include "ash/accelerators/accelerator_controller_impl.h"
|
|
#include "ash/accelerometer/accelerometer_reader.h"
|
|
#include "ash/app_list/app_list_controller_impl.h"
|
|
#include "ash/app_list/app_list_presenter_impl.h"
|
|
#include "ash/app_list/views/app_list_view.h"
|
|
#include "ash/hud_display/hud_display.h"
|
|
#include "ash/keyboard/keyboard_controller_impl.h"
|
|
#include "ash/public/cpp/autotest_private_api_utils.h"
|
|
#include "ash/public/cpp/tablet_mode_observer.h"
|
|
#include "ash/root_window_controller.h"
|
|
#include "ash/shell.h"
|
|
#include "ash/system/message_center/session_state_notification_blocker.h"
|
|
#include "ash/system/power/backlights_forced_off_setter.h"
|
|
#include "ash/system/power/power_button_controller.h"
|
|
#include "ash/wm/overview/overview_animation_state_waiter.h"
|
|
#include "ash/wm/overview/overview_controller.h"
|
|
#include "ash/wm/splitview/split_view_controller.h"
|
|
#include "ash/wm/tablet_mode/tablet_mode_controller.h"
|
|
#include "ash/wm/workspace_controller.h"
|
|
#include "base/bind.h"
|
|
#include "base/run_loop.h"
|
|
#include "components/prefs/testing_pref_service.h"
|
|
#include "ui/aura/window_tree_host.h"
|
|
#include "ui/compositor/compositor.h"
|
|
#include "ui/compositor/compositor_observer.h"
|
|
#include "ui/compositor/layer.h"
|
|
#include "ui/compositor/layer_animation_observer.h"
|
|
#include "ui/display/manager/display_manager.h"
|
|
#include "ui/events/devices/device_data_manager_test_api.h"
|
|
#include "ui/events/gesture_detection/gesture_configuration.h"
|
|
|
|
namespace ash {
|
|
namespace {
|
|
|
|
// Wait for a WindowTreeHost to no longer be holding pointer events.
|
|
class PointerMoveLoopWaiter : public ui::CompositorObserver {
|
|
public:
|
|
explicit PointerMoveLoopWaiter(aura::WindowTreeHost* window_tree_host)
|
|
: window_tree_host_(window_tree_host) {
|
|
window_tree_host_->compositor()->AddObserver(this);
|
|
}
|
|
|
|
~PointerMoveLoopWaiter() override {
|
|
window_tree_host_->compositor()->RemoveObserver(this);
|
|
}
|
|
|
|
void Wait() {
|
|
// Use a while loop as it's possible for releasing the lock to trigger
|
|
// processing events, which again grabs the lock.
|
|
while (window_tree_host_->holding_pointer_moves()) {
|
|
run_loop_ = std::make_unique<base::RunLoop>(
|
|
base::RunLoop::Type::kNestableTasksAllowed);
|
|
run_loop_->Run();
|
|
run_loop_.reset();
|
|
}
|
|
}
|
|
|
|
// ui::CompositorObserver:
|
|
void OnCompositingEnded(ui::Compositor* compositor) override {
|
|
if (run_loop_)
|
|
run_loop_->Quit();
|
|
}
|
|
|
|
private:
|
|
aura::WindowTreeHost* window_tree_host_;
|
|
std::unique_ptr<base::RunLoop> run_loop_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(PointerMoveLoopWaiter);
|
|
};
|
|
|
|
class WindowAnimationWaiter : public ui::LayerAnimationObserver {
|
|
public:
|
|
explicit WindowAnimationWaiter(aura::Window* window)
|
|
: animator_(window->layer()->GetAnimator()) {
|
|
animator_->AddObserver(this);
|
|
}
|
|
~WindowAnimationWaiter() override = default;
|
|
|
|
WindowAnimationWaiter(const WindowAnimationWaiter& other) = delete;
|
|
WindowAnimationWaiter& operator=(const WindowAnimationWaiter& rhs) = delete;
|
|
|
|
// ui::LayerAnimationObserver:
|
|
void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override {
|
|
if (!animator_->is_animating()) {
|
|
animator_->RemoveObserver(this);
|
|
run_loop_.Quit();
|
|
}
|
|
}
|
|
void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override {}
|
|
void OnLayerAnimationScheduled(
|
|
ui::LayerAnimationSequence* sequence) override {}
|
|
|
|
void Wait() {
|
|
run_loop_.Run();
|
|
}
|
|
|
|
private:
|
|
ui::LayerAnimator* animator_;
|
|
base::RunLoop run_loop_;
|
|
};
|
|
|
|
} // namespace
|
|
|
|
ShellTestApi::ShellTestApi() : shell_(Shell::Get()) {}
|
|
ShellTestApi::~ShellTestApi() = default;
|
|
|
|
// static
|
|
void ShellTestApi::SetTabletControllerUseScreenshotForTest(
|
|
bool use_screenshot) {
|
|
TabletModeController::SetUseScreenshotForTest(use_screenshot);
|
|
}
|
|
|
|
// static
|
|
void ShellTestApi::SetUseLoginNotificationDelayForTest(bool use_delay) {
|
|
SessionStateNotificationBlocker::SetUseLoginNotificationDelayForTest(
|
|
use_delay);
|
|
}
|
|
|
|
// static
|
|
void ShellTestApi::SetShouldShowShortcutNotificationForTest(
|
|
bool show_notification) {
|
|
AcceleratorControllerImpl::SetShouldShowShortcutNotificationForTest(
|
|
show_notification);
|
|
}
|
|
|
|
MessageCenterController* ShellTestApi::message_center_controller() {
|
|
return shell_->message_center_controller_.get();
|
|
}
|
|
|
|
WorkspaceController* ShellTestApi::workspace_controller() {
|
|
// TODO(afakhry): Split this into two, one for root, and one for context.
|
|
return GetActiveWorkspaceController(shell_->GetPrimaryRootWindow());
|
|
}
|
|
|
|
ScreenPositionController* ShellTestApi::screen_position_controller() {
|
|
return shell_->screen_position_controller_.get();
|
|
}
|
|
|
|
NativeCursorManagerAsh* ShellTestApi::native_cursor_manager_ash() {
|
|
return shell_->native_cursor_manager_;
|
|
}
|
|
|
|
DragDropController* ShellTestApi::drag_drop_controller() {
|
|
return shell_->drag_drop_controller_.get();
|
|
}
|
|
|
|
PowerPrefs* ShellTestApi::power_prefs() {
|
|
return shell_->power_prefs_.get();
|
|
}
|
|
|
|
display::DisplayManager* ShellTestApi::display_manager() {
|
|
return shell_->display_manager();
|
|
}
|
|
|
|
void ShellTestApi::ResetPowerButtonControllerForTest() {
|
|
shell_->backlights_forced_off_setter_->ResetForTest();
|
|
shell_->power_button_controller_ = std::make_unique<PowerButtonController>(
|
|
shell_->backlights_forced_off_setter_.get());
|
|
}
|
|
|
|
void ShellTestApi::SimulateModalWindowOpenForTest(bool modal_window_open) {
|
|
shell_->simulate_modal_window_open_for_test_ = modal_window_open;
|
|
}
|
|
|
|
bool ShellTestApi::IsSystemModalWindowOpen() {
|
|
return Shell::IsSystemModalWindowOpen();
|
|
}
|
|
|
|
void ShellTestApi::SetTabletModeEnabledForTest(bool enable) {
|
|
// Detach mouse devices, so we can enter tablet mode.
|
|
// Calling RunUntilIdle() here is necessary before setting the mouse devices
|
|
// to prevent the callback from evdev thread from overwriting whatever we set
|
|
// here below. See `InputDeviceFactoryEvdevProxy::OnStartupScanComplete()`.
|
|
base::RunLoop().RunUntilIdle();
|
|
ui::DeviceDataManagerTestApi().OnDeviceListsComplete();
|
|
ui::DeviceDataManagerTestApi().SetMouseDevices({});
|
|
|
|
TabletMode::Waiter waiter(enable);
|
|
shell_->tablet_mode_controller()->SetEnabledForTest(enable);
|
|
waiter.Wait();
|
|
}
|
|
|
|
void ShellTestApi::EnableVirtualKeyboard() {
|
|
shell_->keyboard_controller()->SetEnableFlag(
|
|
keyboard::KeyboardEnableFlag::kCommandLineEnabled);
|
|
}
|
|
|
|
void ShellTestApi::ToggleFullscreen() {
|
|
accelerators::ToggleFullscreen();
|
|
}
|
|
|
|
void ShellTestApi::AddRemoveDisplay() {
|
|
shell_->display_manager()->AddRemoveDisplay();
|
|
}
|
|
|
|
void ShellTestApi::WaitForNoPointerHoldLock() {
|
|
aura::WindowTreeHost* primary_host =
|
|
Shell::GetPrimaryRootWindowController()->GetHost();
|
|
if (primary_host->holding_pointer_moves())
|
|
PointerMoveLoopWaiter(primary_host).Wait();
|
|
}
|
|
|
|
void ShellTestApi::WaitForNextFrame(base::OnceClosure closure) {
|
|
Shell::GetPrimaryRootWindowController()
|
|
->GetHost()
|
|
->compositor()
|
|
->RequestPresentationTimeForNextFrame(base::BindOnce(
|
|
[](base::OnceClosure closure,
|
|
const gfx::PresentationFeedback& feedback) {
|
|
std::move(closure).Run();
|
|
},
|
|
std::move(closure)));
|
|
}
|
|
|
|
void ShellTestApi::WaitForOverviewAnimationState(OverviewAnimationState state) {
|
|
auto* overview_controller = shell_->overview_controller();
|
|
if (state == OverviewAnimationState::kEnterAnimationComplete &&
|
|
overview_controller->InOverviewSession() &&
|
|
!overview_controller->IsInStartAnimation()) {
|
|
// If there is no animation applied, call the callback immediately.
|
|
return;
|
|
}
|
|
if (state == OverviewAnimationState::kExitAnimationComplete &&
|
|
!overview_controller->InOverviewSession() &&
|
|
!overview_controller->IsCompletingShutdownAnimations()) {
|
|
// If there is no animation applied, call the callback immediately.
|
|
return;
|
|
}
|
|
base::RunLoop run_loop;
|
|
new OverviewAnimationStateWaiter(
|
|
state, base::BindOnce([](base::RunLoop* run_loop,
|
|
bool finished) { run_loop->QuitWhenIdle(); },
|
|
base::Unretained(&run_loop)));
|
|
run_loop.Run();
|
|
}
|
|
|
|
void ShellTestApi::WaitForLauncherAnimationState(
|
|
AppListViewState target_state) {
|
|
base::RunLoop run_loop;
|
|
WaitForLauncherState(target_state, run_loop.QuitWhenIdleClosure());
|
|
run_loop.Run();
|
|
}
|
|
|
|
void ShellTestApi::WaitForWindowFinishAnimating(aura::Window* window) {
|
|
WindowAnimationWaiter waiter(window);
|
|
waiter.Wait();
|
|
}
|
|
|
|
base::OnceClosure ShellTestApi::CreateWaiterForFinishingWindowAnimation(
|
|
aura::Window* window) {
|
|
auto waiter = std::make_unique<WindowAnimationWaiter>(window);
|
|
return base::BindOnce(&WindowAnimationWaiter::Wait, std::move(waiter));
|
|
}
|
|
|
|
PaginationModel* ShellTestApi::GetAppListPaginationModel() {
|
|
AppListView* view =
|
|
Shell::Get()->app_list_controller()->presenter()->GetView();
|
|
if (!view)
|
|
return nullptr;
|
|
return view->GetAppsPaginationModel();
|
|
}
|
|
|
|
bool ShellTestApi::IsContextMenuShown() const {
|
|
return Shell::GetPrimaryRootWindowController()->IsContextMenuShown();
|
|
}
|
|
|
|
bool ShellTestApi::IsActionForAcceleratorEnabled(
|
|
const ui::Accelerator& accelerator) const {
|
|
return Shell::Get()->accelerator_controller()->IsActionForAcceleratorEnabled(
|
|
accelerator);
|
|
}
|
|
|
|
bool ShellTestApi::PressAccelerator(const ui::Accelerator& accelerator) {
|
|
return Shell::Get()->accelerator_controller()->AcceleratorPressed(
|
|
accelerator);
|
|
}
|
|
|
|
bool ShellTestApi::IsHUDShown() {
|
|
return hud_display::HUDDisplayView::IsShown();
|
|
}
|
|
|
|
} // namespace ash
|