1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ash/wm/window_cycle_controller.h"
6 
7 #include <algorithm>
8 #include <memory>
9 
10 #include "ash/app_list/test/app_list_test_helper.h"
11 #include "ash/focus_cycler.h"
12 #include "ash/frame_throttler/frame_throttling_controller.h"
13 #include "ash/frame_throttler/mock_frame_throttling_observer.h"
14 #include "ash/home_screen/home_screen_controller.h"
15 #include "ash/public/cpp/ash_features.h"
16 #include "ash/public/cpp/shell_window_ids.h"
17 #include "ash/public/cpp/window_properties.h"
18 #include "ash/session/session_controller_impl.h"
19 #include "ash/session/test_session_controller_client.h"
20 #include "ash/shelf/shelf.h"
21 #include "ash/shelf/shelf_view_test_api.h"
22 #include "ash/shelf/shelf_widget.h"
23 #include "ash/shell.h"
24 #include "ash/test/ash_test_base.h"
25 #include "ash/test_shell_delegate.h"
26 #include "ash/wm/desks/desk.h"
27 #include "ash/wm/desks/desks_controller.h"
28 #include "ash/wm/desks/desks_test_util.h"
29 #include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h"
30 #include "ash/wm/window_cycle_list.h"
31 #include "ash/wm/window_state.h"
32 #include "ash/wm/window_util.h"
33 #include "ash/wm/wm_event.h"
34 #include "base/test/metrics/histogram_tester.h"
35 #include "base/test/scoped_feature_list.h"
36 #include "ui/aura/client/aura_constants.h"
37 #include "ui/aura/client/screen_position_client.h"
38 #include "ui/aura/env.h"
39 #include "ui/aura/test/test_windows.h"
40 #include "ui/aura/window.h"
41 #include "ui/aura/window_event_dispatcher.h"
42 #include "ui/display/display_layout_builder.h"
43 #include "ui/display/manager/display_layout_store.h"
44 #include "ui/display/manager/display_manager.h"
45 #include "ui/display/scoped_display_for_new_windows.h"
46 #include "ui/display/test/display_manager_test_api.h"
47 #include "ui/events/event_handler.h"
48 #include "ui/events/test/event_generator.h"
49 #include "ui/gfx/geometry/rect.h"
50 
51 namespace ash {
52 
53 namespace {
54 
55 class EventCounter : public ui::EventHandler {
56  public:
EventCounter()57   EventCounter() : key_events_(0), mouse_events_(0) {}
58   ~EventCounter() override = default;
59 
GetKeyEventCountAndReset()60   int GetKeyEventCountAndReset() {
61     int count = key_events_;
62     key_events_ = 0;
63     return count;
64   }
65 
GetMouseEventCountAndReset()66   int GetMouseEventCountAndReset() {
67     int count = mouse_events_;
68     mouse_events_ = 0;
69     return count;
70   }
71 
72   // ui::EventHandler:
OnKeyEvent(ui::KeyEvent * event)73   void OnKeyEvent(ui::KeyEvent* event) override { key_events_++; }
OnMouseEvent(ui::MouseEvent * event)74   void OnMouseEvent(ui::MouseEvent* event) override { mouse_events_++; }
75 
76  private:
77   int key_events_;
78   int mouse_events_;
79 
80   DISALLOW_COPY_AND_ASSIGN(EventCounter);
81 };
82 
IsWindowMinimized(aura::Window * window)83 bool IsWindowMinimized(aura::Window* window) {
84   return WindowState::Get(window)->IsMinimized();
85 }
86 
87 }  // namespace
88 
89 using aura::test::CreateTestWindowWithId;
90 using aura::test::TestWindowDelegate;
91 using aura::Window;
92 
93 class WindowCycleControllerTest : public AshTestBase {
94  public:
95   WindowCycleControllerTest() = default;
96   ~WindowCycleControllerTest() override = default;
97 
SetUp()98   void SetUp() override {
99     AshTestBase::SetUp();
100 
101     WindowCycleList::DisableInitialDelayForTesting();
102 
103     shelf_view_test_.reset(
104         new ShelfViewTestAPI(GetPrimaryShelf()->GetShelfViewForTesting()));
105     shelf_view_test_->SetAnimationDuration(
106         base::TimeDelta::FromMilliseconds(1));
107   }
108 
GetWindows(WindowCycleController * controller)109   const aura::Window::Windows GetWindows(WindowCycleController* controller) {
110     return controller->window_cycle_list()->windows();
111   }
112 
GetWindowCycleListWidget() const113   const views::Widget* GetWindowCycleListWidget() const {
114     return Shell::Get()
115         ->window_cycle_controller()
116         ->window_cycle_list()
117         ->widget();
118   }
119 
GetWindowCycleItemViews() const120   const views::View::Views& GetWindowCycleItemViews() const {
121     return Shell::Get()
122         ->window_cycle_controller()
123         ->window_cycle_list()
124         ->GetWindowCycleItemViewsForTesting();
125   }
126 
GetTargetWindow() const127   const aura::Window* GetTargetWindow() const {
128     return Shell::Get()
129         ->window_cycle_controller()
130         ->window_cycle_list()
131         ->GetTargetWindowForTesting();
132   }
133 
CycleViewExists() const134   bool CycleViewExists() const {
135     return Shell::Get()
136         ->window_cycle_controller()
137         ->window_cycle_list()
138         ->cycle_view_for_testing();
139   }
140 
GetCurrentIndex() const141   int GetCurrentIndex() const {
142     return Shell::Get()
143         ->window_cycle_controller()
144         ->window_cycle_list()
145         ->current_index_for_testing();
146   }
147 
148  private:
149   std::unique_ptr<ShelfViewTestAPI> shelf_view_test_;
150 
151   DISALLOW_COPY_AND_ASSIGN(WindowCycleControllerTest);
152 };
153 
TEST_F(WindowCycleControllerTest,HandleCycleWindowBaseCases)154 TEST_F(WindowCycleControllerTest, HandleCycleWindowBaseCases) {
155   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
156 
157   // Cycling doesn't crash if there are no windows.
158   controller->HandleCycleWindow(WindowCycleController::FORWARD);
159 
160   // Create a single test window.
161   std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
162   wm::ActivateWindow(window0.get());
163   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
164 
165   // Cycling works for a single window, even though nothing changes.
166   controller->HandleCycleWindow(WindowCycleController::FORWARD);
167   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
168 }
169 
170 // Verifies if there is only one window and it isn't active that cycling
171 // activates it.
TEST_F(WindowCycleControllerTest,SingleWindowNotActive)172 TEST_F(WindowCycleControllerTest, SingleWindowNotActive) {
173   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
174 
175   // Create a single test window.
176   std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
177   wm::ActivateWindow(window0.get());
178   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
179 
180   // Rotate focus, this should move focus to another window that isn't part of
181   // the default container.
182   Shell::Get()->focus_cycler()->RotateFocus(FocusCycler::FORWARD);
183   EXPECT_FALSE(wm::IsActiveWindow(window0.get()));
184 
185   // Cycling should activate the window.
186   controller->HandleCycleWindow(WindowCycleController::FORWARD);
187   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
188 }
189 
TEST_F(WindowCycleControllerTest,HandleCycleWindow)190 TEST_F(WindowCycleControllerTest, HandleCycleWindow) {
191   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
192 
193   // Set up several windows to use to test cycling.  Create them in reverse
194   // order so they are stacked 0 over 1 over 2.
195   std::unique_ptr<Window> window2(CreateTestWindowInShellWithId(2));
196   std::unique_ptr<Window> window1(CreateTestWindowInShellWithId(1));
197   std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
198   wm::ActivateWindow(window0.get());
199 
200   // Simulate pressing and releasing Alt-tab.
201   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
202   controller->HandleCycleWindow(WindowCycleController::FORWARD);
203 
204   // Window lists should return the topmost window in front.
205   ASSERT_TRUE(controller->window_cycle_list());
206   ASSERT_EQ(3u, GetWindows(controller).size());
207   ASSERT_EQ(window0.get(), GetWindows(controller)[0]);
208   ASSERT_EQ(window1.get(), GetWindows(controller)[1]);
209   ASSERT_EQ(window2.get(), GetWindows(controller)[2]);
210 
211   controller->CompleteCycling();
212   EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
213 
214   // Pressing and releasing Alt-tab again should cycle back to the most-
215   // recently-used window in the current child order.
216   controller->HandleCycleWindow(WindowCycleController::FORWARD);
217   controller->CompleteCycling();
218   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
219 
220   // Cancelled cycling shouldn't move the active window.
221   controller->HandleCycleWindow(WindowCycleController::FORWARD);
222   controller->CancelCycling();
223   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
224 
225   // Pressing Alt-tab multiple times without releasing Alt should cycle through
226   // all the windows and wrap around.
227   controller->HandleCycleWindow(WindowCycleController::FORWARD);
228   EXPECT_TRUE(controller->IsCycling());
229 
230   controller->HandleCycleWindow(WindowCycleController::FORWARD);
231   EXPECT_TRUE(controller->IsCycling());
232 
233   controller->HandleCycleWindow(WindowCycleController::FORWARD);
234   EXPECT_TRUE(controller->IsCycling());
235 
236   controller->CompleteCycling();
237   EXPECT_FALSE(controller->IsCycling());
238   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
239 
240   // Reset our stacking order.
241   wm::ActivateWindow(window2.get());
242   wm::ActivateWindow(window1.get());
243   wm::ActivateWindow(window0.get());
244 
245   // Likewise we can cycle backwards through the windows.
246   controller->HandleCycleWindow(WindowCycleController::BACKWARD);
247   controller->HandleCycleWindow(WindowCycleController::BACKWARD);
248   controller->CompleteCycling();
249   EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
250 
251   // Reset our stacking order.
252   wm::ActivateWindow(window2.get());
253   wm::ActivateWindow(window1.get());
254   wm::ActivateWindow(window0.get());
255 
256   // When the screen is locked, cycling window does not take effect.
257   GetSessionControllerClient()->LockScreen();
258   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
259   controller->HandleCycleWindow(WindowCycleController::FORWARD);
260   EXPECT_FALSE(controller->IsCycling());
261 
262   // Unlock, it works again.
263   GetSessionControllerClient()->UnlockScreen();
264   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
265   controller->HandleCycleWindow(WindowCycleController::FORWARD);
266   controller->HandleCycleWindow(WindowCycleController::FORWARD);
267   controller->CompleteCycling();
268   EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
269 
270   // When a modal window is active, cycling window does not take effect.
271   aura::Window* modal_container = Shell::GetContainer(
272       Shell::GetPrimaryRootWindow(), kShellWindowId_SystemModalContainer);
273   std::unique_ptr<Window> modal_window(
274       CreateTestWindowWithId(-2, modal_container));
275   modal_window->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_SYSTEM);
276   wm::ActivateWindow(modal_window.get());
277   EXPECT_TRUE(wm::IsActiveWindow(modal_window.get()));
278   controller->HandleCycleWindow(WindowCycleController::FORWARD);
279   EXPECT_TRUE(wm::IsActiveWindow(modal_window.get()));
280   EXPECT_FALSE(controller->IsCycling());
281   EXPECT_FALSE(wm::IsActiveWindow(window0.get()));
282   EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
283   EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
284   controller->HandleCycleWindow(WindowCycleController::BACKWARD);
285   EXPECT_TRUE(wm::IsActiveWindow(modal_window.get()));
286   EXPECT_FALSE(controller->IsCycling());
287   EXPECT_FALSE(wm::IsActiveWindow(window0.get()));
288   EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
289   EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
290 
291   modal_window.reset();
292   std::unique_ptr<Window> skip_overview_window(
293       CreateTestWindowInShellWithId(-3));
294   skip_overview_window->SetProperty(kHideInOverviewKey, true);
295   wm::ActivateWindow(window0.get());
296   wm::ActivateWindow(skip_overview_window.get());
297   wm::ActivateWindow(window1.get());
298   EXPECT_FALSE(wm::IsActiveWindow(window0.get()));
299   controller->HandleCycleWindow(WindowCycleController::FORWARD);
300   controller->CompleteCycling();
301   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
302   EXPECT_FALSE(wm::IsActiveWindow(skip_overview_window.get()));
303   EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
304 }
305 
TEST_F(WindowCycleControllerTest,Scroll)306 TEST_F(WindowCycleControllerTest, Scroll) {
307   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
308 
309   // Doesn't crash if there are no windows.
310   controller->Scroll(WindowCycleController::FORWARD);
311 
312   // Create test windows.
313   std::unique_ptr<Window> w5 = CreateTestWindow(gfx::Rect(0, 0, 200, 200));
314   std::unique_ptr<Window> w4 = CreateTestWindow(gfx::Rect(0, 0, 200, 200));
315   std::unique_ptr<Window> w3 = CreateTestWindow(gfx::Rect(0, 0, 200, 200));
316   std::unique_ptr<Window> w2 = CreateTestWindow(gfx::Rect(0, 0, 200, 200));
317   std::unique_ptr<Window> w1 = CreateTestWindow(gfx::Rect(0, 0, 200, 200));
318   std::unique_ptr<Window> w0 = CreateTestWindow(gfx::Rect(0, 0, 200, 200));
319 
320   auto ScrollAndReturnCurrentIndex =
321       [this](WindowCycleController::Direction direction, int num_of_scrolls) {
322         WindowCycleController* controller =
323             Shell::Get()->window_cycle_controller();
324         for (int i = 0; i < num_of_scrolls; i++)
325           controller->Scroll(direction);
326 
327         return GetCurrentIndex();
328       };
329 
330   auto GetXOfCycleListCenterPoint = [this]() {
331     return GetWindowCycleListWidget()
332         ->GetWindowBoundsInScreen()
333         .CenterPoint()
334         .x();
335   };
336 
337   auto GetXOfWindowCycleItemViewCenterPoint = [this](int index) {
338     return GetWindowCycleItemViews()[index]
339         ->GetBoundsInScreen()
340         .CenterPoint()
341         .x();
342   };
343 
344   // Start cycling and scroll forward. The list should be not be centered around
345   // w1. Since w1 is so close to the beginning of the list.
346   controller->StartCycling();
347   int current_index =
348       ScrollAndReturnCurrentIndex(WindowCycleController::FORWARD, 1);
349   EXPECT_EQ(1, current_index);
350   EXPECT_GT(GetXOfCycleListCenterPoint(),
351             GetXOfWindowCycleItemViewCenterPoint(current_index));
352 
353   // Scroll forward twice. The list should be centered around w3.
354   current_index =
355       ScrollAndReturnCurrentIndex(WindowCycleController::FORWARD, 2);
356   EXPECT_EQ(3, current_index);
357   EXPECT_EQ(GetXOfCycleListCenterPoint(),
358             GetXOfWindowCycleItemViewCenterPoint(current_index));
359 
360   // Scroll backward once. The list should be centered around w2.
361   current_index =
362       ScrollAndReturnCurrentIndex(WindowCycleController::BACKWARD, 1);
363   EXPECT_EQ(2, current_index);
364   EXPECT_EQ(GetXOfCycleListCenterPoint(),
365             GetXOfWindowCycleItemViewCenterPoint(current_index));
366 
367   // Scroll backward three times. The list should not be centered around w5.
368   current_index =
369       ScrollAndReturnCurrentIndex(WindowCycleController::BACKWARD, 3);
370   EXPECT_EQ(5, current_index);
371   EXPECT_LT(GetXOfCycleListCenterPoint(),
372             GetXOfWindowCycleItemViewCenterPoint(current_index));
373 
374   // Cycle forward. Since the target window != current window, it should scroll
375   // to target window then cycle. The target_window was w0 prior to cycling.
376   controller->HandleCycleWindow(WindowCycleController::FORWARD);
377   current_index = GetCurrentIndex();
378   EXPECT_EQ(1, current_index);
379   EXPECT_GT(GetXOfCycleListCenterPoint(),
380             GetXOfWindowCycleItemViewCenterPoint(current_index));
381   controller->CompleteCycling();
382   EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
383 
384   // Start cycling, scroll backward once and complete cycling. Scroll should not
385   // affect the selected window.
386   controller->StartCycling();
387   current_index =
388       ScrollAndReturnCurrentIndex(WindowCycleController::BACKWARD, 1);
389   EXPECT_EQ(5, current_index);
390   controller->CompleteCycling();
391   EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
392 }
393 
394 // Cycles between a maximized and normal window.
TEST_F(WindowCycleControllerTest,MaximizedWindow)395 TEST_F(WindowCycleControllerTest, MaximizedWindow) {
396   // Create a couple of test windows.
397   std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
398   std::unique_ptr<Window> window1(CreateTestWindowInShellWithId(1));
399   WindowState* window1_state = WindowState::Get(window1.get());
400   window1_state->Maximize();
401   window1_state->Activate();
402   EXPECT_TRUE(window1_state->IsActive());
403 
404   // Rotate focus, this should move focus to window0.
405   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
406   controller->HandleCycleWindow(WindowCycleController::FORWARD);
407   controller->CompleteCycling();
408   EXPECT_TRUE(WindowState::Get(window0.get())->IsActive());
409   EXPECT_FALSE(window1_state->IsActive());
410 
411   // One more time.
412   controller->HandleCycleWindow(WindowCycleController::FORWARD);
413   controller->CompleteCycling();
414   EXPECT_TRUE(window1_state->IsActive());
415 }
416 
417 // Cycles to a minimized window.
TEST_F(WindowCycleControllerTest,Minimized)418 TEST_F(WindowCycleControllerTest, Minimized) {
419   // Create a couple of test windows.
420   std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
421   std::unique_ptr<Window> window1(CreateTestWindowInShellWithId(1));
422   WindowState* window0_state = WindowState::Get(window0.get());
423   WindowState* window1_state = WindowState::Get(window1.get());
424 
425   window1_state->Minimize();
426   window0_state->Activate();
427   EXPECT_TRUE(window0_state->IsActive());
428 
429   // Rotate focus, this should move focus to window1 and unminimize it.
430   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
431   controller->HandleCycleWindow(WindowCycleController::FORWARD);
432   controller->CompleteCycling();
433   EXPECT_FALSE(window0_state->IsActive());
434   EXPECT_FALSE(window1_state->IsMinimized());
435   EXPECT_TRUE(window1_state->IsActive());
436 
437   // One more time back to w0.
438   controller->HandleCycleWindow(WindowCycleController::FORWARD);
439   controller->CompleteCycling();
440   EXPECT_TRUE(window0_state->IsActive());
441 }
442 
443 // Tests that when all windows are minimized, cycling starts with the first one
444 // rather than the second.
TEST_F(WindowCycleControllerTest,AllAreMinimized)445 TEST_F(WindowCycleControllerTest, AllAreMinimized) {
446   // Create a couple of test windows.
447   std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
448   std::unique_ptr<Window> window1(CreateTestWindowInShellWithId(1));
449   WindowState* window0_state = WindowState::Get(window0.get());
450   WindowState* window1_state = WindowState::Get(window1.get());
451 
452   window0_state->Minimize();
453   window1_state->Minimize();
454 
455   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
456   controller->HandleCycleWindow(WindowCycleController::FORWARD);
457   controller->CompleteCycling();
458   EXPECT_TRUE(window0_state->IsActive());
459   EXPECT_FALSE(window0_state->IsMinimized());
460   EXPECT_TRUE(window1_state->IsMinimized());
461 
462   // But it's business as usual when cycling backwards.
463   window0_state->Minimize();
464   window1_state->Minimize();
465   controller->HandleCycleWindow(WindowCycleController::BACKWARD);
466   controller->CompleteCycling();
467   EXPECT_TRUE(window0_state->IsMinimized());
468   EXPECT_TRUE(window1_state->IsActive());
469   EXPECT_FALSE(window1_state->IsMinimized());
470 }
471 
TEST_F(WindowCycleControllerTest,AlwaysOnTopWindow)472 TEST_F(WindowCycleControllerTest, AlwaysOnTopWindow) {
473   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
474 
475   // Set up several windows to use to test cycling.
476   std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
477   std::unique_ptr<Window> window1(CreateTestWindowInShellWithId(1));
478 
479   Window* top_container = Shell::GetContainer(
480       Shell::GetPrimaryRootWindow(), kShellWindowId_AlwaysOnTopContainer);
481   std::unique_ptr<Window> window2(CreateTestWindowWithId(2, top_container));
482   wm::ActivateWindow(window0.get());
483 
484   // Simulate pressing and releasing Alt-tab.
485   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
486   controller->HandleCycleWindow(WindowCycleController::FORWARD);
487 
488   // Window lists should return the topmost window in front.
489   ASSERT_TRUE(controller->window_cycle_list());
490   ASSERT_EQ(3u, GetWindows(controller).size());
491   EXPECT_EQ(window0.get(), GetWindows(controller)[0]);
492   EXPECT_EQ(window2.get(), GetWindows(controller)[1]);
493   EXPECT_EQ(window1.get(), GetWindows(controller)[2]);
494 
495   controller->CompleteCycling();
496 }
497 
TEST_F(WindowCycleControllerTest,AlwaysOnTopMultiWindow)498 TEST_F(WindowCycleControllerTest, AlwaysOnTopMultiWindow) {
499   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
500 
501   // Set up several windows to use to test cycling.
502   std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
503   std::unique_ptr<Window> window1(CreateTestWindowInShellWithId(1));
504 
505   Window* top_container = Shell::GetContainer(
506       Shell::GetPrimaryRootWindow(), kShellWindowId_AlwaysOnTopContainer);
507   std::unique_ptr<Window> window2(CreateTestWindowWithId(2, top_container));
508   std::unique_ptr<Window> window3(CreateTestWindowWithId(3, top_container));
509   wm::ActivateWindow(window0.get());
510 
511   // Simulate pressing and releasing Alt-tab.
512   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
513   controller->HandleCycleWindow(WindowCycleController::FORWARD);
514 
515   // Window lists should return the topmost window in front.
516   ASSERT_TRUE(controller->window_cycle_list());
517   ASSERT_EQ(4u, GetWindows(controller).size());
518   EXPECT_EQ(window0.get(), GetWindows(controller)[0]);
519   EXPECT_EQ(window3.get(), GetWindows(controller)[1]);
520   EXPECT_EQ(window2.get(), GetWindows(controller)[2]);
521   EXPECT_EQ(window1.get(), GetWindows(controller)[3]);
522 
523   controller->CompleteCycling();
524 }
525 
TEST_F(WindowCycleControllerTest,AlwaysOnTopMultipleRootWindows)526 TEST_F(WindowCycleControllerTest, AlwaysOnTopMultipleRootWindows) {
527   // Set up a second root window
528   UpdateDisplay("1000x600,600x400");
529   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
530   ASSERT_EQ(2U, root_windows.size());
531 
532   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
533 
534   // Create two windows in the primary root.
535   std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
536   EXPECT_EQ(root_windows[0], window0->GetRootWindow());
537   Window* top_container0 =
538       Shell::GetContainer(root_windows[0], kShellWindowId_AlwaysOnTopContainer);
539   std::unique_ptr<Window> window1(CreateTestWindowWithId(1, top_container0));
540   EXPECT_EQ(root_windows[0], window1->GetRootWindow());
541 
542   // Move the active root window to the secondary root and create two windows.
543   display::ScopedDisplayForNewWindows display_for_new_windows(root_windows[1]);
544   std::unique_ptr<Window> window2(CreateTestWindowInShellWithId(2));
545   EXPECT_EQ(root_windows[1], window2->GetRootWindow());
546 
547   Window* top_container1 =
548       Shell::GetContainer(root_windows[1], kShellWindowId_AlwaysOnTopContainer);
549   std::unique_ptr<Window> window3(CreateTestWindowWithId(3, top_container1));
550   EXPECT_EQ(root_windows[1], window3->GetRootWindow());
551 
552   wm::ActivateWindow(window2.get());
553 
554   EXPECT_EQ(root_windows[0], window0->GetRootWindow());
555   EXPECT_EQ(root_windows[0], window1->GetRootWindow());
556   EXPECT_EQ(root_windows[1], window2->GetRootWindow());
557   EXPECT_EQ(root_windows[1], window3->GetRootWindow());
558 
559   // Simulate pressing and releasing Alt-tab.
560   EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
561   controller->HandleCycleWindow(WindowCycleController::FORWARD);
562 
563   // Window lists should return the topmost window in front.
564   ASSERT_TRUE(controller->window_cycle_list());
565   ASSERT_EQ(4u, GetWindows(controller).size());
566   EXPECT_EQ(window2.get(), GetWindows(controller)[0]);
567   EXPECT_EQ(window3.get(), GetWindows(controller)[1]);
568   EXPECT_EQ(window1.get(), GetWindows(controller)[2]);
569   EXPECT_EQ(window0.get(), GetWindows(controller)[3]);
570 
571   controller->CompleteCycling();
572 }
573 
TEST_F(WindowCycleControllerTest,MostRecentlyUsed)574 TEST_F(WindowCycleControllerTest, MostRecentlyUsed) {
575   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
576 
577   // Set up several windows to use to test cycling.
578   std::unique_ptr<Window> window0(CreateTestWindowInShellWithId(0));
579   std::unique_ptr<Window> window1(CreateTestWindowInShellWithId(1));
580   std::unique_ptr<Window> window2(CreateTestWindowInShellWithId(2));
581 
582   wm::ActivateWindow(window0.get());
583 
584   // Simulate pressing and releasing Alt-tab.
585   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
586   controller->HandleCycleWindow(WindowCycleController::FORWARD);
587 
588   // Window lists should return the topmost window in front.
589   ASSERT_TRUE(controller->window_cycle_list());
590   ASSERT_EQ(3u, GetWindows(controller).size());
591   EXPECT_EQ(window0.get(), GetWindows(controller)[0]);
592   EXPECT_EQ(window2.get(), GetWindows(controller)[1]);
593   EXPECT_EQ(window1.get(), GetWindows(controller)[2]);
594 
595   // Cycling through then stopping the cycling will activate a window.
596   controller->HandleCycleWindow(WindowCycleController::FORWARD);
597   controller->CompleteCycling();
598   EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
599 
600   // Cycling alone (without CompleteCycling()) doesn't activate.
601   controller->HandleCycleWindow(WindowCycleController::FORWARD);
602   EXPECT_FALSE(wm::IsActiveWindow(window0.get()));
603 
604   controller->CompleteCycling();
605 }
606 
607 // Tests that beginning window selection hides the app list.
TEST_F(WindowCycleControllerTest,SelectingHidesAppList)608 TEST_F(WindowCycleControllerTest, SelectingHidesAppList) {
609   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
610 
611   std::unique_ptr<aura::Window> window0(CreateTestWindowInShellWithId(0));
612   std::unique_ptr<aura::Window> window1(CreateTestWindowInShellWithId(1));
613   wm::ActivateWindow(window0.get());
614 
615   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplay().id());
616   GetAppListTestHelper()->CheckVisibility(true);
617   controller->HandleCycleWindow(WindowCycleController::FORWARD);
618   GetAppListTestHelper()->WaitUntilIdle();
619   GetAppListTestHelper()->CheckVisibility(false);
620 
621   // Make sure that dismissing the app list this way doesn't pass activation
622   // to a different window.
623   EXPECT_TRUE(wm::IsActiveWindow(window0.get()));
624   EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
625 
626   controller->CompleteCycling();
627 }
628 
629 // Tests that beginning window selection doesn't hide the app list in tablet
630 // mode.
TEST_F(WindowCycleControllerTest,SelectingDoesNotHideAppListInTabletMode)631 TEST_F(WindowCycleControllerTest, SelectingDoesNotHideAppListInTabletMode) {
632   TabletModeControllerTestApi().EnterTabletMode();
633   EXPECT_TRUE(TabletModeControllerTestApi().IsTabletModeStarted());
634   EXPECT_TRUE(Shell::Get()->home_screen_controller()->IsHomeScreenVisible());
635 
636   std::unique_ptr<aura::Window> window0(CreateTestWindowInShellWithId(0));
637   std::unique_ptr<aura::Window> window1(CreateTestWindowInShellWithId(1));
638   wm::ActivateWindow(window0.get());
639 
640   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
641   controller->HandleCycleWindow(WindowCycleController::FORWARD);
642 
643   window0->Hide();
644   window1->Hide();
645   EXPECT_TRUE(Shell::Get()->home_screen_controller()->IsHomeScreenVisible());
646 }
647 
648 // Tests that cycling through windows doesn't change their minimized state.
TEST_F(WindowCycleControllerTest,CyclePreservesMinimization)649 TEST_F(WindowCycleControllerTest, CyclePreservesMinimization) {
650   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
651 
652   std::unique_ptr<aura::Window> window0(CreateTestWindowInShellWithId(0));
653   std::unique_ptr<aura::Window> window1(CreateTestWindowInShellWithId(1));
654   wm::ActivateWindow(window1.get());
655   WindowState::Get(window1.get())->Minimize();
656   wm::ActivateWindow(window0.get());
657   EXPECT_TRUE(IsWindowMinimized(window1.get()));
658 
659   // On window 2.
660   controller->HandleCycleWindow(WindowCycleController::FORWARD);
661   EXPECT_TRUE(IsWindowMinimized(window1.get()));
662 
663   // Back on window 1.
664   controller->HandleCycleWindow(WindowCycleController::FORWARD);
665   EXPECT_TRUE(IsWindowMinimized(window1.get()));
666 
667   controller->CompleteCycling();
668 
669   EXPECT_TRUE(IsWindowMinimized(window1.get()));
670 }
671 
672 // Tests that the tab key events are not sent to the window.
TEST_F(WindowCycleControllerTest,TabKeyNotLeaked)673 TEST_F(WindowCycleControllerTest, TabKeyNotLeaked) {
674   std::unique_ptr<Window> w0(CreateTestWindowInShellWithId(0));
675   std::unique_ptr<Window> w1(CreateTestWindowInShellWithId(1));
676   EventCounter event_count;
677   w0->AddPreTargetHandler(&event_count);
678   w1->AddPreTargetHandler(&event_count);
679   ui::test::EventGenerator* generator = GetEventGenerator();
680   WindowState::Get(w0.get())->Activate();
681   generator->PressKey(ui::VKEY_MENU, ui::EF_NONE);
682   EXPECT_EQ(1, event_count.GetKeyEventCountAndReset());
683   generator->PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
684   EXPECT_EQ(0, event_count.GetKeyEventCountAndReset());
685   generator->ReleaseKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
686   EXPECT_EQ(0, event_count.GetKeyEventCountAndReset());
687   generator->ReleaseKey(ui::VKEY_MENU, ui::EF_NONE);
688   EXPECT_TRUE(WindowState::Get(w1.get())->IsActive());
689   EXPECT_EQ(0, event_count.GetKeyEventCountAndReset());
690 }
691 
692 // While the UI is active, mouse events are captured.
TEST_F(WindowCycleControllerTest,MouseEventsCaptured)693 TEST_F(WindowCycleControllerTest, MouseEventsCaptured) {
694   if (features::IsInteractiveWindowCycleListEnabled())
695     return;
696 
697   // Set up a second root window
698   UpdateDisplay("1000x600,600x400");
699   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
700   ASSERT_EQ(2U, root_windows.size());
701 
702   // This delegate allows the window to receive mouse events.
703   aura::test::TestWindowDelegate delegate;
704   std::unique_ptr<Window> w0(CreateTestWindowInShellWithDelegate(
705       &delegate, 0, gfx::Rect(0, 0, 100, 100)));
706   std::unique_ptr<Window> w1(CreateTestWindowInShellWithId(1));
707   EventCounter event_count;
708   w0->AddPreTargetHandler(&event_count);
709   w1->SetTargetHandler(&event_count);
710   ui::test::EventGenerator* generator = GetEventGenerator();
711   wm::ActivateWindow(w0.get());
712 
713   // Events get through while not cycling.
714   generator->MoveMouseToCenterOf(w0.get());
715   generator->ClickLeftButton();
716   EXPECT_LT(0, event_count.GetMouseEventCountAndReset());
717 
718   // Start cycling.
719   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
720   controller->HandleCycleWindow(WindowCycleController::FORWARD);
721 
722   // Mouse events not over the cycle view don't get through.
723   generator->PressLeftButton();
724   EXPECT_EQ(0, event_count.GetMouseEventCountAndReset());
725 
726   // Although releases do, regardless of mouse position.
727   generator->ReleaseLeftButton();
728   EXPECT_LT(0, event_count.GetMouseEventCountAndReset());
729 
730   // Stop cycling: once again, events get through.
731   controller->CompleteCycling();
732   generator->ClickLeftButton();
733   EXPECT_LT(0, event_count.GetMouseEventCountAndReset());
734 
735   // Click somewhere on the second root window.
736   generator->MoveMouseToCenterOf(root_windows[1]);
737   generator->ClickLeftButton();
738   EXPECT_EQ(0, event_count.GetMouseEventCountAndReset());
739 }
740 
741 // Tests that we can cycle past fullscreen windows: https://crbug.com/622396.
742 // Fullscreen windows are special in that they are allowed to handle alt+tab
743 // keypresses, which means the window cycle event filter should not handle
744 // the tab press else it prevents cycling past that window.
TEST_F(WindowCycleControllerTest,TabPastFullscreenWindow)745 TEST_F(WindowCycleControllerTest, TabPastFullscreenWindow) {
746   std::unique_ptr<Window> w0(CreateTestWindowInShellWithId(0));
747   std::unique_ptr<Window> w1(CreateTestWindowInShellWithId(1));
748   WMEvent maximize_event(WM_EVENT_FULLSCREEN);
749 
750   // To make this test work with or without the new alt+tab selector we make
751   // both the initial window and the second window fullscreen.
752   WindowState::Get(w0.get())->OnWMEvent(&maximize_event);
753   WindowState::Get(w1.get())->Activate();
754   WindowState::Get(w1.get())->OnWMEvent(&maximize_event);
755   EXPECT_TRUE(WindowState::Get(w0.get())->IsFullscreen());
756   EXPECT_TRUE(WindowState::Get(w1.get())->IsFullscreen());
757   WindowState::Get(w0.get())->Activate();
758   EXPECT_TRUE(WindowState::Get(w0.get())->IsActive());
759 
760   ui::test::EventGenerator* generator = GetEventGenerator();
761   generator->PressKey(ui::VKEY_MENU, ui::EF_NONE);
762 
763   generator->PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
764   generator->ReleaseKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
765 
766   // Because w0 and w1 are full-screen, the event should be passed to the
767   // browser window to handle it (which if the browser doesn't handle it will
768   // pass on the alt+tab to continue cycling). To make this test work with or
769   // without the new alt+tab selector we check for the event on either
770   // fullscreen window.
771   EventCounter event_count;
772   w0->AddPreTargetHandler(&event_count);
773   w1->AddPreTargetHandler(&event_count);
774   generator->PressKey(ui::VKEY_TAB, ui::EF_ALT_DOWN);
775   EXPECT_EQ(1, event_count.GetKeyEventCountAndReset());
776 }
777 
778 // Tests that the Alt+Tab UI's position isn't affected by the origin of the
779 // display it's on. See crbug.com/675718
TEST_F(WindowCycleControllerTest,MultiDisplayPositioning)780 TEST_F(WindowCycleControllerTest, MultiDisplayPositioning) {
781   int64_t primary_id = GetPrimaryDisplay().id();
782   display::DisplayIdList list =
783       display::test::CreateDisplayIdListN(primary_id, 2);
784 
785   auto placements = {
786       display::DisplayPlacement::BOTTOM, display::DisplayPlacement::TOP,
787       display::DisplayPlacement::LEFT, display::DisplayPlacement::RIGHT,
788   };
789 
790   gfx::Rect expected_bounds;
791   for (auto placement : placements) {
792     SCOPED_TRACE(placement);
793 
794     display::DisplayLayoutBuilder builder(primary_id);
795     builder.AddDisplayPlacement(list[1], primary_id, placement, 0);
796     display_manager()->layout_store()->RegisterLayoutForDisplayIdList(
797         list, builder.Build());
798 
799     // Use two displays.
800     UpdateDisplay("500x500,600x600");
801 
802     gfx::Rect second_display_bounds =
803         display_manager()->GetDisplayAt(1).bounds();
804     std::unique_ptr<Window> window0(
805         CreateTestWindowInShellWithBounds(second_display_bounds));
806     // Activate this window so that the secondary display becomes the one where
807     // the Alt+Tab UI is shown.
808     wm::ActivateWindow(window0.get());
809     std::unique_ptr<Window> window1(
810         CreateTestWindowInShellWithBounds(second_display_bounds));
811 
812     WindowCycleController* controller = Shell::Get()->window_cycle_controller();
813     controller->HandleCycleWindow(WindowCycleController::FORWARD);
814 
815     const gfx::Rect bounds =
816         GetWindowCycleListWidget()->GetWindowBoundsInScreen();
817     EXPECT_TRUE(second_display_bounds.Contains(bounds));
818     EXPECT_FALSE(
819         display_manager()->GetDisplayAt(0).bounds().Intersects(bounds));
820     const gfx::Rect display_relative_bounds =
821         bounds - second_display_bounds.OffsetFromOrigin();
822     // Base case sets the expectation for other cases.
823     if (expected_bounds.IsEmpty())
824       expected_bounds = display_relative_bounds;
825     else
826       EXPECT_EQ(expected_bounds, display_relative_bounds);
827     controller->CompleteCycling();
828   }
829 }
830 
TEST_F(WindowCycleControllerTest,CycleShowsAllDesksWindows)831 TEST_F(WindowCycleControllerTest, CycleShowsAllDesksWindows) {
832   auto win0 = CreateAppWindow(gfx::Rect(0, 0, 250, 100));
833   auto win1 = CreateAppWindow(gfx::Rect(50, 50, 200, 200));
834   auto* desks_controller = DesksController::Get();
835   desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
836   desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
837   ASSERT_EQ(3u, desks_controller->desks().size());
838   const Desk* desk_2 = desks_controller->desks()[1].get();
839   ActivateDesk(desk_2);
840   EXPECT_EQ(desk_2, desks_controller->active_desk());
841   auto win2 = CreateAppWindow(gfx::Rect(0, 0, 300, 200));
842   const Desk* desk_3 = desks_controller->desks()[2].get();
843   ActivateDesk(desk_3);
844   EXPECT_EQ(desk_3, desks_controller->active_desk());
845   auto win3 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
846 
847   WindowCycleController* cycle_controller =
848       Shell::Get()->window_cycle_controller();
849   cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD);
850   // All desks' windows are included in the cycle list.
851   auto cycle_windows = GetWindows(cycle_controller);
852   EXPECT_EQ(4u, cycle_windows.size());
853   EXPECT_TRUE(base::Contains(cycle_windows, win0.get()));
854   EXPECT_TRUE(base::Contains(cycle_windows, win1.get()));
855   EXPECT_TRUE(base::Contains(cycle_windows, win2.get()));
856   EXPECT_TRUE(base::Contains(cycle_windows, win3.get()));
857 
858   // The MRU order is {win3, win2, win1, win0}. We're now at win2. Cycling one
859   // more time and completing the cycle, will activate win1 which exists on a
860   // desk_1. This should activate desk_1.
861   {
862     base::HistogramTester histogram_tester;
863     DeskSwitchAnimationWaiter waiter;
864     cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD);
865     cycle_controller->CompleteCycling();
866     waiter.Wait();
867     Desk* desk_1 = desks_controller->desks()[0].get();
868     EXPECT_EQ(desk_1, desks_controller->active_desk());
869     EXPECT_EQ(win1.get(), window_util::GetActiveWindow());
870     histogram_tester.ExpectUniqueSample(
871         "Ash.WindowCycleController.DesksSwitchDistance",
872         /*desk distance of 3 - 1 = */ 2, /*expected_count=*/1);
873   }
874 
875   // Cycle again and activate win2, which exist on desk_2. Expect that desk to
876   // be activated, and a histogram sample of distance of 1 is recorded.
877   // MRU is {win1, win3, win2, win0}.
878   {
879     base::HistogramTester histogram_tester;
880     DeskSwitchAnimationWaiter waiter;
881     cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD);
882     cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD);
883     cycle_controller->CompleteCycling();
884     waiter.Wait();
885     EXPECT_EQ(desk_2, desks_controller->active_desk());
886     EXPECT_EQ(win2.get(), window_util::GetActiveWindow());
887     histogram_tester.ExpectUniqueSample(
888         "Ash.WindowCycleController.DesksSwitchDistance",
889         /*desk distance of 2 - 1 = */ 1, /*expected_count=*/1);
890   }
891 }
892 
893 class LimitedWindowCycleControllerTest : public WindowCycleControllerTest {
894  public:
895   LimitedWindowCycleControllerTest() = default;
896   LimitedWindowCycleControllerTest(const LimitedWindowCycleControllerTest&) =
897       delete;
898   LimitedWindowCycleControllerTest& operator=(
899       const LimitedWindowCycleControllerTest&) = delete;
900   ~LimitedWindowCycleControllerTest() override = default;
901 
902   // WindowCycleControllerTest:
SetUp()903   void SetUp() override {
904     scoped_feature_list_.InitAndEnableFeature(
905         features::kLimitAltTabToActiveDesk);
906     WindowCycleControllerTest::SetUp();
907   }
908 
909  private:
910   base::test::ScopedFeatureList scoped_feature_list_;
911 };
912 
TEST_F(LimitedWindowCycleControllerTest,CycleShowsActiveDeskWindows)913 TEST_F(LimitedWindowCycleControllerTest, CycleShowsActiveDeskWindows) {
914   auto win0 = CreateAppWindow(gfx::Rect(0, 0, 250, 100));
915   auto win1 = CreateAppWindow(gfx::Rect(50, 50, 200, 200));
916   auto* desks_controller = DesksController::Get();
917   desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
918   desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
919   ASSERT_EQ(3u, desks_controller->desks().size());
920   const Desk* desk_2 = desks_controller->desks()[1].get();
921   ActivateDesk(desk_2);
922   EXPECT_EQ(desk_2, desks_controller->active_desk());
923   auto win2 = CreateAppWindow(gfx::Rect(0, 0, 300, 200));
924   const Desk* desk_3 = desks_controller->desks()[2].get();
925   ActivateDesk(desk_3);
926   EXPECT_EQ(desk_3, desks_controller->active_desk());
927   auto win3 = CreateAppWindow(gfx::Rect(10, 30, 400, 200));
928 
929   WindowCycleController* cycle_controller =
930       Shell::Get()->window_cycle_controller();
931 
932   // Should contain only windows from |desk_3|.
933   cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD);
934   auto cycle_windows = GetWindows(cycle_controller);
935   EXPECT_EQ(1u, cycle_windows.size());
936   EXPECT_TRUE(base::Contains(cycle_windows, win3.get()));
937   cycle_controller->CompleteCycling();
938   EXPECT_EQ(win3.get(), window_util::GetActiveWindow());
939 
940   // Should contain only windows from |desk_2|.
941   ActivateDesk(desk_2);
942   cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD);
943   cycle_windows = GetWindows(cycle_controller);
944   EXPECT_EQ(1u, cycle_windows.size());
945   EXPECT_TRUE(base::Contains(cycle_windows, win2.get()));
946   cycle_controller->CompleteCycling();
947   EXPECT_EQ(win2.get(), window_util::GetActiveWindow());
948 
949   // Should contain only windows from |desk_1|.
950   const Desk* desk_1 = desks_controller->desks()[0].get();
951   ActivateDesk(desk_1);
952   cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD);
953   cycle_windows = GetWindows(cycle_controller);
954   EXPECT_EQ(2u, cycle_windows.size());
955   EXPECT_TRUE(base::Contains(cycle_windows, win0.get()));
956   EXPECT_TRUE(base::Contains(cycle_windows, win1.get()));
957   cycle_controller->CompleteCycling();
958   EXPECT_EQ(win0.get(), window_util::GetActiveWindow());
959 
960   // Swap desks while cycling, contents should update.
961   cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD);
962   cycle_windows = GetWindows(cycle_controller);
963   EXPECT_EQ(2u, cycle_windows.size());
964   EXPECT_TRUE(base::Contains(cycle_windows, win0.get()));
965   EXPECT_TRUE(base::Contains(cycle_windows, win1.get()));
966   ActivateDesk(desk_2);
967   EXPECT_TRUE(cycle_controller->IsCycling());
968   cycle_windows = GetWindows(cycle_controller);
969   EXPECT_EQ(1u, cycle_windows.size());
970   EXPECT_TRUE(base::Contains(cycle_windows, win2.get()));
971   cycle_controller->CompleteCycling();
972   EXPECT_EQ(win2.get(), window_util::GetActiveWindow());
973 }
974 
975 class InteractiveWindowCycleControllerTest : public WindowCycleControllerTest {
976  public:
977   InteractiveWindowCycleControllerTest() = default;
978   InteractiveWindowCycleControllerTest(const InteractiveWindowCycleControllerTest&) =
979       delete;
980   InteractiveWindowCycleControllerTest& operator=(
981       const InteractiveWindowCycleControllerTest&) = delete;
982   ~InteractiveWindowCycleControllerTest() override = default;
983 
984   // WindowCycleControllerTest:
SetUp()985   void SetUp() override {
986     scoped_feature_list_.InitAndEnableFeature(
987         features::kInteractiveWindowCycleList);
988     WindowCycleControllerTest::SetUp();
989   }
990 
991  private:
992   base::test::ScopedFeatureList scoped_feature_list_;
993 };
994 
995 // Tests that when the cycle view is not open, the event filter does not check
996 // whether events occur within the cycle view.
997 // TODO(chinsenj): Add this to WindowCycleControllerTest.MouseEventsCaptured
998 // after feature launch.
TEST_F(InteractiveWindowCycleControllerTest,MouseEventWhenCycleViewDoesNotExist)999 TEST_F(InteractiveWindowCycleControllerTest,
1000        MouseEventWhenCycleViewDoesNotExist) {
1001   aura::test::TestWindowDelegate delegate;
1002   std::unique_ptr<Window> w0(CreateTestWindowInShellWithDelegate(
1003       &delegate, 0, gfx::Rect(0, 0, 100, 100)));
1004   EventCounter event_count;
1005   w0->AddPreTargetHandler(&event_count);
1006   ui::test::EventGenerator* generator = GetEventGenerator();
1007   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
1008 
1009   // Mouse events get through if the cycle view is not open.
1010   // Cycling with one window open ensures the UI doesn't show but the event
1011   // filter is.
1012   controller->HandleCycleWindow(WindowCycleController::FORWARD);
1013   generator->MoveMouseToCenterOf(w0.get());
1014   generator->ClickLeftButton();
1015   EXPECT_TRUE(controller->IsCycling());
1016   EXPECT_FALSE(CycleViewExists());
1017   EXPECT_LT(0, event_count.GetMouseEventCountAndReset());
1018   controller->CompleteCycling();
1019 }
1020 
1021 // When a user hovers their mouse over an item, it should cycle to it.
1022 // The items in the list should not move, only the focus ring.
1023 // If a user clicks on an item, it should complete cycling and activate
1024 // the hovered item.
TEST_F(InteractiveWindowCycleControllerTest,MouseHoverAndSelect)1025 TEST_F(InteractiveWindowCycleControllerTest, MouseHoverAndSelect) {
1026   std::unique_ptr<Window> w0 = CreateTestWindow();
1027   std::unique_ptr<Window> w1 = CreateTestWindow();
1028   std::unique_ptr<Window> w2 = CreateTestWindow();
1029   std::unique_ptr<Window> w3 = CreateTestWindow();
1030   std::unique_ptr<Window> w4 = CreateTestWindow();
1031   std::unique_ptr<Window> w5 = CreateTestWindow();
1032   std::unique_ptr<Window> w6 = CreateTestWindow();
1033   ui::test::EventGenerator* generator = GetEventGenerator();
1034   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
1035 
1036   // Cycle to the third item, mouse over second item, and release alt-tab.
1037   // Starting order of windows in cycle list is [6,5,4,3,2,1,0].
1038   controller->HandleCycleWindow(WindowCycleController::FORWARD);
1039   controller->HandleCycleWindow(WindowCycleController::FORWARD);
1040   gfx::Point target_item_center =
1041       GetWindowCycleItemViews()[1]->GetBoundsInScreen().CenterPoint();
1042   generator->MoveMouseTo(target_item_center);
1043   EXPECT_EQ(target_item_center,
1044             GetWindowCycleItemViews()[1]->GetBoundsInScreen().CenterPoint());
1045   controller->CompleteCycling();
1046   EXPECT_TRUE(wm::IsActiveWindow(w5.get()));
1047 
1048   // Start cycle, mouse over third item, and release alt-tab.
1049   // Starting order of windows in cycle list is [5,6,4,3,2,1,0].
1050   controller->StartCycling();
1051   target_item_center =
1052       GetWindowCycleItemViews()[2]->GetBoundsInScreen().CenterPoint();
1053   generator->MoveMouseTo(target_item_center);
1054   EXPECT_EQ(target_item_center,
1055             GetWindowCycleItemViews()[2]->GetBoundsInScreen().CenterPoint());
1056   controller->CompleteCycling();
1057   EXPECT_TRUE(wm::IsActiveWindow(w4.get()));
1058 
1059   // Start cycle, cycle to the fifth item, mouse over seventh item, and click.
1060   // Starting order of windows in cycle list is [4,5,6,3,2,1,0].
1061   controller->StartCycling();
1062   for (int i = 0; i < 5; i++)
1063     controller->HandleCycleWindow(WindowCycleController::FORWARD);
1064   target_item_center =
1065       GetWindowCycleItemViews()[6]->GetBoundsInScreen().CenterPoint();
1066   generator->MoveMouseTo(target_item_center);
1067   EXPECT_EQ(target_item_center,
1068             GetWindowCycleItemViews()[6]->GetBoundsInScreen().CenterPoint());
1069   generator->PressLeftButton();
1070   EXPECT_TRUE(wm::IsActiveWindow(w0.get()));
1071 }
1072 
1073 // Tests that the left and right keys cycle after the cycle list has been
1074 // initialized.
TEST_F(InteractiveWindowCycleControllerTest,LeftRightCycle)1075 TEST_F(InteractiveWindowCycleControllerTest, LeftRightCycle) {
1076   std::unique_ptr<Window> w0 = CreateTestWindow();
1077   std::unique_ptr<Window> w1 = CreateTestWindow();
1078   std::unique_ptr<Window> w2 = CreateTestWindow();
1079   ui::test::EventGenerator* generator = GetEventGenerator();
1080   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
1081 
1082   // Start cycle, simulating alt button being held down. Cycle right to the
1083   // third item.
1084   // Starting order of windows in cycle list is [2,1,0].
1085   controller->StartCycling();
1086   generator->PressKey(ui::VKEY_RIGHT, ui::EF_NONE);
1087   generator->PressKey(ui::VKEY_RIGHT, ui::EF_NONE);
1088   controller->CompleteCycling();
1089   EXPECT_TRUE(wm::IsActiveWindow(w0.get()));
1090 
1091   // Start cycle. Cycle right once, then left two times.
1092   // Starting order of windows in cycle list is [0,2,1].
1093   controller->StartCycling();
1094   generator->PressKey(ui::VKEY_RIGHT, ui::EF_NONE);
1095   generator->PressKey(ui::VKEY_LEFT, ui::EF_NONE);
1096   generator->PressKey(ui::VKEY_LEFT, ui::EF_NONE);
1097   controller->CompleteCycling();
1098   EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
1099 
1100   // Start cycle. Cycle right once, then left once, then right once.
1101   // Starting order of windows in cycle list is [0,2,1].
1102   controller->StartCycling();
1103   generator->PressKey(ui::VKEY_LEFT, ui::EF_ALT_DOWN);
1104   generator->PressKey(ui::VKEY_RIGHT, ui::EF_ALT_DOWN);
1105   generator->PressKey(ui::VKEY_LEFT, ui::EF_ALT_DOWN);
1106   controller->CompleteCycling();
1107   EXPECT_TRUE(wm::IsActiveWindow(w2.get()));
1108 }
1109 
1110 // Tests that pressing the space key, pressing the enter key, or releasing the
1111 // alt key during window cycle confirms a selection.
TEST_F(InteractiveWindowCycleControllerTest,KeysConfirmSelection)1112 TEST_F(InteractiveWindowCycleControllerTest, KeysConfirmSelection) {
1113   std::unique_ptr<Window> w0 = CreateTestWindow();
1114   std::unique_ptr<Window> w1 = CreateTestWindow();
1115   std::unique_ptr<Window> w2 = CreateTestWindow();
1116   ui::test::EventGenerator* generator = GetEventGenerator();
1117   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
1118 
1119   // Start cycle, simulating alt button being held down. Cycle right once and
1120   // complete cycle using space.
1121   // Starting order of windows in cycle list is [2,1,0].
1122   controller->StartCycling();
1123   controller->HandleCycleWindow(WindowCycleController::FORWARD);
1124   generator->PressKey(ui::VKEY_SPACE, ui::EF_NONE);
1125   EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
1126 
1127   // Start cycle, simulating alt button being held down. Cycle right once and
1128   // complete cycle using enter.
1129   // Starting order of windows in cycle list is [1,2,0].
1130   controller->StartCycling();
1131   controller->HandleCycleWindow(WindowCycleController::FORWARD);
1132   generator->PressKey(ui::VKEY_RETURN, ui::EF_NONE);
1133   EXPECT_TRUE(wm::IsActiveWindow(w2.get()));
1134 
1135   // Start cycle, simulating alt button being held down. Cycle right once and
1136   // complete cycle by releasing alt key (Views uses VKEY_MENU for both left and
1137   // right alt keys).
1138   // Starting order of windows in cycle list is [2,1,0].
1139   controller->StartCycling();
1140   controller->HandleCycleWindow(WindowCycleController::FORWARD);
1141   generator->ReleaseKey(ui::VKEY_MENU, ui::EF_NONE);
1142   EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
1143 }
1144 
1145 // When a user taps on an item, it should set the focus ring to that item. After
1146 // they release their finger it should confirm the selection.
TEST_F(InteractiveWindowCycleControllerTest,TapSelect)1147 TEST_F(InteractiveWindowCycleControllerTest, TapSelect) {
1148   std::unique_ptr<Window> w0 = CreateTestWindow();
1149   std::unique_ptr<Window> w1 = CreateTestWindow();
1150   std::unique_ptr<Window> w2 = CreateTestWindow();
1151   ui::test::EventGenerator* generator = GetEventGenerator();
1152   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
1153 
1154   // Start cycle and tap third item. On tap down, the focus ring should be set
1155   // to the third item. On tap release, the selection should be confirmed.
1156   // Starting order of windows in cycle list is [2,1,0].
1157   controller->StartCycling();
1158   generator->PressTouch(
1159       GetWindowCycleItemViews()[2]->GetBoundsInScreen().CenterPoint());
1160   EXPECT_TRUE(controller->IsCycling());
1161   EXPECT_EQ(GetTargetWindow(), w0.get());
1162   generator->ReleaseTouch();
1163   EXPECT_FALSE(controller->IsCycling());
1164   EXPECT_TRUE(wm::IsActiveWindow(w0.get()));
1165 
1166   // Start cycle and tap second item. On tap down, the focus ring should be set
1167   // to the second item. On tap release, the selection should be confirmed.
1168   // Starting order of windows in cycle list is [0,2,1].
1169   controller->StartCycling();
1170   generator->PressTouch(
1171       GetWindowCycleItemViews()[1]->GetBoundsInScreen().CenterPoint());
1172   EXPECT_TRUE(controller->IsCycling());
1173   EXPECT_EQ(GetTargetWindow(), w2.get());
1174   generator->ReleaseTouch();
1175   EXPECT_FALSE(controller->IsCycling());
1176   EXPECT_TRUE(wm::IsActiveWindow(w2.get()));
1177 }
1178 
1179 // Tests that mouse events are filtered until the mouse is actually used,
1180 // preventing the mouse from unexpectedly triggering events.
1181 // See crbug.com/1143275.
TEST_F(InteractiveWindowCycleControllerTest,FilterMouseEventsUntilUsed)1182 TEST_F(InteractiveWindowCycleControllerTest, FilterMouseEventsUntilUsed) {
1183   std::unique_ptr<Window> w0 = CreateTestWindow();
1184   std::unique_ptr<Window> w1 = CreateTestWindow();
1185   std::unique_ptr<Window> w2 = CreateTestWindow();
1186   EventCounter event_count;
1187   ui::test::EventGenerator* generator = GetEventGenerator();
1188   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
1189 
1190   // Start cycling.
1191   // Current window order is [2,1,0].
1192   controller->StartCycling();
1193   auto item_views = GetWindowCycleItemViews();
1194   item_views[2]->AddPreTargetHandler(&event_count);
1195 
1196   // Move the mouse over to the third item and complete cycling. These mouse
1197   // events shouldn't be filtered since the user has moved their mouse.
1198   generator->MoveMouseTo(gfx::Point(0, 0));
1199   const gfx::Point third_item_center =
1200       GetWindowCycleItemViews()[2]->GetBoundsInScreen().CenterPoint();
1201   generator->MoveMouseTo(third_item_center);
1202   controller->CompleteCycling();
1203   EXPECT_TRUE(wm::IsActiveWindow(w0.get()));
1204   EXPECT_LT(0, event_count.GetMouseEventCountAndReset());
1205 
1206   // Start cycling again while the mouse is over where the third item will be
1207   // when cycling starts.
1208   // Current window order is [0,2,1].
1209   controller->StartCycling();
1210   item_views = GetWindowCycleItemViews();
1211   item_views[2]->AddPreTargetHandler(&event_count);
1212 
1213   // Generate mouse events at the cursor's initial position. These mouse events
1214   // should be filtered because the user hasn't moved their mouse yet.
1215   generator->MoveMouseTo(third_item_center);
1216   controller->CompleteCycling();
1217   EXPECT_TRUE(wm::IsActiveWindow(w0.get()));
1218   EXPECT_EQ(0, event_count.GetMouseEventCountAndReset());
1219 
1220   // Start cycling again and click. This should not be filtered out.
1221   // Current window order is [0,2,1].
1222   controller->StartCycling();
1223   generator->PressLeftButton();
1224   EXPECT_FALSE(controller->IsCycling());
1225   EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
1226 }
1227 
1228 // When a user has the window cycle list open and clicks outside of it, it
1229 // should cancel cycling.
TEST_F(InteractiveWindowCycleControllerTest,MousePressOutsideOfListCancelsCycling)1230 TEST_F(InteractiveWindowCycleControllerTest,
1231        MousePressOutsideOfListCancelsCycling) {
1232   std::unique_ptr<Window> w0 = CreateTestWindow();
1233   std::unique_ptr<Window> w1 = CreateTestWindow();
1234   std::unique_ptr<Window> w2 = CreateTestWindow();
1235   ui::test::EventGenerator* generator = GetEventGenerator();
1236   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
1237 
1238   // Cycle to second item, move to above the window cycle list, and click.
1239   controller->StartCycling();
1240   controller->HandleCycleWindow(WindowCycleController::FORWARD);
1241   gfx::Point above_window_cycle_list =
1242       GetWindowCycleListWidget()->GetWindowBoundsInScreen().top_center();
1243   above_window_cycle_list.Offset(0, 100);
1244   generator->MoveMouseTo(above_window_cycle_list);
1245   generator->ClickLeftButton();
1246   EXPECT_FALSE(controller->IsCycling());
1247   EXPECT_TRUE(wm::IsActiveWindow(w1.get()));
1248 }
1249 
1250 // When the user has one window open, the window cycle view isn't shown. In this
1251 // case we should not eat mouse events.
TEST_F(InteractiveWindowCycleControllerTest,MouseEventsNotEatenWhenCycleViewNotVisible)1252 TEST_F(InteractiveWindowCycleControllerTest,
1253        MouseEventsNotEatenWhenCycleViewNotVisible) {
1254   std::unique_ptr<Window> w0 = CreateTestWindow();
1255   EventCounter event_count;
1256   w0->AddPreTargetHandler(&event_count);
1257   ui::test::EventGenerator* generator = GetEventGenerator();
1258 
1259   // Start cycling. Since there's only one window the cycle view shouldn't be
1260   // visible.
1261   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
1262   controller->HandleCycleWindow(WindowCycleController::FORWARD);
1263   ASSERT_TRUE(controller->IsCycling());
1264   ASSERT_FALSE(controller->IsWindowListVisible());
1265 
1266   generator->MoveMouseToCenterOf(w0.get());
1267   generator->ClickLeftButton();
1268   EXPECT_LT(0, event_count.GetMouseEventCountAndReset());
1269 }
1270 
1271 // Tests that frame throttling starts and ends accordingly when window cycling
1272 // starts and ends.
TEST_F(WindowCycleControllerTest,FrameThrottling)1273 TEST_F(WindowCycleControllerTest, FrameThrottling) {
1274   MockFrameThrottlingObserver observer;
1275   FrameThrottlingController* frame_throttling_controller =
1276       Shell::Get()->frame_throttling_controller();
1277   uint8_t throttled_fps = frame_throttling_controller->throttled_fps();
1278   frame_throttling_controller->AddObserver(&observer);
1279   const int window_count = 5;
1280   std::unique_ptr<aura::Window> created_windows[window_count];
1281   std::vector<aura::Window*> windows(window_count, nullptr);
1282   for (int i = 0; i < window_count; ++i) {
1283     created_windows[i] = CreateAppWindow(gfx::Rect(), AppType::BROWSER);
1284     windows[i] = created_windows[i].get();
1285   }
1286 
1287   WindowCycleController* controller = Shell::Get()->window_cycle_controller();
1288   EXPECT_CALL(observer,
1289               OnThrottlingStarted(testing::UnorderedElementsAreArray(windows),
1290                                   throttled_fps));
1291   controller->HandleCycleWindow(WindowCycleController::FORWARD);
1292   EXPECT_CALL(observer,
1293               OnThrottlingStarted(testing::UnorderedElementsAreArray(windows),
1294                                   throttled_fps))
1295       .Times(0);
1296   controller->HandleCycleWindow(WindowCycleController::FORWARD);
1297   EXPECT_CALL(observer, OnThrottlingEnded());
1298   controller->CompleteCycling();
1299 
1300   EXPECT_CALL(observer,
1301               OnThrottlingStarted(testing::UnorderedElementsAreArray(windows),
1302                                   throttled_fps));
1303   controller->HandleCycleWindow(WindowCycleController::FORWARD);
1304   EXPECT_CALL(observer, OnThrottlingEnded());
1305   controller->CancelCycling();
1306   frame_throttling_controller->RemoveObserver(&observer);
1307 }
1308 
1309 // Tests that pressing Alt+Tab while there is an on-going desk animation
1310 // prevents a new window cycle from starting.
TEST_F(WindowCycleControllerTest,DoubleAltTabWithDeskSwitch)1311 TEST_F(WindowCycleControllerTest, DoubleAltTabWithDeskSwitch) {
1312   WindowCycleController* cycle_controller =
1313       Shell::Get()->window_cycle_controller();
1314 
1315   auto win0 = CreateAppWindow(gfx::Rect(250, 100));
1316   auto* desks_controller = DesksController::Get();
1317   desks_controller->NewDesk(DesksCreationRemovalSource::kButton);
1318   ASSERT_EQ(2u, desks_controller->desks().size());
1319   const Desk* desk_0 = desks_controller->desks()[0].get();
1320   const Desk* desk_1 = desks_controller->desks()[1].get();
1321   ActivateDesk(desk_1);
1322   EXPECT_EQ(desk_1, desks_controller->active_desk());
1323   auto win1 = CreateAppWindow(gfx::Rect(300, 200));
1324   ASSERT_EQ(win1.get(), window_util::GetActiveWindow());
1325   auto desk_1_windows = desk_1->windows();
1326   EXPECT_EQ(1u, desk_1_windows.size());
1327   EXPECT_TRUE(base::Contains(desk_1_windows, win1.get()));
1328 
1329   DeskSwitchAnimationWaiter waiter;
1330   cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD);
1331   cycle_controller->CompleteCycling();
1332   EXPECT_FALSE(cycle_controller->CanCycle());
1333   cycle_controller->HandleCycleWindow(WindowCycleController::FORWARD);
1334   EXPECT_FALSE(cycle_controller->IsCycling());
1335   waiter.Wait();
1336   EXPECT_EQ(desk_0, desks_controller->active_desk());
1337   EXPECT_EQ(win0.get(), window_util::GetActiveWindow());
1338 }
1339 
1340 }  // namespace ash
1341