Commit 8d1faf1c authored by Manu Cornet's avatar Manu Cornet Committed by Commit Bot

CrOS Shelf: Finish moving hotseat widget tests to their own test class

Split out some helper classes into their own files in the process:
HotseatStateWatcher, OverviewAnimationWaiter,
ShelfLayoutManagerTestBase.

This is a pure (albeit large) refactoring and does not modify any of the
actual test semantics.

Change-Id: Ica79e3dcead839daa83022de329b5aca8f636c40
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2015672
Commit-Queue: Manu Cornet <manucornet@chromium.org>
Reviewed-by: default avatarAlex Newcomer <newcomer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#734615}
parent 783e7037
......@@ -1842,6 +1842,12 @@ test("ash_unittests") {
"shelf/shelf_view_unittest.cc",
"shelf/shelf_widget_unittest.cc",
"shelf/shelf_window_watcher_unittest.cc",
"shelf/test/hotseat_state_watcher.cc",
"shelf/test/hotseat_state_watcher.h",
"shelf/test/overview_animation_waiter.cc",
"shelf/test/overview_animation_waiter.h",
"shelf/test/shelf_layout_manager_test_base.cc",
"shelf/test/shelf_layout_manager_test_base.h",
"shell_state_unittest.cc",
"shell_unittest.cc",
"sticky_keys/sticky_keys_overlay_unittest.cc",
......
......@@ -4,17 +4,36 @@
#include "ash/app_list/app_list_controller_impl.h"
#include "ash/app_list/test/app_list_test_helper.h"
#include "ash/focus_cycler.h"
#include "ash/home_screen/drag_window_from_shelf_controller_test_api.h"
#include "ash/public/cpp/ash_features.h"
#include "ash/public/cpp/test/shell_test_api.h"
#include "ash/shelf/home_button.h"
#include "ash/shelf/shelf.h"
#include "ash/shelf/shelf_app_button.h"
#include "ash/shelf/shelf_focus_cycler.h"
#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shelf/shelf_metrics.h"
#include "ash/shelf/shelf_navigation_widget.h"
#include "ash/shelf/shelf_test_util.h"
#include "ash/shelf/shelf_view.h"
#include "ash/shelf/shelf_view_test_api.h"
#include "ash/shelf/test/hotseat_state_watcher.h"
#include "ash/shelf/test/overview_animation_waiter.h"
#include "ash/shelf/test/shelf_layout_manager_test_base.h"
#include "ash/shell.h"
#include "ash/system/overview/overview_button_tray.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/unified/unified_system_tray.h"
#include "ash/test/ash_test_base.h"
#include "ash/wm/overview/overview_controller.h"
#include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h"
#include "ash/wm/window_state.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "chromeos/constants/chromeos_features.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/events/gesture_detection/gesture_configuration.h"
#include "ui/events/test/event_generator.h"
#include "ui/wm/core/window_util.h"
......@@ -22,44 +41,63 @@
namespace ash {
namespace {
ShelfWidget* GetShelfWidget() {
return AshTestBase::GetPrimaryShelf()->shelf_widget();
}
ShelfLayoutManager* GetShelfLayoutManager() {
return AshTestBase::GetPrimaryShelf()->shelf_layout_manager();
}
} // namespace
class HotseatWidgetTest
: public AshTestBase,
: public ShelfLayoutManagerTestBase,
public testing::WithParamInterface<ShelfAutoHideBehavior> {
public:
HotseatWidgetTest() = default;
// Performs a swipe up gesture to show an auto-hidden shelf.
void SwipeUpOnShelf() {
gfx::Rect display_bounds =
display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
const gfx::Point start(display_bounds.bottom_center());
const gfx::Point end(start + gfx::Vector2d(0, -80));
const base::TimeDelta kTimeDelta = base::TimeDelta::FromMilliseconds(100);
const int kNumScrollSteps = 4;
GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
kNumScrollSteps);
}
void SwipeDownOnShelf() {
gfx::Point start(GetPrimaryShelf()
->shelf_widget()
->shelf_view_for_testing()
->GetBoundsInScreen()
.top_center());
const gfx::Point end(start + gfx::Vector2d(0, 40));
const base::TimeDelta kTimeDelta = base::TimeDelta::FromMilliseconds(100);
const int kNumScrollSteps = 4;
GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
kNumScrollSteps);
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
// Counts the number of times the work area changes.
class DisplayWorkAreaChangeCounter : public display::DisplayObserver {
public:
DisplayWorkAreaChangeCounter() {
Shell::Get()->display_manager()->AddObserver(this);
}
~DisplayWorkAreaChangeCounter() override {
Shell::Get()->display_manager()->RemoveObserver(this);
}
void OnDisplayMetricsChanged(const display::Display& display,
uint32_t metrics) override {
if (metrics & display::DisplayObserver::DISPLAY_METRIC_WORK_AREA)
work_area_change_count_++;
}
int count() const { return work_area_change_count_; }
private:
base::test::ScopedFeatureList scoped_feature_list_;
int work_area_change_count_ = 0;
DISALLOW_COPY_AND_ASSIGN(DisplayWorkAreaChangeCounter);
};
// Watches the shelf for state changes.
class ShelfStateWatcher : public ShelfObserver {
public:
ShelfStateWatcher() { AshTestBase::GetPrimaryShelf()->AddObserver(this); }
~ShelfStateWatcher() override {
AshTestBase::GetPrimaryShelf()->RemoveObserver(this);
}
void WillChangeVisibilityState(ShelfVisibilityState new_state) override {
state_change_count_++;
}
int state_change_count() const { return state_change_count_; }
private:
int state_change_count_ = 0;
};
// Used to test the Hotseat, ScrollabeShelf, and DenseShelf features.
......@@ -177,4 +215,1506 @@ TEST_P(HotseatWidgetTest, CloseLastWindowOpenedInTabletMode) {
GetAppListTestHelper()->CheckVisibility(true);
}
// Tests that swiping up on an autohidden shelf shows the hotseat, and swiping
// down hides it.
TEST_F(HotseatWidgetTest, ShowingAndHidingAutohiddenShelf) {
GetPrimaryShelf()->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
SwipeUpOnShelf();
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, GetPrimaryShelf()->GetAutoHideState());
SwipeDownOnShelf();
EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, GetPrimaryShelf()->GetAutoHideState());
// Swipe down again, nothing should change.
SwipeDownOnShelf();
EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, GetPrimaryShelf()->GetAutoHideState());
}
// Tests that swiping up on several places in the in-app shelf shows the
// hotseat (crbug.com/1016931).
TEST_F(HotseatWidgetTest, SwipeUpInAppShelfShowsHotseat) {
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
base::HistogramTester histogram_tester;
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 0);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 0);
// Swipe up from the center of the shelf.
SwipeUpOnShelf();
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 0);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 1);
// Swipe down from the hotseat to hide it.
gfx::Rect hotseat_bounds =
GetShelfWidget()->hotseat_widget()->GetWindowBoundsInScreen();
gfx::Point start = hotseat_bounds.top_center();
gfx::Point end = start + gfx::Vector2d(0, 80);
const base::TimeDelta kTimeDelta = base::TimeDelta::FromMilliseconds(100);
const int kNumScrollSteps = 4;
GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
kNumScrollSteps);
ASSERT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 1);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 1);
// Swipe up from the right part of the shelf (the system tray).
start = GetShelfWidget()
->status_area_widget()
->GetWindowBoundsInScreen()
.CenterPoint();
end = start + gfx::Vector2d(0, -80);
GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
kNumScrollSteps);
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 1);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 2);
// Swipe down from the hotseat to hide it.
start = hotseat_bounds.top_center();
end = start + gfx::Vector2d(0, 80);
GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
kNumScrollSteps);
ASSERT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 2);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 2);
// Swipe up from the left part of the shelf (the home/back button).
start = GetShelfWidget()
->navigation_widget()
->GetWindowBoundsInScreen()
.CenterPoint();
end = start + gfx::Vector2d(0, -80);
GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
kNumScrollSteps);
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 2);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 3);
}
// Tests that swiping up on the hotseat does nothing.
TEST_P(HotseatWidgetTest, SwipeUpOnHotseatBackgroundDoesNothing) {
GetPrimaryShelf()->SetAutoHideBehavior(GetParam());
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
base::HistogramTester histogram_tester;
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 0);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 0);
// Swipe up on the shelf to show the hotseat.
EXPECT_FALSE(Shell::Get()->app_list_controller()->IsVisible());
SwipeUpOnShelf();
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 0);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 1);
if (GetParam() == ShelfAutoHideBehavior::kAlways)
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, GetPrimaryShelf()->GetAutoHideState());
// Swipe up on the Hotseat (parent of ShelfView) does nothing.
gfx::Point start(GetPrimaryShelf()
->shelf_widget()
->hotseat_widget()
->GetWindowBoundsInScreen()
.top_center());
const gfx::Point end(start + gfx::Vector2d(0, -300));
const base::TimeDelta kTimeDelta = base::TimeDelta::FromMilliseconds(100);
const int kNumScrollSteps = 4;
GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
kNumScrollSteps);
EXPECT_FALSE(Shell::Get()->app_list_controller()->IsVisible());
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
if (GetParam() == ShelfAutoHideBehavior::kAlways)
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, GetPrimaryShelf()->GetAutoHideState());
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 0);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 1);
}
// Tests that tapping an active window with an extended hotseat results in a
// hidden hotseat.
TEST_P(HotseatWidgetTest, TappingActiveWindowHidesHotseat) {
GetPrimaryShelf()->SetAutoHideBehavior(GetParam());
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
base::HistogramTester histogram_tester;
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 0);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 0);
// Swipe up on the shelf to show the hotseat.
SwipeUpOnShelf();
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 0);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 1);
// Tap the shelf background, nothing should happen.
gfx::Rect display_bounds =
display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
gfx::Point tap_point = display_bounds.bottom_center();
GetEventGenerator()->GestureTapAt(tap_point);
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
if (GetParam() == ShelfAutoHideBehavior::kAlways)
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, GetPrimaryShelf()->GetAutoHideState());
// Tap the active window, the hotseat should hide.
tap_point.Offset(0, -200);
GetEventGenerator()->GestureTapAt(tap_point);
EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
if (GetParam() == ShelfAutoHideBehavior::kAlways)
EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, GetPrimaryShelf()->GetAutoHideState());
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 0);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 1);
}
// Tests that gesture dragging an active window hides the hotseat.
TEST_P(HotseatWidgetTest, GestureDraggingActiveWindowHidesHotseat) {
GetPrimaryShelf()->SetAutoHideBehavior(GetParam());
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
base::HistogramTester histogram_tester;
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 0);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 0);
// Swipe up on the shelf to show the hotseat.
SwipeUpOnShelf();
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 0);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 1);
if (GetParam() == ShelfAutoHideBehavior::kAlways)
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, GetPrimaryShelf()->GetAutoHideState());
// Gesture drag on the active window, the hotseat should hide.
gfx::Rect display_bounds =
display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
gfx::Point start = display_bounds.bottom_center();
start.Offset(0, -200);
gfx::Point end = start;
end.Offset(0, -200);
GetEventGenerator()->GestureScrollSequence(
start, end, base::TimeDelta::FromMilliseconds(10), 4);
EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
if (GetParam() == ShelfAutoHideBehavior::kAlways)
EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, GetPrimaryShelf()->GetAutoHideState());
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 0);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 1);
}
// Tests that a swipe up on the shelf shows the hotseat while in split view.
TEST_F(HotseatWidgetTest, SwipeUpOnShelfShowsHotseatInSplitView) {
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
base::HistogramTester histogram_tester;
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 0);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 0);
// Go into split view mode by first going into overview, and then snapping
// the open window on one side.
OverviewController* overview_controller = Shell::Get()->overview_controller();
overview_controller->StartOverview();
SplitViewController* split_view_controller =
SplitViewController::Get(Shell::GetPrimaryRootWindow());
split_view_controller->SnapWindow(window.get(), SplitViewController::LEFT);
EXPECT_TRUE(split_view_controller->InSplitViewMode());
// We should still be able to drag up the hotseat.
SwipeUpOnShelf();
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 0);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 1);
}
// Tests that releasing the hotseat gesture below the threshold results in a
// kHidden hotseat when the shelf is shown.
TEST_F(HotseatWidgetTest, ReleasingSlowDragBelowThreshold) {
GetPrimaryShelf()->SetAutoHideBehavior(ShelfAutoHideBehavior::kNever);
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
base::HistogramTester histogram_tester;
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 0);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 0);
gfx::Rect display_bounds =
display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
const gfx::Point start(display_bounds.bottom_center());
const int hotseat_size = GetPrimaryShelf()
->shelf_widget()
->hotseat_widget()
->GetWindowBoundsInScreen()
.height();
const gfx::Point end(start + gfx::Vector2d(0, -hotseat_size / 2 + 1));
const base::TimeDelta kTimeDelta = base::TimeDelta::FromMilliseconds(1000);
const int kNumScrollSteps = 4;
GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
kNumScrollSteps);
EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 0);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 0);
}
// Tests that releasing the hotseat gesture above the threshold results in a
// kExtended hotseat.
TEST_P(HotseatWidgetTest, ReleasingSlowDragAboveThreshold) {
GetPrimaryShelf()->SetAutoHideBehavior(GetParam());
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
base::HistogramTester histogram_tester;
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 0);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 0);
gfx::Rect display_bounds =
display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
const gfx::Point start(display_bounds.bottom_center());
const int hotseat_size = GetPrimaryShelf()
->shelf_widget()
->hotseat_widget()
->GetWindowBoundsInScreen()
.height();
const gfx::Point end(start + gfx::Vector2d(0, -hotseat_size * 3.0f / 2.0f));
const base::TimeDelta kTimeDelta = base::TimeDelta::FromMilliseconds(1000);
const int kNumScrollSteps = 4;
GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
kNumScrollSteps);
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
if (GetParam() == ShelfAutoHideBehavior::kAlways)
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, GetPrimaryShelf()->GetAutoHideState());
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeDownToHide, 0);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 1);
}
// Tests that showing overview after showing the hotseat results in only one
// animation, to |kExtended|.
TEST_P(HotseatWidgetTest, ShowingOverviewFromShownAnimatesOnce) {
GetPrimaryShelf()->SetAutoHideBehavior(GetParam());
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
std::unique_ptr<HotseatStateWatcher> state_watcher_ =
std::make_unique<HotseatStateWatcher>(GetShelfLayoutManager());
SwipeUpOnShelf();
ASSERT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
const gfx::Point overview_button_center = GetPrimaryShelf()
->shelf_widget()
->status_area_widget()
->overview_button_tray()
->GetBoundsInScreen()
.CenterPoint();
GetEventGenerator()->GestureTapAt(overview_button_center);
state_watcher_->CheckEqual({HotseatState::kExtended});
}
// Tests that the hotseat is not flush with the bottom of the screen when home
// launcher is showing.
TEST_P(HotseatWidgetTest, HotseatNotFlushWhenHomeLauncherShowing) {
GetPrimaryShelf()->SetAutoHideBehavior(GetParam());
TabletModeControllerTestApi().EnterTabletMode();
const int display_height =
display::Screen::GetScreen()->GetPrimaryDisplay().bounds().height();
const int hotseat_bottom = GetPrimaryShelf()
->shelf_widget()
->hotseat_widget()
->GetWindowBoundsInScreen()
.bottom();
EXPECT_LT(hotseat_bottom, display_height);
}
// Tests that home -> overview results in only one hotseat state change.
TEST_P(HotseatWidgetTest, HomeToOverviewChangesStateOnce) {
GetPrimaryShelf()->SetAutoHideBehavior(GetParam());
TabletModeControllerTestApi().EnterTabletMode();
// First, try with no windows open.
const gfx::Point overview_button_center = GetPrimaryShelf()
->shelf_widget()
->status_area_widget()
->overview_button_tray()
->GetBoundsInScreen()
.CenterPoint();
{
HotseatStateWatcher watcher(GetShelfLayoutManager());
OverviewAnimationWaiter waiter;
GetEventGenerator()->GestureTapAt(overview_button_center);
waiter.Wait();
watcher.CheckEqual({HotseatState::kExtended});
}
// Open a window, then open the home launcher.
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
if (GetParam() == ShelfAutoHideBehavior::kAlways)
SwipeUpOnShelf();
views::View* home_button =
GetPrimaryShelf()->shelf_widget()->navigation_widget()->GetHomeButton();
GetEventGenerator()->GestureTapAt(
home_button->GetBoundsInScreen().CenterPoint());
GetAppListTestHelper()->CheckVisibility(true);
// Activate overview and expect the hotseat only changes state to extended.
{
HotseatStateWatcher watcher(GetShelfLayoutManager());
OverviewAnimationWaiter waiter;
GetEventGenerator()->GestureTapAt(overview_button_center);
waiter.Wait();
watcher.CheckEqual({HotseatState::kExtended});
}
}
// Tests that home -> in-app results in only one state change.
TEST_P(HotseatWidgetTest, HomeToInAppChangesStateOnce) {
GetPrimaryShelf()->SetAutoHideBehavior(GetParam());
TabletModeControllerTestApi().EnterTabletMode();
// Go to in-app, the hotseat should hide.
HotseatStateWatcher watcher(GetShelfLayoutManager());
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
watcher.CheckEqual({HotseatState::kHidden});
}
// Tests that in-app -> home via closing the only window, swiping from the
// bottom of the shelf, and tapping the home launcher button results in only one
// state change.
TEST_P(HotseatWidgetTest, InAppToHomeChangesStateOnce) {
GetPrimaryShelf()->SetAutoHideBehavior(GetParam());
TabletModeControllerTestApi().EnterTabletMode();
// Go to in-app with an extended hotseat.
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
SwipeUpOnShelf();
// Press the home button, the hotseat should transition directly to kShown.
{
HotseatStateWatcher watcher(GetShelfLayoutManager());
views::View* home_button =
GetPrimaryShelf()->shelf_widget()->navigation_widget()->GetHomeButton();
GetEventGenerator()->GestureTapAt(
home_button->GetBoundsInScreen().CenterPoint());
watcher.CheckEqual({HotseatState::kShown});
}
// Go to in-app.
window->Show();
wm::ActivateWindow(window.get());
// Extend the hotseat, then Swipe up to go home, the hotseat should transition
// directly to kShown.
SwipeUpOnShelf();
{
ui::ScopedAnimationDurationScaleMode regular_animations(
ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
HotseatStateWatcher watcher(GetShelfLayoutManager());
FlingUpOnShelf();
watcher.CheckEqual({HotseatState::kShown});
// Wait for the window animation to complete, and verify the hotseat state
// remained kShown.
ShellTestApi().WaitForWindowFinishAnimating(window.get());
watcher.CheckEqual({HotseatState::kShown});
}
// Nothing left to test for autohidden shelf.
if (GetParam() == ShelfAutoHideBehavior::kAlways)
return;
// Go to in-app and do not extend the hotseat.
window->Show();
wm::ActivateWindow(window.get());
// Press the home button, the hotseat should transition directly to kShown.
{
HotseatStateWatcher watcher(GetShelfLayoutManager());
views::View* home_button =
GetPrimaryShelf()->shelf_widget()->navigation_widget()->GetHomeButton();
GetEventGenerator()->GestureTapAt(
home_button->GetBoundsInScreen().CenterPoint());
watcher.CheckEqual({HotseatState::kShown});
}
}
// Tests that transitioning from overview to home while a transition from home
// to overview is still in progress ends up with hotseat in kShown state (and in
// app shelf not visible).
TEST_P(HotseatWidgetTest, HomeToOverviewAndBack) {
GetPrimaryShelf()->SetAutoHideBehavior(GetParam());
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
WindowState::Get(window.get())->Minimize();
// Start going to overview - hotseat should transition to extended state.
HotseatStateWatcher watcher(GetShelfLayoutManager());
{
gfx::Point overview_button_center = GetPrimaryShelf()
->shelf_widget()
->status_area_widget()
->overview_button_tray()
->GetBoundsInScreen()
.CenterPoint();
ui::ScopedAnimationDurationScaleMode regular_animations(
ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
GetEventGenerator()->GestureTapAt(overview_button_center);
watcher.CheckEqual({HotseatState::kExtended});
}
OverviewController* overview_controller = Shell::Get()->overview_controller();
EXPECT_TRUE(overview_controller->InOverviewSession());
views::View* home_button =
GetPrimaryShelf()->shelf_widget()->navigation_widget()->GetHomeButton();
GetEventGenerator()->GestureTapAt(
home_button->GetBoundsInScreen().CenterPoint());
GetAppListTestHelper()->CheckVisibility(true);
EXPECT_FALSE(overview_controller->InOverviewSession());
EXPECT_FALSE(ShelfConfig::Get()->is_in_app());
watcher.CheckEqual({HotseatState::kExtended, HotseatState::kShown});
}
TEST_P(HotseatWidgetTest, InAppToOverviewAndBack) {
GetPrimaryShelf()->SetAutoHideBehavior(GetParam());
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
// Start watching hotseat state before swipping up the shelf, so hotseat
// change expectation match for both auto-hidden and always-shown shelf.
HotseatStateWatcher watcher(GetShelfLayoutManager());
// Make sure shelf (and overview button) are visible - this is moves the
// hotseat into kExtended state.
if (GetParam() == ShelfAutoHideBehavior::kAlways)
SwipeUpOnShelf();
gfx::Point overview_button_center = GetPrimaryShelf()
->shelf_widget()
->status_area_widget()
->overview_button_tray()
->GetBoundsInScreen()
.CenterPoint();
// Start going to overview - use non zero animation so transition is not
// immediate.
{
ui::ScopedAnimationDurationScaleMode regular_animations(
ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
GetEventGenerator()->GestureTapAt(overview_button_center);
}
OverviewController* overview_controller = Shell::Get()->overview_controller();
EXPECT_TRUE(overview_controller->InOverviewSession());
GetAppListTestHelper()->CheckVisibility(false);
// Hotseat should be extended as overview is starting.
watcher.CheckEqual({HotseatState::kExtended});
// Tapping overview button again should go back to the app window.
GetEventGenerator()->GestureTapAt(overview_button_center);
EXPECT_FALSE(overview_controller->InOverviewSession());
GetAppListTestHelper()->CheckVisibility(false);
EXPECT_TRUE(ShelfConfig::Get()->is_in_app());
// The hotseat is expected to be hidden.
watcher.CheckEqual({HotseatState::kExtended, HotseatState::kHidden});
}
// Tests transition to home screen initiated while transition from app window to
// overview is in progress.
TEST_P(HotseatWidgetTest, GoHomeDuringInAppToOverviewTransition) {
GetPrimaryShelf()->SetAutoHideBehavior(GetParam());
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
// Start watching hotseat state before swipping up the shelf, so hotseat
// change expectation match for both auto-hidden and always-shown shelf.
HotseatStateWatcher watcher(GetShelfLayoutManager());
// Make sure shelf (and overview button) are visible - this is moves the
// hotseat into kExtended state.
if (GetParam() == ShelfAutoHideBehavior::kAlways)
SwipeUpOnShelf();
gfx::Point overview_button_center = GetPrimaryShelf()
->shelf_widget()
->status_area_widget()
->overview_button_tray()
->GetBoundsInScreen()
.CenterPoint();
// Start going to overview - use non zero animation so transition is not
// immediate.
{
ui::ScopedAnimationDurationScaleMode regular_animations(
ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
GetEventGenerator()->GestureTapAt(overview_button_center);
}
OverviewController* overview_controller = Shell::Get()->overview_controller();
EXPECT_TRUE(overview_controller->InOverviewSession());
GetAppListTestHelper()->CheckVisibility(false);
// Hotseat should be extended as overview is starting.
watcher.CheckEqual({HotseatState::kExtended});
// Press home button - expect transition to home (with hotseat in kShown
// state, and in app shelf hidden).
views::View* home_button =
GetPrimaryShelf()->shelf_widget()->navigation_widget()->GetHomeButton();
GetEventGenerator()->GestureTapAt(
home_button->GetBoundsInScreen().CenterPoint());
GetAppListTestHelper()->CheckVisibility(true);
EXPECT_FALSE(overview_controller->InOverviewSession());
EXPECT_FALSE(ShelfConfig::Get()->is_in_app());
watcher.CheckEqual({HotseatState::kExtended, HotseatState::kShown});
}
// Tests that in-app -> overview results in only one state change with an
// autohidden shelf.
TEST_F(HotseatWidgetTest, InAppToOverviewChangesStateOnceAutohiddenShelf) {
GetPrimaryShelf()->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
TabletModeControllerTestApi().EnterTabletMode();
// Test going to overview mode using the controller from an autohide hidden
// shelf. Go to in-app.
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
{
HotseatStateWatcher watcher(GetShelfLayoutManager());
// Enter overview by using the controller.
OverviewAnimationWaiter waiter;
Shell::Get()->overview_controller()->StartOverview();
waiter.Wait();
watcher.CheckEqual({HotseatState::kExtended});
}
{
OverviewAnimationWaiter waiter;
Shell::Get()->overview_controller()->EndOverview();
waiter.Wait();
}
// Test in-app -> overview again with the autohide shown shelf.
EXPECT_TRUE(ShelfConfig::Get()->is_in_app());
EXPECT_EQ(ShelfAutoHideState::SHELF_AUTO_HIDE_HIDDEN,
GetShelfLayoutManager()->auto_hide_state());
SwipeUpOnShelf();
{
HotseatStateWatcher watcher(GetShelfLayoutManager());
// Enter overview by using the controller.
OverviewAnimationWaiter waiter;
Shell::Get()->overview_controller()->StartOverview();
waiter.Wait();
watcher.CheckEqual({});
EXPECT_EQ(HotseatState::kExtended,
GetShelfLayoutManager()->hotseat_state());
}
}
// Tests that going between Applist and overview in tablet mode with no windows
// results in no work area change.
TEST_F(HotseatWidgetTest,
WorkAreaDoesNotUpdateAppListToFromOverviewWithNoWindow) {
TabletModeControllerTestApi().EnterTabletMode();
DisplayWorkAreaChangeCounter counter;
{
OverviewAnimationWaiter waiter;
Shell::Get()->overview_controller()->StartOverview();
waiter.Wait();
}
EXPECT_EQ(0, counter.count());
{
OverviewAnimationWaiter waiter;
Shell::Get()->overview_controller()->EndOverview();
waiter.Wait();
}
EXPECT_EQ(0, counter.count());
}
// Tests that switching between AppList and overview with a window results in no
// work area change.
TEST_F(HotseatWidgetTest,
WorkAreaDoesNotUpdateAppListToFromOverviewWithWindow) {
DisplayWorkAreaChangeCounter counter;
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
ASSERT_EQ(1, counter.count());
views::View* home_button =
GetPrimaryShelf()->shelf_widget()->navigation_widget()->GetHomeButton();
GetEventGenerator()->GestureTapAt(
home_button->GetBoundsInScreen().CenterPoint());
{
OverviewAnimationWaiter waiter;
gfx::Point overview_button_center = GetPrimaryShelf()
->shelf_widget()
->status_area_widget()
->overview_button_tray()
->GetBoundsInScreen()
.CenterPoint();
GetEventGenerator()->GestureTapAt(overview_button_center);
waiter.Wait();
}
EXPECT_EQ(1, counter.count());
{
OverviewAnimationWaiter waiter;
// Overview button has moved a bit now that the shelf is in-app.
gfx::Point overview_button_center = GetPrimaryShelf()
->shelf_widget()
->status_area_widget()
->overview_button_tray()
->GetBoundsInScreen()
.CenterPoint();
GetEventGenerator()->GestureTapAt(overview_button_center);
waiter.Wait();
}
EXPECT_EQ(1, counter.count());
}
// Tests that switching between AppList and an active window does not update the
// work area.
TEST_F(HotseatWidgetTest, WorkAreaDoesNotUpdateOpenWindowToFromAppList) {
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
ASSERT_TRUE(ShelfConfig::Get()->is_in_app());
// Go to the home launcher, work area should not update.
DisplayWorkAreaChangeCounter counter;
views::View* home_button =
GetPrimaryShelf()->shelf_widget()->navigation_widget()->GetHomeButton();
GetEventGenerator()->GestureTapAt(
home_button->GetBoundsInScreen().CenterPoint());
GetAppListTestHelper()->CheckVisibility(true);
EXPECT_EQ(0, counter.count());
// Go back to the window, work area should not update.
wm::ActivateWindow(window.get());
EXPECT_TRUE(ShelfConfig::Get()->is_in_app());
EXPECT_EQ(0, counter.count());
}
// Tests that switching between overview and an active window does not update
// the work area.
TEST_F(HotseatWidgetTest, WorkAreaDoesNotUpdateOpenWindowToFromOverview) {
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
ASSERT_TRUE(ShelfConfig::Get()->is_in_app());
// Go to overview, there should not be a work area update.
DisplayWorkAreaChangeCounter counter;
{
OverviewAnimationWaiter waiter;
gfx::Point overview_button_center = GetPrimaryShelf()
->shelf_widget()
->status_area_widget()
->overview_button_tray()
->GetBoundsInScreen()
.CenterPoint();
GetEventGenerator()->GestureTapAt(overview_button_center);
waiter.Wait();
}
EXPECT_EQ(0, counter.count());
// Go back to the app, there should not be a work area update.
wm::ActivateWindow(window.get());
EXPECT_TRUE(ShelfConfig::Get()->is_in_app());
EXPECT_EQ(0, counter.count());
}
// Tests that the shelf opaque background is properly updated after a tablet
// mode transition with no apps.
TEST_F(HotseatWidgetTest, ShelfBackgroundNotVisibleInTabletModeNoApps) {
TabletModeControllerTestApi().EnterTabletMode();
EXPECT_FALSE(GetShelfWidget()->GetOpaqueBackground()->visible());
}
// Tests that the shelf opaque background is properly updated after a tablet
// mode transition with no apps with dense shelf.
TEST_F(HotseatWidgetTest, DenseShelfBackgroundNotVisibleInTabletModeNoApps) {
UpdateDisplay("300x1000");
TabletModeControllerTestApi().EnterTabletMode();
EXPECT_FALSE(GetShelfWidget()->GetOpaqueBackground()->visible());
}
// Tests that the hotseat is extended if focused with a keyboard.
TEST_F(HotseatWidgetTest, ExtendHotseatIfFocusedWithKeyboard) {
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
ASSERT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
// Focus the shelf. Hotseat should now show extended.
GetPrimaryShelf()->shelf_focus_cycler()->FocusShelf(false /* last_element */);
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
// Focus the navigation widget. Hotseat should now hide, as it was
// automatically extended by focusing it.
GetPrimaryShelf()->shelf_focus_cycler()->FocusNavigation(
false /* last_element */);
EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
// Now swipe up to show the shelf and then focus it with the keyboard. Hotseat
// should keep extended.
SwipeUpOnShelf();
GetPrimaryShelf()->shelf_focus_cycler()->FocusShelf(false /* last_element */);
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
// Now focus the navigation widget again. Hotseat should remain shown, as it
// was manually extended.
GetPrimaryShelf()->shelf_focus_cycler()->FocusNavigation(
false /* last_element */);
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
}
// Tests that if the hotseat was hidden while being focused, doing a traversal
// focus on the next element brings it up again.
TEST_F(HotseatWidgetTest, SwipeDownOnFocusedHotseat) {
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
ShelfTestUtil::AddAppShortcut("app_id_1", TYPE_APP);
ShelfTestUtil::AddAppShortcut("app_id_2", TYPE_APP);
ASSERT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
// Focus the shelf, then swipe down on the shelf to hide it. Hotseat should be
// hidden.
GetPrimaryShelf()->shelf_focus_cycler()->FocusShelf(false /* last_element */);
gfx::Rect hotseat_bounds =
GetShelfWidget()->hotseat_widget()->GetWindowBoundsInScreen();
gfx::Point start = hotseat_bounds.top_center();
gfx::Point end = start + gfx::Vector2d(0, 80);
GetEventGenerator()->GestureScrollSequence(
start, end, base::TimeDelta::FromMilliseconds(100), 4 /*scroll_steps*/);
EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
// Focus to the next element in the hotseat. The hotseat should show again.
GetEventGenerator()->PressKey(ui::VKEY_TAB, 0);
GetEventGenerator()->ReleaseKey(ui::VKEY_TAB, 0);
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
}
// Tests that in overview, we can still exit by clicking on the hotseat if the
// point is not on the visible area.
TEST_F(HotseatWidgetTest, ExitOverviewWithClickOnHotseat) {
std::unique_ptr<aura::Window> window1 = AshTestBase::CreateTestWindow();
ShelfTestUtil::AddAppShortcut("app_id_1", TYPE_APP);
TabletModeControllerTestApi().EnterTabletMode();
ASSERT_TRUE(TabletModeControllerTestApi().IsTabletModeStarted());
ASSERT_FALSE(WindowState::Get(window1.get())->IsMinimized());
// Enter overview, hotseat is visible. Choose the point to the farthest left.
// This point will not be visible.
auto* overview_controller = Shell::Get()->overview_controller();
auto* hotseat_widget = GetShelfWidget()->hotseat_widget();
overview_controller->StartOverview();
ASSERT_TRUE(overview_controller->InOverviewSession());
ASSERT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
gfx::Point far_left_point =
hotseat_widget->GetWindowBoundsInScreen().left_center();
// Tests that on clicking, we exit overview and all windows are minimized.
GetEventGenerator()->set_current_screen_location(far_left_point);
GetEventGenerator()->ClickLeftButton();
EXPECT_EQ(HotseatState::kShown, GetShelfLayoutManager()->hotseat_state());
EXPECT_TRUE(WindowState::Get(window1.get())->IsMinimized());
EXPECT_FALSE(overview_controller->InOverviewSession());
}
// Hides the hotseat if the hotseat is in kExtendedMode and the system tray
// is about to show (see https://crbug.com/1028321).
TEST_F(HotseatWidgetTest, DismissHotseatWhenSystemTrayShows) {
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
SwipeUpOnShelf();
ASSERT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
// Activates the system tray when hotseat is in kExtended mode.
StatusAreaWidget* status_area_widget = GetShelfWidget()->status_area_widget();
const gfx::Point status_area_widget_center =
status_area_widget->GetNativeView()->GetBoundsInScreen().CenterPoint();
GetEventGenerator()->GestureTapAt(status_area_widget_center);
// Expects that the system tray shows and the hotseat is hidden.
EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
EXPECT_TRUE(status_area_widget->unified_system_tray()->IsBubbleShown());
}
// Tests that the work area updates once each when going to/from tablet mode
// with no windows open.
TEST_F(HotseatWidgetTest, WorkAreaUpdatesClamshellToFromHomeLauncherNoWindows) {
DisplayWorkAreaChangeCounter counter;
TabletModeControllerTestApi().EnterTabletMode();
EXPECT_EQ(1, counter.count());
TabletModeControllerTestApi().LeaveTabletMode();
EXPECT_EQ(2, counter.count());
}
// Tests that the work area changes just once when opening a window in tablet
// mode.
TEST_F(HotseatWidgetTest, OpenWindowInTabletModeChangesWorkArea) {
DisplayWorkAreaChangeCounter counter;
TabletModeControllerTestApi().EnterTabletMode();
ASSERT_EQ(1, counter.count());
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
EXPECT_EQ(1, counter.count());
}
// Tests that going to and from tablet mode with an open window results in a
// work area change.
TEST_F(HotseatWidgetTest, ToFromTabletModeWithWindowChangesWorkArea) {
DisplayWorkAreaChangeCounter counter;
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
TabletModeControllerTestApi().EnterTabletMode();
EXPECT_EQ(1, counter.count());
TabletModeControllerTestApi().LeaveTabletMode();
EXPECT_EQ(2, counter.count());
}
// Tests that the hotseat is flush with the bottom of the screen when in
// clamshell mode and the shelf is oriented on the bottom.
TEST_P(HotseatWidgetTest, HotseatFlushWithScreenBottomInClamshell) {
GetPrimaryShelf()->SetAutoHideBehavior(GetParam());
const int display_height =
display::Screen::GetScreen()->GetPrimaryDisplay().bounds().height();
const int hotseat_bottom = GetPrimaryShelf()
->shelf_widget()
->hotseat_widget()
->GetWindowBoundsInScreen()
.bottom();
EXPECT_EQ(hotseat_bottom, display_height);
}
// Tests that when hotseat and drag-window-to-overview features are both
// enabled, HomeLauncherGestureHandler can receive and process events properly.
TEST_P(HotseatWidgetTest, DragActiveWindowInTabletMode) {
base::test::ScopedFeatureList scoped_features;
scoped_features.InitAndEnableFeature(
features::kDragFromShelfToHomeOrOverview);
GetPrimaryShelf()->SetAutoHideBehavior(GetParam());
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
// Swipe up to bring up the hotseat first.
SwipeUpOnShelf();
ASSERT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
// Now swipe up again to start drag the active window.
ui::test::EventGenerator* generator = GetEventGenerator();
const gfx::Rect bottom_shelf_bounds =
GetShelfWidget()->GetWindowBoundsInScreen();
generator->MoveMouseTo(bottom_shelf_bounds.CenterPoint());
generator->PressTouch();
EXPECT_TRUE(window->layer()->transform().IsIdentity());
// Drag upward, test the window transform changes.
const gfx::Rect display_bounds =
display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
generator->MoveTouch(display_bounds.CenterPoint());
const gfx::Transform upward_transform = window->layer()->transform();
EXPECT_FALSE(upward_transform.IsIdentity());
// Drag downwad, test the window tranfrom changes.
generator->MoveTouch(display_bounds.bottom_center());
const gfx::Transform downward_transform = window->layer()->transform();
EXPECT_NE(upward_transform, downward_transform);
generator->ReleaseTouch();
EXPECT_TRUE(window->layer()->transform().IsIdentity());
}
// Tests that when hotseat and drag-window-to-overview features are both
// enabled, hotseat is not extended after dragging a window to overview, and
// then activating the window.
TEST_P(HotseatWidgetTest, ExitingOvervieHidesHotseat) {
base::test::ScopedFeatureList scoped_features;
scoped_features.InitAndEnableFeature(
features::kDragFromShelfToHomeOrOverview);
const ShelfAutoHideBehavior auto_hide_behavior = GetParam();
GetPrimaryShelf()->SetAutoHideBehavior(auto_hide_behavior);
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
// If the shelf is auto-hidden, swipe up to bring up shelf and hotseat first
// (otherwise, the window drag to overview will not be handled).
if (auto_hide_behavior == ShelfAutoHideBehavior::kAlways) {
SwipeUpOnShelf();
ASSERT_EQ(HotseatState::kExtended,
GetShelfLayoutManager()->hotseat_state());
}
// Swipe up to start dragging the active window.
const gfx::Rect bottom_shelf_bounds =
GetShelfWidget()->GetWindowBoundsInScreen();
StartScroll(bottom_shelf_bounds.CenterPoint());
// Drag upward, to the center of the screen, and release (this should enter
// the overview).
const gfx::Rect display_bounds =
display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
UpdateScroll(display_bounds.CenterPoint().y() -
bottom_shelf_bounds.CenterPoint().y());
// Small scroll update, to simulate the user holding the pointer.
UpdateScroll(2);
DragWindowFromShelfController* window_drag_controller =
GetShelfLayoutManager()->window_drag_controller_for_testing();
ASSERT_TRUE(window_drag_controller);
DragWindowFromShelfControllerTestApi test_api;
test_api.WaitUntilOverviewIsShown(window_drag_controller);
EndScroll(/*is_fling=*/false, 0.f);
OverviewController* overview_controller = Shell::Get()->overview_controller();
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
EXPECT_TRUE(overview_controller->InOverviewSession());
// Activate the window - the overview session should exit, and hotseat should
// be hidden.
wm::ActivateWindow(window.get());
EXPECT_FALSE(overview_controller->InOverviewSession());
EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
}
// Tests that failing to drag the maximized window to overview mode results in
// an extended hotseat.
TEST_P(HotseatWidgetTest, FailingOverviewDragResultsInExtendedHotseat) {
base::test::ScopedFeatureList scoped_features;
scoped_features.InitAndEnableFeature(
features::kDragFromShelfToHomeOrOverview);
const ShelfAutoHideBehavior auto_hide_behavior = GetParam();
GetPrimaryShelf()->SetAutoHideBehavior(auto_hide_behavior);
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
// If the shelf is auto-hidden, swipe up to bring up shelf and hotseat first
// (otherwise, the window drag to overview will not be handled).
if (auto_hide_behavior == ShelfAutoHideBehavior::kAlways) {
SwipeUpOnShelf();
ASSERT_EQ(HotseatState::kExtended,
GetShelfLayoutManager()->hotseat_state());
}
// Swipe up to start dragging the active window.
const gfx::Rect bottom_shelf_bounds =
GetShelfWidget()->GetWindowBoundsInScreen();
StartScroll(bottom_shelf_bounds.top_center());
// Drag upward, a bit past the hotseat extended height but not enough to go to
// overview.
const int extended_hotseat_distance_from_top_of_shelf =
ShelfConfig::Get()->hotseat_bottom_padding() +
ShelfConfig::Get()->hotseat_size();
UpdateScroll(-extended_hotseat_distance_from_top_of_shelf - 30);
EndScroll(/*is_fling=*/false, 0.f);
ASSERT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
}
// Tests that hotseat remains in extended state while in overview mode when
// flinging the shelf up or down.
TEST_P(HotseatWidgetTest, SwipeOnHotseatInOverview) {
GetPrimaryShelf()->SetAutoHideBehavior(GetParam());
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
OverviewController* overview_controller = Shell::Get()->overview_controller();
overview_controller->StartOverview();
Shelf* const shelf = GetPrimaryShelf();
SwipeUpOnShelf();
EXPECT_TRUE(overview_controller->InOverviewSession());
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
if (GetParam() == ShelfAutoHideBehavior::kAlways) {
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
} else {
EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
}
// Drag from the hotseat to the bezel, the hotseat should remain in extended
// state.
DragHotseatDownToBezel();
EXPECT_TRUE(overview_controller->InOverviewSession());
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
if (GetParam() == ShelfAutoHideBehavior::kAlways) {
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
} else {
EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
}
SwipeUpOnShelf();
EXPECT_TRUE(overview_controller->InOverviewSession());
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
if (GetParam() == ShelfAutoHideBehavior::kAlways) {
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
} else {
EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
}
}
TEST_P(HotseatWidgetTest, SwipeOnHotseatInSplitViewWithOverview) {
Shelf* const shelf = GetPrimaryShelf();
shelf->SetAutoHideBehavior(GetParam());
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
OverviewController* overview_controller = Shell::Get()->overview_controller();
overview_controller->StartOverview();
SplitViewController* split_view_controller =
SplitViewController::Get(Shell::GetPrimaryRootWindow());
split_view_controller->SnapWindow(window.get(), SplitViewController::LEFT);
SwipeUpOnShelf();
EXPECT_TRUE(split_view_controller->InSplitViewMode());
EXPECT_TRUE(overview_controller->InOverviewSession());
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
if (GetParam() == ShelfAutoHideBehavior::kAlways) {
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
} else {
EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
}
DragHotseatDownToBezel();
EXPECT_TRUE(split_view_controller->InSplitViewMode());
EXPECT_TRUE(overview_controller->InOverviewSession());
EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
if (GetParam() == ShelfAutoHideBehavior::kAlways) {
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
} else {
EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
}
SwipeUpOnShelf();
EXPECT_TRUE(split_view_controller->InSplitViewMode());
EXPECT_TRUE(overview_controller->InOverviewSession());
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
if (GetParam() == ShelfAutoHideBehavior::kAlways) {
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
} else {
EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
}
}
TEST_P(HotseatWidgetTest, SwipeOnHotseatInSplitView) {
Shelf* const shelf = GetPrimaryShelf();
shelf->SetAutoHideBehavior(GetParam());
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window1 =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
std::unique_ptr<aura::Window> window2 =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window1.get());
SplitViewController* split_view_controller =
SplitViewController::Get(Shell::GetPrimaryRootWindow());
split_view_controller->SnapWindow(window1.get(), SplitViewController::LEFT);
split_view_controller->SnapWindow(window2.get(), SplitViewController::RIGHT);
EXPECT_TRUE(split_view_controller->InSplitViewMode());
SwipeUpOnShelf();
EXPECT_TRUE(split_view_controller->InSplitViewMode());
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
if (GetParam() == ShelfAutoHideBehavior::kAlways) {
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
} else {
EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
}
DragHotseatDownToBezel();
EXPECT_TRUE(split_view_controller->InSplitViewMode());
EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
if (GetParam() == ShelfAutoHideBehavior::kAlways) {
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
} else {
EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
}
SwipeUpOnShelf();
EXPECT_TRUE(split_view_controller->InSplitViewMode());
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
if (GetParam() == ShelfAutoHideBehavior::kAlways) {
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
} else {
EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
}
}
// Tests that swiping downward, towards the bezel, from a variety of points
// results in hiding the hotseat.
TEST_F(HotseatWidgetTest, HotseatHidesWhenSwipedToBezel) {
// Go to in-app shelf and extend the hotseat.
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
SwipeUpOnShelf();
// Drag from the hotseat to the bezel, the hotseat should hide.
DragHotseatDownToBezel();
EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
// Reset the hotseat and swipe from the center of the hotseat, it should hide.
SwipeUpOnShelf();
gfx::Rect shelf_widget_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
gfx::Rect hotseat_bounds =
GetShelfWidget()->hotseat_widget()->GetWindowBoundsInScreen();
gfx::Point start = hotseat_bounds.CenterPoint();
const gfx::Point end =
gfx::Point(shelf_widget_bounds.x() + shelf_widget_bounds.width() / 2,
shelf_widget_bounds.bottom() + 1);
const base::TimeDelta kTimeDelta = base::TimeDelta::FromMilliseconds(100);
const int kNumScrollSteps = 4;
GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
kNumScrollSteps);
EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
// Reset the hotseat and swipe from the bottom of the hotseat, it should hide.
SwipeUpOnShelf();
start = hotseat_bounds.bottom_center();
start.Offset(0, -1);
GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
kNumScrollSteps);
EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
// Reset the hotseat and swipe from the center of the in-app shelf, it should
// hide.
SwipeUpOnShelf();
start = shelf_widget_bounds.CenterPoint();
GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
kNumScrollSteps);
EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
// Reset the hotseat and swipe from the bottom of the in-app shelf, it should
// hide.
SwipeUpOnShelf();
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
start = shelf_widget_bounds.bottom_center();
// The first few events which get sent to ShelfLayoutManager are
// ui::ET_TAP_DOWN, and ui::ET_GESTURE_START. After a few px we get
// ui::ET_GESTURE_SCROLL_UPDATE. Add 6 px of slop to get the first events out
// of the way, and 1 extra px to ensure we are not on the bottom edge of the
// display.
start.Offset(0, -7);
GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
kNumScrollSteps);
EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
}
// Tests that flinging up the in-app shelf should show the hotseat.
TEST_F(HotseatWidgetTest, FlingUpHotseatWithShortFling) {
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
GetAppListTestHelper()->CheckVisibility(false);
base::HistogramTester histogram_tester;
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 0);
// Scrolls the hotseat by a distance not sufficuent to trigger the action of
// entering home screen from the in-app shelf.
gfx::Rect display_bounds =
display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
const gfx::Point start(display_bounds.bottom_center());
const gfx::Point end(start + gfx::Vector2d(0, -20));
const int fling_speed =
DragWindowFromShelfController::kVelocityToHomeScreenThreshold + 1;
const int scroll_steps = 20;
base::TimeDelta scroll_time =
GetEventGenerator()->CalculateScrollDurationForFlingVelocity(
start, end, fling_speed, scroll_steps);
GetEventGenerator()->GestureScrollSequence(start, end, scroll_time,
scroll_steps);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
GetAppListTestHelper()->CheckVisibility(false);
histogram_tester.ExpectBucketCount(kHotseatGestureHistogramName,
InAppShelfGestures::kSwipeUpToShow, 1);
}
// Tests that flinging up the in-app shelf should show the home launcher if the
// gesture distance is long enough.
TEST_F(HotseatWidgetTest, FlingUpHotseatWithLongFling) {
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
GetAppListTestHelper()->CheckVisibility(false);
base::HistogramTester histogram_tester;
histogram_tester.ExpectBucketCount(
kHotseatGestureHistogramName,
InAppShelfGestures::kFlingUpToShowHomeScreen, 0);
// Scrolls the hotseat by the sufficient distance to trigger the action of
// entering home screen from the in-app shelf.
gfx::Rect display_bounds =
display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
const gfx::Point start(display_bounds.bottom_center());
const gfx::Point end(start + gfx::Vector2d(0, -200));
const int fling_speed =
DragWindowFromShelfController::kVelocityToHomeScreenThreshold + 1;
const int scroll_steps = 20;
base::TimeDelta scroll_time =
GetEventGenerator()->CalculateScrollDurationForFlingVelocity(
start, end, fling_speed, scroll_steps);
GetEventGenerator()->GestureScrollSequence(start, end, scroll_time,
scroll_steps);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(HotseatState::kShown, GetShelfLayoutManager()->hotseat_state());
GetAppListTestHelper()->CheckVisibility(true);
histogram_tester.ExpectBucketCount(
kHotseatGestureHistogramName,
InAppShelfGestures::kFlingUpToShowHomeScreen, 1);
}
// Tests that UpdateVisibilityState is ignored during a shelf drag. This
// prevents drag from getting interrupted.
TEST_F(HotseatWidgetTest, NoVisibilityStateUpdateDuringDrag) {
// Autohide the shelf, then start a shelf drag.
GetPrimaryShelf()->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
std::unique_ptr<aura::Window> window1 =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window1.get());
ASSERT_EQ(SHELF_AUTO_HIDE_HIDDEN, GetPrimaryShelf()->GetAutoHideState());
// Drag the autohidden shelf up a bit, then open a new window and activate it
// during the drag. The shelf state should not change.
gfx::Point start_drag = GetVisibleShelfWidgetBoundsInScreen().top_center();
GetEventGenerator()->set_current_screen_location(start_drag);
GetEventGenerator()->PressTouch();
GetEventGenerator()->MoveTouchBy(0, -2);
auto shelf_state_watcher = std::make_unique<ShelfStateWatcher>();
std::unique_ptr<aura::Window> window2 =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window2.get());
window2->SetBounds(gfx::Rect(0, 0, 200, 200));
EXPECT_EQ(0, shelf_state_watcher->state_change_count());
}
// Tests that popups don't activate the hotseat. (crbug.com/1018266)
TEST_F(HotseatWidgetTest, HotseatRemainsHiddenIfPopupLaunched) {
// Go to in-app shelf and extend the hotseat.
TabletModeControllerTestApi().EnterTabletMode();
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
SwipeUpOnShelf();
EXPECT_EQ(HotseatState::kExtended, GetShelfLayoutManager()->hotseat_state());
// Hide hotseat by clicking outside its bounds.
gfx::Rect hotseat_bounds =
GetShelfWidget()->hotseat_widget()->GetWindowBoundsInScreen();
gfx::Point start = hotseat_bounds.top_center();
GetEventGenerator()->GestureTapAt(gfx::Point(start.x() + 1, start.y() - 1));
EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
// Create a popup window and wait until all actions finish. The hotseat should
// remain hidden.
aura::Window* window_2 = CreateTestWindowInParent(window.get());
window_2->SetBounds(gfx::Rect(201, 0, 100, 100));
window_2->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
window_2->Show();
GetAppListTestHelper()->WaitUntilIdle();
EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
}
} // namespace ash
This source diff could not be displayed because it is too large. You can view the blob instead.
// Copyright (c) 2020 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/shelf/test/hotseat_state_watcher.h"
namespace ash {
HotseatStateWatcher::HotseatStateWatcher(
ShelfLayoutManager* shelf_layout_manager)
: shelf_layout_manager_(shelf_layout_manager) {
shelf_layout_manager_->AddObserver(this);
}
HotseatStateWatcher::~HotseatStateWatcher() {
shelf_layout_manager_->RemoveObserver(this);
}
void HotseatStateWatcher::OnHotseatStateChanged(HotseatState old_state,
HotseatState new_state) {
run_loop_.QuitWhenIdle();
state_changes_.push_back(new_state);
}
void HotseatStateWatcher::CheckEqual(std::vector<HotseatState> state_changes) {
EXPECT_EQ(state_changes_, state_changes);
}
void HotseatStateWatcher::WaitUntilStateChanged() {
run_loop_.Run();
}
} // namespace ash
// Copyright (c) 2020 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.
#ifndef ASH_SHELF_TEST_HOTSEAT_STATE_WATCHER_H_
#define ASH_SHELF_TEST_HOTSEAT_STATE_WATCHER_H_
#include "ash/shelf/shelf_layout_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace ash {
// Records HotseatState transitions.
class HotseatStateWatcher : public ShelfLayoutManagerObserver {
public:
explicit HotseatStateWatcher(ShelfLayoutManager* shelf_layout_manager);
~HotseatStateWatcher() override;
void OnHotseatStateChanged(HotseatState old_state,
HotseatState new_state) override;
void CheckEqual(std::vector<HotseatState> state_changes);
void WaitUntilStateChanged();
private:
ShelfLayoutManager* shelf_layout_manager_;
std::vector<HotseatState> state_changes_;
base::RunLoop run_loop_;
};
} // namespace ash
#endif // ASH_SHELF_TEST_HOTSEAT_STATE_WATCHER_H_
// Copyright (c) 2020 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/shelf/test/overview_animation_waiter.h"
#include "ash/wm/overview/overview_controller.h"
namespace ash {
OverviewAnimationWaiter::OverviewAnimationWaiter() {
Shell::Get()->overview_controller()->AddObserver(this);
}
OverviewAnimationWaiter::~OverviewAnimationWaiter() {
Shell::Get()->overview_controller()->RemoveObserver(this);
}
void OverviewAnimationWaiter::Wait() {
run_loop_.Run();
}
void OverviewAnimationWaiter::OnOverviewModeStartingAnimationComplete(
bool cancel) {
run_loop_.Quit();
}
void OverviewAnimationWaiter::OnOverviewModeEndingAnimationComplete(
bool cancel) {
run_loop_.Quit();
}
} // namespace ash
// Copyright (c) 2020 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.
#ifndef ASH_SHELF_TEST_OVERVIEW_ANIMATION_WAITER_H_
#define ASH_SHELF_TEST_OVERVIEW_ANIMATION_WAITER_H_
#include "ash/shell.h"
#include "ash/wm/overview/overview_observer.h"
#include "base/run_loop.h"
namespace ash {
class OverviewAnimationWaiter : public OverviewObserver {
public:
explicit OverviewAnimationWaiter();
~OverviewAnimationWaiter() override;
// Note this could only be called once because RunLoop would not run after
// Quit is called. Create a new instance if there's need to wait again.
void Wait();
// OverviewObserver:
void OnOverviewModeStartingAnimationComplete(bool cancel) override;
void OnOverviewModeEndingAnimationComplete(bool cancel) override;
private:
base::RunLoop run_loop_;
};
} // namespace ash
#endif // ASH_SHELF_TEST_OVERVIEW_ANIMATION_WAITER_H_
// Copyright (c) 2020 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/shelf/test/shelf_layout_manager_test_base.h"
#include "ash/home_screen/home_launcher_gesture_handler.h"
#include "ash/home_screen/home_screen_controller.h"
#include "ash/shelf/shelf_layout_manager.h"
#include "ash/shelf/shelf_view.h"
#include "ash/window_factory.h"
#include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h"
#include "ash/wm/window_state.h"
#include "ash/wm/workspace_controller.h"
#include "chromeos/constants/chromeos_switches.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/window_parenting_client.h"
#include "ui/aura/window.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/views/view.h"
#include "ui/wm/core/window_util.h"
namespace ash {
namespace {
ShelfWidget* GetShelfWidget() {
return AshTestBase::GetPrimaryShelf()->shelf_widget();
}
ShelfLayoutManager* GetShelfLayoutManager() {
return AshTestBase::GetPrimaryShelf()->shelf_layout_manager();
}
class ShelfDragCallback {
public:
ShelfDragCallback(const gfx::Rect& auto_hidden_shelf_bounds,
const gfx::Rect& visible_shelf_bounds)
: auto_hidden_shelf_bounds_(auto_hidden_shelf_bounds),
visible_shelf_bounds_(visible_shelf_bounds),
was_visible_on_drag_start_(false) {
EXPECT_EQ(auto_hidden_shelf_bounds_.size(), visible_shelf_bounds_.size());
}
virtual ~ShelfDragCallback() = default;
void ProcessScroll(ui::EventType type, const gfx::Vector2dF& delta) {
ProcessScrollInternal(type, delta, true);
}
void ProcessScrollNoBoundsCheck(ui::EventType type,
const gfx::Vector2dF& delta) {
ProcessScrollInternal(type, delta, false);
}
void ProcessScrollInternal(ui::EventType type,
const gfx::Vector2dF& delta,
bool bounds_check) {
if (GetShelfLayoutManager()->visibility_state() == SHELF_HIDDEN)
return;
if (type == ui::ET_GESTURE_SCROLL_BEGIN) {
scroll_ = gfx::Vector2dF();
was_visible_on_drag_start_ = GetShelfLayoutManager()->IsVisible();
return;
}
// The state of the shelf at the end of the gesture is tested separately.
if (type == ui::ET_GESTURE_SCROLL_END)
return;
if (type == ui::ET_GESTURE_SCROLL_UPDATE)
scroll_.Add(delta);
Shelf* shelf = AshTestBase::GetPrimaryShelf();
gfx::Rect shelf_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
float scroll_delta =
GetShelfLayoutManager()->PrimaryAxisValue(scroll_.y(), scroll_.x());
bool increasing_drag =
GetShelfLayoutManager()->SelectValueForShelfAlignment(
scroll_delta<0, scroll_delta> 0, scroll_delta < 0);
const int shelf_size = GetShelfLayoutManager()->PrimaryAxisValue(
shelf_bounds.height(), shelf_bounds.width());
if (was_visible_on_drag_start_) {
if (increasing_drag) {
// If dragging inwards from the visible state, then the shelf should
// 'overshoot', but not by more than the scroll delta.
const int bounds_delta =
GetShelfLayoutManager()->SelectValueForShelfAlignment(
visible_shelf_bounds_.y() - shelf_bounds.y(),
shelf_bounds.x() - visible_shelf_bounds_.x(),
visible_shelf_bounds_.x() - shelf_bounds.x());
EXPECT_GE(bounds_delta, 0);
EXPECT_LE(bounds_delta, std::abs(scroll_delta));
} else {
// If dragging outwards from the visible state, then the shelf should
// move out.
if (ShelfAlignment::kBottom == shelf->alignment())
EXPECT_LE(visible_shelf_bounds_.y(), shelf_bounds.y());
else if (ShelfAlignment::kLeft == shelf->alignment())
EXPECT_LE(shelf_bounds.x(), visible_shelf_bounds_.x());
else if (ShelfAlignment::kRight == shelf->alignment())
EXPECT_LE(visible_shelf_bounds_.x(), shelf_bounds.x());
}
} else {
// The shelf is invisible at the start of the drag.
if (increasing_drag && bounds_check) {
constexpr float kEpsilon = 1.f;
// Moving the shelf into the screen.
if (std::abs(scroll_delta) < shelf_size) {
// Tests that the shelf sticks with the touch point during the drag
// until the shelf is completely visible.
if (ShelfAlignment::kBottom == shelf->alignment()) {
EXPECT_NEAR(
shelf_bounds.y(),
auto_hidden_shelf_bounds_.y() +
ShelfConfig::Get()->hidden_shelf_in_screen_portion() -
std::abs(scroll_delta),
kEpsilon);
} else if (ShelfAlignment::kLeft == shelf->alignment()) {
EXPECT_NEAR(
shelf_bounds.x(),
auto_hidden_shelf_bounds_.x() -
ShelfConfig::Get()->hidden_shelf_in_screen_portion() +
std::abs(scroll_delta),
kEpsilon);
} else if (ShelfAlignment::kRight == shelf->alignment()) {
EXPECT_NEAR(
shelf_bounds.x(),
auto_hidden_shelf_bounds_.x() +
ShelfConfig::Get()->hidden_shelf_in_screen_portion() -
std::abs(scroll_delta),
kEpsilon);
}
} else {
// Tests that after the shelf is completely visible, the shelf starts
// resisting the drag.
if (ShelfAlignment::kBottom == shelf->alignment()) {
EXPECT_GT(shelf_bounds.y(),
auto_hidden_shelf_bounds_.y() +
ShelfConfig::Get()->hidden_shelf_in_screen_portion() -
std::abs(scroll_delta));
} else if (ShelfAlignment::kLeft == shelf->alignment()) {
EXPECT_LT(shelf_bounds.x(),
auto_hidden_shelf_bounds_.x() -
ShelfConfig::Get()->hidden_shelf_in_screen_portion() +
std::abs(scroll_delta));
} else if (ShelfAlignment::kRight == shelf->alignment()) {
EXPECT_GT(shelf_bounds.x(),
auto_hidden_shelf_bounds_.x() +
ShelfConfig::Get()->hidden_shelf_in_screen_portion() -
std::abs(scroll_delta));
}
}
}
}
}
private:
const gfx::Rect auto_hidden_shelf_bounds_;
const gfx::Rect visible_shelf_bounds_;
gfx::Vector2dF scroll_;
bool was_visible_on_drag_start_;
DISALLOW_COPY_AND_ASSIGN(ShelfDragCallback);
};
} // namespace
void ShelfLayoutManagerTestBase::SetState(ShelfLayoutManager* layout_manager,
ShelfVisibilityState state) {
layout_manager->SetState(state);
}
void ShelfLayoutManagerTestBase::UpdateAutoHideStateNow() {
GetShelfLayoutManager()->UpdateAutoHideStateNow();
}
aura::Window* ShelfLayoutManagerTestBase::CreateTestWindow() {
aura::Window* window = window_factory::NewWindow().release();
window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
window->SetType(aura::client::WINDOW_TYPE_NORMAL);
window->Init(ui::LAYER_TEXTURED);
ParentWindowInPrimaryRootWindow(window);
return window;
}
aura::Window* ShelfLayoutManagerTestBase::CreateTestWindowInParent(
aura::Window* root_window) {
aura::Window* window = window_factory::NewWindow().release();
window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
window->SetType(aura::client::WINDOW_TYPE_NORMAL);
window->Init(ui::LAYER_TEXTURED);
aura::client::ParentWindowWithContext(window, root_window, gfx::Rect());
return window;
}
views::Widget* ShelfLayoutManagerTestBase::CreateTestWidget() {
views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
params.bounds = gfx::Rect(0, 0, 200, 200);
params.context = CurrentContext();
views::Widget* widget = new views::Widget;
widget->Init(std::move(params));
widget->Show();
return widget;
}
gfx::Rect ShelfLayoutManagerTestBase::GetVisibleShelfWidgetBoundsInScreen() {
gfx::Rect bounds = GetShelfWidget()->GetWindowBoundsInScreen();
bounds.Intersect(display::Screen::GetScreen()->GetPrimaryDisplay().bounds());
return bounds;
}
void ShelfLayoutManagerTestBase::LockScreen() {
GetSessionControllerClient()->LockScreen();
}
void ShelfLayoutManagerTestBase::UnlockScreen() {
GetSessionControllerClient()->UnlockScreen();
}
int64_t ShelfLayoutManagerTestBase::GetPrimaryDisplayId() {
return display::Screen::GetScreen()->GetPrimaryDisplay().id();
}
void ShelfLayoutManagerTestBase::StartScroll(gfx::Point start) {
timestamp_ = base::TimeTicks::Now();
current_point_ = start;
ui::GestureEvent event = ui::GestureEvent(
current_point_.x(), current_point_.y(), ui::EF_NONE, timestamp_,
ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, 0, -1.0f));
GetShelfLayoutManager()->ProcessGestureEvent(event);
}
void ShelfLayoutManagerTestBase::UpdateScroll(float delta_y) {
IncreaseTimestamp();
current_point_.set_y(current_point_.y() + delta_y);
ui::GestureEvent event = ui::GestureEvent(
current_point_.x(), current_point_.y(), ui::EF_NONE, timestamp_,
ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, 0, delta_y));
GetShelfLayoutManager()->ProcessGestureEvent(event);
}
void ShelfLayoutManagerTestBase::EndScroll(bool is_fling, float velocity_y) {
IncreaseTimestamp();
ui::GestureEventDetails event_details =
is_fling
? ui::GestureEventDetails(ui::ET_SCROLL_FLING_START, 0, velocity_y)
: ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END);
ui::GestureEvent event =
ui::GestureEvent(current_point_.x(), current_point_.y(), ui::EF_NONE,
timestamp_, event_details);
GetShelfLayoutManager()->ProcessGestureEvent(event);
}
void ShelfLayoutManagerTestBase::IncreaseTimestamp() {
timestamp_ += base::TimeDelta::FromMilliseconds(25);
}
WorkspaceWindowState ShelfLayoutManagerTestBase::GetWorkspaceWindowState()
const {
// Shelf window does not belong to any desk, use the root to get the active
// desk's workspace state.
auto* shelf_window = GetShelfWidget()->GetNativeWindow();
auto* controller =
GetActiveWorkspaceController(shelf_window->GetRootWindow());
DCHECK(controller);
return controller->GetWindowState();
}
const ui::Layer*
ShelfLayoutManagerTestBase::GetNonLockScreenContainersContainerLayer() const {
const auto* shelf_window = GetShelfWidget()->GetNativeWindow();
return shelf_window->GetRootWindow()
->GetChildById(kShellWindowId_NonLockScreenContainersContainer)
->layer();
}
// If |layout_manager->auto_hide_timer_| is running, stops it, runs its task,
// and returns true. Otherwise, returns false.
bool ShelfLayoutManagerTestBase::TriggerAutoHideTimeout() const {
ShelfLayoutManager* layout_manager = GetShelfLayoutManager();
if (!layout_manager->auto_hide_timer_.IsRunning())
return false;
layout_manager->auto_hide_timer_.FireNow();
return true;
}
// Performs a swipe up gesture to show an auto-hidden shelf.
void ShelfLayoutManagerTestBase::SwipeUpOnShelf() {
gfx::Rect display_bounds =
display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
const gfx::Point start(display_bounds.bottom_center());
const gfx::Point end(start + gfx::Vector2d(0, -80));
const base::TimeDelta kTimeDelta = base::TimeDelta::FromMilliseconds(100);
const int kNumScrollSteps = 4;
GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
kNumScrollSteps);
}
void ShelfLayoutManagerTestBase::SwipeDownOnShelf() {
gfx::Point start(GetPrimaryShelf()
->shelf_widget()
->shelf_view_for_testing()
->GetBoundsInScreen()
.top_center());
const gfx::Point end(start + gfx::Vector2d(0, 40));
const base::TimeDelta kTimeDelta = base::TimeDelta::FromMilliseconds(100);
const int kNumScrollSteps = 4;
GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
kNumScrollSteps);
}
void ShelfLayoutManagerTestBase::FlingUpOnShelf() {
gfx::Rect display_bounds =
display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
const gfx::Point start(display_bounds.bottom_center());
const gfx::Point end(start.x(), 10);
const base::TimeDelta kTimeDelta = base::TimeDelta::FromMilliseconds(10);
const int kNumScrollSteps = 4;
GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
kNumScrollSteps);
}
void ShelfLayoutManagerTestBase::DragHotseatDownToBezel() {
gfx::Rect shelf_widget_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
gfx::Rect hotseat_bounds =
GetShelfWidget()->hotseat_widget()->GetWindowBoundsInScreen();
gfx::Point start = hotseat_bounds.top_center();
const gfx::Point end =
gfx::Point(shelf_widget_bounds.x() + shelf_widget_bounds.width() / 2,
shelf_widget_bounds.bottom() + 1);
const base::TimeDelta kTimeDelta = base::TimeDelta::FromMilliseconds(100);
const int kNumScrollSteps = 4;
GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
kNumScrollSteps);
}
// Drag Shelf from |start| to |target| by mouse.
void ShelfLayoutManagerTestBase::MouseDragShelfTo(const gfx::Point& start,
const gfx::Point& target) {
ui::test::EventGenerator* generator = GetEventGenerator();
generator->MoveMouseTo(start);
generator->PressLeftButton();
generator->DragMouseTo(target);
generator->ReleaseLeftButton();
}
// Move mouse to show Shelf in auto-hide mode.
void ShelfLayoutManagerTestBase::MouseMouseToShowAutoHiddenShelf() {
display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
const int display_bottom = display.bounds().bottom();
GetEventGenerator()->MoveMouseTo(1, display_bottom - 1);
ASSERT_TRUE(TriggerAutoHideTimeout());
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, GetPrimaryShelf()->GetAutoHideState());
}
// Move mouse to |location| and do a two-finger vertical scroll.
void ShelfLayoutManagerTestBase::DoTwoFingerVerticalScrollAtLocation(
gfx::Point location,
int y_offset) {
GetEventGenerator()->ScrollSequence(location, base::TimeDelta(),
/*x_offset=*/0, y_offset, /*steps=*/1,
/*num_fingers=*/2);
}
// Move mouse to |location| and do a mousewheel scroll.
void ShelfLayoutManagerTestBase::DoMouseWheelScrollAtLocation(
gfx::Point location,
int delta_y) {
GetEventGenerator()->MoveMouseTo(location);
GetEventGenerator()->MoveMouseWheel(/*delta_x=*/0, delta_y);
}
void ShelfLayoutManagerTestBase::RunGestureDragTests(
const gfx::Point& edge_to_hide,
const gfx::Point& edge_to_show) {
ui::test::EventGenerator* generator = GetEventGenerator();
display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
generator->MoveMouseTo(display.bounds().CenterPoint());
Shelf* shelf = GetPrimaryShelf();
shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kNever);
views::Widget* widget = CreateTestWidget();
widget->Maximize();
// The time delta should be large enough to prevent accidental fling creation.
const base::TimeDelta kTimeDelta = base::TimeDelta::FromMilliseconds(100);
aura::Window* window = widget->GetNativeWindow();
ShelfLayoutManager* layout_manager = GetShelfLayoutManager();
layout_manager->LayoutShelf();
gfx::Rect shelf_shown = GetShelfWidget()->GetWindowBoundsInScreen();
gfx::Rect window_bounds_with_shelf = window->bounds();
EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
layout_manager->LayoutShelf();
EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
gfx::Rect window_bounds_with_noshelf = window->bounds();
gfx::Rect shelf_hidden = GetShelfWidget()->GetWindowBoundsInScreen();
// Tests the gesture drag on always shown shelf.
shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kNever);
layout_manager->LayoutShelf();
const int kNumScrollSteps = 4;
ShelfDragCallback handler(shelf_hidden, shelf_shown);
// Swipe down on the always shown shelf should not auto-hide it.
{
SCOPED_TRACE("SWIPE_DOWN_ALWAYS_SHOWN");
generator->GestureScrollSequenceWithCallback(
edge_to_hide, edge_to_show, kTimeDelta, kNumScrollSteps,
base::BindRepeating(&ShelfDragCallback::ProcessScroll,
base::Unretained(&handler)));
}
EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
EXPECT_EQ(ShelfAutoHideBehavior::kNever, shelf->auto_hide_behavior());
EXPECT_EQ(window_bounds_with_shelf.ToString(), window->bounds().ToString());
EXPECT_EQ(shelf_shown.ToString(),
GetShelfWidget()->GetWindowBoundsInScreen().ToString());
// Verify that the shelf can still enter auto hide if the |widget_| has been
// put into fullscreen.
widget->SetFullscreen(true);
WindowState* window_state = WindowState::Get(window);
window_state->SetHideShelfWhenFullscreen(false);
window->SetProperty(kImmersiveIsActive, true);
layout_manager->UpdateVisibilityState();
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
EXPECT_EQ(ShelfAutoHideBehavior::kNever, shelf->auto_hide_behavior());
// Swiping up should show the shelf if shelf is hidden in fullscreen mode.
generator->GestureScrollSequence(edge_to_hide, edge_to_show, kTimeDelta,
kNumScrollSteps);
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
EXPECT_EQ(ShelfAutoHideBehavior::kNever, shelf->auto_hide_behavior());
// Swiping down should hide the shelf.
generator->GestureScrollSequence(edge_to_show, edge_to_hide, kTimeDelta,
kNumScrollSteps);
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
EXPECT_EQ(ShelfAutoHideBehavior::kNever, shelf->auto_hide_behavior());
// Verify that after toggling fullscreen to off, the shelf is visible.
widget->SetFullscreen(false);
EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
// Minimize the visible window, the shelf should be shown if there are no
// visible windows, even in auto-hide mode.
window_state->Minimize();
EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
EXPECT_EQ(ShelfAutoHideBehavior::kNever, shelf->auto_hide_behavior());
// Tests gesture drag on auto-hide shelf.
window_state->Maximize();
shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
layout_manager->LayoutShelf();
EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
// Swipe up the auto-hide shelf should show it.
{
SCOPED_TRACE("SWIPE_UP_AUTO_HIDE_SHOW");
generator->GestureScrollSequenceWithCallback(
edge_to_hide, edge_to_show, kTimeDelta, kNumScrollSteps,
base::BindRepeating(&ShelfDragCallback::ProcessScroll,
base::Unretained(&handler)));
}
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
// Gesture drag should not change the auto hide behavior of shelf, even though
// its visibility has been changed.
EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
// The auto-hide shelf is above the window, which should not change the bounds
// of the window.
EXPECT_EQ(window_bounds_with_noshelf.ToString(), window->bounds().ToString());
EXPECT_EQ(shelf_shown.ToString(),
GetShelfWidget()->GetWindowBoundsInScreen().ToString());
// Swipe down very little. It shouldn't change any state.
gfx::Point new_point(edge_to_show);
gfx::Vector2d diff = edge_to_hide - edge_to_show;
new_point.Offset(diff.x() * 3 / 10, diff.y() * 3 / 10);
generator->GestureScrollSequence(edge_to_show, new_point, kTimeDelta, 5);
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
EXPECT_EQ(window_bounds_with_noshelf.ToString(), window->bounds().ToString());
EXPECT_EQ(shelf_shown.ToString(),
GetShelfWidget()->GetWindowBoundsInScreen().ToString());
{
SCOPED_TRACE("SWIPE_DOWN_AUTO_HIDE_1");
generator->GestureScrollSequenceWithCallback(
edge_to_show, edge_to_hide, kTimeDelta, kNumScrollSteps,
base::BindRepeating(&ShelfDragCallback::ProcessScroll,
base::Unretained(&handler)));
}
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
EXPECT_EQ(window_bounds_with_noshelf.ToString(), window->bounds().ToString());
EXPECT_EQ(shelf_hidden.ToString(),
GetShelfWidget()->GetWindowBoundsInScreen().ToString());
// Swipe up in extended hit region to show it.
gfx::Point extended_start = edge_to_show;
if (shelf->IsHorizontalAlignment())
extended_start.set_y(GetShelfWidget()->GetWindowBoundsInScreen().y() - 1);
else if (ShelfAlignment::kLeft == shelf->alignment())
extended_start.set_x(GetShelfWidget()->GetWindowBoundsInScreen().right() +
1);
else if (ShelfAlignment::kRight == shelf->alignment())
extended_start.set_x(GetShelfWidget()->GetWindowBoundsInScreen().x() - 1);
{
SCOPED_TRACE("SWIPE_UP_EXTENDED_HIT");
generator->GestureScrollSequenceWithCallback(
extended_start, edge_to_show, kTimeDelta, kNumScrollSteps,
base::BindRepeating(&ShelfDragCallback::ProcessScroll,
base::Unretained(&handler)));
}
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
EXPECT_EQ(window_bounds_with_noshelf.ToString(), window->bounds().ToString());
EXPECT_EQ(shelf_shown.ToString(),
GetShelfWidget()->GetWindowBoundsInScreen().ToString());
// Swipe down again to hide.
{
SCOPED_TRACE("SWIPE_DOWN_AUTO_HIDE_2");
generator->GestureScrollSequenceWithCallback(
edge_to_show, edge_to_hide, kTimeDelta, kNumScrollSteps,
base::BindRepeating(&ShelfDragCallback::ProcessScroll,
base::Unretained(&handler)));
}
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
EXPECT_EQ(window_bounds_with_noshelf.ToString(), window->bounds().ToString());
EXPECT_EQ(shelf_hidden.ToString(),
GetShelfWidget()->GetWindowBoundsInScreen().ToString());
// Swipe up outside the hit area. This should not change anything.
gfx::Point outside_start =
GetShelfWidget()->GetWindowBoundsInScreen().top_center();
outside_start.set_y(outside_start.y() - 50);
gfx::Vector2d delta = edge_to_hide - edge_to_show;
generator->GestureScrollSequence(outside_start, outside_start + delta,
kTimeDelta, kNumScrollSteps);
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
EXPECT_EQ(window_bounds_with_noshelf.ToString(), window->bounds().ToString());
EXPECT_EQ(shelf_hidden.ToString(),
GetShelfWidget()->GetWindowBoundsInScreen().ToString());
// Swipe up from the bottom of the shelf, this should show the shelf.
gfx::Point below_start = edge_to_hide;
generator->GestureScrollSequence(edge_to_hide, edge_to_show, kTimeDelta,
kNumScrollSteps);
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
EXPECT_EQ(window_bounds_with_noshelf.ToString(), window->bounds().ToString());
EXPECT_EQ(shelf_shown.ToString(),
GetShelfWidget()->GetWindowBoundsInScreen().ToString());
// Swipe down again to hide.
{
SCOPED_TRACE("SWIPE_DOWN_AUTO_HIDE_3");
generator->GestureScrollSequenceWithCallback(
edge_to_show, edge_to_hide, kTimeDelta, kNumScrollSteps,
base::BindRepeating(&ShelfDragCallback::ProcessScroll,
base::Unretained(&handler)));
}
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
EXPECT_EQ(window_bounds_with_noshelf.ToString(), window->bounds().ToString());
EXPECT_EQ(shelf_hidden.ToString(),
GetShelfWidget()->GetWindowBoundsInScreen().ToString());
// Put |widget| into fullscreen. Set the shelf to be auto hidden when |widget|
// is fullscreen. (eg browser immersive fullscreen).
widget->SetFullscreen(true);
WindowState::Get(window)->SetHideShelfWhenFullscreen(false);
layout_manager->UpdateVisibilityState();
gfx::Rect window_bounds_fullscreen = window->bounds();
EXPECT_TRUE(widget->IsFullscreen());
EXPECT_EQ(window_bounds_with_noshelf.ToString(),
window_bounds_fullscreen.ToString());
// Swipe up. This should show the shelf.
{
SCOPED_TRACE("SWIPE_UP_AUTO_HIDE_1");
// Do not check bounds because the events outside of the bounds
// will be clipped.
generator->GestureScrollSequenceWithCallback(
below_start, edge_to_show, kTimeDelta, kNumScrollSteps,
base::BindRepeating(&ShelfDragCallback::ProcessScrollNoBoundsCheck,
base::Unretained(&handler)));
}
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
EXPECT_EQ(shelf_shown.ToString(),
GetShelfWidget()->GetWindowBoundsInScreen().ToString());
EXPECT_EQ(window_bounds_fullscreen.ToString(), window->bounds().ToString());
// Swipe down to hide the shelf.
{
SCOPED_TRACE("SWIPE_DOWN_AUTO_HIDE_4");
generator->GestureScrollSequenceWithCallback(
edge_to_show, edge_to_hide, kTimeDelta, kNumScrollSteps,
base::BindRepeating(&ShelfDragCallback::ProcessScroll,
base::Unretained(&handler)));
}
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
EXPECT_EQ(shelf_hidden.ToString(),
GetShelfWidget()->GetWindowBoundsInScreen().ToString());
EXPECT_EQ(window_bounds_fullscreen.ToString(), window->bounds().ToString());
// Set the shelf to be hidden when |widget| is fullscreen. (eg tab fullscreen
// with or without immersive browser fullscreen).
WindowState::Get(window)->SetHideShelfWhenFullscreen(true);
layout_manager->UpdateVisibilityState();
EXPECT_EQ(SHELF_HIDDEN, shelf->GetVisibilityState());
EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
// Swipe-up. This should not change anything.
{
SCOPED_TRACE("SWIPE_UP_NO_CHANGE");
generator->GestureScrollSequenceWithCallback(
below_start, edge_to_show, kTimeDelta, kNumScrollSteps,
base::BindRepeating(&ShelfDragCallback::ProcessScroll,
base::Unretained(&handler)));
EXPECT_EQ(SHELF_HIDDEN, shelf->GetVisibilityState());
EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
EXPECT_EQ(window_bounds_fullscreen.ToString(), window->bounds().ToString());
}
// Minimize actually, otherwise further event may be affected since widget
// is fullscreen status.
widget->Minimize();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(layout_manager->HasVisibleWindow());
// The shelf should be shown because there are no more visible windows.
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
// Swipe-down to hide. This should have no effect because there are no visible
// windows.
{
SCOPED_TRACE("SWIPE_DOWN_AUTO_HIDE_5");
generator->GestureScrollSequenceWithCallback(
edge_to_show, edge_to_hide, kTimeDelta, kNumScrollSteps,
base::BindRepeating(&ShelfDragCallback::ProcessScroll,
base::Unretained(&handler)));
}
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
EXPECT_EQ(shelf_shown.ToString(),
GetShelfWidget()->GetWindowBoundsInScreen().ToString());
widget->Restore();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(layout_manager->HasVisibleWindow());
// Swipe up on the shelf. This should show the shelf but should not change the
// auto-hide behavior, since auto-hide behavior can only be changed through
// context menu of the shelf.
{
SCOPED_TRACE("SWIPE_UP_AUTO_HIDE_2");
// Do not check bounds because the events outside of the bounds
// will be clipped.
generator->GestureScrollSequenceWithCallback(
below_start, edge_to_show, kTimeDelta, kNumScrollSteps,
base::BindRepeating(&ShelfDragCallback::ProcessScrollNoBoundsCheck,
base::Unretained(&handler)));
}
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
EXPECT_EQ(shelf_shown.ToString(),
GetShelfWidget()->GetWindowBoundsInScreen().ToString());
widget->Close();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(layout_manager->HasVisibleWindow());
// Swipe-down to hide. This should have no effect because there are no visible
// windows.
{
SCOPED_TRACE("SWIPE_DOWN_AUTO_HIDE_6");
generator->GestureScrollSequenceWithCallback(
edge_to_show, edge_to_hide, kTimeDelta, kNumScrollSteps,
base::BindRepeating(&ShelfDragCallback::ProcessScroll,
base::Unretained(&handler)));
}
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
EXPECT_EQ(shelf_shown.ToString(),
GetShelfWidget()->GetWindowBoundsInScreen().ToString());
// Swipe up again on AUTO_HIDE_SHOWN shelf shouldn't change any state.
// Swipe up on auto-hide shown shelf should still keep shelf shown.
{
SCOPED_TRACE("SWIPE_UP_AUTO_HIDE_4");
generator->GestureScrollSequenceWithCallback(
edge_to_hide, edge_to_show, kTimeDelta, kNumScrollSteps,
base::BindRepeating(&ShelfDragCallback::ProcessScroll,
base::Unretained(&handler)));
}
EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
EXPECT_EQ(shelf_shown.ToString(),
GetShelfWidget()->GetWindowBoundsInScreen().ToString());
}
void ShelfLayoutManagerTestBase::TestHomeLauncherGestureHandler(
bool autohide_shelf) {
// Home launcher is only available in tablet mode.
TabletModeControllerTestApi().EnterTabletMode();
Shelf* shelf = GetPrimaryShelf();
if (autohide_shelf)
shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
// Create more than one window to prepare for the possibly window stacking
// change during drag.
std::unique_ptr<aura::Window> extra_window =
AshTestBase::CreateTestWindow(gfx::Rect(100, 10, 100, 100));
std::unique_ptr<aura::Window> window =
AshTestBase::CreateTestWindow(gfx::Rect(0, 0, 400, 400));
wm::ActivateWindow(window.get());
if (!chromeos::switches::ShouldShowShelfHotseat()) {
if (autohide_shelf) {
SwipeUpOnShelf();
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
}
} else {
EXPECT_EQ(HotseatState::kHidden, GetShelfLayoutManager()->hotseat_state());
// Swipe up to show the hotseat.
SwipeUpOnShelf();
if (autohide_shelf)
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
EXPECT_EQ(HotseatState::kExtended,
GetShelfLayoutManager()->hotseat_state());
}
const gfx::Point shelf_center =
GetVisibleShelfWidgetBoundsInScreen().CenterPoint();
// Helper to create a scroll event for this test.
auto create_scroll_event = [&shelf_center](ui::EventType type,
float scroll_y) {
ui::GestureEventDetails details =
type == ui::ET_GESTURE_SCROLL_END
? ui::GestureEventDetails(type)
: ui::GestureEventDetails(type, 0, scroll_y);
return ui::GestureEvent(shelf_center.x(), shelf_center.y(), 0,
base::TimeTicks(), details);
};
// The home launcher gesture handler should not be handling any window
// initially.
HomeLauncherGestureHandler* gesture_handler =
Shell::Get()->home_screen_controller()->home_launcher_gesture_handler();
ASSERT_TRUE(gesture_handler);
ASSERT_FALSE(gesture_handler->GetActiveWindow());
// Tests that after kDragFromShelfToHomeOrOverview flag is enabled, the home
// launcher gesture handler does not handle the scroll up events any more.
ShelfLayoutManager* manager = GetShelfLayoutManager();
manager->ProcessGestureEvent(
create_scroll_event(ui::ET_GESTURE_SCROLL_BEGIN, -1.f));
EXPECT_FALSE(gesture_handler->GetActiveWindow());
if (autohide_shelf) {
// Auto-hide shelf should keep visible after scrolling up on it.
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
}
manager->ProcessGestureEvent(
create_scroll_event(ui::ET_GESTURE_SCROLL_UPDATE, -1.f));
EXPECT_FALSE(gesture_handler->GetActiveWindow());
if (autohide_shelf)
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
manager->ProcessGestureEvent(
create_scroll_event(ui::ET_GESTURE_SCROLL_END, 1.f));
ASSERT_FALSE(gesture_handler->GetActiveWindow());
if (autohide_shelf)
EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
// Tests that if the initial scroll event is directed downwards, the home
// launcher gesture handler will not act on |window|.
manager->ProcessGestureEvent(
create_scroll_event(ui::ET_GESTURE_SCROLL_BEGIN, 1.f));
EXPECT_FALSE(gesture_handler->GetActiveWindow());
manager->ProcessGestureEvent(
create_scroll_event(ui::ET_GESTURE_SCROLL_UPDATE, -1.f));
EXPECT_FALSE(gesture_handler->GetActiveWindow());
}
} // namespace ash
// Copyright (c) 2020 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.
#ifndef ASH_SHELF_TEST_SHELF_LAYOUT_MANAGER_TEST_BASE_H_
#define ASH_SHELF_TEST_SHELF_LAYOUT_MANAGER_TEST_BASE_H_
#include "ash/public/cpp/shelf_types.h"
#include "ash/test/ash_test_base.h"
#include "ash/wm/workspace/workspace_types.h"
namespace ui {
class Layer;
}
namespace ash {
class ShelfLayoutManager;
class ShelfLayoutManagerTestBase : public AshTestBase {
public:
ShelfLayoutManagerTestBase() = default;
// Calls the private SetState() function.
void SetState(ShelfLayoutManager* layout_manager, ShelfVisibilityState state);
void UpdateAutoHideStateNow();
aura::Window* CreateTestWindow();
aura::Window* CreateTestWindowInParent(aura::Window* root_window);
// Create a simple widget in the current context (will delete on TearDown).
views::Widget* CreateTestWidget();
void RunGestureDragTests(const gfx::Point& shown, const gfx::Point& hidden);
void TestHomeLauncherGestureHandler(bool autohide_shelf);
gfx::Rect GetVisibleShelfWidgetBoundsInScreen();
// Turn on the lock screen.
void LockScreen();
// Turn off the lock screen.
void UnlockScreen();
int64_t GetPrimaryDisplayId();
void StartScroll(gfx::Point start);
void UpdateScroll(float delta_y);
void EndScroll(bool is_fling, float velocity_y);
void IncreaseTimestamp();
WorkspaceWindowState GetWorkspaceWindowState() const;
const ui::Layer* GetNonLockScreenContainersContainerLayer() const;
// If |layout_manager->auto_hide_timer_| is running, stops it, runs its task,
// and returns true. Otherwise, returns false.
bool TriggerAutoHideTimeout() const;
// Performs a swipe up gesture to show an auto-hidden shelf.
void SwipeUpOnShelf();
void SwipeDownOnShelf();
void FlingUpOnShelf();
void DragHotseatDownToBezel();
// Drag Shelf from |start| to |target| by mouse.
void MouseDragShelfTo(const gfx::Point& start, const gfx::Point& target);
// Move mouse to show Shelf in auto-hide mode.
void MouseMouseToShowAutoHiddenShelf();
// Move mouse to |location| and do a two-finger vertical scroll.
void DoTwoFingerVerticalScrollAtLocation(gfx::Point location, int y_offset);
// Move mouse to |location| and do a mousewheel scroll.
void DoMouseWheelScrollAtLocation(gfx::Point location, int delta_y);
private:
base::TimeTicks timestamp_;
gfx::Point current_point_;
};
} // namespace ash
#endif // ASH_SHELF_TEST_SHELF_LAYOUT_MANAGER_TEST_BASE_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment