1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h"
6
7 #include "ash/public/cpp/ash_switches.h"
8 #include "ash/shell.h"
9 #include "base/command_line.h"
10 #include "base/numerics/math_constants.h"
11 #include "base/run_loop.h"
12 #include "base/time/default_tick_clock.h"
13 #include "ui/events/devices/device_data_manager_test_api.h"
14 #include "ui/events/devices/input_device.h"
15
16 namespace ash {
17
18 namespace {
19
IsTabletModeControllerInitialized()20 bool IsTabletModeControllerInitialized() {
21 return base::CommandLine::ForCurrentProcess()->HasSwitch(
22 switches::kAshEnableTabletMode);
23 }
24
25 } // namespace
26
TabletModeControllerTestApi()27 TabletModeControllerTestApi::TabletModeControllerTestApi()
28 : tablet_mode_controller_(Shell::Get()->tablet_mode_controller()) {
29 tablet_mode_controller_->OnDeviceListsComplete();
30 }
31
32 TabletModeControllerTestApi::~TabletModeControllerTestApi() = default;
33
EnterTabletMode()34 void TabletModeControllerTestApi::EnterTabletMode() {
35 tablet_mode_controller_->SetEnabledForTest(true);
36 }
37
LeaveTabletMode()38 void TabletModeControllerTestApi::LeaveTabletMode() {
39 tablet_mode_controller_->SetEnabledForTest(false);
40 }
41
AttachExternalMouse()42 void TabletModeControllerTestApi::AttachExternalMouse() {
43 // Calling RunUntilIdle() here is necessary before setting the mouse devices
44 // to prevent the callback from evdev thread to overwrite whatever we set
45 // here below. See `InputDeviceFactoryEvdevProxy::OnStartupScanComplete()`.
46 base::RunLoop().RunUntilIdle();
47 ui::DeviceDataManagerTestApi().SetMouseDevices(
48 {ui::InputDevice(3, ui::InputDeviceType::INPUT_DEVICE_USB, "mouse")});
49 if (!IsTabletModeControllerInitialized()) {
50 // The controller is not observing the DeviceDataManager, hence we need to
51 // notify it ourselves.
52 tablet_mode_controller_->OnInputDeviceConfigurationChanged(
53 ui::InputDeviceEventObserver::kMouse);
54 }
55 }
56
AttachExternalTouchpad()57 void TabletModeControllerTestApi::AttachExternalTouchpad() {
58 // Similar to |AttachExternalMouse|.
59 base::RunLoop().RunUntilIdle();
60 ui::DeviceDataManagerTestApi().SetTouchpadDevices(
61 {ui::InputDevice(4, ui::InputDeviceType::INPUT_DEVICE_USB, "touchpad")});
62 if (!IsTabletModeControllerInitialized()) {
63 tablet_mode_controller_->OnInputDeviceConfigurationChanged(
64 ui::InputDeviceEventObserver::kTouchpad);
65 }
66 }
67
DetachAllMice()68 void TabletModeControllerTestApi::DetachAllMice() {
69 // See comment in |AttachExternalMouse| for why we need to call
70 // |base::RunLoop::RunUntilIdle|.
71 base::RunLoop().RunUntilIdle();
72 ui::DeviceDataManagerTestApi().SetMouseDevices({});
73 if (!IsTabletModeControllerInitialized()) {
74 // The controller is not observing the DeviceDataManager, hence we need to
75 // notify it ourselves.
76 tablet_mode_controller_->OnInputDeviceConfigurationChanged(
77 ui::InputDeviceEventObserver::kMouse);
78 }
79 }
80
DetachAllTouchpads()81 void TabletModeControllerTestApi::DetachAllTouchpads() {
82 // Similar to |DetachAllMice|.
83 base::RunLoop().RunUntilIdle();
84 ui::DeviceDataManagerTestApi().SetTouchpadDevices({});
85 if (!IsTabletModeControllerInitialized()) {
86 tablet_mode_controller_->OnInputDeviceConfigurationChanged(
87 ui::InputDeviceEventObserver::kTouchpad);
88 }
89 }
90
TriggerLidUpdate(const gfx::Vector3dF & lid)91 void TabletModeControllerTestApi::TriggerLidUpdate(const gfx::Vector3dF& lid) {
92 scoped_refptr<AccelerometerUpdate> update(new AccelerometerUpdate());
93 update->Set(ACCELEROMETER_SOURCE_SCREEN, lid.x(), lid.y(), lid.z());
94 tablet_mode_controller_->OnAccelerometerUpdated(update);
95 }
96
TriggerBaseAndLidUpdate(const gfx::Vector3dF & base,const gfx::Vector3dF & lid)97 void TabletModeControllerTestApi::TriggerBaseAndLidUpdate(
98 const gfx::Vector3dF& base,
99 const gfx::Vector3dF& lid) {
100 scoped_refptr<AccelerometerUpdate> update(new AccelerometerUpdate());
101 update->Set(ACCELEROMETER_SOURCE_ATTACHED_KEYBOARD, base.x(), base.y(),
102 base.z());
103 update->Set(ACCELEROMETER_SOURCE_SCREEN, lid.x(), lid.y(), lid.z());
104 tablet_mode_controller_->OnAccelerometerUpdated(update);
105 }
106
OpenLidToAngle(float degrees)107 void TabletModeControllerTestApi::OpenLidToAngle(float degrees) {
108 DCHECK(degrees >= 0.0f);
109 DCHECK(degrees <= 360.0f);
110
111 float radians = degrees * kDegreesToRadians;
112 gfx::Vector3dF base_vector(0.0f, -base::kMeanGravityFloat, 0.0f);
113 gfx::Vector3dF lid_vector(0.0f, base::kMeanGravityFloat * cos(radians),
114 base::kMeanGravityFloat * sin(radians));
115 TriggerBaseAndLidUpdate(base_vector, lid_vector);
116 }
117
HoldDeviceVertical()118 void TabletModeControllerTestApi::HoldDeviceVertical() {
119 gfx::Vector3dF base_vector(9.8f, 0.0f, 0.0f);
120 gfx::Vector3dF lid_vector(9.8f, 0.0f, 0.0f);
121 TriggerBaseAndLidUpdate(base_vector, lid_vector);
122 }
123
OpenLid()124 void TabletModeControllerTestApi::OpenLid() {
125 tablet_mode_controller_->LidEventReceived(
126 chromeos::PowerManagerClient::LidState::OPEN, tick_clock()->NowTicks());
127 }
128
CloseLid()129 void TabletModeControllerTestApi::CloseLid() {
130 tablet_mode_controller_->LidEventReceived(
131 chromeos::PowerManagerClient::LidState::CLOSED, tick_clock()->NowTicks());
132 }
133
SetTabletMode(bool on)134 void TabletModeControllerTestApi::SetTabletMode(bool on) {
135 tablet_mode_controller_->TabletModeEventReceived(
136 on ? chromeos::PowerManagerClient::TabletMode::ON
137 : chromeos::PowerManagerClient::TabletMode::OFF,
138 tick_clock()->NowTicks());
139 }
140
SuspendImminent()141 void TabletModeControllerTestApi::SuspendImminent() {
142 tablet_mode_controller_->SuspendImminent(
143 power_manager::SuspendImminent::Reason::SuspendImminent_Reason_IDLE);
144 }
145
SuspendDone(base::TimeDelta sleep_duration)146 void TabletModeControllerTestApi::SuspendDone(base::TimeDelta sleep_duration) {
147 tablet_mode_controller_->SuspendDone(sleep_duration);
148 }
149
150 } // namespace ash
151