| // Copyright 2023 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/virtual_trackpad/virtual_trackpad_view.h" |
| |
| #include "ash/accelerators/accelerator_controller_impl.h" |
| #include "ash/constants/ash_pref_names.h" |
| #include "ash/constants/ash_switches.h" |
| #include "ash/public/cpp/accelerators.h" |
| #include "ash/shell.h" |
| #include "ash/test/ash_test_base.h" |
| #include "ash/wm/desks/desks_controller.h" |
| #include "ash/wm/overview/overview_controller.h" |
| #include "ash/wm/overview/overview_session.h" |
| #include "base/command_line.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "chromeos/constants/chromeos_features.h" |
| #include "ui/views/controls/button/label_button.h" |
| |
| namespace ash { |
| |
| class VirtualTrackpadTest : public AshTestBase { |
| public: |
| VirtualTrackpadTest() = default; |
| VirtualTrackpadTest(const VirtualTrackpadTest&) = delete; |
| VirtualTrackpadTest& operator=(const VirtualTrackpadTest&) = delete; |
| ~VirtualTrackpadTest() override = default; |
| |
| // AshTestBase: |
| void SetUp() override { |
| base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| switches::kAshDebugShortcuts); |
| AshTestBase::SetUp(); |
| } |
| |
| void ToggleVirtualTrackpad() { |
| PressAndReleaseKey(ui::VKEY_Q, kDebugModifier); |
| } |
| |
| views::Widget* GetWidget() { |
| return VirtualTrackpadView::GetWidgetForTesting(); |
| } |
| |
| gfx::Rect GetVirtualTrackpadBoundsInScreen() { |
| views::Widget* widget = GetWidget(); |
| DCHECK(widget); |
| // Get contents view through the delegate because we set the contents view |
| // through the delegate. The reasoning is explained in `Toggle()`. |
| gfx::Rect bounds = static_cast<VirtualTrackpadView*>( |
| widget->widget_delegate()->GetContentsView()) |
| ->GetTrackpadViewForTesting() |
| ->GetBoundsInScreen(); |
| |
| // Inset by a bit to ensure we don't click on the edges. |
| bounds.Inset(3); |
| |
| return bounds; |
| } |
| |
| void ClickFourFingerButton() { |
| views::Widget* widget = GetWidget(); |
| DCHECK(widget); |
| views::LabelButton* four_finger_button = |
| static_cast<VirtualTrackpadView*>( |
| widget->widget_delegate()->GetContentsView()) |
| ->finger_buttons_[4]; |
| |
| LeftClickOn(four_finger_button); |
| } |
| }; |
| |
| // Tests that the accelerator to show and hide the virtual trackpad widget works |
| // as expected. |
| TEST_F(VirtualTrackpadTest, ToggleShowHide) { |
| ASSERT_FALSE(GetWidget()); |
| |
| ToggleVirtualTrackpad(); |
| EXPECT_TRUE(GetWidget()); |
| |
| ToggleVirtualTrackpad(); |
| // Toggle to close uses `views::Widget::Close()` which uses a post task. |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_FALSE(GetWidget()); |
| } |
| |
| class VirtualTrackpadTestReverseScroll |
| : public VirtualTrackpadTest, |
| public testing::WithParamInterface<bool> { |
| public: |
| VirtualTrackpadTestReverseScroll() = default; |
| VirtualTrackpadTestReverseScroll(const VirtualTrackpadTestReverseScroll&) = |
| delete; |
| VirtualTrackpadTestReverseScroll& operator=( |
| const VirtualTrackpadTestReverseScroll&) = delete; |
| ~VirtualTrackpadTestReverseScroll() override = default; |
| |
| void SetUp() override { VirtualTrackpadTest::SetUp(); } |
| |
| void SetNaturalScroll(bool enabled) { |
| PrefService* pref = |
| Shell::Get()->session_controller()->GetActivePrefService(); |
| pref->SetBoolean(prefs::kTouchpadEnabled, true); |
| pref->SetBoolean(prefs::kNaturalScroll, enabled); |
| } |
| }; |
| |
| // Tests that using the virtual trackpad allows us to enter and exit overview. |
| // Also tests this with reverse scrolling enabled. |
| TEST_P(VirtualTrackpadTestReverseScroll, SwipeToToggleOverview) { |
| ToggleVirtualTrackpad(); |
| |
| // Toggle natural scrolling. Behavior should stay the same. |
| SetNaturalScroll(/*enabled=*/GetParam()); |
| |
| OverviewController* overview_controller = Shell::Get()->overview_controller(); |
| ASSERT_FALSE(overview_controller->InOverviewSession()); |
| |
| // Get the trackpad bounds so we can use the mouse to generate scroll events. |
| gfx::Rect trackpad_bounds = GetVirtualTrackpadBoundsInScreen(); |
| |
| // Swipe up to enter overview. There should be no items in overview as the |
| // virtual trackpad window is excluded from overview. |
| auto* event_generator = GetEventGenerator(); |
| event_generator->MoveMouseTo(trackpad_bounds.bottom_center()); |
| event_generator->DragMouseTo(trackpad_bounds.top_center()); |
| ASSERT_TRUE(overview_controller->InOverviewSession()); |
| EXPECT_TRUE(overview_controller->overview_session()->IsEmpty()); |
| |
| // Swipe down to exit overview. |
| event_generator->DragMouseTo(trackpad_bounds.bottom_center()); |
| EXPECT_FALSE(overview_controller->InOverviewSession()); |
| } |
| |
| // Tests that using the virtual trackpad allows us to choose four fingers and |
| // swipe to an adjacent desk. Also tests this with reverse scrolling enabled. |
| TEST_P(VirtualTrackpadTestReverseScroll, SwipeToSwitchDesks) { |
| DesksController* desks_controller = DesksController::Get(); |
| desks_controller->NewDesk(DesksCreationRemovalSource::kKeyboard); |
| desks_controller->NewDesk(DesksCreationRemovalSource::kKeyboard); |
| desks_controller->ActivateDesk(desks_controller->GetDeskAtIndex(1), |
| DesksSwitchSource::kUserSwitch); |
| ASSERT_EQ(1, desks_controller->GetActiveDeskIndex()); |
| |
| ToggleVirtualTrackpad(); |
| |
| // Toggle natural scrolling. |
| SetNaturalScroll(/*enabled=*/GetParam()); |
| |
| // Get the trackpad bounds so we can use the mouse to generate scroll events. |
| gfx::Rect trackpad_bounds = GetVirtualTrackpadBoundsInScreen(); |
| |
| // Try swiping across the virtual trackpad. The desk doesn't change as the |
| // generated swipe is the default three fingers. |
| auto* event_generator = GetEventGenerator(); |
| event_generator->MoveMouseTo(trackpad_bounds.right_center()); |
| event_generator->DragMouseTo(trackpad_bounds.left_center()); |
| ASSERT_EQ(1, desks_controller->GetActiveDeskIndex()); |
| |
| // Click on the button which will make generated swipes be four fingers. |
| // Swiping across the virtual trackpad will now change the desk. |
| ClickFourFingerButton(); |
| event_generator->MoveMouseTo(trackpad_bounds.right_center()); |
| event_generator->DragMouseTo(trackpad_bounds.left_center()); |
| |
| // Natural scroll should flip the behavior of scrolls. |
| bool natural_scroll_enabled = GetParam(); |
| EXPECT_EQ(natural_scroll_enabled ? 2 : 0, |
| desks_controller->GetActiveDeskIndex()); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P(All, |
| VirtualTrackpadTestReverseScroll, |
| ::testing::Bool()); |
| |
| } // namespace ash |