| // Copyright 2012 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/public/cpp/test/shell_test_api.h" |
| #include "base/memory/raw_ptr.h" |
| |
| #include <memory> |
| |
| #include "ash/accelerators/accelerator_commands.h" |
| #include "ash/accelerators/accelerator_controller_impl.h" |
| #include "ash/accelerometer/accelerometer_reader.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/notification_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/functional/bind.h" |
| #include "base/run_loop.h" |
| #include "components/prefs/testing_pref_service.h" |
| #include "ui/compositor/compositor.h" |
| #include "ui/compositor/layer.h" |
| #include "ui/compositor/layer_animation_observer.h" |
| #include "ui/compositor/layer_animator.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 { |
| |
| 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: |
| raw_ptr<ui::LayerAnimator, DanglingUntriaged> 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); |
| } |
| |
| 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_.reset(); |
| 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::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::WaitForWindowFinishAnimating(aura::Window* window) { |
| WindowAnimationWaiter waiter(window); |
| waiter.Wait(); |
| } |
| |
| bool ShellTestApi::IsContextMenuShown() const { |
| return Shell::GetPrimaryRootWindowController()->IsContextMenuShown(); |
| } |
| |
| bool ShellTestApi::IsActionForAcceleratorEnabled( |
| const ui::Accelerator& accelerator) const { |
| auto* controller = Shell::Get()->accelerator_controller(); |
| return AcceleratorControllerImpl::TestApi(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 |