shelf_layout_manager_test_base.cc 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. // Copyright (c) 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/shelf/test/shelf_layout_manager_test_base.h"
  5. #include "ash/constants/ash_pref_names.h"
  6. #include "ash/session/session_controller_impl.h"
  7. #include "ash/shelf/shelf_layout_manager.h"
  8. #include "ash/shelf/shelf_view.h"
  9. #include "ash/shell.h"
  10. #include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h"
  11. #include "ash/wm/window_state.h"
  12. #include "ash/wm/wm_event.h"
  13. #include "ash/wm/workspace_controller.h"
  14. #include "base/bind.h"
  15. #include "chromeos/ui/base/window_properties.h"
  16. #include "components/prefs/pref_service.h"
  17. #include "ui/aura/client/aura_constants.h"
  18. #include "ui/aura/client/window_parenting_client.h"
  19. #include "ui/aura/window.h"
  20. #include "ui/display/display.h"
  21. #include "ui/display/screen.h"
  22. #include "ui/views/view.h"
  23. #include "ui/wm/core/window_util.h"
  24. namespace ash {
  25. namespace {
  26. using ::chromeos::kImmersiveIsActive;
  27. ShelfWidget* GetShelfWidget() {
  28. return AshTestBase::GetPrimaryShelf()->shelf_widget();
  29. }
  30. ShelfLayoutManager* GetShelfLayoutManager() {
  31. return AshTestBase::GetPrimaryShelf()->shelf_layout_manager();
  32. }
  33. class ShelfDragCallback {
  34. public:
  35. ShelfDragCallback(const gfx::Rect& auto_hidden_shelf_bounds,
  36. const gfx::Rect& visible_shelf_bounds)
  37. : auto_hidden_shelf_bounds_(auto_hidden_shelf_bounds),
  38. visible_shelf_bounds_(visible_shelf_bounds) {
  39. EXPECT_EQ(auto_hidden_shelf_bounds_.size(), visible_shelf_bounds_.size());
  40. }
  41. ShelfDragCallback(const ShelfDragCallback&) = delete;
  42. ShelfDragCallback& operator=(const ShelfDragCallback&) = delete;
  43. virtual ~ShelfDragCallback() = default;
  44. void ProcessScroll(ui::EventType type, const gfx::Vector2dF& delta) {
  45. ProcessScrollInternal(type, delta, true);
  46. }
  47. void ProcessScrollNoBoundsCheck(ui::EventType type,
  48. const gfx::Vector2dF& delta) {
  49. ProcessScrollInternal(type, delta, false);
  50. }
  51. void ProcessScrollInternal(ui::EventType type,
  52. const gfx::Vector2dF& delta,
  53. bool bounds_check) {
  54. if (GetShelfLayoutManager()->visibility_state() == SHELF_HIDDEN)
  55. return;
  56. if (type == ui::ET_GESTURE_SCROLL_BEGIN) {
  57. scroll_ = gfx::Vector2dF();
  58. was_visible_on_drag_start_ = GetShelfLayoutManager()->IsVisible();
  59. return;
  60. }
  61. // The state of the shelf at the end of the gesture is tested separately.
  62. if (type == ui::ET_GESTURE_SCROLL_END)
  63. return;
  64. if (type == ui::ET_GESTURE_SCROLL_UPDATE)
  65. scroll_.Add(delta);
  66. Shelf* shelf = AshTestBase::GetPrimaryShelf();
  67. gfx::Rect shelf_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
  68. float scroll_delta = shelf->PrimaryAxisValue(scroll_.y(), scroll_.x());
  69. bool increasing_drag = shelf->SelectValueForShelfAlignment(
  70. scroll_delta<0, scroll_delta> 0, scroll_delta < 0);
  71. const int shelf_size =
  72. shelf->PrimaryAxisValue(shelf_bounds.height(), shelf_bounds.width());
  73. if (was_visible_on_drag_start_) {
  74. if (increasing_drag) {
  75. // If dragging inwards from the visible state, then the shelf should
  76. // 'overshoot', but not by more than the scroll delta.
  77. const int bounds_delta = shelf->SelectValueForShelfAlignment(
  78. visible_shelf_bounds_.y() - shelf_bounds.y(),
  79. shelf_bounds.x() - visible_shelf_bounds_.x(),
  80. visible_shelf_bounds_.x() - shelf_bounds.x());
  81. EXPECT_GE(bounds_delta, 0);
  82. EXPECT_LE(bounds_delta, std::abs(scroll_delta));
  83. } else {
  84. // If dragging outwards from the visible state, then the shelf should
  85. // move out.
  86. if (ShelfAlignment::kBottom == shelf->alignment())
  87. EXPECT_LE(visible_shelf_bounds_.y(), shelf_bounds.y());
  88. else if (ShelfAlignment::kLeft == shelf->alignment())
  89. EXPECT_LE(shelf_bounds.x(), visible_shelf_bounds_.x());
  90. else if (ShelfAlignment::kRight == shelf->alignment())
  91. EXPECT_LE(visible_shelf_bounds_.x(), shelf_bounds.x());
  92. }
  93. } else {
  94. // The shelf is invisible at the start of the drag.
  95. if (increasing_drag && bounds_check) {
  96. constexpr float kEpsilon = 1.f;
  97. // Moving the shelf into the screen.
  98. if (std::abs(scroll_delta) < shelf_size) {
  99. // Tests that the shelf sticks with the touch point during the drag
  100. // until the shelf is completely visible.
  101. if (ShelfAlignment::kBottom == shelf->alignment()) {
  102. EXPECT_NEAR(
  103. shelf_bounds.y(),
  104. auto_hidden_shelf_bounds_.y() +
  105. ShelfConfig::Get()->hidden_shelf_in_screen_portion() -
  106. std::abs(scroll_delta),
  107. kEpsilon);
  108. } else if (ShelfAlignment::kLeft == shelf->alignment()) {
  109. EXPECT_NEAR(
  110. shelf_bounds.x(),
  111. auto_hidden_shelf_bounds_.x() -
  112. ShelfConfig::Get()->hidden_shelf_in_screen_portion() +
  113. std::abs(scroll_delta),
  114. kEpsilon);
  115. } else if (ShelfAlignment::kRight == shelf->alignment()) {
  116. EXPECT_NEAR(
  117. shelf_bounds.x(),
  118. auto_hidden_shelf_bounds_.x() +
  119. ShelfConfig::Get()->hidden_shelf_in_screen_portion() -
  120. std::abs(scroll_delta),
  121. kEpsilon);
  122. }
  123. } else {
  124. // Tests that after the shelf is completely visible, the shelf starts
  125. // resisting the drag.
  126. if (ShelfAlignment::kBottom == shelf->alignment()) {
  127. EXPECT_GT(shelf_bounds.y(),
  128. auto_hidden_shelf_bounds_.y() +
  129. ShelfConfig::Get()->hidden_shelf_in_screen_portion() -
  130. std::abs(scroll_delta));
  131. } else if (ShelfAlignment::kLeft == shelf->alignment()) {
  132. EXPECT_LT(shelf_bounds.x(),
  133. auto_hidden_shelf_bounds_.x() -
  134. ShelfConfig::Get()->hidden_shelf_in_screen_portion() +
  135. std::abs(scroll_delta));
  136. } else if (ShelfAlignment::kRight == shelf->alignment()) {
  137. EXPECT_GT(shelf_bounds.x(),
  138. auto_hidden_shelf_bounds_.x() +
  139. ShelfConfig::Get()->hidden_shelf_in_screen_portion() -
  140. std::abs(scroll_delta));
  141. }
  142. }
  143. }
  144. }
  145. }
  146. private:
  147. const gfx::Rect auto_hidden_shelf_bounds_;
  148. const gfx::Rect visible_shelf_bounds_;
  149. gfx::Vector2dF scroll_;
  150. bool was_visible_on_drag_start_ = false;
  151. };
  152. } // namespace
  153. void ShelfLayoutManagerTestBase::SetState(ShelfLayoutManager* layout_manager,
  154. ShelfVisibilityState state) {
  155. layout_manager->SetState(state);
  156. }
  157. void ShelfLayoutManagerTestBase::UpdateAutoHideStateNow() {
  158. GetShelfLayoutManager()->UpdateAutoHideStateNow();
  159. }
  160. aura::Window* ShelfLayoutManagerTestBase::CreateTestWindow() {
  161. aura::Window* window = new aura::Window(nullptr);
  162. window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
  163. window->SetType(aura::client::WINDOW_TYPE_NORMAL);
  164. window->Init(ui::LAYER_TEXTURED);
  165. ParentWindowInPrimaryRootWindow(window);
  166. return window;
  167. }
  168. aura::Window* ShelfLayoutManagerTestBase::CreateTestWindowInParent(
  169. aura::Window* root_window) {
  170. aura::Window* window = new aura::Window(nullptr);
  171. window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_NORMAL);
  172. window->SetType(aura::client::WINDOW_TYPE_NORMAL);
  173. window->Init(ui::LAYER_TEXTURED);
  174. aura::client::ParentWindowWithContext(window, root_window, gfx::Rect());
  175. return window;
  176. }
  177. views::Widget* ShelfLayoutManagerTestBase::CreateTestWidget() {
  178. views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
  179. params.bounds = gfx::Rect(0, 0, 200, 200);
  180. params.context = GetContext();
  181. views::Widget* widget = new views::Widget;
  182. widget->Init(std::move(params));
  183. widget->Show();
  184. return widget;
  185. }
  186. gfx::Rect ShelfLayoutManagerTestBase::GetVisibleShelfWidgetBoundsInScreen() {
  187. gfx::Rect bounds = GetShelfWidget()->GetWindowBoundsInScreen();
  188. bounds.Intersect(display::Screen::GetScreen()->GetPrimaryDisplay().bounds());
  189. return bounds;
  190. }
  191. void ShelfLayoutManagerTestBase::LockScreen() {
  192. GetSessionControllerClient()->LockScreen();
  193. }
  194. void ShelfLayoutManagerTestBase::UnlockScreen() {
  195. GetSessionControllerClient()->UnlockScreen();
  196. }
  197. int64_t ShelfLayoutManagerTestBase::GetPrimaryDisplayId() {
  198. return display::Screen::GetScreen()->GetPrimaryDisplay().id();
  199. }
  200. void ShelfLayoutManagerTestBase::StartScroll(gfx::Point start) {
  201. timestamp_ = base::TimeTicks::Now();
  202. current_point_ = start;
  203. ui::GestureEvent event = ui::GestureEvent(
  204. current_point_.x(), current_point_.y(), ui::EF_NONE, timestamp_,
  205. ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, 0, -1.0f));
  206. GetShelfLayoutManager()->ProcessGestureEvent(event);
  207. }
  208. void ShelfLayoutManagerTestBase::UpdateScroll(float delta_y) {
  209. IncreaseTimestamp();
  210. current_point_.set_y(current_point_.y() + delta_y);
  211. ui::GestureEvent event = ui::GestureEvent(
  212. current_point_.x(), current_point_.y(), ui::EF_NONE, timestamp_,
  213. ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, 0, delta_y));
  214. GetShelfLayoutManager()->ProcessGestureEvent(event);
  215. }
  216. void ShelfLayoutManagerTestBase::EndScroll(bool is_fling, float velocity_y) {
  217. IncreaseTimestamp();
  218. ui::GestureEventDetails event_details =
  219. is_fling
  220. ? ui::GestureEventDetails(ui::ET_SCROLL_FLING_START, 0, velocity_y)
  221. : ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END);
  222. ui::GestureEvent event =
  223. ui::GestureEvent(current_point_.x(), current_point_.y(), ui::EF_NONE,
  224. timestamp_, event_details);
  225. GetShelfLayoutManager()->ProcessGestureEvent(event);
  226. }
  227. void ShelfLayoutManagerTestBase::IncreaseTimestamp() {
  228. timestamp_ += base::Milliseconds(25);
  229. }
  230. WorkspaceWindowState ShelfLayoutManagerTestBase::GetWorkspaceWindowState()
  231. const {
  232. // Shelf window does not belong to any desk, use the root to get the active
  233. // desk's workspace state.
  234. auto* shelf_window = GetShelfWidget()->GetNativeWindow();
  235. auto* controller =
  236. GetActiveWorkspaceController(shelf_window->GetRootWindow());
  237. DCHECK(controller);
  238. return controller->GetWindowState();
  239. }
  240. const ui::Layer*
  241. ShelfLayoutManagerTestBase::GetNonLockScreenContainersContainerLayer() const {
  242. const auto* shelf_window = GetShelfWidget()->GetNativeWindow();
  243. return shelf_window->GetRootWindow()
  244. ->GetChildById(kShellWindowId_NonLockScreenContainersContainer)
  245. ->layer();
  246. }
  247. // If |layout_manager->auto_hide_timer_| is running, stops it, runs its task,
  248. // and returns true. Otherwise, returns false.
  249. bool ShelfLayoutManagerTestBase::TriggerAutoHideTimeout() const {
  250. ShelfLayoutManager* layout_manager = GetShelfLayoutManager();
  251. if (!layout_manager->auto_hide_timer_.IsRunning())
  252. return false;
  253. layout_manager->auto_hide_timer_.FireNow();
  254. return true;
  255. }
  256. // Performs a swipe up gesture to show an auto-hidden shelf.
  257. void ShelfLayoutManagerTestBase::SwipeUpOnShelf() {
  258. gfx::Rect display_bounds =
  259. display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
  260. const gfx::Point start(display_bounds.bottom_center());
  261. const gfx::Point end(start + gfx::Vector2d(0, -80));
  262. const base::TimeDelta kTimeDelta = base::Milliseconds(100);
  263. const int kNumScrollSteps = 4;
  264. GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
  265. kNumScrollSteps);
  266. }
  267. void ShelfLayoutManagerTestBase::SwipeDownOnShelf() {
  268. gfx::Point start(GetPrimaryShelf()
  269. ->shelf_widget()
  270. ->shelf_view_for_testing()
  271. ->GetBoundsInScreen()
  272. .top_center());
  273. const gfx::Point end(start + gfx::Vector2d(0, 40));
  274. const base::TimeDelta kTimeDelta = base::Milliseconds(100);
  275. const int kNumScrollSteps = 4;
  276. GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
  277. kNumScrollSteps);
  278. }
  279. void ShelfLayoutManagerTestBase::FlingUpOnShelf() {
  280. gfx::Rect display_bounds =
  281. display::Screen::GetScreen()->GetPrimaryDisplay().bounds();
  282. const gfx::Point start(display_bounds.bottom_center());
  283. const gfx::Point end(start.x(), 10);
  284. const base::TimeDelta kTimeDelta = base::Milliseconds(10);
  285. const int kNumScrollSteps = 4;
  286. GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
  287. kNumScrollSteps);
  288. }
  289. void ShelfLayoutManagerTestBase::DragHotseatDownToBezel() {
  290. gfx::Rect shelf_widget_bounds = GetShelfWidget()->GetWindowBoundsInScreen();
  291. gfx::Rect hotseat_bounds =
  292. GetShelfWidget()->hotseat_widget()->GetWindowBoundsInScreen();
  293. gfx::Point start = hotseat_bounds.top_center();
  294. const gfx::Point end =
  295. gfx::Point(shelf_widget_bounds.x() + shelf_widget_bounds.width() / 2,
  296. shelf_widget_bounds.bottom() + 1);
  297. const base::TimeDelta kTimeDelta = base::Milliseconds(100);
  298. const int kNumScrollSteps = 4;
  299. GetEventGenerator()->GestureScrollSequence(start, end, kTimeDelta,
  300. kNumScrollSteps);
  301. }
  302. // Drag Shelf from |start| to |target| by mouse.
  303. void ShelfLayoutManagerTestBase::MouseDragShelfTo(const gfx::Point& start,
  304. const gfx::Point& target) {
  305. ui::test::EventGenerator* generator = GetEventGenerator();
  306. generator->MoveMouseTo(start);
  307. generator->PressLeftButton();
  308. generator->DragMouseTo(target);
  309. generator->ReleaseLeftButton();
  310. }
  311. // Move mouse to show Shelf in auto-hide mode.
  312. void ShelfLayoutManagerTestBase::MouseMouseToShowAutoHiddenShelf() {
  313. display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
  314. const int display_bottom = display.bounds().bottom();
  315. GetEventGenerator()->MoveMouseTo(1, display_bottom - 1);
  316. ASSERT_TRUE(TriggerAutoHideTimeout());
  317. EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, GetPrimaryShelf()->GetAutoHideState());
  318. }
  319. // Move mouse to |location| and do a two-finger vertical scroll.
  320. void ShelfLayoutManagerTestBase::DoTwoFingerVerticalScrollAtLocation(
  321. gfx::Point location,
  322. int y_offset,
  323. bool reverse_scroll) {
  324. PrefService* prefs =
  325. Shell::Get()->session_controller()->GetLastActiveUserPrefService();
  326. prefs->SetBoolean(prefs::kNaturalScroll, reverse_scroll);
  327. y_offset = reverse_scroll ? -y_offset : y_offset;
  328. GetEventGenerator()->ScrollSequence(location, base::TimeDelta(),
  329. /*x_offset=*/0, y_offset, /*steps=*/1,
  330. /*num_fingers=*/2);
  331. }
  332. // Move mouse to |location| and do a mousewheel scroll.
  333. void ShelfLayoutManagerTestBase::DoMouseWheelScrollAtLocation(
  334. gfx::Point location,
  335. int delta_y,
  336. bool reverse_scroll) {
  337. PrefService* prefs =
  338. Shell::Get()->session_controller()->GetLastActiveUserPrefService();
  339. prefs->SetBoolean(prefs::kMouseReverseScroll, reverse_scroll);
  340. delta_y = reverse_scroll ? -delta_y : delta_y;
  341. GetEventGenerator()->MoveMouseTo(location);
  342. GetEventGenerator()->MoveMouseWheel(/*delta_x=*/0, delta_y);
  343. }
  344. void ShelfLayoutManagerTestBase::RunGestureDragTests(
  345. const gfx::Point& edge_to_hide,
  346. const gfx::Point& edge_to_show) {
  347. ui::test::EventGenerator* generator = GetEventGenerator();
  348. display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
  349. generator->MoveMouseTo(display.bounds().CenterPoint());
  350. Shelf* shelf = GetPrimaryShelf();
  351. shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kNever);
  352. views::Widget* widget = CreateTestWidget();
  353. widget->Maximize();
  354. // The time delta should be large enough to prevent accidental fling creation.
  355. const base::TimeDelta kTimeDelta = base::Milliseconds(100);
  356. aura::Window* window = widget->GetNativeWindow();
  357. ShelfLayoutManager* layout_manager = GetShelfLayoutManager();
  358. layout_manager->LayoutShelf();
  359. gfx::Rect shelf_shown = GetShelfWidget()->GetWindowBoundsInScreen();
  360. gfx::Rect window_bounds_with_shelf = window->bounds();
  361. EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
  362. shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
  363. layout_manager->LayoutShelf();
  364. EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
  365. gfx::Rect window_bounds_with_noshelf = window->bounds();
  366. gfx::Rect shelf_hidden = GetShelfWidget()->GetWindowBoundsInScreen();
  367. // Tests the gesture drag on always shown shelf.
  368. shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kNever);
  369. layout_manager->LayoutShelf();
  370. const int kNumScrollSteps = 4;
  371. ShelfDragCallback handler(shelf_hidden, shelf_shown);
  372. // Swipe down on the always shown shelf should not auto-hide it.
  373. {
  374. SCOPED_TRACE("SWIPE_DOWN_ALWAYS_SHOWN");
  375. generator->GestureScrollSequenceWithCallback(
  376. edge_to_hide, edge_to_show, kTimeDelta, kNumScrollSteps,
  377. base::BindRepeating(&ShelfDragCallback::ProcessScroll,
  378. base::Unretained(&handler)));
  379. }
  380. EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
  381. EXPECT_EQ(ShelfAutoHideBehavior::kNever, shelf->auto_hide_behavior());
  382. EXPECT_EQ(window_bounds_with_shelf.ToString(), window->bounds().ToString());
  383. EXPECT_EQ(shelf_shown.ToString(),
  384. GetShelfWidget()->GetWindowBoundsInScreen().ToString());
  385. // Verify that the shelf can still enter auto hide if the |widget_| has been
  386. // put into fullscreen.
  387. widget->SetFullscreen(true);
  388. WindowState* window_state = WindowState::Get(window);
  389. window_state->SetHideShelfWhenFullscreen(false);
  390. window->SetProperty(kImmersiveIsActive, true);
  391. layout_manager->UpdateVisibilityState();
  392. EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
  393. EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
  394. EXPECT_EQ(ShelfAutoHideBehavior::kNever, shelf->auto_hide_behavior());
  395. // Swiping up should show the shelf if shelf is hidden in fullscreen mode.
  396. generator->GestureScrollSequence(edge_to_hide, edge_to_show, kTimeDelta,
  397. kNumScrollSteps);
  398. EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
  399. EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
  400. EXPECT_EQ(ShelfAutoHideBehavior::kNever, shelf->auto_hide_behavior());
  401. // Swiping down should hide the shelf.
  402. generator->GestureScrollSequence(edge_to_show, edge_to_hide, kTimeDelta,
  403. kNumScrollSteps);
  404. EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
  405. EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
  406. EXPECT_EQ(ShelfAutoHideBehavior::kNever, shelf->auto_hide_behavior());
  407. // Verify that after toggling fullscreen to off, the shelf is visible.
  408. widget->SetFullscreen(false);
  409. EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
  410. // Minimize the visible window, the shelf should be shown if there are no
  411. // visible windows, even in auto-hide mode.
  412. window_state->Minimize();
  413. EXPECT_EQ(SHELF_VISIBLE, shelf->GetVisibilityState());
  414. EXPECT_EQ(ShelfAutoHideBehavior::kNever, shelf->auto_hide_behavior());
  415. // Tests gesture drag on auto-hide shelf.
  416. window_state->Maximize();
  417. shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
  418. layout_manager->LayoutShelf();
  419. EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
  420. // Swipe up the auto-hide shelf should show it.
  421. {
  422. SCOPED_TRACE("SWIPE_UP_AUTO_HIDE_SHOW");
  423. generator->GestureScrollSequenceWithCallback(
  424. edge_to_hide, edge_to_show, kTimeDelta, kNumScrollSteps,
  425. base::BindRepeating(&ShelfDragCallback::ProcessScroll,
  426. base::Unretained(&handler)));
  427. }
  428. EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
  429. EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
  430. // Gesture drag should not change the auto hide behavior of shelf, even though
  431. // its visibility has been changed.
  432. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  433. // The auto-hide shelf is above the window, which should not change the bounds
  434. // of the window.
  435. EXPECT_EQ(window_bounds_with_noshelf.ToString(), window->bounds().ToString());
  436. EXPECT_EQ(shelf_shown.ToString(),
  437. GetShelfWidget()->GetWindowBoundsInScreen().ToString());
  438. // Swipe down very little. It shouldn't change any state.
  439. gfx::Point new_point(edge_to_show);
  440. gfx::Vector2d diff = edge_to_hide - edge_to_show;
  441. new_point.Offset(diff.x() * 3 / 10, diff.y() * 3 / 10);
  442. generator->GestureScrollSequence(edge_to_show, new_point, kTimeDelta, 5);
  443. EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
  444. EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
  445. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  446. EXPECT_EQ(window_bounds_with_noshelf.ToString(), window->bounds().ToString());
  447. EXPECT_EQ(shelf_shown.ToString(),
  448. GetShelfWidget()->GetWindowBoundsInScreen().ToString());
  449. {
  450. SCOPED_TRACE("SWIPE_DOWN_AUTO_HIDE_1");
  451. generator->GestureScrollSequenceWithCallback(
  452. edge_to_show, edge_to_hide, kTimeDelta, kNumScrollSteps,
  453. base::BindRepeating(&ShelfDragCallback::ProcessScroll,
  454. base::Unretained(&handler)));
  455. }
  456. EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
  457. EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
  458. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  459. EXPECT_EQ(window_bounds_with_noshelf.ToString(), window->bounds().ToString());
  460. EXPECT_EQ(shelf_hidden.ToString(),
  461. GetShelfWidget()->GetWindowBoundsInScreen().ToString());
  462. // Swipe up in extended hit region to show it.
  463. gfx::Point extended_start = edge_to_show;
  464. if (shelf->IsHorizontalAlignment())
  465. extended_start.set_y(GetShelfWidget()->GetWindowBoundsInScreen().y() - 1);
  466. else if (ShelfAlignment::kLeft == shelf->alignment())
  467. extended_start.set_x(GetShelfWidget()->GetWindowBoundsInScreen().right() +
  468. 1);
  469. else if (ShelfAlignment::kRight == shelf->alignment())
  470. extended_start.set_x(GetShelfWidget()->GetWindowBoundsInScreen().x() - 1);
  471. {
  472. SCOPED_TRACE("SWIPE_UP_EXTENDED_HIT");
  473. generator->GestureScrollSequenceWithCallback(
  474. extended_start, edge_to_show, kTimeDelta, kNumScrollSteps,
  475. base::BindRepeating(&ShelfDragCallback::ProcessScroll,
  476. base::Unretained(&handler)));
  477. }
  478. EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
  479. EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
  480. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  481. EXPECT_EQ(window_bounds_with_noshelf.ToString(), window->bounds().ToString());
  482. EXPECT_EQ(shelf_shown.ToString(),
  483. GetShelfWidget()->GetWindowBoundsInScreen().ToString());
  484. // Swipe down again to hide.
  485. {
  486. SCOPED_TRACE("SWIPE_DOWN_AUTO_HIDE_2");
  487. generator->GestureScrollSequenceWithCallback(
  488. edge_to_show, edge_to_hide, kTimeDelta, kNumScrollSteps,
  489. base::BindRepeating(&ShelfDragCallback::ProcessScroll,
  490. base::Unretained(&handler)));
  491. }
  492. EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
  493. EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
  494. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  495. EXPECT_EQ(window_bounds_with_noshelf.ToString(), window->bounds().ToString());
  496. EXPECT_EQ(shelf_hidden.ToString(),
  497. GetShelfWidget()->GetWindowBoundsInScreen().ToString());
  498. // Swipe up outside the hit area. This should not change anything.
  499. gfx::Point outside_start =
  500. GetShelfWidget()->GetWindowBoundsInScreen().top_center();
  501. outside_start.set_y(outside_start.y() - 50);
  502. gfx::Vector2d delta = edge_to_hide - edge_to_show;
  503. generator->GestureScrollSequence(outside_start, outside_start + delta,
  504. kTimeDelta, kNumScrollSteps);
  505. EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
  506. EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
  507. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  508. EXPECT_EQ(window_bounds_with_noshelf.ToString(), window->bounds().ToString());
  509. EXPECT_EQ(shelf_hidden.ToString(),
  510. GetShelfWidget()->GetWindowBoundsInScreen().ToString());
  511. // Swipe up from the bottom of the shelf, this should show the shelf.
  512. gfx::Point below_start = edge_to_hide;
  513. generator->GestureScrollSequence(edge_to_hide, edge_to_show, kTimeDelta,
  514. kNumScrollSteps);
  515. EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
  516. EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
  517. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  518. EXPECT_EQ(window_bounds_with_noshelf.ToString(), window->bounds().ToString());
  519. EXPECT_EQ(shelf_shown.ToString(),
  520. GetShelfWidget()->GetWindowBoundsInScreen().ToString());
  521. // Swipe down again to hide.
  522. {
  523. SCOPED_TRACE("SWIPE_DOWN_AUTO_HIDE_3");
  524. generator->GestureScrollSequenceWithCallback(
  525. edge_to_show, edge_to_hide, kTimeDelta, kNumScrollSteps,
  526. base::BindRepeating(&ShelfDragCallback::ProcessScroll,
  527. base::Unretained(&handler)));
  528. }
  529. EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
  530. EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
  531. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  532. EXPECT_EQ(window_bounds_with_noshelf.ToString(), window->bounds().ToString());
  533. EXPECT_EQ(shelf_hidden.ToString(),
  534. GetShelfWidget()->GetWindowBoundsInScreen().ToString());
  535. // Put |widget| into fullscreen. Set the shelf to be auto hidden when |widget|
  536. // is fullscreen. (eg browser immersive fullscreen).
  537. widget->SetFullscreen(true);
  538. WindowState::Get(window)->SetHideShelfWhenFullscreen(false);
  539. layout_manager->UpdateVisibilityState();
  540. gfx::Rect window_bounds_fullscreen = window->bounds();
  541. EXPECT_TRUE(widget->IsFullscreen());
  542. EXPECT_EQ(window_bounds_with_noshelf.ToString(),
  543. window_bounds_fullscreen.ToString());
  544. // Swipe up. This should show the shelf.
  545. {
  546. SCOPED_TRACE("SWIPE_UP_AUTO_HIDE_1");
  547. // Do not check bounds because the events outside of the bounds
  548. // will be clipped.
  549. generator->GestureScrollSequenceWithCallback(
  550. below_start, edge_to_show, kTimeDelta, kNumScrollSteps,
  551. base::BindRepeating(&ShelfDragCallback::ProcessScrollNoBoundsCheck,
  552. base::Unretained(&handler)));
  553. }
  554. EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
  555. EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
  556. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  557. EXPECT_EQ(shelf_shown.ToString(),
  558. GetShelfWidget()->GetWindowBoundsInScreen().ToString());
  559. EXPECT_EQ(window_bounds_fullscreen.ToString(), window->bounds().ToString());
  560. // Swipe down to hide the shelf.
  561. {
  562. SCOPED_TRACE("SWIPE_DOWN_AUTO_HIDE_4");
  563. generator->GestureScrollSequenceWithCallback(
  564. edge_to_show, edge_to_hide, kTimeDelta, kNumScrollSteps,
  565. base::BindRepeating(&ShelfDragCallback::ProcessScroll,
  566. base::Unretained(&handler)));
  567. }
  568. EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
  569. EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
  570. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  571. EXPECT_EQ(shelf_hidden.ToString(),
  572. GetShelfWidget()->GetWindowBoundsInScreen().ToString());
  573. EXPECT_EQ(window_bounds_fullscreen.ToString(), window->bounds().ToString());
  574. // Set the shelf to be hidden when |widget| is fullscreen. (eg tab fullscreen
  575. // with or without immersive browser fullscreen).
  576. WindowState::Get(window)->SetHideShelfWhenFullscreen(true);
  577. layout_manager->UpdateVisibilityState();
  578. EXPECT_EQ(SHELF_HIDDEN, shelf->GetVisibilityState());
  579. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  580. // Swipe-up. This should not change anything.
  581. {
  582. SCOPED_TRACE("SWIPE_UP_NO_CHANGE");
  583. generator->GestureScrollSequenceWithCallback(
  584. below_start, edge_to_show, kTimeDelta, kNumScrollSteps,
  585. base::BindRepeating(&ShelfDragCallback::ProcessScroll,
  586. base::Unretained(&handler)));
  587. EXPECT_EQ(SHELF_HIDDEN, shelf->GetVisibilityState());
  588. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  589. EXPECT_EQ(window_bounds_fullscreen.ToString(), window->bounds().ToString());
  590. }
  591. // Minimize actually, otherwise further event may be affected since widget
  592. // is fullscreen status.
  593. widget->Minimize();
  594. base::RunLoop().RunUntilIdle();
  595. EXPECT_FALSE(layout_manager->HasVisibleWindow());
  596. // The shelf should be shown because there are no more visible windows.
  597. EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
  598. EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
  599. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  600. // Swipe-down to hide. This should have no effect because there are no visible
  601. // windows.
  602. {
  603. SCOPED_TRACE("SWIPE_DOWN_AUTO_HIDE_5");
  604. generator->GestureScrollSequenceWithCallback(
  605. edge_to_show, edge_to_hide, kTimeDelta, kNumScrollSteps,
  606. base::BindRepeating(&ShelfDragCallback::ProcessScroll,
  607. base::Unretained(&handler)));
  608. }
  609. EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
  610. EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
  611. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  612. EXPECT_EQ(shelf_shown.ToString(),
  613. GetShelfWidget()->GetWindowBoundsInScreen().ToString());
  614. // Change the window state back to its Normal state. We do that by sending
  615. // a WM_EVENT_NORMAL to the window, instead of calling Widget::Restore()
  616. // function, because restoring from a kMinimized window state will take
  617. // the window back to its pre-minimized window state.
  618. WMEvent restore_event(WM_EVENT_NORMAL);
  619. WindowState::Get(widget->GetNativeWindow())->OnWMEvent(&restore_event);
  620. base::RunLoop().RunUntilIdle();
  621. EXPECT_TRUE(layout_manager->HasVisibleWindow());
  622. // Swipe up on the shelf. This should show the shelf but should not change the
  623. // auto-hide behavior, since auto-hide behavior can only be changed through
  624. // context menu of the shelf.
  625. {
  626. SCOPED_TRACE("SWIPE_UP_AUTO_HIDE_2");
  627. // Do not check bounds because the events outside of the bounds
  628. // will be clipped.
  629. generator->GestureScrollSequenceWithCallback(
  630. below_start, edge_to_show, kTimeDelta, kNumScrollSteps,
  631. base::BindRepeating(&ShelfDragCallback::ProcessScrollNoBoundsCheck,
  632. base::Unretained(&handler)));
  633. }
  634. EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
  635. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  636. EXPECT_EQ(shelf_shown.ToString(),
  637. GetShelfWidget()->GetWindowBoundsInScreen().ToString());
  638. widget->Close();
  639. base::RunLoop().RunUntilIdle();
  640. EXPECT_FALSE(layout_manager->HasVisibleWindow());
  641. // Swipe-down to hide. This should have no effect because there are no visible
  642. // windows.
  643. {
  644. SCOPED_TRACE("SWIPE_DOWN_AUTO_HIDE_6");
  645. generator->GestureScrollSequenceWithCallback(
  646. edge_to_show, edge_to_hide, kTimeDelta, kNumScrollSteps,
  647. base::BindRepeating(&ShelfDragCallback::ProcessScroll,
  648. base::Unretained(&handler)));
  649. }
  650. EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
  651. EXPECT_EQ(ShelfAutoHideBehavior::kAlways, shelf->auto_hide_behavior());
  652. EXPECT_EQ(shelf_shown.ToString(),
  653. GetShelfWidget()->GetWindowBoundsInScreen().ToString());
  654. // Swipe up again on AUTO_HIDE_SHOWN shelf shouldn't change any state.
  655. // Swipe up on auto-hide shown shelf should still keep shelf shown.
  656. {
  657. SCOPED_TRACE("SWIPE_UP_AUTO_HIDE_4");
  658. generator->GestureScrollSequenceWithCallback(
  659. edge_to_hide, edge_to_show, kTimeDelta, kNumScrollSteps,
  660. base::BindRepeating(&ShelfDragCallback::ProcessScroll,
  661. base::Unretained(&handler)));
  662. }
  663. EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
  664. EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
  665. EXPECT_EQ(shelf_shown.ToString(),
  666. GetShelfWidget()->GetWindowBoundsInScreen().ToString());
  667. }
  668. bool ShelfLayoutManagerTestBase::RunVisibilityUpdateForTrayCallback() {
  669. if (!GetShelfLayoutManager()
  670. ->visibility_update_for_tray_callback_.callback()) {
  671. return false;
  672. }
  673. GetShelfLayoutManager()
  674. ->visibility_update_for_tray_callback_.callback()
  675. .Run();
  676. return true;
  677. }
  678. } // namespace ash