1 // Copyright 2013 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/overview/overview_session.h"
6 
7 #include <algorithm>
8 #include <memory>
9 #include <string>
10 #include <utility>
11 #include <vector>
12 
13 #include "ash/accelerators/accelerator_controller_impl.h"
14 #include "ash/accelerators/exit_warning_handler.h"
15 #include "ash/accessibility/accessibility_controller_impl.h"
16 #include "ash/accessibility/test_accessibility_controller_client.h"
17 #include "ash/app_list/app_list_controller_impl.h"
18 #include "ash/display/screen_orientation_controller.h"
19 #include "ash/display/screen_orientation_controller_test_api.h"
20 #include "ash/drag_drop/drag_drop_controller.h"
21 #include "ash/home_screen/home_screen_controller.h"
22 #include "ash/magnifier/docked_magnifier_controller_impl.h"
23 #include "ash/public/cpp/app_types.h"
24 #include "ash/public/cpp/ash_features.h"
25 #include "ash/public/cpp/shelf_config.h"
26 #include "ash/public/cpp/test/shell_test_api.h"
27 #include "ash/public/cpp/window_properties.h"
28 #include "ash/screen_util.h"
29 #include "ash/shelf/shelf.h"
30 #include "ash/shelf/shelf_view_test_api.h"
31 #include "ash/shell.h"
32 #include "ash/test/ash_test_base.h"
33 #include "ash/wm/desks/desks_util.h"
34 #include "ash/wm/drag_window_resizer.h"
35 #include "ash/wm/gestures/back_gesture/back_gesture_event_handler.h"
36 #include "ash/wm/mru_window_tracker.h"
37 #include "ash/wm/overview/overview_constants.h"
38 #include "ash/wm/overview/overview_controller.h"
39 #include "ash/wm/overview/overview_grid.h"
40 #include "ash/wm/overview/overview_grid_event_handler.h"
41 #include "ash/wm/overview/overview_highlight_controller.h"
42 #include "ash/wm/overview/overview_item.h"
43 #include "ash/wm/overview/overview_item_view.h"
44 #include "ash/wm/overview/overview_test_util.h"
45 #include "ash/wm/overview/overview_utils.h"
46 #include "ash/wm/overview/overview_wallpaper_controller.h"
47 #include "ash/wm/overview/overview_window_drag_controller.h"
48 #include "ash/wm/overview/rounded_label_widget.h"
49 #include "ash/wm/overview/scoped_overview_transform_window.h"
50 #include "ash/wm/resize_shadow.h"
51 #include "ash/wm/resize_shadow_controller.h"
52 #include "ash/wm/splitview/multi_display_overview_and_split_view_test.h"
53 #include "ash/wm/splitview/split_view_controller.h"
54 #include "ash/wm/splitview/split_view_divider.h"
55 #include "ash/wm/splitview/split_view_drag_indicators.h"
56 #include "ash/wm/splitview/split_view_utils.h"
57 #include "ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h"
58 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
59 #include "ash/wm/tablet_mode/tablet_mode_controller_test_api.h"
60 #include "ash/wm/tablet_mode/tablet_mode_window_resizer.h"
61 #include "ash/wm/window_preview_view.h"
62 #include "ash/wm/window_state.h"
63 #include "ash/wm/window_state_delegate.h"
64 #include "ash/wm/window_util.h"
65 #include "ash/wm/wm_event.h"
66 #include "ash/wm/workspace/workspace_window_resizer.h"
67 #include "base/macros.h"
68 #include "base/memory/ptr_util.h"
69 #include "base/run_loop.h"
70 #include "base/stl_util.h"
71 #include "base/strings/utf_string_conversions.h"
72 #include "base/test/metrics/histogram_tester.h"
73 #include "base/test/metrics/user_action_tester.h"
74 #include "base/test/scoped_feature_list.h"
75 #include "base/time/time.h"
76 #include "ui/aura/client/aura_constants.h"
77 #include "ui/aura/client/window_types.h"
78 #include "ui/aura/test/test_window_delegate.h"
79 #include "ui/aura/window.h"
80 #include "ui/aura/window_event_dispatcher.h"
81 #include "ui/aura/window_tree_host.h"
82 #include "ui/base/hit_test.h"
83 #include "ui/compositor/layer_animation_sequence.h"
84 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
85 #include "ui/compositor/test/draw_waiter_for_test.h"
86 #include "ui/compositor/test/test_utils.h"
87 #include "ui/display/display_layout.h"
88 #include "ui/display/manager/display_manager.h"
89 #include "ui/display/test/display_manager_test_api.h"
90 #include "ui/events/event_utils.h"
91 #include "ui/events/gesture_detection/gesture_configuration.h"
92 #include "ui/events/test/event_generator.h"
93 #include "ui/gfx/geometry/point_conversions.h"
94 #include "ui/gfx/transform.h"
95 #include "ui/gfx/transform_util.h"
96 #include "ui/views/accessibility/view_accessibility.h"
97 #include "ui/views/controls/button/image_button.h"
98 #include "ui/views/controls/label.h"
99 #include "ui/views/widget/widget.h"
100 #include "ui/wm/core/coordinate_conversion.h"
101 #include "ui/wm/core/cursor_manager.h"
102 #include "ui/wm/core/shadow_controller.h"
103 #include "ui/wm/core/window_util.h"
104 
105 namespace ash {
106 namespace {
107 
108 using ::chromeos::WindowStateType;
109 
110 constexpr const char kActiveWindowChangedFromOverview[] =
111     "WindowSelector_ActiveWindowChanged";
112 
113 // Helper function to get the index of |child|, given its parent window
114 // |parent|.
IndexOf(aura::Window * child,aura::Window * parent)115 int IndexOf(aura::Window* child, aura::Window* parent) {
116   aura::Window::Windows children = parent->children();
117   auto it = std::find(children.begin(), children.end(), child);
118   DCHECK(it != children.end());
119 
120   return static_cast<int>(std::distance(children.begin(), it));
121 }
122 
123 class TweenTester : public ui::LayerAnimationObserver {
124  public:
TweenTester(aura::Window * window)125   explicit TweenTester(aura::Window* window) : window_(window) {
126     window->layer()->GetAnimator()->AddObserver(this);
127   }
128 
~TweenTester()129   ~TweenTester() override {
130     window_->layer()->GetAnimator()->RemoveObserver(this);
131     EXPECT_TRUE(will_animate_);
132   }
133 
134   // ui::LayerAnimationObserver:
OnLayerAnimationEnded(ui::LayerAnimationSequence * sequence)135   void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override {}
OnLayerAnimationAborted(ui::LayerAnimationSequence * sequence)136   void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override {}
OnLayerAnimationScheduled(ui::LayerAnimationSequence * sequence)137   void OnLayerAnimationScheduled(
138       ui::LayerAnimationSequence* sequence) override {}
OnAttachedToSequence(ui::LayerAnimationSequence * sequence)139   void OnAttachedToSequence(ui::LayerAnimationSequence* sequence) override {
140     ui::LayerAnimationObserver::OnAttachedToSequence(sequence);
141     if (!will_animate_) {
142       tween_type_ = sequence->FirstElement()->tween_type();
143       will_animate_ = true;
144     }
145   }
146 
tween_type() const147   gfx::Tween::Type tween_type() const { return tween_type_; }
148 
149  private:
150   gfx::Tween::Type tween_type_ = gfx::Tween::LINEAR;
151   aura::Window* window_;
152   bool will_animate_ = false;
153 
154   DISALLOW_COPY_AND_ASSIGN(TweenTester);
155 };
156 
157 }  // namespace
158 
159 // TODO(bruthig): Move all non-simple method definitions out of class
160 // declaration.
161 class OverviewSessionTest : public MultiDisplayOverviewAndSplitViewTest {
162  public:
163   OverviewSessionTest() = default;
164   ~OverviewSessionTest() override = default;
165 
166   // AshTestBase:
SetUp()167   void SetUp() override {
168     MultiDisplayOverviewAndSplitViewTest::SetUp();
169 
170     aura::Env::GetInstance()->set_throttle_input_on_resize_for_testing(false);
171     shelf_view_test_api_ = std::make_unique<ShelfViewTestAPI>(
172         GetPrimaryShelf()->GetShelfViewForTesting());
173     shelf_view_test_api_->SetAnimationDuration(
174         base::TimeDelta::FromMilliseconds(1));
175     ScopedOverviewTransformWindow::SetImmediateCloseForTests(
176         /*immediate=*/true);
177     OverviewWallpaperController::SetDoNotChangeWallpaperForTests();
178     PresentationTimeRecorder::SetReportPresentationTimeImmediatelyForTest(true);
179   }
TearDown()180   void TearDown() override {
181     PresentationTimeRecorder::SetReportPresentationTimeImmediatelyForTest(
182         false);
183     trace_names_.clear();
184     MultiDisplayOverviewAndSplitViewTest::TearDown();
185   }
186 
187   // Enters tablet mode. Needed by tests that test dragging and or splitview,
188   // which are tablet mode only.
EnterTabletMode()189   void EnterTabletMode() {
190     // Ensure calls to SetEnabledForTest complete.
191     base::RunLoop().RunUntilIdle();
192     Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
193     base::RunLoop().RunUntilIdle();
194   }
195 
WindowsOverlapping(aura::Window * window1,aura::Window * window2)196   bool WindowsOverlapping(aura::Window* window1, aura::Window* window2) {
197     const gfx::Rect window1_bounds = GetTransformedTargetBounds(window1);
198     const gfx::Rect window2_bounds = GetTransformedTargetBounds(window2);
199     return window1_bounds.Intersects(window2_bounds);
200   }
201 
overview_controller()202   OverviewController* overview_controller() {
203     return Shell::Get()->overview_controller();
204   }
205 
overview_session()206   OverviewSession* overview_session() {
207     return overview_controller()->overview_session_.get();
208   }
209 
split_view_controller()210   SplitViewController* split_view_controller() {
211     return SplitViewController::Get(Shell::GetPrimaryRootWindow());
212   }
213 
GetTransformedBounds(aura::Window * window)214   gfx::Rect GetTransformedBounds(aura::Window* window) {
215     gfx::Rect bounds_in_screen = window->layer()->bounds();
216     ::wm::ConvertRectToScreen(window->parent(), &bounds_in_screen);
217     gfx::RectF bounds(bounds_in_screen);
218     gfx::Transform transform(gfx::TransformAboutPivot(
219         gfx::ToFlooredPoint(bounds.origin()), window->layer()->transform()));
220     transform.TransformRect(&bounds);
221     return ToStableSizeRoundedRect(bounds);
222   }
223 
GetTransformedTargetBounds(aura::Window * window)224   gfx::Rect GetTransformedTargetBounds(aura::Window* window) {
225     gfx::Rect bounds_in_screen = window->layer()->GetTargetBounds();
226     ::wm::ConvertRectToScreen(window->parent(), &bounds_in_screen);
227     gfx::RectF bounds(bounds_in_screen);
228     gfx::Transform transform(
229         gfx::TransformAboutPivot(gfx::ToFlooredPoint(bounds.origin()),
230                                  window->layer()->GetTargetTransform()));
231     transform.TransformRect(&bounds);
232     return ToStableSizeRoundedRect(bounds);
233   }
234 
GetTransformedBoundsInRootWindow(aura::Window * window)235   gfx::Rect GetTransformedBoundsInRootWindow(aura::Window* window) {
236     gfx::RectF bounds = gfx::RectF(gfx::SizeF(window->bounds().size()));
237     aura::Window* root = window->GetRootWindow();
238     CHECK(window->layer());
239     CHECK(root->layer());
240     gfx::Transform transform;
241     if (!window->layer()->GetTargetTransformRelativeTo(root->layer(),
242                                                        &transform)) {
243       return gfx::Rect();
244     }
245     transform.TransformRect(&bounds);
246     return gfx::ToEnclosingRect(bounds);
247   }
248 
ClickWindow(aura::Window * window)249   void ClickWindow(aura::Window* window) {
250     ui::test::EventGenerator event_generator(window->GetRootWindow(), window);
251     event_generator.ClickLeftButton();
252   }
253 
InOverviewSession()254   bool InOverviewSession() {
255     return overview_controller()->InOverviewSession();
256   }
257 
GetDropTarget(int grid_index)258   OverviewItem* GetDropTarget(int grid_index) {
259     return overview_session()->grid_list_[grid_index]->GetDropTarget();
260   }
261 
GetCloseButton(OverviewItem * item)262   views::ImageButton* GetCloseButton(OverviewItem* item) {
263     return item->overview_item_view_->close_button();
264   }
265 
GetLabelView(OverviewItem * item)266   views::Label* GetLabelView(OverviewItem* item) {
267     return item->overview_item_view_->title_label();
268   }
269 
GetBackdropView(OverviewItem * item)270   views::View* GetBackdropView(OverviewItem* item) {
271     return item->overview_item_view_->backdrop_view();
272   }
273 
GetPreviewView(OverviewItem * item)274   WindowPreviewView* GetPreviewView(OverviewItem* item) {
275     return item->overview_item_view_->preview_view();
276   }
277 
GetCloseButtonOpacity(OverviewItem * item)278   float GetCloseButtonOpacity(OverviewItem* item) {
279     return GetCloseButton(item)->layer()->opacity();
280   }
281 
GetTitlebarOpacity(OverviewItem * item)282   float GetTitlebarOpacity(OverviewItem* item) {
283     return item->overview_item_view_->header_view()->layer()->opacity();
284   }
285 
286   // Tests that a window is contained within a given OverviewItem, and that both
287   // the window and its matching close button are within the same screen.
CheckWindowAndCloseButtonInScreen(aura::Window * window,OverviewItem * window_item)288   void CheckWindowAndCloseButtonInScreen(aura::Window* window,
289                                          OverviewItem* window_item) {
290     const gfx::Rect screen_bounds =
291         window_item->root_window()->GetBoundsInScreen();
292     EXPECT_TRUE(window_item->Contains(window));
293     EXPECT_TRUE(screen_bounds.Contains(GetTransformedTargetBounds(window)));
294     EXPECT_TRUE(screen_bounds.Contains(
295         GetCloseButton(window_item)->GetBoundsInScreen()));
296   }
297 
SetGridBounds(OverviewGrid * grid,const gfx::Rect & bounds)298   void SetGridBounds(OverviewGrid* grid, const gfx::Rect& bounds) {
299     grid->bounds_ = bounds;
300   }
301 
GetGridBounds()302   gfx::Rect GetGridBounds() {
303     if (overview_session())
304       return overview_session()->grid_list_[0]->bounds_;
305 
306     return gfx::Rect();
307   }
308 
transform_window(OverviewItem * item) const309   const ScopedOverviewTransformWindow& transform_window(
310       OverviewItem* item) const {
311     return item->transform_window_;
312   }
313 
CheckOverviewEnterExitHistogram(const char * trace,std::vector<int> && enter_counts,std::vector<int> && exit_counts)314   void CheckOverviewEnterExitHistogram(const char* trace,
315                                        std::vector<int>&& enter_counts,
316                                        std::vector<int>&& exit_counts) {
317     CheckForDuplicateTraceName(trace);
318 
319     // Overview histograms recorded via ui::ThroughputTracker is reported
320     // on the next frame presented after animation stops. Wait for the next
321     // frame with a 100ms timeout for the report, regardless of whether there
322     // is a next frame.
323     ignore_result(ui::WaitForNextFrameToBePresented(
324         Shell::GetPrimaryRootWindow()->layer()->GetCompositor(),
325         base::TimeDelta::FromMilliseconds(100)));
326 
327     {
328       SCOPED_TRACE(trace + std::string(".Enter"));
329       CheckOverviewHistogram("Ash.Overview.AnimationSmoothness.Enter",
330                              std::move(enter_counts));
331     }
332     {
333       SCOPED_TRACE(trace + std::string(".Exit"));
334       CheckOverviewHistogram("Ash.Overview.AnimationSmoothness.Exit",
335                              std::move(exit_counts));
336     }
337   }
338 
339   // Creates a window which cannot be snapped by splitview.
CreateUnsnappableWindow(const gfx::Rect & bounds=gfx::Rect ())340   std::unique_ptr<aura::Window> CreateUnsnappableWindow(
341       const gfx::Rect& bounds = gfx::Rect()) {
342     std::unique_ptr<aura::Window> window = CreateTestWindow(bounds);
343     window->SetProperty(aura::client::kResizeBehaviorKey,
344                         aura::client::kResizeBehaviorNone);
345     return window;
346   }
347 
HasRoundedCorner(OverviewItem * item)348   bool HasRoundedCorner(OverviewItem* item) {
349     const ui::Layer* layer = item->transform_window_.IsMinimized()
350                                  ? GetPreviewView(item)->layer()
351                                  : transform_window(item).window()->layer();
352     return !layer->rounded_corner_radii().IsEmpty();
353   }
354 
StubForTest(ExitWarningHandler * ewh)355   static void StubForTest(ExitWarningHandler* ewh) {
356     ewh->stub_timer_for_test_ = true;
357   }
is_ui_shown(ExitWarningHandler * ewh)358   static bool is_ui_shown(ExitWarningHandler* ewh) { return !!ewh->widget_; }
359 
360  protected:
CheckForDuplicateTraceName(const char * trace)361   void CheckForDuplicateTraceName(const char* trace) {
362     DCHECK(!base::Contains(trace_names_, trace)) << trace;
363     trace_names_.push_back(trace);
364   }
365 
366   base::HistogramTester histograms_;
367 
368  private:
CheckOverviewHistogram(const char * histogram,std::vector<int> && counts)369   void CheckOverviewHistogram(const char* histogram,
370                               std::vector<int>&& counts) {
371     ASSERT_EQ(5u, counts.size());
372 
373     histograms_.ExpectTotalCount(histogram + std::string(".ClamshellMode"),
374                                  counts[0]);
375     histograms_.ExpectTotalCount(
376         histogram + std::string(".SingleClamshellMode"), counts[1]);
377     histograms_.ExpectTotalCount(histogram + std::string(".TabletMode"),
378                                  counts[2]);
379     histograms_.ExpectTotalCount(
380         histogram + std::string(".MinimizedTabletMode"), counts[3]);
381     histograms_.ExpectTotalCount(histogram + std::string(".SplitView"),
382                                  counts[4]);
383   }
384 
385   std::unique_ptr<ShelfViewTestAPI> shelf_view_test_api_;
386   std::vector<std::string> trace_names_;
387 
388   DISALLOW_COPY_AND_ASSIGN(OverviewSessionTest);
389 };
390 
391 // Tests that an a11y alert is sent on entering overview mode.
TEST_P(OverviewSessionTest,A11yAlertOnOverviewMode)392 TEST_P(OverviewSessionTest, A11yAlertOnOverviewMode) {
393   TestAccessibilityControllerClient client;
394   std::unique_ptr<aura::Window> window(CreateTestWindow());
395   EXPECT_NE(AccessibilityAlert::WINDOW_OVERVIEW_MODE_ENTERED,
396             client.last_a11y_alert());
397   ToggleOverview();
398   EXPECT_EQ(AccessibilityAlert::WINDOW_OVERVIEW_MODE_ENTERED,
399             client.last_a11y_alert());
400 }
401 
402 // Tests that there are no crashes when there is not enough screen space
403 // available to show all of the windows.
TEST_P(OverviewSessionTest,SmallDisplay)404 TEST_P(OverviewSessionTest, SmallDisplay) {
405   UpdateDisplay("3x1");
406   gfx::Rect bounds(0, 0, 1, 1);
407   std::unique_ptr<aura::Window> window1(CreateTestWindow(bounds));
408   std::unique_ptr<aura::Window> window2(CreateTestWindow(bounds));
409   std::unique_ptr<aura::Window> window3(CreateTestWindow(bounds));
410   std::unique_ptr<aura::Window> window4(CreateTestWindow(bounds));
411   window1->SetProperty(aura::client::kTopViewInset, 0);
412   window2->SetProperty(aura::client::kTopViewInset, 0);
413   window3->SetProperty(aura::client::kTopViewInset, 0);
414   window4->SetProperty(aura::client::kTopViewInset, 0);
415   ToggleOverview();
416 }
417 
418 // Tests entering overview mode with two windows and selecting one by clicking.
TEST_P(OverviewSessionTest,Basic)419 TEST_P(OverviewSessionTest, Basic) {
420   ui::ScopedAnimationDurationScaleMode anmatin_scale(
421       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
422 
423   // Overview disabled by default.
424   EXPECT_FALSE(InOverviewSession());
425 
426   aura::Window* root_window = Shell::GetPrimaryRootWindow();
427   std::unique_ptr<aura::Window> window1(CreateTestWindow());
428   std::unique_ptr<aura::Window> window2(CreateTestWindow());
429 
430   EXPECT_TRUE(WindowsOverlapping(window1.get(), window2.get()));
431   wm::ActivateWindow(window2.get());
432   EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
433   EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
434   EXPECT_EQ(window2.get(), window_util::GetFocusedWindow());
435 
436   // Hide the cursor before entering overview to test that it will be shown.
437   aura::client::GetCursorClient(root_window)->HideCursor();
438 
439   CheckOverviewEnterExitHistogram("Init", {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0});
440   // In overview mode the windows should no longer overlap and the overview
441   // focus window should be focused.
442   ToggleOverview();
443   WaitForOverviewEnterAnimation();
444 
445   EXPECT_EQ(overview_session()->GetOverviewFocusWindow(),
446             window_util::GetFocusedWindow());
447   EXPECT_FALSE(WindowsOverlapping(window1.get(), window2.get()));
448   CheckOverviewEnterExitHistogram("Enter", {1, 0, 0, 0, 0}, {0, 0, 0, 0, 0});
449 
450   // Clicking window 1 should activate it.
451   ClickWindow(window1.get());
452   WaitForOverviewExitAnimation();
453 
454   EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
455   EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
456   EXPECT_EQ(window1.get(), window_util::GetFocusedWindow());
457 
458   // Cursor should have been unlocked.
459   EXPECT_FALSE(aura::client::GetCursorClient(root_window)->IsCursorLocked());
460 
461   CheckOverviewEnterExitHistogram("Exit", {1, 0, 0, 0, 0}, {1, 0, 0, 0, 0});
462 }
463 
464 // Tests activating minimized window.
TEST_P(OverviewSessionTest,ActivateMinimized)465 TEST_P(OverviewSessionTest, ActivateMinimized) {
466   std::unique_ptr<aura::Window> window(CreateTestWindow());
467 
468   WindowState* window_state = WindowState::Get(window.get());
469   WMEvent minimize_event(WM_EVENT_MINIMIZE);
470   window_state->OnWMEvent(&minimize_event);
471   EXPECT_FALSE(window->IsVisible());
472   EXPECT_EQ(0.f, window->layer()->GetTargetOpacity());
473   EXPECT_EQ(WindowStateType::kMinimized,
474             WindowState::Get(window.get())->GetStateType());
475 
476   ToggleOverview();
477 
478   EXPECT_FALSE(window->IsVisible());
479   EXPECT_EQ(0.f, window->layer()->GetTargetOpacity());
480   EXPECT_EQ(WindowStateType::kMinimized, window_state->GetStateType());
481   WindowPreviewView* preview_view =
482       GetPreviewView(GetOverviewItemForWindow(window.get()));
483   EXPECT_TRUE(preview_view);
484 
485   const gfx::Point point = preview_view->GetBoundsInScreen().CenterPoint();
486   GetEventGenerator()->set_current_screen_location(point);
487   GetEventGenerator()->ClickLeftButton();
488 
489   EXPECT_FALSE(InOverviewSession());
490 
491   EXPECT_TRUE(window->IsVisible());
492   EXPECT_EQ(1.f, window->layer()->GetTargetOpacity());
493   EXPECT_EQ(WindowStateType::kNormal, window_state->GetStateType());
494 }
495 
496 // Tests that the ordering of windows is stable across different overview
497 // sessions even when the windows have the same bounds.
TEST_P(OverviewSessionTest,WindowsOrder)498 TEST_P(OverviewSessionTest, WindowsOrder) {
499   std::unique_ptr<aura::Window> window1(CreateTestWindowInShellWithId(1));
500   std::unique_ptr<aura::Window> window2(CreateTestWindowInShellWithId(2));
501   std::unique_ptr<aura::Window> window3(CreateTestWindowInShellWithId(3));
502 
503   // The order of windows in overview mode is MRU.
504   WindowState::Get(window1.get())->Activate();
505   ToggleOverview();
506   const std::vector<std::unique_ptr<OverviewItem>>& overview1 =
507       GetOverviewItemsForRoot(0);
508   EXPECT_EQ(1, overview1[0]->GetWindow()->id());
509   EXPECT_EQ(3, overview1[1]->GetWindow()->id());
510   EXPECT_EQ(2, overview1[2]->GetWindow()->id());
511   ToggleOverview();
512 
513   // Activate the second window.
514   WindowState::Get(window2.get())->Activate();
515   ToggleOverview();
516   const std::vector<std::unique_ptr<OverviewItem>>& overview2 =
517       GetOverviewItemsForRoot(0);
518 
519   // The order should be MRU.
520   EXPECT_EQ(2, overview2[0]->GetWindow()->id());
521   EXPECT_EQ(1, overview2[1]->GetWindow()->id());
522   EXPECT_EQ(3, overview2[2]->GetWindow()->id());
523   ToggleOverview();
524 }
525 
526 // Tests selecting a window by tapping on it.
TEST_P(OverviewSessionTest,BasicGesture)527 TEST_P(OverviewSessionTest, BasicGesture) {
528   std::unique_ptr<aura::Window> window1(CreateTestWindow());
529   std::unique_ptr<aura::Window> window2(CreateTestWindow());
530   wm::ActivateWindow(window1.get());
531   EXPECT_EQ(window1.get(), window_util::GetFocusedWindow());
532   ToggleOverview();
533   EXPECT_EQ(overview_session()->GetOverviewFocusWindow(),
534             window_util::GetFocusedWindow());
535   GetEventGenerator()->GestureTapAt(
536       GetTransformedTargetBounds(window2.get()).CenterPoint());
537   EXPECT_EQ(window2.get(), window_util::GetFocusedWindow());
538 }
539 
540 // Tests that the user action WindowSelector_ActiveWindowChanged is
541 // recorded when the mouse/touchscreen/keyboard are used to select a window
542 // in overview mode which is different from the previously-active window.
TEST_P(OverviewSessionTest,ActiveWindowChangedUserActionRecorded)543 TEST_P(OverviewSessionTest, ActiveWindowChangedUserActionRecorded) {
544   base::UserActionTester user_action_tester;
545   std::unique_ptr<aura::Window> window1(CreateTestWindow());
546   std::unique_ptr<aura::Window> window2(CreateTestWindow());
547   wm::ActivateWindow(window1.get());
548   ToggleOverview();
549 
550   // Tap on |window2| to activate it and exit overview.
551   GetEventGenerator()->GestureTapAt(
552       GetTransformedTargetBounds(window2.get()).CenterPoint());
553   EXPECT_EQ(
554       1, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview));
555 
556   // Click on |window2| to activate it and exit overview.
557   wm::ActivateWindow(window1.get());
558   ToggleOverview();
559   ClickWindow(window2.get());
560   EXPECT_EQ(
561       2, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview));
562 
563   // Highlight |window2| using the arrow keys. Activate it (and exit overview)
564   // by pressing the return key.
565   wm::ActivateWindow(window1.get());
566   ToggleOverview();
567   ASSERT_TRUE(HighlightOverviewWindow(window2.get()));
568   SendKey(ui::VKEY_RETURN);
569   EXPECT_EQ(
570       3, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview));
571 }
572 
573 // Tests that the user action WindowSelector_ActiveWindowChanged is not
574 // recorded when the mouse/touchscreen/keyboard are used to select the
575 // already-active window from overview mode. Also verifies that entering and
576 // exiting overview without selecting a window does not record the action.
TEST_P(OverviewSessionTest,ActiveWindowChangedUserActionNotRecorded)577 TEST_P(OverviewSessionTest, ActiveWindowChangedUserActionNotRecorded) {
578   base::UserActionTester user_action_tester;
579   std::unique_ptr<aura::Window> window1(CreateTestWindow());
580   std::unique_ptr<aura::Window> window2(CreateTestWindow());
581   wm::ActivateWindow(window1.get());
582   ToggleOverview();
583 
584   // Tap on |window1| to exit overview.
585   GetEventGenerator()->GestureTapAt(
586       GetTransformedTargetBounds(window1.get()).CenterPoint());
587   EXPECT_EQ(
588       0, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview));
589 
590   // |window1| remains active. Click on it to exit overview.
591   ASSERT_EQ(window1.get(), window_util::GetFocusedWindow());
592   ToggleOverview();
593   ClickWindow(window1.get());
594   EXPECT_EQ(
595       0, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview));
596 
597   // |window1| remains active. Select using the keyboard.
598   ASSERT_EQ(window1.get(), window_util::GetFocusedWindow());
599   ToggleOverview();
600   ASSERT_TRUE(HighlightOverviewWindow(window1.get()));
601   SendKey(ui::VKEY_RETURN);
602   EXPECT_EQ(
603       0, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview));
604 
605   // Entering and exiting overview without user input should not record
606   // the action.
607   ToggleOverview();
608   ToggleOverview();
609   EXPECT_EQ(
610       0, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview));
611 }
612 
613 // Tests that the user action WindowSelector_ActiveWindowChanged is not
614 // recorded when overview mode exits as a result of closing its only window.
TEST_P(OverviewSessionTest,ActiveWindowChangedUserActionWindowClose)615 TEST_P(OverviewSessionTest, ActiveWindowChangedUserActionWindowClose) {
616   base::UserActionTester user_action_tester;
617   std::unique_ptr<views::Widget> widget(CreateTestWidget(
618       nullptr, desks_util::GetActiveDeskContainerId(), gfx::Rect(400, 400)));
619 
620   ToggleOverview();
621   aura::Window* window = widget->GetNativeWindow();
622   const gfx::Point point = GetCloseButton(GetOverviewItemForWindow(window))
623                                ->GetBoundsInScreen()
624                                .CenterPoint();
625   ASSERT_FALSE(widget->IsClosed());
626   GetEventGenerator()->set_current_screen_location(point);
627   GetEventGenerator()->ClickLeftButton();
628   ASSERT_TRUE(widget->IsClosed());
629   EXPECT_EQ(
630       0, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview));
631 }
632 
633 // Tests that we do not crash and overview mode remains engaged if the desktop
634 // is tapped while a finger is already down over a window.
TEST_P(OverviewSessionTest,NoCrashWithDesktopTap)635 TEST_P(OverviewSessionTest, NoCrashWithDesktopTap) {
636   std::unique_ptr<aura::Window> window(
637       CreateTestWindow(gfx::Rect(200, 300, 250, 450)));
638 
639   ToggleOverview();
640 
641   const gfx::Rect bounds = GetTransformedBoundsInRootWindow(window.get());
642   GetEventGenerator()->set_current_screen_location(bounds.CenterPoint());
643 
644   // Press down on the window.
645   const int kTouchId = 19;
646   GetEventGenerator()->PressTouchId(kTouchId);
647 
648   // Tap on the desktop, which should not cause a crash. Overview mode should
649   // remain engaged.
650   GetEventGenerator()->GestureTapAt(GetGridBounds().CenterPoint());
651   EXPECT_TRUE(InOverviewSession());
652 
653   GetEventGenerator()->ReleaseTouchId(kTouchId);
654 }
655 
656 // Tests that we do not crash and a window is selected when appropriate when
657 // we click on a window during touch.
TEST_P(OverviewSessionTest,ClickOnWindowDuringTouch)658 TEST_P(OverviewSessionTest, ClickOnWindowDuringTouch) {
659   std::unique_ptr<aura::Window> window1(CreateTestWindow());
660   std::unique_ptr<aura::Window> window2(CreateTestWindow());
661   wm::ActivateWindow(window2.get());
662   EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
663   EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
664 
665   ToggleOverview();
666 
667   gfx::Rect window1_bounds = GetTransformedBoundsInRootWindow(window1.get());
668   GetEventGenerator()->set_current_screen_location(
669       window1_bounds.CenterPoint());
670 
671   // Clicking on |window2| while touching on |window1| should not cause a
672   // crash, it should do nothing since overview only handles one click or touch
673   // at a time.
674   const int kTouchId = 19;
675   GetEventGenerator()->PressTouchId(kTouchId);
676   GetEventGenerator()->MoveMouseToCenterOf(window2.get());
677   GetEventGenerator()->ClickLeftButton();
678   EXPECT_TRUE(InOverviewSession());
679   EXPECT_FALSE(wm::IsActiveWindow(window2.get()));
680 
681   // Clicking on |window1| while touching on |window1| should not cause
682   // a crash, overview mode should be disengaged, and |window1| should
683   // be active.
684   GetEventGenerator()->MoveMouseToCenterOf(window1.get());
685   GetEventGenerator()->ClickLeftButton();
686   EXPECT_FALSE(InOverviewSession());
687   EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
688   GetEventGenerator()->ReleaseTouchId(kTouchId);
689 }
690 
691 // Tests that a window does not receive located events when in overview mode.
TEST_P(OverviewSessionTest,WindowDoesNotReceiveEvents)692 TEST_P(OverviewSessionTest, WindowDoesNotReceiveEvents) {
693   std::unique_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(400, 400)));
694   const gfx::Point point1 = window->bounds().CenterPoint();
695   ui::MouseEvent event1(ui::ET_MOUSE_PRESSED, point1, point1,
696                         ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
697 
698   aura::Window* root_window = Shell::GetPrimaryRootWindow();
699   ui::EventTarget* root_target = root_window;
700   ui::EventTargeter* targeter =
701       root_window->GetHost()->dispatcher()->GetDefaultEventTargeter();
702 
703   // The event should target the window because we are still not in overview
704   // mode.
705   EXPECT_EQ(window.get(), targeter->FindTargetForEvent(root_target, &event1));
706 
707   ToggleOverview();
708 
709   // The bounds have changed, take that into account.
710   const gfx::Point point2 =
711       GetTransformedBoundsInRootWindow(window.get()).CenterPoint();
712   ui::MouseEvent event2(ui::ET_MOUSE_PRESSED, point2, point2,
713                         ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
714 
715   // Now the transparent window should be intercepting this event.
716   EXPECT_NE(window.get(), targeter->FindTargetForEvent(root_target, &event2));
717 }
718 
719 // Tests that clicking on the close button effectively closes the window.
TEST_P(OverviewSessionTest,CloseButton)720 TEST_P(OverviewSessionTest, CloseButton) {
721   std::unique_ptr<views::Widget> widget(CreateTestWidget());
722   std::unique_ptr<views::Widget> minimized_widget(CreateTestWidget());
723   minimized_widget->Minimize();
724 
725   ToggleOverview();
726   aura::Window* window = widget->GetNativeWindow();
727   const gfx::Point point = GetCloseButton(GetOverviewItemForWindow(window))
728                                ->GetBoundsInScreen()
729                                .CenterPoint();
730   GetEventGenerator()->set_current_screen_location(point);
731 
732   EXPECT_FALSE(widget->IsClosed());
733   GetEventGenerator()->ClickLeftButton();
734   EXPECT_TRUE(widget->IsClosed());
735   ASSERT_TRUE(InOverviewSession());
736 
737   aura::Window* minimized_window = minimized_widget->GetNativeWindow();
738   WindowPreviewView* preview_view =
739       GetPreviewView(GetOverviewItemForWindow(minimized_window));
740   EXPECT_TRUE(preview_view);
741   const gfx::Point point2 =
742       GetCloseButton(GetOverviewItemForWindow(minimized_window))
743           ->GetBoundsInScreen()
744           .CenterPoint();
745   GetEventGenerator()->MoveMouseTo(point2);
746   EXPECT_FALSE(minimized_widget->IsClosed());
747 
748   GetEventGenerator()->ClickLeftButton();
749   EXPECT_TRUE(minimized_widget->IsClosed());
750 
751   // All minimized windows are closed, so it should exit overview mode.
752   base::RunLoop().RunUntilIdle();
753   EXPECT_FALSE(InOverviewSession());
754 }
755 
756 // Tests that the shadow disappears before the close animation starts.
757 // Regression test for https://crbug.com/981509.
TEST_P(OverviewSessionTest,CloseAnimationShadow)758 TEST_P(OverviewSessionTest, CloseAnimationShadow) {
759   // Give us some time to check if the shadow has disappeared.
760   ScopedOverviewTransformWindow::SetImmediateCloseForTests(/*immediate=*/false);
761   ui::ScopedAnimationDurationScaleMode test_duration_mode(
762       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
763 
764   std::unique_ptr<views::Widget> widget = CreateTestWidget();
765 
766   ToggleOverview();
767   ShellTestApi().WaitForOverviewAnimationState(
768       OverviewAnimationState::kEnterAnimationComplete);
769   // Click the close button.
770   OverviewItem* item = GetOverviewItemForWindow(widget->GetNativeWindow());
771   const gfx::Point point =
772       GetCloseButton(item)->GetBoundsInScreen().CenterPoint();
773   GetEventGenerator()->set_current_screen_location(point);
774   GetEventGenerator()->ClickLeftButton();
775   ASSERT_FALSE(widget->IsClosed());
776   ASSERT_TRUE(InOverviewSession());
777 
778   // The shadow bounds are empty, which means its not visible.
779   EXPECT_EQ(gfx::Rect(), item->GetShadowBoundsForTesting());
780 }
781 
782 // Tests minimizing/unminimizing in overview mode.
TEST_P(OverviewSessionTest,MinimizeUnminimize)783 TEST_P(OverviewSessionTest, MinimizeUnminimize) {
784   std::unique_ptr<views::Widget> widget(CreateTestWidget());
785   aura::Window* window = widget->GetNativeWindow();
786 
787   ToggleOverview();
788   EXPECT_FALSE(GetPreviewView(GetOverviewItemForWindow(window)));
789 
790   widget->Minimize();
791   EXPECT_TRUE(widget->IsMinimized());
792   EXPECT_TRUE(InOverviewSession());
793   EXPECT_TRUE(GetPreviewView(GetOverviewItemForWindow(window)));
794 
795   widget->Restore();
796   EXPECT_FALSE(widget->IsMinimized());
797   EXPECT_FALSE(GetPreviewView(GetOverviewItemForWindow(window)));
798   EXPECT_TRUE(InOverviewSession());
799 }
800 
801 // Tests that clicking on the close button on a secondary display effectively
802 // closes the window.
TEST_P(OverviewSessionTest,CloseButtonOnMultipleDisplay)803 TEST_P(OverviewSessionTest, CloseButtonOnMultipleDisplay) {
804   UpdateDisplay("600x400,600x400");
805 
806   // We need a widget for the close button to work because windows are closed
807   // via the widget. We also use the widget to determine if the window has been
808   // closed or not. Parent the window to a window in a non-primary root window.
809   std::unique_ptr<aura::Window> window(
810       CreateTestWindow(gfx::Rect(650, 300, 250, 450)));
811   std::unique_ptr<views::Widget> widget(CreateTestWidget());
812   widget->SetBounds(gfx::Rect(650, 0, 400, 400));
813   aura::Window* window2 = widget->GetNativeWindow();
814   window2->SetProperty(aura::client::kTopViewInset, kHeaderHeightDp);
815   views::Widget::ReparentNativeView(window2, window->parent());
816   ASSERT_EQ(Shell::GetAllRootWindows()[1], window2->GetRootWindow());
817 
818   ToggleOverview();
819   gfx::Rect bounds = GetTransformedBoundsInRootWindow(window2);
820   gfx::Point point(bounds.right() - 5, bounds.y() + 5);
821   ui::test::EventGenerator event_generator(window2->GetRootWindow(), point);
822 
823   EXPECT_FALSE(widget->IsClosed());
824   event_generator.ClickLeftButton();
825   EXPECT_TRUE(widget->IsClosed());
826 }
827 
828 // Tests entering overview mode with two windows and selecting one.
TEST_P(OverviewSessionTest,FullscreenWindow)829 TEST_P(OverviewSessionTest, FullscreenWindow) {
830   ui::ScopedAnimationDurationScaleMode anmatin_scale(
831       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
832 
833   std::unique_ptr<aura::Window> window1(CreateTestWindow());
834   std::unique_ptr<aura::Window> window2(CreateTestWindow());
835   wm::ActivateWindow(window1.get());
836 
837   const WMEvent toggle_fullscreen_event(WM_EVENT_TOGGLE_FULLSCREEN);
838   WindowState::Get(window1.get())->OnWMEvent(&toggle_fullscreen_event);
839   EXPECT_TRUE(WindowState::Get(window1.get())->IsFullscreen());
840 
841   // Enter overview and select the fullscreen window.
842   ToggleOverview();
843   WaitForOverviewEnterAnimation();
844   CheckOverviewEnterExitHistogram("FullscreenWindowEnter1", {0, 1, 0, 0, 0},
845                                   {0, 0, 0, 0, 0});
846   ClickWindow(window1.get());
847   WaitForOverviewExitAnimation();
848   EXPECT_TRUE(WindowState::Get(window1.get())->IsFullscreen());
849   CheckOverviewEnterExitHistogram("FullscreenWindowExit1", {0, 1, 0, 0, 0},
850                                   {0, 1, 0, 0, 0});
851 
852   // Entering overview and selecting another window, the previous window remains
853   // fullscreen.
854   ToggleOverview();
855   WaitForOverviewEnterAnimation();
856   CheckOverviewEnterExitHistogram("FullscreenWindowEnter2", {0, 2, 0, 0, 0},
857                                   {0, 1, 0, 0, 0});
858   ClickWindow(window2.get());
859   WaitForOverviewExitAnimation();
860   EXPECT_TRUE(WindowState::Get(window1.get())->IsFullscreen());
861   CheckOverviewEnterExitHistogram("FullscreenWindowExit2", {0, 2, 0, 0, 0},
862                                   {1, 1, 0, 0, 0});
863 }
864 
865 // Tests entering overview mode with maximized window.
TEST_P(OverviewSessionTest,MaximizedWindow)866 TEST_P(OverviewSessionTest, MaximizedWindow) {
867   ui::ScopedAnimationDurationScaleMode anmatin_scale(
868       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
869 
870   std::unique_ptr<aura::Window> window1(CreateTestWindow());
871   std::unique_ptr<aura::Window> window2(CreateTestWindow());
872   wm::ActivateWindow(window1.get());
873 
874   const WMEvent maximize_event(WM_EVENT_MAXIMIZE);
875   WindowState::Get(window1.get())->OnWMEvent(&maximize_event);
876   EXPECT_TRUE(WindowState::Get(window1.get())->IsMaximized());
877 
878   // Enter overview and select the fullscreen window.
879   ToggleOverview();
880   WaitForOverviewEnterAnimation();
881   CheckOverviewEnterExitHistogram("MaximizedWindowEnter1", {0, 1, 0, 0, 0},
882                                   {0, 0, 0, 0, 0});
883   ClickWindow(window1.get());
884   WaitForOverviewExitAnimation();
885   EXPECT_TRUE(WindowState::Get(window1.get())->IsMaximized());
886   CheckOverviewEnterExitHistogram("MaximizedWindowExit1", {0, 1, 0, 0, 0},
887                                   {0, 1, 0, 0, 0});
888 
889   ToggleOverview();
890   WaitForOverviewEnterAnimation();
891   CheckOverviewEnterExitHistogram("MaximizedWindowEnter2", {0, 2, 0, 0, 0},
892                                   {0, 1, 0, 0, 0});
893   ClickWindow(window2.get());
894   WaitForOverviewExitAnimation();
895   EXPECT_TRUE(WindowState::Get(window1.get())->IsMaximized());
896   CheckOverviewEnterExitHistogram("MaximizedWindowExit2", {0, 2, 0, 0, 0},
897                                   {1, 1, 0, 0, 0});
898 }
899 
TEST_P(OverviewSessionTest,TabletModeHistograms)900 TEST_P(OverviewSessionTest, TabletModeHistograms) {
901   ui::ScopedAnimationDurationScaleMode anmatin_scale(
902       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
903 
904   EnterTabletMode();
905   std::unique_ptr<aura::Window> window1(CreateTestWindow());
906 
907   // Enter overview with the window maximized.
908   ToggleOverview();
909   WaitForOverviewEnterAnimation();
910   CheckOverviewEnterExitHistogram("MaximizedWindowTabletEnter", {0, 0, 1, 0, 0},
911                                   {0, 0, 0, 0, 0});
912 
913   ToggleOverview();
914   WaitForOverviewExitAnimation();
915   CheckOverviewEnterExitHistogram("MaximizedWindowTabletExit", {0, 0, 1, 0, 0},
916                                   {0, 0, 1, 0, 0});
917 
918   WindowState::Get(window1.get())->Minimize();
919   ToggleOverview();
920   WaitForOverviewEnterAnimation();
921   CheckOverviewEnterExitHistogram("MinimizedWindowTabletEnter", {0, 0, 1, 1, 0},
922                                   {0, 0, 1, 0, 0});
923 
924   ToggleOverview();
925   WaitForOverviewExitAnimation();
926   CheckOverviewEnterExitHistogram("MinimizedWindowTabletExit", {0, 0, 1, 1, 0},
927                                   {0, 0, 1, 1, 0});
928 }
929 
930 // Tests that entering overview when a fullscreen window is active in maximized
931 // mode correctly applies the transformations to the window and correctly
932 // updates the window bounds on exiting overview mode: http://crbug.com/401664.
TEST_P(OverviewSessionTest,FullscreenWindowTabletMode)933 TEST_P(OverviewSessionTest, FullscreenWindowTabletMode) {
934   ui::ScopedAnimationDurationScaleMode anmatin_scale(
935       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
936 
937   UpdateDisplay("800x600");
938   const gfx::Rect bounds(400, 400);
939   std::unique_ptr<aura::Window> window1(CreateTestWindow(bounds));
940   std::unique_ptr<aura::Window> window2(CreateTestWindow(bounds));
941   wm::ActivateWindow(window2.get());
942   wm::ActivateWindow(window1.get());
943 
944   EnterTabletMode();
945   gfx::Rect normal_window_bounds(window1->bounds());
946   const WMEvent toggle_fullscreen_event(WM_EVENT_TOGGLE_FULLSCREEN);
947   WindowState::Get(window1.get())->OnWMEvent(&toggle_fullscreen_event);
948 
949   // Finish fullscreen state change animation since it is irrelevant.
950   window1->layer()->GetAnimator()->StopAnimating();
951 
952   gfx::Rect fullscreen_window_bounds(window1->bounds());
953   EXPECT_NE(normal_window_bounds, fullscreen_window_bounds);
954   EXPECT_EQ(fullscreen_window_bounds, window2->GetTargetBounds());
955 
956   const gfx::Rect fullscreen(800, 600);
957   const int shelf_inset = 600 - ShelfConfig::Get()->shelf_size();
958   const gfx::Rect normal_work_area(800, shelf_inset);
959   display::Screen* screen = display::Screen::GetScreen();
960   EXPECT_EQ(gfx::Rect(800, 600),
961             screen->GetDisplayNearestWindow(window1.get()).work_area());
962   ToggleOverview();
963   WaitForOverviewEnterAnimation();
964   EXPECT_EQ(fullscreen,
965             screen->GetDisplayNearestWindow(window1.get()).work_area());
966   CheckOverviewEnterExitHistogram("FullscreenWindowTabletEnter1",
967                                   {0, 0, 1, 0, 0}, {0, 0, 0, 0, 0});
968 
969   // Window 2 would normally resize to normal window bounds on showing the shelf
970   // for overview but this is deferred until overview is exited.
971   EXPECT_EQ(fullscreen_window_bounds, window2->GetTargetBounds());
972   EXPECT_FALSE(WindowsOverlapping(window1.get(), window2.get()));
973   ToggleOverview();
974   WaitForOverviewExitAnimation();
975   EXPECT_EQ(fullscreen,
976             screen->GetDisplayNearestWindow(window1.get()).work_area());
977   // Since the fullscreen window is still active, window2 will still have the
978   // larger bounds.
979   EXPECT_EQ(fullscreen_window_bounds, window2->GetTargetBounds());
980   CheckOverviewEnterExitHistogram("FullscreenWindowTabletExit1",
981                                   {0, 0, 1, 0, 0}, {0, 0, 1, 0, 0});
982 
983   // Enter overview again and select window 2. Selecting window 2 should show
984   // the shelf bringing window2 back to the normal bounds.
985   ToggleOverview();
986   WaitForOverviewEnterAnimation();
987   CheckOverviewEnterExitHistogram("FullscreenWindowTabletEnter2",
988                                   {0, 0, 2, 0, 0}, {0, 0, 1, 0, 0});
989 
990   ClickWindow(window2.get());
991   WaitForOverviewExitAnimation();
992   // Selecting non fullscreen window should set the work area back to normal.
993   EXPECT_EQ(normal_work_area,
994             screen->GetDisplayNearestWindow(window1.get()).work_area());
995   EXPECT_EQ(normal_window_bounds, window2->GetTargetBounds());
996   CheckOverviewEnterExitHistogram("FullscreenWindowTabletExit2",
997                                   {0, 0, 2, 0, 0}, {0, 0, 2, 0, 0});
998 
999   ToggleOverview();
1000   WaitForOverviewEnterAnimation();
1001   CheckOverviewEnterExitHistogram("FullscreenWindowTabletEnter3",
1002                                   {0, 0, 3, 0, 0}, {0, 0, 2, 0, 0});
1003   EXPECT_EQ(normal_work_area,
1004             screen->GetDisplayNearestWindow(window1.get()).work_area());
1005   ClickWindow(window1.get());
1006   WaitForOverviewExitAnimation();
1007   // Selecting fullscreen. The work area should be updated to fullscreen as
1008   // well.
1009   EXPECT_EQ(fullscreen,
1010             screen->GetDisplayNearestWindow(window1.get()).work_area());
1011   CheckOverviewEnterExitHistogram("FullscreenWindowTabletExit3",
1012                                   {0, 0, 3, 0, 0}, {0, 0, 3, 0, 0});
1013 }
1014 
TEST_P(OverviewSessionTest,SkipOverviewWindow)1015 TEST_P(OverviewSessionTest, SkipOverviewWindow) {
1016   std::unique_ptr<aura::Window> window1(CreateTestWindow());
1017   std::unique_ptr<aura::Window> window2(CreateTestWindow());
1018   window2->SetProperty(kHideInOverviewKey, true);
1019 
1020   // Enter overview.
1021   ToggleOverview();
1022   EXPECT_TRUE(window1->IsVisible());
1023   EXPECT_FALSE(window2->IsVisible());
1024 
1025   // Exit overview.
1026   ToggleOverview();
1027   base::RunLoop().RunUntilIdle();
1028   EXPECT_TRUE(window1->IsVisible());
1029   EXPECT_TRUE(window2->IsVisible());
1030 }
1031 
1032 // Tests that a minimized window's visibility and layer visibility
1033 // stay invisible (A minimized window is cloned during overview).
TEST_P(OverviewSessionTest,MinimizedWindowState)1034 TEST_P(OverviewSessionTest, MinimizedWindowState) {
1035   std::unique_ptr<aura::Window> window1(CreateTestWindow());
1036   WindowState::Get(window1.get())->Minimize();
1037   EXPECT_FALSE(window1->IsVisible());
1038   EXPECT_FALSE(window1->layer()->GetTargetVisibility());
1039 
1040   ToggleOverview();
1041   EXPECT_FALSE(window1->IsVisible());
1042   EXPECT_FALSE(window1->layer()->GetTargetVisibility());
1043 
1044   ToggleOverview();
1045   EXPECT_FALSE(window1->IsVisible());
1046   EXPECT_FALSE(window1->layer()->GetTargetVisibility());
1047 }
1048 
1049 // Tests that a bounds change during overview is corrected for.
TEST_P(OverviewSessionTest,BoundsChangeDuringOverview)1050 TEST_P(OverviewSessionTest, BoundsChangeDuringOverview) {
1051   std::unique_ptr<aura::Window> window(
1052       CreateTestWindowInShellWithDelegate(nullptr, -1, gfx::Rect(400, 400)));
1053   // Use overview headers above the window in this test.
1054   window->SetProperty(aura::client::kTopViewInset, 0);
1055   ToggleOverview();
1056   gfx::Rect overview_bounds = GetTransformedTargetBounds(window.get());
1057   window->SetBounds(gfx::Rect(200, 0, 200, 200));
1058   gfx::Rect new_overview_bounds = GetTransformedTargetBounds(window.get());
1059   EXPECT_EQ(overview_bounds, new_overview_bounds);
1060   ToggleOverview();
1061 }
1062 
1063 // Tests that a change to the |kTopViewInset| window property during overview is
1064 // corrected for.
TEST_P(OverviewSessionTest,TopViewInsetChangeDuringOverview)1065 TEST_P(OverviewSessionTest, TopViewInsetChangeDuringOverview) {
1066   std::unique_ptr<aura::Window> window = CreateTestWindow(gfx::Rect(400, 400));
1067   window->SetProperty(aura::client::kTopViewInset, 32);
1068   ToggleOverview();
1069   gfx::Rect overview_bounds = GetTransformedTargetBounds(window.get());
1070   window->SetProperty(aura::client::kTopViewInset, 0);
1071   gfx::Rect new_overview_bounds = GetTransformedTargetBounds(window.get());
1072   EXPECT_NE(overview_bounds, new_overview_bounds);
1073   ToggleOverview();
1074 }
1075 
1076 // Tests that a newly created window aborts overview.
TEST_P(OverviewSessionTest,NewWindowCancelsOverview)1077 TEST_P(OverviewSessionTest, NewWindowCancelsOverview) {
1078   std::unique_ptr<aura::Window> window1(CreateTestWindow());
1079   ToggleOverview();
1080   EXPECT_TRUE(InOverviewSession());
1081 
1082   // A window being created should exit overview mode.
1083   std::unique_ptr<aura::Window> window2(CreateTestWindow());
1084   EXPECT_FALSE(InOverviewSession());
1085 }
1086 
1087 // Tests that a window activation exits overview mode.
TEST_P(OverviewSessionTest,ActivationCancelsOverview)1088 TEST_P(OverviewSessionTest, ActivationCancelsOverview) {
1089   std::unique_ptr<aura::Window> window1(CreateTestWindow());
1090   std::unique_ptr<aura::Window> window2(CreateTestWindow());
1091   window2->Focus();
1092   ToggleOverview();
1093   EXPECT_TRUE(InOverviewSession());
1094 
1095   // A window being activated should exit overview mode.
1096   window1->Focus();
1097   EXPECT_FALSE(InOverviewSession());
1098 
1099   // window1 should be focused after exiting even though window2 was focused on
1100   // entering overview because we exited due to an activation.
1101   EXPECT_EQ(window1.get(), window_util::GetFocusedWindow());
1102 }
1103 
1104 // Tests that if a window is dragged while overview is open, the activation
1105 // of the dragged window does not cancel overview.
TEST_P(OverviewSessionTest,ActivateDraggedWindowNotCancelOverview)1106 TEST_P(OverviewSessionTest, ActivateDraggedWindowNotCancelOverview) {
1107   UpdateDisplay("800x600");
1108   EnterTabletMode();
1109   std::unique_ptr<aura::Window> window1(CreateTestWindow());
1110   window1->SetProperty(aura::client::kAppType,
1111                        static_cast<int>(AppType::BROWSER));
1112   std::unique_ptr<aura::Window> window2(CreateTestWindow());
1113   EXPECT_FALSE(InOverviewSession());
1114 
1115   // Start drag on |window1|.
1116   std::unique_ptr<WindowResizer> resizer(CreateWindowResizer(
1117       window1.get(), gfx::PointF(), HTCAPTION, ::wm::WINDOW_MOVE_SOURCE_TOUCH));
1118   EXPECT_TRUE(InOverviewSession());
1119 
1120   resizer->Drag(gfx::PointF(400, 0), 0);
1121   EXPECT_TRUE(InOverviewSession());
1122 
1123   wm::ActivateWindow(window1.get());
1124   EXPECT_TRUE(InOverviewSession());
1125 
1126   resizer->CompleteDrag();
1127   EXPECT_FALSE(InOverviewSession());
1128 }
1129 
1130 // Tests that activate a non-dragged window during window drag will not cancel
1131 // overview mode.
TEST_P(OverviewSessionTest,ActivateAnotherWindowDuringDragNotCancelOverview)1132 TEST_P(OverviewSessionTest, ActivateAnotherWindowDuringDragNotCancelOverview) {
1133   UpdateDisplay("800x600");
1134   EnterTabletMode();
1135   std::unique_ptr<aura::Window> window1(CreateTestWindow());
1136   window1->SetProperty(aura::client::kAppType,
1137                        static_cast<int>(AppType::BROWSER));
1138   std::unique_ptr<aura::Window> window2(CreateTestWindow());
1139   EXPECT_FALSE(InOverviewSession());
1140 
1141   // Start drag on |window1|.
1142   wm::ActivateWindow(window1.get());
1143   std::unique_ptr<WindowResizer> resizer(CreateWindowResizer(
1144       window1.get(), gfx::PointF(), HTCAPTION, ::wm::WINDOW_MOVE_SOURCE_TOUCH));
1145   EXPECT_TRUE(InOverviewSession());
1146 
1147   // Activate |window2| should not cancel overview mode.
1148   wm::ActivateWindow(window2.get());
1149   EXPECT_FALSE(WindowState::Get(window2.get())->is_dragged());
1150   EXPECT_TRUE(wm::IsActiveWindow(window2.get()));
1151   EXPECT_TRUE(InOverviewSession());
1152 }
1153 
1154 // Tests that if an overview item is dragged, the activation of the
1155 // corresponding window does not cancel overview.
TEST_P(OverviewSessionTest,ActivateDraggedOverviewWindowNotCancelOverview)1156 TEST_P(OverviewSessionTest, ActivateDraggedOverviewWindowNotCancelOverview) {
1157   UpdateDisplay("800x600");
1158   EnterTabletMode();
1159   std::unique_ptr<aura::Window> window(CreateTestWindow());
1160   ToggleOverview();
1161   OverviewItem* item = GetOverviewItemForWindow(window.get());
1162   gfx::PointF drag_point = item->target_bounds().CenterPoint();
1163   overview_session()->InitiateDrag(item, drag_point,
1164                                    /*is_touch_dragging=*/false);
1165   drag_point.Offset(5.f, 0.f);
1166   overview_session()->Drag(item, drag_point);
1167   wm::ActivateWindow(window.get());
1168   EXPECT_TRUE(InOverviewSession());
1169 }
1170 
1171 // Tests that if an overview item is dragged, the activation of the window
1172 // corresponding to another overview item does not cancel overview.
TEST_P(OverviewSessionTest,ActivateAnotherOverviewWindowDuringOverviewDragNotCancelOverview)1173 TEST_P(OverviewSessionTest,
1174        ActivateAnotherOverviewWindowDuringOverviewDragNotCancelOverview) {
1175   UpdateDisplay("800x600");
1176   EnterTabletMode();
1177   std::unique_ptr<aura::Window> window1(CreateTestWindow());
1178   std::unique_ptr<aura::Window> window2(CreateTestWindow());
1179   ToggleOverview();
1180   OverviewItem* item1 = GetOverviewItemForWindow(window1.get());
1181   gfx::PointF drag_point = item1->target_bounds().CenterPoint();
1182   overview_session()->InitiateDrag(item1, drag_point,
1183                                    /*is_touch_dragging=*/false);
1184   drag_point.Offset(5.f, 0.f);
1185   overview_session()->Drag(item1, drag_point);
1186   wm::ActivateWindow(window2.get());
1187   EXPECT_TRUE(InOverviewSession());
1188 }
1189 
1190 // Tests that if an overview item is dragged, the activation of a window
1191 // excluded from overview does not cancel overview.
TEST_P(OverviewSessionTest,ActivateWindowExcludedFromOverviewDuringOverviewDragNotCancelOverview)1192 TEST_P(OverviewSessionTest,
1193        ActivateWindowExcludedFromOverviewDuringOverviewDragNotCancelOverview) {
1194   UpdateDisplay("800x600");
1195   EnterTabletMode();
1196   std::unique_ptr<aura::Window> window1(CreateTestWindow());
1197   std::unique_ptr<aura::Window> window2(
1198       CreateTestWindow(gfx::Rect(), aura::client::WINDOW_TYPE_POPUP));
1199   EXPECT_TRUE(window_util::ShouldExcludeForOverview(window2.get()));
1200   ToggleOverview();
1201   OverviewItem* item1 = GetOverviewItemForWindow(window1.get());
1202   gfx::PointF drag_point = item1->target_bounds().CenterPoint();
1203   overview_session()->InitiateDrag(item1, drag_point,
1204                                    /*is_touch_dragging=*/false);
1205   drag_point.Offset(5.f, 0.f);
1206   overview_session()->Drag(item1, drag_point);
1207   wm::ActivateWindow(window2.get());
1208   EXPECT_TRUE(InOverviewSession());
1209 }
1210 
1211 // Tests that exiting overview mode without selecting a window restores focus
1212 // to the previously focused window.
TEST_P(OverviewSessionTest,CancelRestoresFocus)1213 TEST_P(OverviewSessionTest, CancelRestoresFocus) {
1214   std::unique_ptr<aura::Window> window(CreateTestWindow());
1215   wm::ActivateWindow(window.get());
1216   EXPECT_EQ(window.get(), window_util::GetFocusedWindow());
1217 
1218   // In overview mode, the overview focus window should be focused.
1219   ToggleOverview();
1220   EXPECT_EQ(overview_session()->GetOverviewFocusWindow(),
1221             window_util::GetFocusedWindow());
1222 
1223   // If canceling overview mode, focus should be restored.
1224   ToggleOverview();
1225   EXPECT_EQ(window.get(), window_util::GetFocusedWindow());
1226 }
1227 
1228 // Tests that overview mode is exited if the last remaining window is destroyed.
TEST_P(OverviewSessionTest,LastWindowDestroyed)1229 TEST_P(OverviewSessionTest, LastWindowDestroyed) {
1230   std::unique_ptr<aura::Window> window1(CreateTestWindow());
1231   std::unique_ptr<aura::Window> window2(CreateTestWindow());
1232   ToggleOverview();
1233 
1234   window1.reset();
1235   window2.reset();
1236   EXPECT_FALSE(InOverviewSession());
1237 }
1238 
1239 // Tests that entering overview mode restores a window to its original
1240 // target location.
TEST_P(OverviewSessionTest,QuickReentryRestoresInitialTransform)1241 TEST_P(OverviewSessionTest, QuickReentryRestoresInitialTransform) {
1242   std::unique_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(400, 400)));
1243   gfx::Rect initial_bounds = GetTransformedBounds(window.get());
1244   ToggleOverview();
1245   // Quickly exit and reenter overview mode. The window should still be
1246   // animating when we reenter. We cannot short circuit animations for this but
1247   // we also don't have to wait for them to complete.
1248   {
1249     ui::ScopedAnimationDurationScaleMode test_duration_mode(
1250         ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
1251     ToggleOverview();
1252     ToggleOverview();
1253   }
1254   EXPECT_NE(initial_bounds, GetTransformedTargetBounds(window.get()));
1255   ToggleOverview();
1256   EXPECT_FALSE(InOverviewSession());
1257   EXPECT_EQ(initial_bounds, GetTransformedTargetBounds(window.get()));
1258 }
1259 
1260 // Tests that windows with modal child windows are transformed with the modal
1261 // child even though not activatable themselves.
TEST_P(OverviewSessionTest,ModalChild)1262 TEST_P(OverviewSessionTest, ModalChild) {
1263   const gfx::Rect bounds(400, 400);
1264   std::unique_ptr<aura::Window> window(CreateTestWindow(bounds));
1265   std::unique_ptr<aura::Window> child(CreateTestWindow(bounds));
1266   child->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
1267   ::wm::AddTransientChild(window.get(), child.get());
1268   EXPECT_EQ(window->parent(), child->parent());
1269   ToggleOverview();
1270   EXPECT_TRUE(window->IsVisible());
1271   EXPECT_TRUE(child->IsVisible());
1272   EXPECT_EQ(GetTransformedTargetBounds(child.get()),
1273             GetTransformedTargetBounds(window.get()));
1274   ToggleOverview();
1275 }
1276 
1277 // Tests that clicking a modal window's parent activates the modal window in
1278 // overview.
TEST_P(OverviewSessionTest,ClickModalWindowParent)1279 TEST_P(OverviewSessionTest, ClickModalWindowParent) {
1280   std::unique_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(180, 180)));
1281   std::unique_ptr<aura::Window> child(
1282       CreateTestWindow(gfx::Rect(200, 0, 180, 180)));
1283   child->SetProperty(aura::client::kModalKey, ui::MODAL_TYPE_WINDOW);
1284   ::wm::AddTransientChild(window.get(), child.get());
1285   EXPECT_FALSE(WindowsOverlapping(window.get(), child.get()));
1286   EXPECT_EQ(window->parent(), child->parent());
1287   ToggleOverview();
1288   // Given that their relative positions are preserved, the windows should still
1289   // not overlap.
1290   EXPECT_FALSE(WindowsOverlapping(window.get(), child.get()));
1291   ClickWindow(window.get());
1292   EXPECT_FALSE(InOverviewSession());
1293 
1294   // Clicking on window1 should activate child1.
1295   EXPECT_TRUE(wm::IsActiveWindow(child.get()));
1296 }
1297 
1298 // Tests that windows remain on the display they are currently on in overview
1299 // mode, and that the close buttons are on matching displays.
TEST_P(OverviewSessionTest,MultipleDisplays)1300 TEST_P(OverviewSessionTest, MultipleDisplays) {
1301   UpdateDisplay("600x400,600x400");
1302   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1303   gfx::Rect bounds1(0, 0, 400, 400);
1304   gfx::Rect bounds2(650, 0, 400, 400);
1305 
1306   std::unique_ptr<aura::Window> window1(CreateTestWindow(bounds1));
1307   std::unique_ptr<aura::Window> window2(CreateTestWindow(bounds1));
1308   std::unique_ptr<aura::Window> window3(CreateTestWindow(bounds2));
1309   std::unique_ptr<aura::Window> window4(CreateTestWindow(bounds2));
1310   EXPECT_EQ(root_windows[0], window1->GetRootWindow());
1311   EXPECT_EQ(root_windows[0], window2->GetRootWindow());
1312   EXPECT_EQ(root_windows[1], window3->GetRootWindow());
1313   EXPECT_EQ(root_windows[1], window4->GetRootWindow());
1314 
1315   // In overview mode, each window remains in the same root window.
1316   ToggleOverview();
1317   EXPECT_EQ(root_windows[0], window1->GetRootWindow());
1318   EXPECT_EQ(root_windows[0], window2->GetRootWindow());
1319   EXPECT_EQ(root_windows[1], window3->GetRootWindow());
1320   EXPECT_EQ(root_windows[1], window4->GetRootWindow());
1321 
1322   // Window indices are based on top-down order. The reverse of our creation.
1323   CheckWindowAndCloseButtonInScreen(window1.get(),
1324                                     GetOverviewItemForWindow(window1.get()));
1325   CheckWindowAndCloseButtonInScreen(window2.get(),
1326                                     GetOverviewItemForWindow(window2.get()));
1327   CheckWindowAndCloseButtonInScreen(window3.get(),
1328                                     GetOverviewItemForWindow(window3.get()));
1329   CheckWindowAndCloseButtonInScreen(window4.get(),
1330                                     GetOverviewItemForWindow(window4.get()));
1331 }
1332 
1333 // Tests shutting down during overview.
TEST_P(OverviewSessionTest,Shutdown)1334 TEST_P(OverviewSessionTest, Shutdown) {
1335   // These windows will be deleted when the test exits and the Shell instance
1336   // is shut down.
1337   std::unique_ptr<aura::Window> window1(CreateTestWindow());
1338   std::unique_ptr<aura::Window> window2(CreateTestWindow());
1339 
1340   wm::ActivateWindow(window2.get());
1341   wm::ActivateWindow(window1.get());
1342 
1343   ToggleOverview();
1344 }
1345 
1346 // Tests adding a display during overview.
TEST_P(OverviewSessionTest,AddDisplay)1347 TEST_P(OverviewSessionTest, AddDisplay) {
1348   UpdateDisplay("400x400");
1349   ToggleOverview();
1350   EXPECT_TRUE(InOverviewSession());
1351   UpdateDisplay("400x400,400x400");
1352   EXPECT_FALSE(InOverviewSession());
1353 }
1354 
1355 // Tests removing a display during overview.
TEST_P(OverviewSessionTest,RemoveDisplay)1356 TEST_P(OverviewSessionTest, RemoveDisplay) {
1357   UpdateDisplay("400x400,400x400");
1358   std::unique_ptr<aura::Window> window1(CreateTestWindow(gfx::Rect(100, 100)));
1359   std::unique_ptr<aura::Window> window2(
1360       CreateTestWindow(gfx::Rect(450, 0, 100, 100)));
1361 
1362   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1363   EXPECT_EQ(root_windows[0], window1->GetRootWindow());
1364   EXPECT_EQ(root_windows[1], window2->GetRootWindow());
1365 
1366   wm::ActivateWindow(window2.get());
1367   wm::ActivateWindow(window1.get());
1368 
1369   ToggleOverview();
1370   EXPECT_TRUE(InOverviewSession());
1371   UpdateDisplay("400x400");
1372   EXPECT_FALSE(InOverviewSession());
1373 }
1374 
1375 // Tests removing a display during overview with NON_ZERO_DURATION animation.
TEST_P(OverviewSessionTest,RemoveDisplayWithAnimation)1376 TEST_P(OverviewSessionTest, RemoveDisplayWithAnimation) {
1377   UpdateDisplay("400x400,400x400");
1378   std::unique_ptr<aura::Window> window1(CreateTestWindow(gfx::Rect(100, 100)));
1379   std::unique_ptr<aura::Window> window2(
1380       CreateTestWindow(gfx::Rect(450, 0, 100, 100)));
1381 
1382   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1383   EXPECT_EQ(root_windows[0], window1->GetRootWindow());
1384   EXPECT_EQ(root_windows[1], window2->GetRootWindow());
1385 
1386   wm::ActivateWindow(window2.get());
1387   wm::ActivateWindow(window1.get());
1388 
1389   ToggleOverview();
1390   EXPECT_TRUE(InOverviewSession());
1391 
1392   ui::ScopedAnimationDurationScaleMode test_duration_mode(
1393       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
1394   UpdateDisplay("400x400");
1395   EXPECT_FALSE(InOverviewSession());
1396 }
1397 
1398 // Tests that tab key does not cause crash if pressed just after overview
1399 // session exits.
TEST_P(OverviewSessionTest,NoCrashOnTabAfterExit)1400 TEST_P(OverviewSessionTest, NoCrashOnTabAfterExit) {
1401   std::unique_ptr<aura::Window> window = CreateTestWindow();
1402   wm::ActivateWindow(window.get());
1403 
1404   ToggleOverview();
1405   EXPECT_TRUE(InOverviewSession());
1406 
1407   ToggleOverview();
1408   SendKey(ui::VKEY_TAB);
1409   EXPECT_FALSE(InOverviewSession());
1410 }
1411 
1412 // Tests that tab key does not cause crash if pressed just after overview
1413 // session exits, and a child window was active before session start.
TEST_P(OverviewSessionTest,NoCrashOnTabAfterExitWithChildWindowInitiallyFocused)1414 TEST_P(OverviewSessionTest,
1415        NoCrashOnTabAfterExitWithChildWindowInitiallyFocused) {
1416   std::unique_ptr<aura::Window> window = CreateTestWindow();
1417   std::unique_ptr<aura::Window> child_window = CreateChildWindow(window.get());
1418 
1419   wm::ActivateWindow(child_window.get());
1420 
1421   ToggleOverview();
1422   EXPECT_TRUE(InOverviewSession());
1423 
1424   ToggleOverview();
1425   SendKey(ui::VKEY_TAB);
1426   EXPECT_FALSE(InOverviewSession());
1427 }
1428 
1429 // Tests that tab key does not cause crash if pressed just after overview
1430 // session exits when no windows existed before starting overview session.
TEST_P(OverviewSessionTest,NoCrashOnTabAfterExitWithNoWindows)1431 TEST_P(OverviewSessionTest, NoCrashOnTabAfterExitWithNoWindows) {
1432   ToggleOverview();
1433   EXPECT_TRUE(InOverviewSession());
1434 
1435   ToggleOverview();
1436   SendKey(ui::VKEY_TAB);
1437   EXPECT_FALSE(InOverviewSession());
1438 }
1439 
1440 // Tests that dragging a window from overview creates a drop target on the same
1441 // display.
TEST_P(OverviewSessionTest,DropTargetOnCorrectDisplayForDraggingFromOverview)1442 TEST_P(OverviewSessionTest, DropTargetOnCorrectDisplayForDraggingFromOverview) {
1443   UpdateDisplay("600x600,600x600");
1444   EnterTabletMode();
1445   // DisplayConfigurationObserver enables mirror mode when tablet mode is
1446   // enabled. Disable mirror mode to test multiple displays.
1447   display_manager()->SetMirrorMode(display::MirrorMode::kOff, base::nullopt);
1448   base::RunLoop().RunUntilIdle();
1449 
1450   const aura::Window::Windows root_windows = Shell::Get()->GetAllRootWindows();
1451   ASSERT_EQ(2u, root_windows.size());
1452 
1453   std::unique_ptr<aura::Window> primary_screen_window =
1454       CreateTestWindow(gfx::Rect(0, 0, 600, 600));
1455   ASSERT_EQ(root_windows[0], primary_screen_window->GetRootWindow());
1456   std::unique_ptr<aura::Window> secondary_screen_window =
1457       CreateTestWindow(gfx::Rect(600, 0, 600, 600));
1458   ASSERT_EQ(root_windows[1], secondary_screen_window->GetRootWindow());
1459 
1460   ToggleOverview();
1461   OverviewItem* primary_screen_item =
1462       GetOverviewItemForWindow(primary_screen_window.get());
1463   OverviewItem* secondary_screen_item =
1464       GetOverviewItemForWindow(secondary_screen_window.get());
1465 
1466   EXPECT_FALSE(GetDropTarget(0));
1467   EXPECT_FALSE(GetDropTarget(1));
1468   gfx::PointF drag_point = primary_screen_item->target_bounds().CenterPoint();
1469   overview_session()->InitiateDrag(primary_screen_item, drag_point,
1470                                    /*is_touch_dragging=*/true);
1471   EXPECT_FALSE(GetDropTarget(0));
1472   EXPECT_FALSE(GetDropTarget(1));
1473   drag_point.Offset(5.f, 0.f);
1474   overview_session()->Drag(primary_screen_item, drag_point);
1475   EXPECT_FALSE(GetDropTarget(1));
1476   ASSERT_TRUE(GetDropTarget(0));
1477   EXPECT_EQ(root_windows[0], GetDropTarget(0)->root_window());
1478   overview_session()->CompleteDrag(primary_screen_item, drag_point);
1479   EXPECT_FALSE(GetDropTarget(0));
1480   EXPECT_FALSE(GetDropTarget(1));
1481   drag_point = secondary_screen_item->target_bounds().CenterPoint();
1482   overview_session()->InitiateDrag(secondary_screen_item, drag_point,
1483                                    /*is_touch_dragging=*/true);
1484   EXPECT_FALSE(GetDropTarget(0));
1485   EXPECT_FALSE(GetDropTarget(1));
1486   drag_point.Offset(5.f, 0.f);
1487   overview_session()->Drag(secondary_screen_item, drag_point);
1488   EXPECT_FALSE(GetDropTarget(0));
1489   ASSERT_TRUE(GetDropTarget(1));
1490   EXPECT_EQ(root_windows[1], GetDropTarget(1)->root_window());
1491   overview_session()->CompleteDrag(secondary_screen_item, drag_point);
1492   EXPECT_FALSE(GetDropTarget(0));
1493   EXPECT_FALSE(GetDropTarget(1));
1494 }
1495 
1496 // Tests that the drop target is removed if a window is destroyed while being
1497 // dragged from the top.
TEST_P(OverviewSessionTest,DropTargetRemovedIfWindowDraggedFromTopIsDestroyed)1498 TEST_P(OverviewSessionTest,
1499        DropTargetRemovedIfWindowDraggedFromTopIsDestroyed) {
1500   EnterTabletMode();
1501   std::unique_ptr<aura::Window> window = CreateTestWindow();
1502   std::unique_ptr<aura::Window> window2 = CreateTestWindow();
1503   window->SetProperty(aura::client::kAppType,
1504                       static_cast<int>(AppType::BROWSER));
1505   std::unique_ptr<WindowResizer> resizer =
1506       CreateWindowResizer(window.get(), gfx::PointF(400, 0), HTCAPTION,
1507                           ::wm::WINDOW_MOVE_SOURCE_TOUCH);
1508   ASSERT_TRUE(InOverviewSession());
1509   EXPECT_TRUE(GetDropTarget(0));
1510   resizer.reset();
1511   window.reset();
1512   ASSERT_TRUE(InOverviewSession());
1513   EXPECT_FALSE(GetDropTarget(0));
1514 }
1515 
1516 namespace {
1517 
1518 // A simple window delegate that returns the specified hit-test code when
1519 // requested and applies a minimum size constraint if there is one.
1520 class TestDragWindowDelegate : public aura::test::TestWindowDelegate {
1521  public:
TestDragWindowDelegate()1522   TestDragWindowDelegate() { set_window_component(HTCAPTION); }
1523   ~TestDragWindowDelegate() override = default;
1524 
1525  private:
1526   // aura::Test::TestWindowDelegate:
OnWindowDestroyed(aura::Window * window)1527   void OnWindowDestroyed(aura::Window* window) override { delete this; }
1528 
1529   DISALLOW_COPY_AND_ASSIGN(TestDragWindowDelegate);
1530 };
1531 
1532 }  // namespace
1533 
1534 // Tests that toggling overview on and off does not cancel drag.
TEST_P(OverviewSessionTest,DragDropInProgress)1535 TEST_P(OverviewSessionTest, DragDropInProgress) {
1536   std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
1537       new TestDragWindowDelegate(), -1, gfx::Rect(100, 100)));
1538 
1539   GetEventGenerator()->set_current_screen_location(
1540       window->GetBoundsInScreen().CenterPoint());
1541   GetEventGenerator()->PressLeftButton();
1542   GetEventGenerator()->MoveMouseBy(10, 10);
1543   EXPECT_EQ(gfx::Rect(10, 10, 100, 100), window->bounds());
1544 
1545   ToggleOverview();
1546   ASSERT_TRUE(InOverviewSession());
1547 
1548   GetEventGenerator()->MoveMouseBy(10, 10);
1549 
1550   ToggleOverview();
1551   ASSERT_FALSE(InOverviewSession());
1552 
1553   GetEventGenerator()->MoveMouseBy(10, 10);
1554   GetEventGenerator()->ReleaseLeftButton();
1555   base::RunLoop().RunUntilIdle();
1556   EXPECT_EQ(gfx::Rect(30, 30, 100, 100), window->bounds());
1557 }
1558 
1559 // Tests that toggling overview on removes any resize shadows that may have been
1560 // present.
TEST_P(OverviewSessionTest,DragWindowShadow)1561 TEST_P(OverviewSessionTest, DragWindowShadow) {
1562   std::unique_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(100, 100)));
1563   wm::ActivateWindow(window.get());
1564   Shell::Get()->resize_shadow_controller()->ShowShadow(window.get(), HTTOP);
1565 
1566   ToggleOverview();
1567   ResizeShadow* shadow =
1568       Shell::Get()->resize_shadow_controller()->GetShadowForWindowForTest(
1569           window.get());
1570   EXPECT_FALSE(shadow);
1571 }
1572 
1573 // Test that a label is created under the window on entering overview mode.
TEST_P(OverviewSessionTest,CreateLabelUnderWindow)1574 TEST_P(OverviewSessionTest, CreateLabelUnderWindow) {
1575   std::unique_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(300, 500)));
1576   const base::string16 window_title = base::UTF8ToUTF16("My window");
1577   window->SetTitle(window_title);
1578   ToggleOverview();
1579   OverviewItem* window_item = GetOverviewItemsForRoot(0).back().get();
1580   views::Label* label = GetLabelView(window_item);
1581   ASSERT_TRUE(label);
1582 
1583   // Verify the label matches the window title.
1584   EXPECT_EQ(window_title, label->GetText());
1585 
1586   // Update the window title and check that the label is updated, too.
1587   const base::string16 updated_title = base::UTF8ToUTF16("Updated title");
1588   window->SetTitle(updated_title);
1589   EXPECT_EQ(updated_title, label->GetText());
1590 
1591   // Labels are located based on target_bounds, not the actual window item
1592   // bounds.
1593   gfx::RectF label_bounds(label->GetWidget()->GetWindowBoundsInScreen());
1594   EXPECT_EQ(label_bounds, window_item->target_bounds());
1595 }
1596 
1597 // Tests that overview updates the window positions if the display orientation
1598 // changes.
TEST_P(OverviewSessionTest,DisplayOrientationChanged)1599 TEST_P(OverviewSessionTest, DisplayOrientationChanged) {
1600   aura::Window* root_window = Shell::Get()->GetPrimaryRootWindow();
1601   UpdateDisplay("600x200");
1602   EXPECT_EQ(gfx::Rect(600, 200), root_window->bounds());
1603   std::vector<std::unique_ptr<aura::Window>> windows;
1604   for (int i = 0; i < 3; i++) {
1605     windows.push_back(
1606         std::unique_ptr<aura::Window>(CreateTestWindow(gfx::Rect(150, 150))));
1607   }
1608 
1609   ToggleOverview();
1610   for (const auto& window : windows) {
1611     EXPECT_TRUE(root_window->bounds().Contains(
1612         GetTransformedTargetBounds(window.get())));
1613   }
1614 
1615   // Rotate the display, windows should be repositioned to be within the screen
1616   // bounds.
1617   UpdateDisplay("600x200/r");
1618   EXPECT_EQ(gfx::Rect(200, 600), root_window->bounds());
1619   for (const auto& window : windows) {
1620     EXPECT_TRUE(root_window->bounds().Contains(
1621         GetTransformedTargetBounds(window.get())));
1622   }
1623 }
1624 
TEST_P(OverviewSessionTest,AcceleratorInOverviewSession)1625 TEST_P(OverviewSessionTest, AcceleratorInOverviewSession) {
1626   ToggleOverview();
1627   auto* accelerator_controller = Shell::Get()->accelerator_controller();
1628   auto* ewh = accelerator_controller->GetExitWarningHandlerForTest();
1629   ASSERT_TRUE(ewh);
1630   StubForTest(ewh);
1631   EXPECT_FALSE(is_ui_shown(ewh));
1632 
1633   ui::test::EventGenerator event_generator(Shell::GetPrimaryRootWindow());
1634   event_generator.PressKey(ui::VKEY_Q, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN);
1635   event_generator.ReleaseKey(ui::VKEY_Q,
1636                              ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN);
1637 
1638   EXPECT_TRUE(is_ui_shown(ewh));
1639 }
1640 
1641 // Tests hitting the escape and back keys exits overview mode.
TEST_P(OverviewSessionTest,ExitOverviewWithKey)1642 TEST_P(OverviewSessionTest, ExitOverviewWithKey) {
1643   std::unique_ptr<aura::Window> window(CreateTestWindow());
1644 
1645   ToggleOverview();
1646   ASSERT_TRUE(overview_controller()->InOverviewSession());
1647   SendKey(ui::VKEY_ESCAPE);
1648   EXPECT_FALSE(overview_controller()->InOverviewSession());
1649 
1650   ToggleOverview();
1651   ASSERT_TRUE(overview_controller()->InOverviewSession());
1652   SendKey(ui::VKEY_BROWSER_BACK);
1653   EXPECT_FALSE(overview_controller()->InOverviewSession());
1654 
1655   // Tests that in tablet mode, if we snap the only overview window, we cannot
1656   // exit overview mode.
1657   EnterTabletMode();
1658   ToggleOverview();
1659   ASSERT_TRUE(overview_controller()->InOverviewSession());
1660   split_view_controller()->SnapWindow(window.get(), SplitViewController::LEFT);
1661   ASSERT_TRUE(overview_controller()->InOverviewSession());
1662   SendKey(ui::VKEY_ESCAPE);
1663   EXPECT_TRUE(overview_controller()->InOverviewSession());
1664   SendKey(ui::VKEY_BROWSER_BACK);
1665   EXPECT_TRUE(overview_controller()->InOverviewSession());
1666 }
1667 
1668 // Regression test for clusterfuzz crash. https://crbug.com/920568
TEST_P(OverviewSessionTest,TypeThenPressEscapeTwice)1669 TEST_P(OverviewSessionTest, TypeThenPressEscapeTwice) {
1670   std::unique_ptr<aura::Window> window(CreateTestWindow());
1671   ToggleOverview();
1672 
1673   // Type some characters.
1674   SendKey(ui::VKEY_A);
1675   SendKey(ui::VKEY_B);
1676   SendKey(ui::VKEY_C);
1677   EXPECT_TRUE(overview_session()->GetOverviewFocusWindow());
1678 
1679   // Pressing escape twice should not crash.
1680   SendKey(ui::VKEY_ESCAPE);
1681   SendKey(ui::VKEY_ESCAPE);
1682 }
1683 
TEST_P(OverviewSessionTest,CancelOverviewOnMouseClick)1684 TEST_P(OverviewSessionTest, CancelOverviewOnMouseClick) {
1685   std::unique_ptr<aura::Window> window(
1686       CreateTestWindow(gfx::Rect(10, 10, 100, 100)));
1687   // Move mouse to point in the background page. Sending an event here will pass
1688   // it to the WallpaperController in both regular and overview mode.
1689   GetEventGenerator()->MoveMouseTo(gfx::Point(0, 0));
1690 
1691   // Clicking on the background page while not in overview should not toggle
1692   // overview.
1693   GetEventGenerator()->ClickLeftButton();
1694   EXPECT_FALSE(InOverviewSession());
1695 
1696   // Switch to overview mode. Clicking should now exit overview mode.
1697   ToggleOverview();
1698   ASSERT_TRUE(InOverviewSession());
1699   // Choose a point that doesn't intersect with the window or the desks bar.
1700   const gfx::Point point_in_background_page = GetGridBounds().CenterPoint();
1701   GetEventGenerator()->MoveMouseTo(point_in_background_page);
1702   GetEventGenerator()->ClickLeftButton();
1703   EXPECT_FALSE(InOverviewSession());
1704 }
1705 
1706 // Tests tapping on the desktop itself to cancel overview mode.
TEST_P(OverviewSessionTest,CancelOverviewOnTap)1707 TEST_P(OverviewSessionTest, CancelOverviewOnTap) {
1708   std::unique_ptr<aura::Window> window(
1709       CreateTestWindow(gfx::Rect(10, 10, 100, 100)));
1710 
1711   // Tapping on the background page while not in overview should not toggle
1712   // overview.
1713   GetEventGenerator()->GestureTapAt(gfx::Point(0, 0));
1714   EXPECT_FALSE(InOverviewSession());
1715 
1716   // Switch to overview mode. Tapping should now exit overview mode.
1717   ToggleOverview();
1718   ASSERT_TRUE(InOverviewSession());
1719   // A point that doesn't intersect with the window nor the desks bar. This
1720   // causes events located at the point to be passed to WallpaperController, and
1721   // not the window.
1722   const gfx::Point point_in_background_page = GetGridBounds().CenterPoint();
1723   GetEventGenerator()->GestureTapAt(point_in_background_page);
1724   EXPECT_FALSE(InOverviewSession());
1725 }
1726 
1727 // Start dragging a window and activate overview mode. This test should not
1728 // crash or DCHECK inside aura::Window::StackChildRelativeTo().
TEST_P(OverviewSessionTest,OverviewWhileDragging)1729 TEST_P(OverviewSessionTest, OverviewWhileDragging) {
1730   std::unique_ptr<aura::Window> window(CreateTestWindow());
1731   std::unique_ptr<WindowResizer> resizer(CreateWindowResizer(
1732       window.get(), gfx::PointF(), HTCAPTION, ::wm::WINDOW_MOVE_SOURCE_MOUSE));
1733   ASSERT_TRUE(resizer.get());
1734   gfx::PointF location = resizer->GetInitialLocation();
1735   location.Offset(20, 20);
1736   resizer->Drag(location, 0);
1737   ToggleOverview();
1738   resizer->RevertDrag();
1739 }
1740 
1741 // Verify that the overview no windows indicator appears when entering overview
1742 // mode with no windows.
TEST_P(OverviewSessionTest,NoWindowsIndicator)1743 TEST_P(OverviewSessionTest, NoWindowsIndicator) {
1744   // Verify that by entering overview mode without windows, the no items
1745   // indicator appears.
1746   ToggleOverview();
1747   ASSERT_TRUE(overview_session());
1748   ASSERT_EQ(0u, GetOverviewItemsForRoot(0).size());
1749   EXPECT_TRUE(overview_session()->no_windows_widget_for_testing());
1750 }
1751 
1752 // Verify that the overview no windows indicator position is as expected.
TEST_P(OverviewSessionTest,NoWindowsIndicatorPosition)1753 TEST_P(OverviewSessionTest, NoWindowsIndicatorPosition) {
1754   UpdateDisplay("400x300");
1755 
1756   ToggleOverview();
1757   ASSERT_TRUE(overview_session());
1758   RoundedLabelWidget* no_windows_widget =
1759       overview_session()->no_windows_widget_for_testing();
1760   ASSERT_TRUE(no_windows_widget);
1761 
1762   // Verify that originally the label is in the center of the workspace.
1763   // Midpoint of height minus shelf.
1764   int expected_y = (300 - ShelfConfig::Get()->shelf_size()) / 2;
1765   EXPECT_EQ(gfx::Point(200, expected_y),
1766             no_windows_widget->GetWindowBoundsInScreen().CenterPoint());
1767 
1768   // Verify that after rotating the display, the label is centered in the
1769   // workspace 300x(400-shelf).
1770   display::Screen* screen = display::Screen::GetScreen();
1771   const display::Display& display = screen->GetPrimaryDisplay();
1772   display_manager()->SetDisplayRotation(
1773       display.id(), display::Display::ROTATE_90,
1774       display::Display::RotationSource::ACTIVE);
1775   expected_y = (400 - ShelfConfig::Get()->shelf_size()) / 2;
1776   EXPECT_EQ(gfx::Point(150, (400 - ShelfConfig::Get()->shelf_size()) / 2),
1777             no_windows_widget->GetWindowBoundsInScreen().CenterPoint());
1778 }
1779 
1780 // Tests that toggling overview on removes any resize shadows that may have been
1781 // present.
TEST_P(OverviewSessionTest,DragMinimizedWindowHasStableSize)1782 TEST_P(OverviewSessionTest, DragMinimizedWindowHasStableSize) {
1783   UpdateDisplay(base::StringPrintf("1920x1200*%s", display::kDsfStr_1_777));
1784   EnterTabletMode();
1785   std::unique_ptr<aura::Window> window(CreateTestWindow());
1786 
1787   WindowState::Get(window.get())->Minimize();
1788   ToggleOverview();
1789   OverviewItem* overview_item = GetOverviewItemForWindow(window.get());
1790   auto* widget = overview_item->item_widget();
1791 
1792   gfx::Rect workarea =
1793       display::Screen::GetScreen()->GetPrimaryDisplay().work_area();
1794 
1795   gfx::PointF drag_point(workarea.CenterPoint());
1796   overview_session()->InitiateDrag(overview_item, drag_point,
1797                                    /*is_touch_dragging=*/true);
1798   gfx::Size target_size =
1799       GetTransformedTargetBounds(widget->GetNativeWindow()).size();
1800 
1801   drag_point.Offset(0, 10.5f);
1802   overview_session()->Drag(overview_item, drag_point);
1803   gfx::Size new_target_size =
1804       GetTransformedTargetBounds(widget->GetNativeWindow()).size();
1805   EXPECT_EQ(target_size, new_target_size);
1806   target_size = new_target_size;
1807 
1808   drag_point.Offset(0, 10.5f);
1809   overview_session()->Drag(overview_item, drag_point);
1810   EXPECT_EQ(target_size,
1811             GetTransformedTargetBounds(widget->GetNativeWindow()).size());
1812 
1813   overview_session()->CompleteDrag(overview_item, drag_point);
1814 }
1815 
1816 // Tests that the bounds of the grid do not intersect the shelf or its hotseat.
TEST_P(OverviewSessionTest,OverviewGridBounds)1817 TEST_P(OverviewSessionTest, OverviewGridBounds) {
1818   EnterTabletMode();
1819   std::unique_ptr<aura::Window> window(CreateTestWindow());
1820 
1821   ToggleOverview();
1822   ASSERT_TRUE(overview_session());
1823 
1824   Shelf* shelf = Shelf::ForWindow(Shell::GetPrimaryRootWindow());
1825   const gfx::Rect shelf_bounds = shelf->GetIdealBounds();
1826   const gfx::Rect hotseat_bounds =
1827       shelf->hotseat_widget()->GetWindowBoundsInScreen();
1828   EXPECT_FALSE(GetGridBounds().Intersects(shelf_bounds));
1829   EXPECT_FALSE(GetGridBounds().Intersects(hotseat_bounds));
1830 }
1831 
TEST_P(OverviewSessionTest,NoWindowsIndicatorPositionSplitview)1832 TEST_P(OverviewSessionTest, NoWindowsIndicatorPositionSplitview) {
1833   UpdateDisplay("400x300");
1834   EnterTabletMode();
1835   std::unique_ptr<aura::Window> window(CreateTestWindow());
1836 
1837   ToggleOverview();
1838   ASSERT_TRUE(overview_session());
1839   RoundedLabelWidget* no_windows_widget =
1840       overview_session()->no_windows_widget_for_testing();
1841   EXPECT_FALSE(no_windows_widget);
1842 
1843   // Tests that when snapping a window to the left in splitview, the no windows
1844   // indicator shows up in the middle of the right side of the screen.
1845   split_view_controller()->SnapWindow(window.get(), SplitViewController::LEFT);
1846   no_windows_widget = overview_session()->no_windows_widget_for_testing();
1847   ASSERT_TRUE(no_windows_widget);
1848 
1849   // There is a 8dp divider in splitview, the indicator should take that into
1850   // account.
1851   const int bounds_left = 200 + 4;
1852   int expected_x = bounds_left + (400 - (bounds_left)) / 2;
1853   const int workarea_bottom_inset = ShelfConfig::Get()->in_app_shelf_size();
1854   const int expected_y = (300 - workarea_bottom_inset) / 2;
1855   EXPECT_EQ(gfx::Point(expected_x, expected_y),
1856             no_windows_widget->GetWindowBoundsInScreen().CenterPoint());
1857 
1858   // Tests that when snapping a window to the right in splitview, the no windows
1859   // indicator shows up in the middle of the left side of the screen.
1860   split_view_controller()->SnapWindow(window.get(), SplitViewController::RIGHT);
1861   expected_x = /*bounds_right=*/(200 - 4) / 2;
1862   EXPECT_EQ(gfx::Point(expected_x, expected_y),
1863             no_windows_widget->GetWindowBoundsInScreen().CenterPoint());
1864 }
1865 
1866 // Tests that the no windows indicator shows properly after adding an item.
TEST_P(OverviewSessionTest,NoWindowsIndicatorAddItem)1867 TEST_P(OverviewSessionTest, NoWindowsIndicatorAddItem) {
1868   EnterTabletMode();
1869   std::unique_ptr<aura::Window> window(CreateTestWindow());
1870 
1871   ToggleOverview();
1872   split_view_controller()->SnapWindow(window.get(), SplitViewController::LEFT);
1873   EXPECT_TRUE(overview_session()->no_windows_widget_for_testing());
1874 
1875   overview_session()->AddItem(window.get(), /*reposition=*/true,
1876                               /*animate=*/false, /*ignored_items=*/{},
1877                               /*index=*/0u);
1878   EXPECT_FALSE(overview_session()->no_windows_widget_for_testing());
1879 }
1880 
1881 // Verify that when opening overview mode with multiple displays, the no items
1882 // indicator on the primary grid if there are no windows.
TEST_P(OverviewSessionTest,NoWindowsIndicatorPositionMultiDisplay)1883 TEST_P(OverviewSessionTest, NoWindowsIndicatorPositionMultiDisplay) {
1884   UpdateDisplay("400x400,400x400,400x400");
1885 
1886   // Enter overview mode. Verify that the no windows indicator is located on the
1887   // primary display.
1888   ToggleOverview();
1889   ASSERT_TRUE(overview_session());
1890   RoundedLabelWidget* no_windows_widget =
1891       overview_session()->no_windows_widget_for_testing();
1892   const int expected_y = (400 - ShelfConfig::Get()->shelf_size()) / 2;
1893   EXPECT_EQ(gfx::Point(200, expected_y),
1894             no_windows_widget->GetWindowBoundsInScreen().CenterPoint());
1895 }
1896 
1897 // Tests that we do not exit overview mode until all the grids are empty.
TEST_P(OverviewSessionTest,ExitOverviewWhenAllGridsEmpty)1898 TEST_P(OverviewSessionTest, ExitOverviewWhenAllGridsEmpty) {
1899   UpdateDisplay("400x400,400x400,400x400");
1900 
1901   // Create two windows with widgets (widgets are needed to close the windows
1902   // later in the test), one each on the first two monitors.
1903   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1904   std::unique_ptr<views::Widget> widget1(CreateTestWidget());
1905   std::unique_ptr<views::Widget> widget2(CreateTestWidget());
1906   aura::Window* window1 = widget1->GetNativeWindow();
1907   aura::Window* window2 = widget2->GetNativeWindow();
1908   ASSERT_TRUE(
1909       window_util::MoveWindowToDisplay(window2, GetSecondaryDisplay().id()));
1910   ASSERT_EQ(root_windows[0], window1->GetRootWindow());
1911   ASSERT_EQ(root_windows[1], window2->GetRootWindow());
1912 
1913   // Enter overview mode. Verify that the no windows indicator is not visible on
1914   // any display.
1915   ToggleOverview();
1916   auto& grids = overview_session()->grid_list();
1917   ASSERT_TRUE(overview_session());
1918   ASSERT_EQ(3u, grids.size());
1919   EXPECT_FALSE(overview_session()->no_windows_widget_for_testing());
1920 
1921   OverviewItem* item1 = GetOverviewItemForWindow(window1);
1922   OverviewItem* item2 = GetOverviewItemForWindow(window2);
1923   ASSERT_TRUE(item1 && item2);
1924 
1925   // Close |item2|. Verify that we are still in overview mode because |window1|
1926   // is still open. The non primary root grids are empty however.
1927   item2->CloseWindow();
1928   base::RunLoop().RunUntilIdle();
1929   ASSERT_TRUE(overview_session());
1930   ASSERT_EQ(3u, grids.size());
1931   EXPECT_FALSE(grids[0]->empty());
1932   EXPECT_TRUE(grids[1]->empty());
1933   EXPECT_TRUE(grids[2]->empty());
1934   EXPECT_FALSE(overview_session()->no_windows_widget_for_testing());
1935 
1936   // Close |item1|. Verify that since no windows are open, we exit overview
1937   // mode.
1938   item1->CloseWindow();
1939   base::RunLoop().RunUntilIdle();
1940   EXPECT_FALSE(overview_session());
1941 }
1942 
1943 // Tests window list animation states are correctly updated.
TEST_P(OverviewSessionTest,SetWindowListAnimationStates)1944 TEST_P(OverviewSessionTest, SetWindowListAnimationStates) {
1945   std::unique_ptr<aura::Window> window1(CreateTestWindow());
1946   std::unique_ptr<aura::Window> window2(CreateTestWindow());
1947   std::unique_ptr<aura::Window> window3(CreateTestWindow());
1948   wm::ActivateWindow(window3.get());
1949   wm::ActivateWindow(window2.get());
1950   wm::ActivateWindow(window1.get());
1951 
1952   EXPECT_FALSE(WindowState::Get(window1.get())->IsFullscreen());
1953   EXPECT_FALSE(WindowState::Get(window2.get())->IsFullscreen());
1954   EXPECT_FALSE(WindowState::Get(window3.get())->IsFullscreen());
1955 
1956   const WMEvent toggle_fullscreen_event(WM_EVENT_TOGGLE_FULLSCREEN);
1957   WindowState::Get(window2.get())->OnWMEvent(&toggle_fullscreen_event);
1958   WindowState::Get(window3.get())->OnWMEvent(&toggle_fullscreen_event);
1959   EXPECT_FALSE(WindowState::Get(window1.get())->IsFullscreen());
1960   EXPECT_TRUE(WindowState::Get(window2.get())->IsFullscreen());
1961   EXPECT_TRUE(WindowState::Get(window3.get())->IsFullscreen());
1962 
1963   ui::ScopedAnimationDurationScaleMode test_duration_mode(
1964       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
1965   // Enter overview.
1966   ToggleOverview();
1967   EXPECT_TRUE(window1->layer()->GetAnimator()->is_animating());
1968   EXPECT_TRUE(window2->layer()->GetAnimator()->is_animating());
1969   EXPECT_FALSE(window3->layer()->GetAnimator()->is_animating());
1970 
1971   ToggleOverview();
1972 }
1973 
1974 // Tests window list animation states are correctly updated with selected
1975 // window.
TEST_P(OverviewSessionTest,SetWindowListAnimationStatesWithSelectedWindow)1976 TEST_P(OverviewSessionTest, SetWindowListAnimationStatesWithSelectedWindow) {
1977   std::unique_ptr<aura::Window> window1(CreateTestWindow());
1978   std::unique_ptr<aura::Window> window2(CreateTestWindow());
1979   std::unique_ptr<aura::Window> window3(CreateTestWindow());
1980   wm::ActivateWindow(window3.get());
1981   wm::ActivateWindow(window2.get());
1982   wm::ActivateWindow(window1.get());
1983 
1984   EXPECT_FALSE(WindowState::Get(window1.get())->IsFullscreen());
1985   EXPECT_FALSE(WindowState::Get(window2.get())->IsFullscreen());
1986   EXPECT_FALSE(WindowState::Get(window3.get())->IsFullscreen());
1987 
1988   const WMEvent toggle_fullscreen_event(WM_EVENT_TOGGLE_FULLSCREEN);
1989   WindowState::Get(window2.get())->OnWMEvent(&toggle_fullscreen_event);
1990   WindowState::Get(window3.get())->OnWMEvent(&toggle_fullscreen_event);
1991   EXPECT_FALSE(WindowState::Get(window1.get())->IsFullscreen());
1992   EXPECT_TRUE(WindowState::Get(window2.get())->IsFullscreen());
1993   EXPECT_TRUE(WindowState::Get(window3.get())->IsFullscreen());
1994 
1995   // Enter overview.
1996   ToggleOverview();
1997 
1998   ui::ScopedAnimationDurationScaleMode test_duration_mode(
1999       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2000   // Click on |window3| to activate it and exit overview.
2001   // Should only set |should_animate_when_exiting_| and
2002   // |should_be_observed_when_exiting_| on window 3.
2003   TweenTester tester1(window1.get());
2004   TweenTester tester2(window2.get());
2005   TweenTester tester3(window3.get());
2006   ClickWindow(window3.get());
2007   EXPECT_EQ(gfx::Tween::ZERO, tester1.tween_type());
2008   EXPECT_EQ(gfx::Tween::ZERO, tester2.tween_type());
2009   EXPECT_EQ(gfx::Tween::EASE_OUT, tester3.tween_type());
2010 }
2011 
2012 // Tests OverviewWindowAnimationObserver can handle deleted window.
TEST_P(OverviewSessionTest,OverviewWindowAnimationObserverCanHandleDeletedWindow)2013 TEST_P(OverviewSessionTest,
2014        OverviewWindowAnimationObserverCanHandleDeletedWindow) {
2015   std::unique_ptr<aura::Window> window1(CreateTestWindow());
2016   std::unique_ptr<aura::Window> window2(CreateTestWindow());
2017   std::unique_ptr<aura::Window> window3(CreateTestWindow());
2018   wm::ActivateWindow(window3.get());
2019   wm::ActivateWindow(window2.get());
2020   wm::ActivateWindow(window1.get());
2021 
2022   EXPECT_FALSE(WindowState::Get(window1.get())->IsFullscreen());
2023   EXPECT_FALSE(WindowState::Get(window2.get())->IsFullscreen());
2024   EXPECT_FALSE(WindowState::Get(window3.get())->IsFullscreen());
2025 
2026   const WMEvent toggle_fullscreen_event(WM_EVENT_TOGGLE_FULLSCREEN);
2027   WindowState::Get(window2.get())->OnWMEvent(&toggle_fullscreen_event);
2028   WindowState::Get(window3.get())->OnWMEvent(&toggle_fullscreen_event);
2029   EXPECT_FALSE(WindowState::Get(window1.get())->IsFullscreen());
2030   EXPECT_TRUE(WindowState::Get(window2.get())->IsFullscreen());
2031   EXPECT_TRUE(WindowState::Get(window3.get())->IsFullscreen());
2032 
2033   // Enter overview.
2034   ToggleOverview();
2035 
2036   ui::ScopedAnimationDurationScaleMode test_duration_mode(
2037       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2038   // Click on |window3| to activate it and exit overview.
2039   // Should only set |should_animate_when_exiting_| and
2040   // |should_be_observed_when_exiting_| on window 3.
2041   {
2042     TweenTester tester1(window1.get());
2043     TweenTester tester2(window2.get());
2044     TweenTester tester3(window3.get());
2045     ClickWindow(window3.get());
2046     EXPECT_EQ(gfx::Tween::ZERO, tester1.tween_type());
2047     EXPECT_EQ(gfx::Tween::ZERO, tester2.tween_type());
2048     EXPECT_EQ(gfx::Tween::EASE_OUT, tester3.tween_type());
2049   }
2050   // Destroy |window1| and |window2| before |window3| finishes animation can be
2051   // handled in OverviewWindowAnimationObserver.
2052   window1.reset();
2053   window2.reset();
2054 }
2055 
2056 // Tests can handle OverviewWindowAnimationObserver was deleted.
TEST_P(OverviewSessionTest,HandleOverviewWindowAnimationObserverWasDeleted)2057 TEST_P(OverviewSessionTest, HandleOverviewWindowAnimationObserverWasDeleted) {
2058   std::unique_ptr<aura::Window> window1(CreateTestWindow());
2059   std::unique_ptr<aura::Window> window2(CreateTestWindow());
2060   std::unique_ptr<aura::Window> window3(CreateTestWindow());
2061   wm::ActivateWindow(window3.get());
2062   wm::ActivateWindow(window2.get());
2063   wm::ActivateWindow(window1.get());
2064 
2065   EXPECT_FALSE(WindowState::Get(window1.get())->IsFullscreen());
2066   EXPECT_FALSE(WindowState::Get(window2.get())->IsFullscreen());
2067   EXPECT_FALSE(WindowState::Get(window3.get())->IsFullscreen());
2068 
2069   const WMEvent toggle_fullscreen_event(WM_EVENT_TOGGLE_FULLSCREEN);
2070   WindowState::Get(window2.get())->OnWMEvent(&toggle_fullscreen_event);
2071   WindowState::Get(window3.get())->OnWMEvent(&toggle_fullscreen_event);
2072   EXPECT_FALSE(WindowState::Get(window1.get())->IsFullscreen());
2073   EXPECT_TRUE(WindowState::Get(window2.get())->IsFullscreen());
2074   EXPECT_TRUE(WindowState::Get(window3.get())->IsFullscreen());
2075 
2076   // Enter overview.
2077   ToggleOverview();
2078 
2079   // Click on |window2| to activate it and exit overview. Should only set
2080   // |should_animate_when_exiting_| and |should_be_observed_when_exiting_| on
2081   // window 2. Because the animation duration is zero in test, the
2082   // OverviewWindowAnimationObserver will delete itself immediately before
2083   // |window3| is added to it.
2084   ClickWindow(window2.get());
2085   EXPECT_FALSE(window1->layer()->GetAnimator()->is_animating());
2086   EXPECT_FALSE(window2->layer()->GetAnimator()->is_animating());
2087   EXPECT_FALSE(window3->layer()->GetAnimator()->is_animating());
2088 }
2089 
2090 // Tests can handle |gained_active| window is not in the |overview_grid| when
2091 // OnWindowActivated.
TEST_P(OverviewSessionTest,HandleActiveWindowNotInOverviewGrid)2092 TEST_P(OverviewSessionTest, HandleActiveWindowNotInOverviewGrid) {
2093   std::unique_ptr<aura::Window> window1(CreateTestWindow());
2094   std::unique_ptr<aura::Window> window2(CreateTestWindow());
2095   std::unique_ptr<aura::Window> window3(CreateTestWindow());
2096   wm::ActivateWindow(window3.get());
2097   wm::ActivateWindow(window2.get());
2098   wm::ActivateWindow(window1.get());
2099 
2100   EXPECT_FALSE(WindowState::Get(window1.get())->IsFullscreen());
2101   EXPECT_FALSE(WindowState::Get(window2.get())->IsFullscreen());
2102   EXPECT_FALSE(WindowState::Get(window3.get())->IsFullscreen());
2103 
2104   const WMEvent toggle_fullscreen_event(WM_EVENT_TOGGLE_FULLSCREEN);
2105   WindowState::Get(window2.get())->OnWMEvent(&toggle_fullscreen_event);
2106   WindowState::Get(window3.get())->OnWMEvent(&toggle_fullscreen_event);
2107   EXPECT_FALSE(WindowState::Get(window1.get())->IsFullscreen());
2108   EXPECT_TRUE(WindowState::Get(window2.get())->IsFullscreen());
2109   EXPECT_TRUE(WindowState::Get(window3.get())->IsFullscreen());
2110 
2111   // Enter overview.
2112   ToggleOverview();
2113 
2114   ui::ScopedAnimationDurationScaleMode test_duration_mode(
2115       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2116   // Create and active a new window should exit overview without error.
2117   auto widget = CreateTestWidget();
2118 
2119   TweenTester tester1(window1.get());
2120   TweenTester tester2(window2.get());
2121   TweenTester tester3(window3.get());
2122 
2123   ClickWindow(widget->GetNativeWindow());
2124 
2125   // |window1| and |window2| should animate.
2126   EXPECT_EQ(gfx::Tween::EASE_OUT, tester1.tween_type());
2127   EXPECT_EQ(gfx::Tween::EASE_OUT, tester2.tween_type());
2128   EXPECT_EQ(gfx::Tween::ZERO, tester3.tween_type());
2129 }
2130 
2131 // Tests that AlwaysOnTopWindow can be handled correctly in new overview
2132 // animations.
2133 // Fails consistently; see https://crbug.com/812497.
TEST_P(OverviewSessionTest,DISABLED_HandleAlwaysOnTopWindow)2134 TEST_P(OverviewSessionTest, DISABLED_HandleAlwaysOnTopWindow) {
2135   const gfx::Rect bounds(400, 400);
2136   std::unique_ptr<aura::Window> window1(CreateTestWindow(bounds));
2137   std::unique_ptr<aura::Window> window2(CreateTestWindow(bounds));
2138   std::unique_ptr<aura::Window> window3(CreateTestWindow(bounds));
2139   std::unique_ptr<aura::Window> window4(CreateTestWindow(bounds));
2140   std::unique_ptr<aura::Window> window5(CreateTestWindow(bounds));
2141   std::unique_ptr<aura::Window> window6(CreateTestWindow(bounds));
2142   std::unique_ptr<aura::Window> window7(CreateTestWindow(bounds));
2143   std::unique_ptr<aura::Window> window8(CreateTestWindow(bounds));
2144   window3->SetProperty(aura::client::kZOrderingKey,
2145                        ui::ZOrderLevel::kFloatingWindow);
2146   window5->SetProperty(aura::client::kZOrderingKey,
2147                        ui::ZOrderLevel::kFloatingWindow);
2148 
2149   // Control z order and MRU order.
2150   wm::ActivateWindow(window8.get());
2151   wm::ActivateWindow(window7.get());  // Will be fullscreen.
2152   wm::ActivateWindow(window6.get());  // Will be maximized.
2153   wm::ActivateWindow(window5.get());  // AlwaysOnTop window.
2154   wm::ActivateWindow(window4.get());
2155   wm::ActivateWindow(window3.get());  // AlwaysOnTop window.
2156   wm::ActivateWindow(window2.get());  // Will be fullscreen.
2157   wm::ActivateWindow(window1.get());
2158 
2159   EXPECT_FALSE(WindowState::Get(window2.get())->IsFullscreen());
2160   EXPECT_FALSE(WindowState::Get(window6.get())->IsFullscreen());
2161   EXPECT_FALSE(WindowState::Get(window7.get())->IsMaximized());
2162 
2163   const WMEvent toggle_maximize_event(WM_EVENT_TOGGLE_MAXIMIZE);
2164   WindowState::Get(window6.get())->OnWMEvent(&toggle_maximize_event);
2165   const WMEvent toggle_fullscreen_event(WM_EVENT_TOGGLE_FULLSCREEN);
2166   WindowState::Get(window2.get())->OnWMEvent(&toggle_fullscreen_event);
2167   WindowState::Get(window7.get())->OnWMEvent(&toggle_fullscreen_event);
2168   EXPECT_TRUE(WindowState::Get(window2.get())->IsFullscreen());
2169   EXPECT_TRUE(WindowState::Get(window7.get())->IsFullscreen());
2170   EXPECT_TRUE(WindowState::Get(window6.get())->IsMaximized());
2171 
2172   // Case 1: Click on |window1| to activate it and exit overview.
2173   std::unique_ptr<ui::ScopedAnimationDurationScaleMode> test_duration_mode =
2174       std::make_unique<ui::ScopedAnimationDurationScaleMode>(
2175           ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2176   ToggleOverview();
2177   // For entering animation, only animate |window1|, |window2|, |window3| and
2178   // |window5| because |window3| and |window5| are AlwaysOnTop windows and
2179   // |window2| is fullscreen.
2180   EXPECT_TRUE(window1->layer()->GetAnimator()->is_animating());
2181   EXPECT_TRUE(window2->layer()->GetAnimator()->is_animating());
2182   EXPECT_TRUE(window3->layer()->GetAnimator()->is_animating());
2183   EXPECT_FALSE(window4->layer()->GetAnimator()->is_animating());
2184   EXPECT_TRUE(window5->layer()->GetAnimator()->is_animating());
2185   EXPECT_FALSE(window6->layer()->GetAnimator()->is_animating());
2186   EXPECT_FALSE(window7->layer()->GetAnimator()->is_animating());
2187   EXPECT_FALSE(window8->layer()->GetAnimator()->is_animating());
2188   base::RunLoop().RunUntilIdle();
2189 
2190   // Click on |window1| to activate it and exit overview.
2191   // Should animate |window1|, |window2|, |window3| and |window5| because
2192   // |window3| and |window5| are AlwaysOnTop windows and |window2| is
2193   // fullscreen.
2194   ClickWindow(window1.get());
2195   EXPECT_TRUE(window1->layer()->GetAnimator()->is_animating());
2196   EXPECT_TRUE(window2->layer()->GetAnimator()->is_animating());
2197   EXPECT_TRUE(window3->layer()->GetAnimator()->is_animating());
2198   EXPECT_FALSE(window4->layer()->GetAnimator()->is_animating());
2199   EXPECT_TRUE(window5->layer()->GetAnimator()->is_animating());
2200   EXPECT_FALSE(window6->layer()->GetAnimator()->is_animating());
2201   EXPECT_FALSE(window7->layer()->GetAnimator()->is_animating());
2202   EXPECT_FALSE(window8->layer()->GetAnimator()->is_animating());
2203   base::RunLoop().RunUntilIdle();
2204 
2205   // Case 2: Click on |window3| to activate it and exit overview.
2206   // Should animate |window1|, |window2|, |window3| and |window5|.
2207   // Reset window z-order. Need to toggle fullscreen first to workaround
2208   // https://crbug.com/816224.
2209   WindowState::Get(window2.get())->OnWMEvent(&toggle_fullscreen_event);
2210   WindowState::Get(window7.get())->OnWMEvent(&toggle_fullscreen_event);
2211   wm::ActivateWindow(window8.get());
2212   wm::ActivateWindow(window7.get());  // Will be fullscreen.
2213   wm::ActivateWindow(window6.get());  // Maximized.
2214   wm::ActivateWindow(window5.get());  // AlwaysOnTop window.
2215   wm::ActivateWindow(window4.get());
2216   wm::ActivateWindow(window3.get());  // AlwaysOnTop window.
2217   wm::ActivateWindow(window2.get());  // Will be fullscreen.
2218   wm::ActivateWindow(window1.get());
2219   WindowState::Get(window2.get())->OnWMEvent(&toggle_fullscreen_event);
2220   WindowState::Get(window7.get())->OnWMEvent(&toggle_fullscreen_event);
2221   // Enter overview.
2222   test_duration_mode = std::make_unique<ui::ScopedAnimationDurationScaleMode>(
2223       ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
2224   ToggleOverview();
2225   base::RunLoop().RunUntilIdle();
2226   test_duration_mode = std::make_unique<ui::ScopedAnimationDurationScaleMode>(
2227       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2228 
2229   ClickWindow(window3.get());
2230   EXPECT_TRUE(window1->layer()->GetAnimator()->is_animating());
2231   EXPECT_TRUE(window2->layer()->GetAnimator()->is_animating());
2232   EXPECT_TRUE(window3->layer()->GetAnimator()->is_animating());
2233   EXPECT_FALSE(window4->layer()->GetAnimator()->is_animating());
2234   EXPECT_TRUE(window5->layer()->GetAnimator()->is_animating());
2235   EXPECT_FALSE(window6->layer()->GetAnimator()->is_animating());
2236   EXPECT_FALSE(window7->layer()->GetAnimator()->is_animating());
2237   EXPECT_FALSE(window8->layer()->GetAnimator()->is_animating());
2238   base::RunLoop().RunUntilIdle();
2239 
2240   // Case 3: Click on maximized |window6| to activate it and exit overview.
2241   // Should animate |window6|, |window3| and |window5| because |window3| and
2242   // |window5| are AlwaysOnTop windows. |window6| is maximized.
2243   // Reset window z-order. Need to toggle fullscreen first to workaround
2244   // https://crbug.com/816224.
2245   WindowState::Get(window2.get())->OnWMEvent(&toggle_fullscreen_event);
2246   WindowState::Get(window7.get())->OnWMEvent(&toggle_fullscreen_event);
2247   wm::ActivateWindow(window8.get());
2248   wm::ActivateWindow(window7.get());  // Will be fullscreen.
2249   wm::ActivateWindow(window6.get());  // Maximized.
2250   wm::ActivateWindow(window5.get());  // AlwaysOnTop window.
2251   wm::ActivateWindow(window4.get());
2252   wm::ActivateWindow(window3.get());  // AlwaysOnTop window.
2253   wm::ActivateWindow(window2.get());  // Will be fullscreen.
2254   wm::ActivateWindow(window1.get());
2255   WindowState::Get(window2.get())->OnWMEvent(&toggle_fullscreen_event);
2256   WindowState::Get(window7.get())->OnWMEvent(&toggle_fullscreen_event);
2257   // Enter overview.
2258   test_duration_mode = std::make_unique<ui::ScopedAnimationDurationScaleMode>(
2259       ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
2260   ToggleOverview();
2261   base::RunLoop().RunUntilIdle();
2262   test_duration_mode = std::make_unique<ui::ScopedAnimationDurationScaleMode>(
2263       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2264 
2265   ClickWindow(window6.get());
2266   EXPECT_FALSE(window1->layer()->GetAnimator()->is_animating());
2267   EXPECT_FALSE(window2->layer()->GetAnimator()->is_animating());
2268   EXPECT_TRUE(window3->layer()->GetAnimator()->is_animating());
2269   EXPECT_FALSE(window4->layer()->GetAnimator()->is_animating());
2270   EXPECT_TRUE(window5->layer()->GetAnimator()->is_animating());
2271   EXPECT_TRUE(window6->layer()->GetAnimator()->is_animating());
2272   EXPECT_FALSE(window7->layer()->GetAnimator()->is_animating());
2273   EXPECT_FALSE(window8->layer()->GetAnimator()->is_animating());
2274   base::RunLoop().RunUntilIdle();
2275 
2276   // Case 4: Click on |window8| to activate it and exit overview.
2277   // Should animate |window8|, |window1|, |window2|, |window3| and |window5|
2278   // because |window3| and |window5| are AlwaysOnTop windows and |window2| is
2279   // fullscreen.
2280   // Reset window z-order. Need to toggle fullscreen first to workaround
2281   // https://crbug.com/816224.
2282   WindowState::Get(window2.get())->OnWMEvent(&toggle_fullscreen_event);
2283   WindowState::Get(window7.get())->OnWMEvent(&toggle_fullscreen_event);
2284   wm::ActivateWindow(window8.get());
2285   wm::ActivateWindow(window7.get());  // Will be fullscreen.
2286   wm::ActivateWindow(window6.get());  // Maximized.
2287   wm::ActivateWindow(window5.get());  // AlwaysOnTop window.
2288   wm::ActivateWindow(window4.get());
2289   wm::ActivateWindow(window3.get());  // AlwaysOnTop window.
2290   wm::ActivateWindow(window2.get());  // Will be fullscreen.
2291   wm::ActivateWindow(window1.get());
2292   WindowState::Get(window2.get())->OnWMEvent(&toggle_fullscreen_event);
2293   WindowState::Get(window7.get())->OnWMEvent(&toggle_fullscreen_event);
2294   // Enter overview.
2295   test_duration_mode = std::make_unique<ui::ScopedAnimationDurationScaleMode>(
2296       ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
2297   ToggleOverview();
2298   base::RunLoop().RunUntilIdle();
2299   test_duration_mode = std::make_unique<ui::ScopedAnimationDurationScaleMode>(
2300       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2301 
2302   ClickWindow(window8.get());
2303   EXPECT_TRUE(window1->layer()->GetAnimator()->is_animating());
2304   EXPECT_TRUE(window2->layer()->GetAnimator()->is_animating());
2305   EXPECT_TRUE(window3->layer()->GetAnimator()->is_animating());
2306   EXPECT_FALSE(window4->layer()->GetAnimator()->is_animating());
2307   EXPECT_TRUE(window5->layer()->GetAnimator()->is_animating());
2308   EXPECT_FALSE(window6->layer()->GetAnimator()->is_animating());
2309   EXPECT_FALSE(window7->layer()->GetAnimator()->is_animating());
2310   EXPECT_TRUE(window8->layer()->GetAnimator()->is_animating());
2311   base::RunLoop().RunUntilIdle();
2312 }
2313 
2314 // Verify that the selector item can animate after the item is dragged and
2315 // released.
TEST_P(OverviewSessionTest,WindowItemCanAnimateOnDragRelease)2316 TEST_P(OverviewSessionTest, WindowItemCanAnimateOnDragRelease) {
2317   base::HistogramTester histogram_tester;
2318   UpdateDisplay("400x400");
2319   std::unique_ptr<aura::Window> window1(CreateTestWindow());
2320   std::unique_ptr<aura::Window> window2(CreateTestWindow());
2321   wm::ActivateWindow(window2.get());
2322   wm::ActivateWindow(window1.get());
2323 
2324   EnterTabletMode();
2325   ToggleOverview();
2326   OverviewItem* item2 = GetOverviewItemForWindow(window2.get());
2327   // Drag |item2| in a way so that |window2| does not get activated.
2328   ui::test::EventGenerator* generator = GetEventGenerator();
2329   generator->MoveMouseTo(
2330       gfx::ToRoundedPoint(item2->target_bounds().CenterPoint()));
2331   generator->PressLeftButton();
2332   base::RunLoop().RunUntilIdle();
2333 
2334   generator->MoveMouseTo(gfx::Point(200, 200));
2335   histogram_tester.ExpectTotalCount(
2336       "Ash.Overview.WindowDrag.PresentationTime.TabletMode", 1);
2337   histogram_tester.ExpectTotalCount(
2338       "Ash.Overview.WindowDrag.PresentationTime.MaxLatency.TabletMode", 0);
2339 
2340   ui::ScopedAnimationDurationScaleMode test_duration_mode(
2341       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2342   generator->ReleaseLeftButton();
2343   EXPECT_TRUE(window2->layer()->GetAnimator()->IsAnimatingProperty(
2344       ui::LayerAnimationElement::AnimatableProperty::TRANSFORM));
2345   base::RunLoop().RunUntilIdle();
2346   histogram_tester.ExpectTotalCount(
2347       "Ash.Overview.WindowDrag.PresentationTime.TabletMode", 1);
2348   histogram_tester.ExpectTotalCount(
2349       "Ash.Overview.WindowDrag.PresentationTime.MaxLatency.TabletMode", 1);
2350 }
2351 
2352 // Verify that the overview items titlebar and close button change visibility
2353 // when a item is being dragged.
TEST_P(OverviewSessionTest,OverviewItemTitleCloseVisibilityOnDrag)2354 TEST_P(OverviewSessionTest, OverviewItemTitleCloseVisibilityOnDrag) {
2355   base::HistogramTester histogram_tester;
2356   UpdateDisplay("400x400");
2357   std::unique_ptr<aura::Window> window1(CreateTestWindow());
2358   std::unique_ptr<aura::Window> window2(CreateTestWindow());
2359 
2360   EnterTabletMode();
2361   ToggleOverview();
2362   OverviewItem* item1 = GetOverviewItemForWindow(window1.get());
2363   OverviewItem* item2 = GetOverviewItemForWindow(window2.get());
2364   // Start the drag on |item1|. Verify the dragged item, |item1| has both the
2365   // close button and titlebar hidden. The close button opacity however is
2366   // opaque as its a child of the header which handles fading away the whole
2367   // header. All other items, |item2| should only have the close button hidden.
2368   ui::test::EventGenerator* generator = GetEventGenerator();
2369   generator->MoveMouseTo(
2370       gfx::ToRoundedPoint(item1->target_bounds().CenterPoint()));
2371   generator->PressLeftButton();
2372   base::RunLoop().RunUntilIdle();
2373   EXPECT_EQ(0.f, GetTitlebarOpacity(item1));
2374   EXPECT_EQ(1.f, GetCloseButtonOpacity(item1));
2375   EXPECT_EQ(1.f, GetTitlebarOpacity(item2));
2376   EXPECT_EQ(0.f, GetCloseButtonOpacity(item2));
2377 
2378   // Drag |item1| in a way so that |window1| does not get activated (drags
2379   // within a certain threshold count as clicks). Verify the close button and
2380   // titlebar is visible for all items.
2381   generator->MoveMouseTo(gfx::Point(200, 200));
2382   histogram_tester.ExpectTotalCount(
2383       "Ash.Overview.WindowDrag.PresentationTime.TabletMode", 1);
2384   histogram_tester.ExpectTotalCount(
2385       "Ash.Overview.WindowDrag.PresentationTime.MaxLatency.TabletMode", 0);
2386 
2387   generator->ReleaseLeftButton();
2388   base::RunLoop().RunUntilIdle();
2389   EXPECT_EQ(1.f, GetTitlebarOpacity(item1));
2390   EXPECT_EQ(1.f, GetCloseButtonOpacity(item1));
2391   EXPECT_EQ(1.f, GetTitlebarOpacity(item2));
2392   EXPECT_EQ(1.f, GetCloseButtonOpacity(item2));
2393   histogram_tester.ExpectTotalCount(
2394       "Ash.Overview.WindowDrag.PresentationTime.TabletMode", 1);
2395   histogram_tester.ExpectTotalCount(
2396       "Ash.Overview.WindowDrag.PresentationTime.MaxLatency.TabletMode", 1);
2397 }
2398 
2399 // Tests that overview widgets are stacked in the correct order.
TEST_P(OverviewSessionTest,OverviewWidgetStackingOrder)2400 TEST_P(OverviewSessionTest, OverviewWidgetStackingOrder) {
2401   base::HistogramTester histogram_tester;
2402   // Create three windows, including one minimized.
2403   std::unique_ptr<aura::Window> minimized(CreateTestWindow());
2404   WindowState::Get(minimized.get())->Minimize();
2405   std::unique_ptr<aura::Window> window(CreateTestWindow());
2406   std::unique_ptr<aura::Window> window3(CreateTestWindow());
2407 
2408   aura::Window* parent = window->parent();
2409   EXPECT_EQ(parent, minimized->parent());
2410 
2411   EnterTabletMode();
2412   ToggleOverview();
2413   OverviewItem* item1 = GetOverviewItemForWindow(minimized.get());
2414   OverviewItem* item2 = GetOverviewItemForWindow(window.get());
2415   OverviewItem* item3 = GetOverviewItemForWindow(window3.get());
2416 
2417   views::Widget* widget1 = item1->item_widget();
2418   views::Widget* widget2 = item2->item_widget();
2419   views::Widget* widget3 = item3->item_widget();
2420 
2421   // The original order of stacking is determined by the order the associated
2422   // window was activated.
2423   EXPECT_GT(IndexOf(widget3->GetNativeWindow(), parent),
2424             IndexOf(widget2->GetNativeWindow(), parent));
2425   EXPECT_GT(IndexOf(widget2->GetNativeWindow(), parent),
2426             IndexOf(widget1->GetNativeWindow(), parent));
2427 
2428   // Verify that the item widget is stacked below the window.
2429   EXPECT_LT(IndexOf(widget1->GetNativeWindow(), parent),
2430             IndexOf(minimized.get(), parent));
2431   EXPECT_LT(IndexOf(widget2->GetNativeWindow(), parent),
2432             IndexOf(window.get(), parent));
2433   EXPECT_LT(IndexOf(widget3->GetNativeWindow(), parent),
2434             IndexOf(window3.get(), parent));
2435 
2436   // Drag the first window. Verify that it's item widget is not stacked above
2437   // the other two.
2438   const gfx::Point start_drag =
2439       gfx::ToRoundedPoint(item1->target_bounds().CenterPoint());
2440   ui::test::EventGenerator* generator = GetEventGenerator();
2441   generator->MoveMouseTo(start_drag);
2442   generator->PressLeftButton();
2443   EXPECT_GT(IndexOf(widget1->GetNativeWindow(), parent),
2444             IndexOf(widget2->GetNativeWindow(), parent));
2445   EXPECT_GT(IndexOf(widget1->GetNativeWindow(), parent),
2446             IndexOf(widget3->GetNativeWindow(), parent));
2447   histogram_tester.ExpectTotalCount(
2448       "Ash.Overview.WindowDrag.PresentationTime.TabletMode", 0);
2449 
2450   // Drag to origin and then back to the start to avoid activating the window or
2451   // entering splitview.
2452   generator->MoveMouseTo(gfx::Point());
2453   histogram_tester.ExpectTotalCount(
2454       "Ash.Overview.WindowDrag.PresentationTime.TabletMode", 1);
2455 
2456   generator->MoveMouseTo(start_drag);
2457   histogram_tester.ExpectTotalCount(
2458       "Ash.Overview.WindowDrag.PresentationTime.TabletMode", 2);
2459   histogram_tester.ExpectTotalCount(
2460       "Ash.Overview.WindowDrag.PresentationTime.MaxLatency.TabletMode", 0);
2461 
2462   generator->ReleaseLeftButton();
2463 
2464   // Verify the stacking order is same as before dragging started.
2465   EXPECT_GT(IndexOf(widget3->GetNativeWindow(), parent),
2466             IndexOf(widget2->GetNativeWindow(), parent));
2467   EXPECT_GT(IndexOf(widget2->GetNativeWindow(), parent),
2468             IndexOf(widget1->GetNativeWindow(), parent));
2469 
2470   histogram_tester.ExpectTotalCount(
2471       "Ash.Overview.WindowDrag.PresentationTime.TabletMode", 2);
2472   histogram_tester.ExpectTotalCount(
2473       "Ash.Overview.WindowDrag.PresentationTime.MaxLatency.TabletMode", 1);
2474 }
2475 
2476 // Test that dragging a window from the top creates a drop target stacked at the
2477 // bottom. Test that dropping into overview removes the drop target.
TEST_P(OverviewSessionTest,DropTargetStackedAtBottomForWindowDraggedFromTop)2478 TEST_P(OverviewSessionTest, DropTargetStackedAtBottomForWindowDraggedFromTop) {
2479   UpdateDisplay("800x600");
2480   EnterTabletMode();
2481   std::unique_ptr<aura::Window> window1(CreateTestWindow());
2482   window1->SetProperty(aura::client::kAppType,
2483                        static_cast<int>(AppType::BROWSER));
2484   std::unique_ptr<aura::Window> window2(CreateTestWindow());
2485   aura::Window* parent = window1->parent();
2486   ASSERT_EQ(parent, window2->parent());
2487   wm::ActivateWindow(window2.get());
2488   wm::ActivateWindow(window1.get());
2489   std::unique_ptr<WindowResizer> resizer =
2490       CreateWindowResizer(window1.get(), gfx::PointF(400, 0), HTCAPTION,
2491                           ::wm::WINDOW_MOVE_SOURCE_TOUCH);
2492   ASSERT_TRUE(GetDropTarget(0));
2493   EXPECT_LT(IndexOf(GetDropTarget(0)->GetWindow(), parent),
2494             IndexOf(window2.get(), parent));
2495   resizer->Drag(gfx::PointF(400, 500), ui::EF_NONE);
2496   resizer->CompleteDrag();
2497   EXPECT_FALSE(GetDropTarget(0));
2498 }
2499 
2500 // Test that dragging an overview item to snap creates a drop target stacked at
2501 // the bottom. Test that ending the drag removes the drop target.
TEST_P(OverviewSessionTest,DropTargetStackedAtBottomForOverviewItem)2502 TEST_P(OverviewSessionTest, DropTargetStackedAtBottomForOverviewItem) {
2503   EnterTabletMode();
2504   std::unique_ptr<aura::Window> window1(CreateTestWindow());
2505   std::unique_ptr<aura::Window> window2(CreateTestWindow());
2506   aura::Window* parent = window1->parent();
2507   ASSERT_EQ(parent, window2->parent());
2508   wm::ActivateWindow(window2.get());
2509   wm::ActivateWindow(window1.get());
2510   ToggleOverview();
2511   ui::test::EventGenerator* generator = GetEventGenerator();
2512   generator->MoveMouseTo(gfx::ToRoundedPoint(
2513       GetOverviewItemForWindow(window1.get())->target_bounds().CenterPoint()));
2514   generator->PressLeftButton();
2515   generator->MoveMouseBy(5, 0);
2516   ASSERT_TRUE(GetDropTarget(0));
2517   EXPECT_LT(IndexOf(GetDropTarget(0)->GetWindow(), parent),
2518             IndexOf(window2.get(), parent));
2519   generator->ReleaseLeftButton();
2520   EXPECT_FALSE(GetDropTarget(0));
2521 }
2522 
2523 // Verify that a windows which enter overview mode have a visible backdrop, if
2524 // the window is to be letter or pillar fitted.
TEST_P(OverviewSessionTest,Backdrop)2525 TEST_P(OverviewSessionTest, Backdrop) {
2526   // Add three windows which in overview mode will be considered wide, tall and
2527   // normal. Window |wide|, with size (400, 160) will be resized to (300, 160)
2528   // when the 400x300 is rotated to 300x400, and should be considered a normal
2529   // overview window after display change.
2530   UpdateDisplay("400x300");
2531   std::unique_ptr<aura::Window> wide(CreateTestWindow(gfx::Rect(400, 160)));
2532   std::unique_ptr<aura::Window> tall(CreateTestWindow(gfx::Rect(100, 300)));
2533   std::unique_ptr<aura::Window> normal(CreateTestWindow(gfx::Rect(300, 300)));
2534 
2535   ToggleOverview();
2536   base::RunLoop().RunUntilIdle();
2537   OverviewItem* wide_item = GetOverviewItemForWindow(wide.get());
2538   OverviewItem* tall_item = GetOverviewItemForWindow(tall.get());
2539   OverviewItem* normal_item = GetOverviewItemForWindow(normal.get());
2540 
2541   // Only very tall and very wide windows will have a backdrop. The backdrop
2542   // only gets created if we need it once during the overview session.
2543   ASSERT_TRUE(GetBackdropView(wide_item));
2544   EXPECT_TRUE(GetBackdropView(wide_item)->GetVisible());
2545   EXPECT_TRUE(GetBackdropView(tall_item));
2546   ASSERT_TRUE(GetBackdropView(tall_item)->GetVisible());
2547   EXPECT_FALSE(GetBackdropView(normal_item));
2548 
2549   display::Screen* screen = display::Screen::GetScreen();
2550   const display::Display& display = screen->GetPrimaryDisplay();
2551   display_manager()->SetDisplayRotation(
2552       display.id(), display::Display::ROTATE_90,
2553       display::Display::RotationSource::ACTIVE);
2554 
2555   // After rotation the former wide window will be a normal window and its
2556   // backdrop will still be there but invisible.
2557   ASSERT_TRUE(GetBackdropView(wide_item));
2558   EXPECT_FALSE(GetBackdropView(wide_item)->GetVisible());
2559   EXPECT_TRUE(GetBackdropView(tall_item));
2560   ASSERT_TRUE(GetBackdropView(tall_item)->GetVisible());
2561   EXPECT_FALSE(GetBackdropView(normal_item));
2562 
2563   // Test that leaving overview mode cleans up properly.
2564   ToggleOverview();
2565 }
2566 
2567 // Test that the rounded corners are removed during animations.
TEST_P(OverviewSessionTest,RoundedCornersVisibility)2568 TEST_P(OverviewSessionTest, RoundedCornersVisibility) {
2569   std::unique_ptr<aura::Window> window1(CreateTestWindow());
2570   std::unique_ptr<aura::Window> window2(CreateTestWindow());
2571 
2572   wm::ActivateWindow(window2.get());
2573   wm::ActivateWindow(window1.get());
2574 
2575   ui::ScopedAnimationDurationScaleMode test_duration_mode(
2576       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2577 
2578   // Test that entering overview mode normally will disable all the rounded
2579   // corners until the animation is complete.
2580   EnterTabletMode();
2581   ToggleOverview();
2582   OverviewItem* item1 = GetOverviewItemForWindow(window1.get());
2583   OverviewItem* item2 = GetOverviewItemForWindow(window2.get());
2584   EXPECT_FALSE(HasRoundedCorner(item1));
2585   EXPECT_FALSE(HasRoundedCorner(item2));
2586   ShellTestApi().WaitForOverviewAnimationState(
2587       OverviewAnimationState::kEnterAnimationComplete);
2588   EXPECT_TRUE(HasRoundedCorner(item1));
2589   EXPECT_TRUE(HasRoundedCorner(item2));
2590 
2591   // Tests that entering overview mode with all windows minimized (launcher
2592   // button pressed) will still disable all the rounded corners until the
2593   // animation is complete.
2594   ToggleOverview();
2595   ShellTestApi().WaitForOverviewAnimationState(
2596       OverviewAnimationState::kExitAnimationComplete);
2597   WindowState::Get(window1.get())->Minimize();
2598   WindowState::Get(window2.get())->Minimize();
2599 
2600   ToggleOverview();
2601   item1 = GetOverviewItemForWindow(window1.get());
2602   item2 = GetOverviewItemForWindow(window2.get());
2603   EXPECT_FALSE(HasRoundedCorner(item1));
2604   EXPECT_FALSE(HasRoundedCorner(item2));
2605   ShellTestApi().WaitForOverviewAnimationState(
2606       OverviewAnimationState::kEnterAnimationComplete);
2607   EXPECT_TRUE(HasRoundedCorner(item1));
2608   EXPECT_TRUE(HasRoundedCorner(item2));
2609 
2610   // Test that leaving overview mode cleans up properly.
2611   ToggleOverview();
2612   ShellTestApi().WaitForOverviewAnimationState(
2613       OverviewAnimationState::kExitAnimationComplete);
2614 }
2615 
2616 // Test that the shadow disappears while dragging an overview item.
TEST_P(OverviewSessionTest,ShadowVisibilityDragging)2617 TEST_P(OverviewSessionTest, ShadowVisibilityDragging) {
2618   std::unique_ptr<aura::Window> window1(CreateTestWindow());
2619   std::unique_ptr<aura::Window> window2(CreateTestWindow());
2620 
2621   wm::ActivateWindow(window2.get());
2622   wm::ActivateWindow(window1.get());
2623 
2624   EnterTabletMode();
2625   ToggleOverview();
2626   OverviewItem* item1 = GetOverviewItemForWindow(window1.get());
2627   OverviewItem* item2 = GetOverviewItemForWindow(window2.get());
2628   ui::ScopedAnimationDurationScaleMode test_duration_mode(
2629       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2630 
2631   // Drag the first window. Verify that the shadow was removed for the first
2632   // window but still exists for the second window as we do not make shadow
2633   // for a dragged window.
2634   const gfx::Point start_drag =
2635       gfx::ToRoundedPoint(item1->target_bounds().CenterPoint());
2636   ui::test::EventGenerator* generator = GetEventGenerator();
2637   generator->MoveMouseTo(start_drag);
2638   generator->PressLeftButton();
2639   EXPECT_FALSE(window1->layer()->GetAnimator()->is_animating());
2640   EXPECT_FALSE(window2->layer()->GetAnimator()->is_animating());
2641 
2642   EXPECT_TRUE(item1->GetShadowBoundsForTesting().IsEmpty());
2643   EXPECT_FALSE(item2->GetShadowBoundsForTesting().IsEmpty());
2644 
2645   // Drag to horizontally and then back to the start to avoid activating the
2646   // window, drag to close or entering splitview. Verify that the shadow is
2647   // invisible on both items during animation.
2648   generator->MoveMouseTo(gfx::Point(0, start_drag.y()));
2649 
2650   // The drop target window should be created with no shadow.
2651   OverviewItem* drop_target_item = GetDropTarget(0);
2652   ASSERT_TRUE(drop_target_item);
2653   EXPECT_TRUE(drop_target_item->GetShadowBoundsForTesting().IsEmpty());
2654 
2655   generator->MoveMouseTo(start_drag);
2656   generator->ReleaseLeftButton();
2657   EXPECT_TRUE(window1->layer()->GetAnimator()->is_animating());
2658   EXPECT_TRUE(window2->layer()->GetAnimator()->is_animating());
2659   EXPECT_TRUE(item1->GetShadowBoundsForTesting().IsEmpty());
2660   EXPECT_TRUE(item2->GetShadowBoundsForTesting().IsEmpty());
2661 
2662   // Verify that the shadow is visble again after animation is finished.
2663   window1->layer()->GetAnimator()->StopAnimating();
2664   window2->layer()->GetAnimator()->StopAnimating();
2665   EXPECT_FALSE(item1->GetShadowBoundsForTesting().IsEmpty());
2666   EXPECT_FALSE(item2->GetShadowBoundsForTesting().IsEmpty());
2667 }
2668 
2669 // Tests that the shadows in overview mode are placed correctly.
TEST_P(OverviewSessionTest,ShadowBounds)2670 TEST_P(OverviewSessionTest, ShadowBounds) {
2671   // Helper function to check if the bounds of a shadow owned by |shadow_parent|
2672   // is contained within the bounds of |widget|.
2673   auto contains = [](views::Widget* widget, OverviewItem* shadow_parent) {
2674     return gfx::Rect(widget->GetNativeWindow()->bounds().size())
2675         .Contains(shadow_parent->GetShadowBoundsForTesting());
2676   };
2677 
2678   // Helper function which returns the ratio of the shadow owned by
2679   // |shadow_parent| width and height.
2680   auto shadow_ratio = [](OverviewItem* shadow_parent) {
2681     gfx::RectF boundsf = gfx::RectF(shadow_parent->GetShadowBoundsForTesting());
2682     return boundsf.width() / boundsf.height();
2683   };
2684 
2685   // Add three windows which in overview mode will be considered wide, tall and
2686   // normal. Set top view insets to 0 so it is easy to check the ratios of the
2687   // shadows match the ratios of the untransformed windows.
2688   UpdateDisplay("800x800");
2689   std::unique_ptr<aura::Window> wide(
2690       CreateTestWindowInShellWithDelegate(nullptr, -1, gfx::Rect(400, 100)));
2691   std::unique_ptr<aura::Window> tall(
2692       CreateTestWindowInShellWithDelegate(nullptr, -1, gfx::Rect(100, 400)));
2693   std::unique_ptr<aura::Window> normal(
2694       CreateTestWindowInShellWithDelegate(nullptr, -1, gfx::Rect(200, 200)));
2695   wide->SetProperty(aura::client::kTopViewInset, 0);
2696   tall->SetProperty(aura::client::kTopViewInset, 0);
2697   normal->SetProperty(aura::client::kTopViewInset, 0);
2698 
2699   ToggleOverview();
2700   base::RunLoop().RunUntilIdle();
2701   OverviewItem* wide_item = GetOverviewItemForWindow(wide.get());
2702   OverviewItem* tall_item = GetOverviewItemForWindow(tall.get());
2703   OverviewItem* normal_item = GetOverviewItemForWindow(normal.get());
2704 
2705   views::Widget* wide_widget = wide_item->item_widget();
2706   views::Widget* tall_widget = tall_item->item_widget();
2707   views::Widget* normal_widget = normal_item->item_widget();
2708 
2709   OverviewGrid* grid = overview_session()->grid_list()[0].get();
2710 
2711   // Verify all the shadows are within the bounds of their respective item
2712   // widgets when the overview windows are positioned without animations.
2713   SetGridBounds(grid, gfx::Rect(400, 800));
2714   grid->PositionWindows(false);
2715   EXPECT_TRUE(contains(wide_widget, wide_item));
2716   EXPECT_TRUE(contains(tall_widget, tall_item));
2717   EXPECT_TRUE(contains(normal_widget, normal_item));
2718 
2719   // Verify the shadows preserve the ratios of the original windows.
2720   EXPECT_NEAR(shadow_ratio(wide_item), 4.f, 0.01f);
2721   EXPECT_NEAR(shadow_ratio(tall_item), 0.25f, 0.01f);
2722   EXPECT_NEAR(shadow_ratio(normal_item), 1.f, 0.01f);
2723 
2724   // Verify all the shadows are within the bounds of their respective item
2725   // widgets when the overview windows are positioned with animations.
2726   SetGridBounds(grid, gfx::Rect(400, 800));
2727   grid->PositionWindows(true);
2728   base::RunLoop().RunUntilIdle();
2729   EXPECT_TRUE(contains(wide_widget, wide_item));
2730   EXPECT_TRUE(contains(tall_widget, tall_item));
2731   EXPECT_TRUE(contains(normal_widget, normal_item));
2732 
2733   EXPECT_NEAR(shadow_ratio(wide_item), 4.f, 0.01f);
2734   EXPECT_NEAR(shadow_ratio(tall_item), 0.25f, 0.01f);
2735   EXPECT_NEAR(shadow_ratio(normal_item), 1.f, 0.01f);
2736 
2737   // Test that leaving overview mode cleans up properly.
2738   ToggleOverview();
2739 }
2740 
2741 // Verify that attempting to drag with a secondary finger works as expected.
TEST_P(OverviewSessionTest,DraggingWithTwoFingers)2742 TEST_P(OverviewSessionTest, DraggingWithTwoFingers) {
2743   std::unique_ptr<aura::Window> window1(CreateTestWindow());
2744   std::unique_ptr<aura::Window> window2(CreateTestWindow());
2745 
2746   EnterTabletMode();
2747   ToggleOverview();
2748   OverviewItem* item1 = GetOverviewItemForWindow(window1.get());
2749   OverviewItem* item2 = GetOverviewItemForWindow(window2.get());
2750 
2751   const gfx::RectF original_bounds1 = item1->target_bounds();
2752   const gfx::RectF original_bounds2 = item2->target_bounds();
2753 
2754   constexpr int kTouchId1 = 1;
2755   constexpr int kTouchId2 = 2;
2756 
2757   // Dispatches a long press event at the event generators current location.
2758   // Long press is one way to start dragging in splitview.
2759   auto dispatch_long_press = [this]() {
2760     ui::GestureEventDetails event_details(ui::ET_GESTURE_LONG_PRESS);
2761     const gfx::Point location = GetEventGenerator()->current_screen_location();
2762     ui::GestureEvent long_press(location.x(), location.y(), 0,
2763                                 ui::EventTimeForNow(), event_details);
2764     GetEventGenerator()->Dispatch(&long_press);
2765   };
2766 
2767   // Verify that the bounds of the tapped window expand when touched.
2768   ui::test::EventGenerator* generator = GetEventGenerator();
2769   generator->set_current_screen_location(
2770       gfx::ToRoundedPoint(original_bounds1.CenterPoint()));
2771   generator->PressTouchId(kTouchId1);
2772   dispatch_long_press();
2773   EXPECT_GT(item1->target_bounds().width(), original_bounds1.width());
2774   EXPECT_GT(item1->target_bounds().height(), original_bounds1.height());
2775 
2776   // Verify that attempting to touch the second window with a second finger does
2777   // nothing to the second window. The first window remains the window to be
2778   // dragged.
2779   generator->set_current_screen_location(
2780       gfx::ToRoundedPoint(original_bounds2.CenterPoint()));
2781   generator->PressTouchId(kTouchId2);
2782   dispatch_long_press();
2783   EXPECT_GT(item1->target_bounds().width(), original_bounds1.width());
2784   EXPECT_GT(item1->target_bounds().height(), original_bounds1.height());
2785   EXPECT_EQ(item2->target_bounds(), original_bounds2);
2786 
2787   // Verify the first window moves on drag.
2788   gfx::PointF last_center_point = item1->target_bounds().CenterPoint();
2789   generator->MoveTouchIdBy(kTouchId1, 40, 40);
2790   EXPECT_NE(last_center_point, item1->target_bounds().CenterPoint());
2791   EXPECT_EQ(original_bounds2.CenterPoint(),
2792             item2->target_bounds().CenterPoint());
2793 
2794   // Verify the first window moves on drag, even if we switch to a second
2795   // finger.
2796   last_center_point = item1->target_bounds().CenterPoint();
2797   generator->ReleaseTouchId(kTouchId2);
2798   generator->PressTouchId(kTouchId2);
2799   generator->MoveTouchIdBy(kTouchId2, 40, 40);
2800   EXPECT_NE(last_center_point, item1->target_bounds().CenterPoint());
2801   EXPECT_EQ(original_bounds2.CenterPoint(),
2802             item2->target_bounds().CenterPoint());
2803 }
2804 
2805 // Verify that shadows on windows disappear for the duration of overview mode.
TEST_P(OverviewSessionTest,ShadowDisappearsInOverview)2806 TEST_P(OverviewSessionTest, ShadowDisappearsInOverview) {
2807   std::unique_ptr<aura::Window> window(CreateTestWindow());
2808 
2809   // Verify that the shadow is initially visible.
2810   ::wm::ShadowController* shadow_controller = Shell::Get()->shadow_controller();
2811   EXPECT_TRUE(shadow_controller->IsShadowVisibleForWindow(window.get()));
2812 
2813   // Verify that the shadow is invisible after entering overview mode.
2814   ToggleOverview();
2815   EXPECT_FALSE(shadow_controller->IsShadowVisibleForWindow(window.get()));
2816 
2817   // Verify that the shadow is visible again after exiting overview mode.
2818   ToggleOverview();
2819   EXPECT_TRUE(shadow_controller->IsShadowVisibleForWindow(window.get()));
2820 }
2821 
2822 // Verify that PIP windows will be excluded from the overview, but not hidden.
TEST_P(OverviewSessionTest,PipWindowShownButExcludedFromOverview)2823 TEST_P(OverviewSessionTest, PipWindowShownButExcludedFromOverview) {
2824   std::unique_ptr<aura::Window> pip_window(
2825       CreateTestWindow(gfx::Rect(200, 200)));
2826   WindowState* window_state = WindowState::Get(pip_window.get());
2827   const WMEvent enter_pip(WM_EVENT_PIP);
2828   window_state->OnWMEvent(&enter_pip);
2829 
2830   // Enter overview.
2831   ToggleOverview();
2832 
2833   // PIP window should be visible but not in the overview.
2834   EXPECT_TRUE(pip_window->IsVisible());
2835   EXPECT_FALSE(HighlightOverviewWindow(pip_window.get()));
2836 }
2837 
2838 // Tests the PositionWindows function works as expected.
TEST_P(OverviewSessionTest,PositionWindows)2839 TEST_P(OverviewSessionTest, PositionWindows) {
2840   std::unique_ptr<aura::Window> window1(CreateTestWindow());
2841   std::unique_ptr<aura::Window> window2(CreateTestWindow());
2842   std::unique_ptr<aura::Window> window3(CreateTestWindow());
2843 
2844   ToggleOverview();
2845   OverviewItem* item1 = GetOverviewItemForWindow(window1.get());
2846   OverviewItem* item2 = GetOverviewItemForWindow(window2.get());
2847   OverviewItem* item3 = GetOverviewItemForWindow(window3.get());
2848   const gfx::RectF bounds1 = item1->target_bounds();
2849   const gfx::RectF bounds2 = item2->target_bounds();
2850   const gfx::RectF bounds3 = item3->target_bounds();
2851 
2852   // Verify that the bounds remain the same when calling PositionWindows again.
2853   overview_session()->PositionWindows(/*animate=*/false);
2854   EXPECT_EQ(bounds1, item1->target_bounds());
2855   EXPECT_EQ(bounds2, item2->target_bounds());
2856   EXPECT_EQ(bounds3, item3->target_bounds());
2857 
2858   // Verify that |item2| and |item3| change bounds when calling PositionWindows
2859   // while ignoring |item1|.
2860   overview_session()->PositionWindows(/*animate=*/false, {item1});
2861   EXPECT_EQ(bounds1, item1->target_bounds());
2862   EXPECT_NE(bounds2, item2->target_bounds());
2863   EXPECT_NE(bounds3, item3->target_bounds());
2864 
2865   // Return the windows to their original bounds.
2866   overview_session()->PositionWindows(/*animate=*/false);
2867 
2868   // Verify that items that are animating before closing are ignored by
2869   // PositionWindows.
2870   item1->set_animating_to_close(true);
2871   item2->set_animating_to_close(true);
2872   overview_session()->PositionWindows(/*animate=*/false);
2873   EXPECT_EQ(bounds1, item1->target_bounds());
2874   EXPECT_EQ(bounds2, item2->target_bounds());
2875   EXPECT_NE(bounds3, item3->target_bounds());
2876 }
2877 
2878 // Tests that overview mode is entered with kWindowDragged mode when a window is
2879 // dragged from the top of the screen. For the purposes of this test, we use a
2880 // browser window.
TEST_P(OverviewSessionTest,DraggingFromTopAnimation)2881 TEST_P(OverviewSessionTest, DraggingFromTopAnimation) {
2882   EnterTabletMode();
2883   std::unique_ptr<views::Widget> widget(CreateTestWidget(
2884       nullptr, desks_util::GetActiveDeskContainerId(), gfx::Rect(200, 200)));
2885   widget->GetNativeWindow()->SetProperty(aura::client::kTopViewInset, 20);
2886 
2887   // Drag from the the top of the app to enter overview.
2888   ui::GestureEvent event(0, 0, 0, base::TimeTicks(),
2889                          ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN));
2890   WindowState* window_state = WindowState::Get(widget->GetNativeWindow());
2891   window_state->CreateDragDetails(event.location_f(), HTCAPTION,
2892                                   ::wm::WINDOW_MOVE_SOURCE_TOUCH);
2893   auto drag_controller = std::make_unique<TabletModeWindowResizer>(
2894       window_state, std::make_unique<TabletModeBrowserWindowDragDelegate>());
2895   ui::Event::DispatcherApi dispatch_helper(&event);
2896   dispatch_helper.set_target(widget->GetNativeWindow());
2897   drag_controller->Drag(event.location_f(), event.flags());
2898 
2899   ASSERT_TRUE(InOverviewSession());
2900   EXPECT_EQ(OverviewEnterExitType::kImmediateEnter,
2901             overview_session()->enter_exit_overview_type());
2902 }
2903 
2904 // Tests the grid bounds are as expected with different shelf auto hide
2905 // behaviors and alignments.
TEST_P(OverviewSessionTest,GridBounds)2906 TEST_P(OverviewSessionTest, GridBounds) {
2907   UpdateDisplay("600x600");
2908   std::unique_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(200, 200)));
2909 
2910   Shelf* shelf = GetPrimaryShelf();
2911   shelf->SetAlignment(ShelfAlignment::kBottom);
2912   shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kNever);
2913 
2914   // Test that with the bottom shelf, the grid should take up the entire display
2915   // minus the shelf area on the bottom regardless of auto hide behavior.
2916   const int shelf_size = ShelfConfig::Get()->shelf_size();
2917   ToggleOverview();
2918   EXPECT_EQ(gfx::Rect(0, 0, 600, 600 - shelf_size), GetGridBounds());
2919   ToggleOverview();
2920 
2921   shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
2922   ToggleOverview();
2923   EXPECT_EQ(gfx::Rect(0, 0, 600, 600 - shelf_size), GetGridBounds());
2924   ToggleOverview();
2925 
2926   // Test that with the right shelf, the grid should take up the entire display
2927   // minus the shelf area on the right regardless of auto hide behavior.
2928   shelf->SetAlignment(ShelfAlignment::kRight);
2929   shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kNever);
2930   ToggleOverview();
2931   EXPECT_EQ(gfx::Rect(0, 0, 600 - shelf_size, 600), GetGridBounds());
2932   ToggleOverview();
2933 
2934   shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
2935   ToggleOverview();
2936   EXPECT_EQ(gfx::Rect(0, 0, 600 - shelf_size, 600), GetGridBounds());
2937   ToggleOverview();
2938 }
2939 
2940 // Tests that windows that have a backdrop can still be tapped normally.
2941 // Regression test for crbug.com/938645.
TEST_P(OverviewSessionTest,SelectingWindowWithBackdrop)2942 TEST_P(OverviewSessionTest, SelectingWindowWithBackdrop) {
2943   std::unique_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(500, 200)));
2944 
2945   ToggleOverview();
2946   OverviewItem* item = GetOverviewItemForWindow(window.get());
2947   ASSERT_EQ(OverviewGridWindowFillMode::kLetterBoxed,
2948             item->GetWindowDimensionsType());
2949 
2950   // Tap the target.
2951   GetEventGenerator()->set_current_screen_location(
2952       gfx::ToRoundedPoint(item->target_bounds().CenterPoint()));
2953   GetEventGenerator()->ClickLeftButton();
2954   EXPECT_FALSE(InOverviewSession());
2955 }
2956 
TEST_P(OverviewSessionTest,ShelfAlignmentChangeWhileInOverview)2957 TEST_P(OverviewSessionTest, ShelfAlignmentChangeWhileInOverview) {
2958   Shelf* shelf = GetPrimaryShelf();
2959   shelf->SetAlignment(ShelfAlignment::kBottom);
2960   ToggleOverview();
2961   shelf->SetAlignment(ShelfAlignment::kRight);
2962   EXPECT_FALSE(InOverviewSession());
2963 }
2964 
2965 namespace {
2966 class TestEventHandler : public ui::EventHandler {
2967  public:
2968   TestEventHandler() = default;
2969   ~TestEventHandler() override = default;
2970   // ui::EventHandler:
OnKeyEvent(ui::KeyEvent * event)2971   void OnKeyEvent(ui::KeyEvent* event) override {
2972     if (event->type() != ui::ET_KEY_PRESSED)
2973       return;
2974 
2975     has_seen_event_ = true;
2976     event->SetHandled();
2977     event->StopPropagation();
2978   }
HasSeenEvent()2979   bool HasSeenEvent() { return has_seen_event_; }
Reset()2980   void Reset() { has_seen_event_ = false; }
2981 
2982  private:
2983   bool has_seen_event_ = false;
2984 };
2985 }  // namespace
2986 
2987 // Test that keys are eaten when entering overview mode.
TEST_P(OverviewSessionTest,EatKeysDuringStartAnimation)2988 TEST_P(OverviewSessionTest, EatKeysDuringStartAnimation) {
2989   std::unique_ptr<aura::Window> test_window(CreateTestWindow());
2990   TestEventHandler test_event_handler;
2991   test_window->SetTargetHandler(&test_event_handler);
2992   test_window->Focus();
2993 
2994   ui::ScopedAnimationDurationScaleMode animation_scale(
2995       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2996 
2997   // Keys shouldn't be eaten by overview session normally.
2998   SendKey(ui::VKEY_A);
2999   ASSERT_TRUE(test_window->HasFocus());
3000   EXPECT_TRUE(test_event_handler.HasSeenEvent());
3001   test_event_handler.Reset();
3002 
3003   // Keys should be eaten by overview session when entering overview mode.
3004   ToggleOverview();
3005   ASSERT_TRUE(Shell::Get()->overview_controller()->IsInStartAnimation());
3006   ASSERT_TRUE(test_window->HasFocus());
3007   SendKey(ui::VKEY_B);
3008   EXPECT_FALSE(test_event_handler.HasSeenEvent());
3009   EXPECT_TRUE(InOverviewSession());
3010 
3011   WaitForOverviewEnterAnimation();
3012   ASSERT_FALSE(Shell::Get()->overview_controller()->IsInStartAnimation());
3013   EXPECT_FALSE(test_window->HasFocus());
3014 
3015   ToggleOverview();
3016   SendKey(ui::VKEY_C);
3017   EXPECT_FALSE(InOverviewSession());
3018   EXPECT_TRUE(test_event_handler.HasSeenEvent());
3019 }
3020 
3021 // Tests that in tablet mode, tapping on the background will go to home screen.
TEST_P(OverviewSessionTest,TapOnBackgroundGoToHome)3022 TEST_P(OverviewSessionTest, TapOnBackgroundGoToHome) {
3023   EnterTabletMode();
3024   UpdateDisplay("800x600");
3025   std::unique_ptr<aura::Window> window(CreateTestWindow());
3026   WindowState* window_state = WindowState::Get(window.get());
3027 
3028   EXPECT_FALSE(window_state->IsMinimized());
3029   EXPECT_FALSE(Shell::Get()->home_screen_controller()->IsHomeScreenVisible());
3030   ToggleOverview();
3031   EXPECT_TRUE(InOverviewSession());
3032 
3033   // Tap on the background. The tap location should be out of the tapping area
3034   // for back gesture. Otherwise, the touch event will be consumed and no
3035   // gesture event will be generated.
3036   ui::ScopedAnimationDurationScaleMode test_duration_mode(
3037       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
3038   GetEventGenerator()->GestureTapAt(
3039       gfx::Point(BackGestureEventHandler::kStartGoingBackLeftEdgeInset, 10));
3040   ShellTestApi().WaitForOverviewAnimationState(
3041       OverviewAnimationState::kExitAnimationComplete);
3042 
3043   EXPECT_FALSE(InOverviewSession());
3044   EXPECT_TRUE(window_state->IsMinimized());
3045   EXPECT_TRUE(Shell::Get()->home_screen_controller()->IsHomeScreenVisible());
3046 }
3047 
3048 // Tests that in tablet mode, tapping on the background in split view mode will
3049 // be no-op.
TEST_P(OverviewSessionTest,TapOnBackgroundInSplitView)3050 TEST_P(OverviewSessionTest, TapOnBackgroundInSplitView) {
3051   EnterTabletMode();
3052   UpdateDisplay("800x600");
3053   std::unique_ptr<aura::Window> window1(CreateTestWindow());
3054 
3055   std::unique_ptr<aura::Window> window2(CreateTestWindow());
3056 
3057   EXPECT_FALSE(Shell::Get()->home_screen_controller()->IsHomeScreenVisible());
3058   ToggleOverview();
3059   EXPECT_TRUE(InOverviewSession());
3060 
3061   split_view_controller()->SnapWindow(window2.get(),
3062                                       SplitViewController::RIGHT);
3063   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
3064 
3065   // Tap on the background.
3066   GetEventGenerator()->GestureTapAt(gfx::Point(10, 10));
3067 
3068   EXPECT_TRUE(InOverviewSession());
3069   EXPECT_FALSE(Shell::Get()->home_screen_controller()->IsHomeScreenVisible());
3070   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
3071 }
3072 
3073 // Tests starting the overview session using kFadeInEnter type.
TEST_P(OverviewSessionTest,FadeIn)3074 TEST_P(OverviewSessionTest, FadeIn) {
3075   EnterTabletMode();
3076   // Create a minimized window.
3077   std::unique_ptr<aura::Window> window = CreateTestWindow();
3078   WindowState::Get(window.get())->Minimize();
3079 
3080   ui::ScopedAnimationDurationScaleMode test_duration_mode(
3081       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
3082 
3083   ToggleOverview(OverviewEnterExitType::kFadeInEnter);
3084   ASSERT_TRUE(InOverviewSession());
3085 
3086   OverviewItem* item = GetOverviewItemForWindow(window.get());
3087 
3088   // Verify that the item widget's transform is not animated as part of the
3089   // animation.
3090   views::Widget* widget = item->item_widget();
3091   EXPECT_FALSE(widget->GetLayer()->GetAnimator()->IsAnimatingProperty(
3092       ui::LayerAnimationElement::TRANSFORM));
3093 
3094   // Opacity should be animated to full opacity.
3095   EXPECT_EQ(1.0f, widget->GetLayer()->GetTargetOpacity());
3096   EXPECT_TRUE(widget->GetLayer()->GetAnimator()->IsAnimatingProperty(
3097       ui::LayerAnimationElement::OPACITY));
3098 
3099   // Validate item bounds are within the grid.
3100   const gfx::Rect bounds = gfx::ToEnclosedRect(item->target_bounds());
3101   EXPECT_TRUE(GetGridBounds().Contains(bounds));
3102 
3103   // Header is expected to be shown immediately.
3104   EXPECT_EQ(
3105       1.0f,
3106       item->overview_item_view()->header_view()->layer()->GetTargetOpacity());
3107 
3108   EXPECT_EQ(OverviewEnterExitType::kFadeInEnter,
3109             overview_session()->enter_exit_overview_type());
3110 }
3111 
3112 // Tests exiting the overview session using kFadeOutExit type.
TEST_P(OverviewSessionTest,FadeOutExit)3113 TEST_P(OverviewSessionTest, FadeOutExit) {
3114   EnterTabletMode();
3115   // Create a test window.
3116   std::unique_ptr<views::Widget> test_widget(CreateTestWidget());
3117   ToggleOverview();
3118   ASSERT_TRUE(InOverviewSession());
3119   EXPECT_FALSE(test_widget->IsMinimized());
3120 
3121   ui::ScopedAnimationDurationScaleMode test_duration_mode(
3122       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
3123 
3124   // Grab the item widget before the session starts shutting down. The widget
3125   // should outlive the session, at least until the animations are done - given
3126   // that NON_ZERO_DURATION animation duration scale, it should be safe to
3127   // dereference the widget pointer immediately (synchronously) after the
3128   // session ends.
3129   OverviewItem* item = GetOverviewItemForWindow(test_widget->GetNativeWindow());
3130   views::Widget* grid_item_widget = item->item_widget();
3131   gfx::Rect item_bounds = grid_item_widget->GetWindowBoundsInScreen();
3132 
3133   ToggleOverview(OverviewEnterExitType::kFadeOutExit);
3134   ASSERT_FALSE(InOverviewSession());
3135 
3136   // The test window should be minimized as overview fade out exit starts.
3137   EXPECT_TRUE(test_widget->IsMinimized());
3138 
3139   // Verify that the item widget's transform is not animated as part of the
3140   // animation, and that item widget bounds are not changed after minimizing the
3141   // window.
3142   EXPECT_FALSE(grid_item_widget->GetLayer()->GetAnimator()->IsAnimatingProperty(
3143       ui::LayerAnimationElement::TRANSFORM));
3144   EXPECT_EQ(item_bounds, grid_item_widget->GetWindowBoundsInScreen());
3145 
3146   // Opacity should be animated to zero opacity.
3147   EXPECT_EQ(0.0f, grid_item_widget->GetLayer()->GetTargetOpacity());
3148   EXPECT_TRUE(grid_item_widget->GetLayer()->GetAnimator()->IsAnimatingProperty(
3149       ui::LayerAnimationElement::OPACITY));
3150 }
3151 
3152 // Tests that accessibility overrides are set as expected on overview related
3153 // widgets.
TEST_P(OverviewSessionTest,AccessibilityFocusAnnotator)3154 TEST_P(OverviewSessionTest, AccessibilityFocusAnnotator) {
3155   auto window3 = CreateTestWindow(gfx::Rect(100, 100));
3156   auto window2 = CreateTestWindow(gfx::Rect(100, 100));
3157   auto window1 = CreateTestWindow(gfx::Rect(100, 100));
3158 
3159   ToggleOverview();
3160   WaitForOverviewEnterAnimation();
3161 
3162   auto* focus_widget = views::Widget::GetWidgetForNativeWindow(
3163       GetOverviewSession()->GetOverviewFocusWindow());
3164   DCHECK(focus_widget);
3165 
3166   OverviewGrid* grid = GetOverviewSession()->grid_list()[0].get();
3167   auto* desk_widget = const_cast<views::Widget*>(grid->desks_widget());
3168   DCHECK(desk_widget);
3169 
3170   // Overview items are in MRU order, so the expected order in the grid list is
3171   // the reverse creation order.
3172   auto* item_widget1 = GetOverviewItemForWindow(window1.get())->item_widget();
3173   auto* item_widget2 = GetOverviewItemForWindow(window2.get())->item_widget();
3174   auto* item_widget3 = GetOverviewItemForWindow(window3.get())->item_widget();
3175 
3176   // Helper that takes in a current widget and checks if the accessibility next
3177   // and previous focus widgets match the given.
3178   auto check_a11y_overrides = [](const std::string& id, views::Widget* widget,
3179                                  views::Widget* expected_previous,
3180                                  views::Widget* expected_next) -> void {
3181     SCOPED_TRACE(id);
3182     views::View* contents_view = widget->GetContentsView();
3183     views::ViewAccessibility& view_accessibility =
3184         contents_view->GetViewAccessibility();
3185     EXPECT_EQ(expected_previous, view_accessibility.GetPreviousFocus());
3186     EXPECT_EQ(expected_next, view_accessibility.GetNextFocus());
3187   };
3188 
3189   // Order should be [focus_widget, desk_widget, item_widget1, item_widget2,
3190   // item_widget3].
3191   check_a11y_overrides("focus", focus_widget, item_widget3, desk_widget);
3192   check_a11y_overrides("desk", desk_widget, focus_widget, item_widget1);
3193   check_a11y_overrides("item1", item_widget1, desk_widget, item_widget2);
3194   check_a11y_overrides("item2", item_widget2, item_widget1, item_widget3);
3195   check_a11y_overrides("item3", item_widget3, item_widget2, focus_widget);
3196 
3197   // Remove |window2|. The new order should be [focus_widget, desk_widget,
3198   // item_widget1, item_widget3].
3199   window2.reset();
3200   check_a11y_overrides("focus", focus_widget, item_widget3, desk_widget);
3201   check_a11y_overrides("desk", desk_widget, focus_widget, item_widget1);
3202   check_a11y_overrides("item1", item_widget1, desk_widget, item_widget3);
3203   check_a11y_overrides("item3", item_widget3, item_widget1, focus_widget);
3204 }
3205 
3206 // Tests that removing a transient child during overview does not result in a
3207 // crash when exiting overview.
TEST_P(OverviewSessionTest,RemoveTransientNoCrash)3208 TEST_P(OverviewSessionTest, RemoveTransientNoCrash) {
3209   auto child = CreateTestWindow();
3210   auto parent = CreateTestWindow();
3211   wm::AddTransientChild(parent.get(), child.get());
3212 
3213   ToggleOverview();
3214   wm::RemoveTransientChild(parent.get(), child.get());
3215   ToggleOverview();
3216 }
3217 
3218 class TabletModeOverviewSessionTest : public OverviewSessionTest {
3219  public:
3220   TabletModeOverviewSessionTest() = default;
3221   ~TabletModeOverviewSessionTest() override = default;
3222 
3223   TabletModeOverviewSessionTest(const TabletModeOverviewSessionTest&) = delete;
3224   TabletModeOverviewSessionTest& operator=(
3225       const TabletModeOverviewSessionTest&) = delete;
3226 
SetUp()3227   void SetUp() override {
3228     OverviewSessionTest::SetUp();
3229     EnterTabletMode();
3230   }
3231 
split_view_controller()3232   SplitViewController* split_view_controller() {
3233     return SplitViewController::Get(Shell::GetPrimaryRootWindow());
3234   }
3235 
3236  protected:
GenerateScrollSequence(const gfx::Point & start,const gfx::Point & end)3237   void GenerateScrollSequence(const gfx::Point& start, const gfx::Point& end) {
3238     GetEventGenerator()->GestureScrollSequence(
3239         start, end, base::TimeDelta::FromMilliseconds(100), 1000);
3240   }
3241 
DispatchLongPress(OverviewItem * item)3242   void DispatchLongPress(OverviewItem* item) {
3243     ui::TouchEvent long_press(
3244         ui::ET_GESTURE_LONG_PRESS,
3245         gfx::ToRoundedPoint(item->target_bounds().CenterPoint()),
3246         base::TimeTicks::Now(),
3247         ui::PointerDetails(ui::EventPointerType::kTouch));
3248     GetEventGenerator()->Dispatch(&long_press);
3249   }
3250 
3251   // Creates |n| test windows. They are created in reverse order, so that the
3252   // first window in the vector is the MRU window.
CreateTestWindows(int n)3253   std::vector<std::unique_ptr<aura::Window>> CreateTestWindows(int n) {
3254     std::vector<std::unique_ptr<aura::Window>> windows(n);
3255     for (int i = n - 1; i >= 0; --i)
3256       windows[i] = CreateTestWindow();
3257     return windows;
3258   }
3259 };
3260 
3261 // Tests that windows are in proper positions in the new overview layout.
TEST_P(TabletModeOverviewSessionTest,CheckNewLayoutWindowPositions)3262 TEST_P(TabletModeOverviewSessionTest, CheckNewLayoutWindowPositions) {
3263   auto windows = CreateTestWindows(6);
3264   ToggleOverview();
3265   ASSERT_TRUE(InOverviewSession());
3266 
3267   OverviewItem* item1 = GetOverviewItemForWindow(windows[0].get());
3268   OverviewItem* item2 = GetOverviewItemForWindow(windows[1].get());
3269   OverviewItem* item3 = GetOverviewItemForWindow(windows[2].get());
3270   OverviewItem* item4 = GetOverviewItemForWindow(windows[3].get());
3271 
3272   const gfx::RectF item1_bounds = item1->target_bounds();
3273   const gfx::RectF item2_bounds = item2->target_bounds();
3274   const gfx::RectF item3_bounds = item3->target_bounds();
3275   const gfx::RectF item4_bounds = item4->target_bounds();
3276 
3277   // |window1| should be in the top left position. |window2| should be directly
3278   // below |window1|, thus sharing the same x-value but not the same y-value.
3279   EXPECT_EQ(item1_bounds.x(), item2_bounds.x());
3280   EXPECT_LT(item1_bounds.y(), item2_bounds.y());
3281   // |window3| should be directly right of |window1|, thus sharing the same
3282   // y-value, but not the same x-value.
3283   EXPECT_LT(item1_bounds.x(), item3_bounds.x());
3284   EXPECT_EQ(item1_bounds.y(), item3_bounds.y());
3285   // |window4| should be directly right of |window2| and directly below
3286   // |window3|.
3287   EXPECT_LT(item2_bounds.x(), item4_bounds.x());
3288   EXPECT_EQ(item2_bounds.y(), item4_bounds.y());
3289   EXPECT_EQ(item3_bounds.x(), item4_bounds.x());
3290   EXPECT_LT(item3_bounds.y(), item4_bounds.y());
3291 }
3292 
TEST_P(TabletModeOverviewSessionTest,CheckOffscreenWindows)3293 TEST_P(TabletModeOverviewSessionTest, CheckOffscreenWindows) {
3294   auto windows = CreateTestWindows(8);
3295   ToggleOverview();
3296   ASSERT_TRUE(InOverviewSession());
3297 
3298   OverviewItem* item0 = GetOverviewItemForWindow(windows[0].get());
3299   OverviewItem* item1 = GetOverviewItemForWindow(windows[1].get());
3300   OverviewItem* item6 = GetOverviewItemForWindow(windows[6].get());
3301   OverviewItem* item7 = GetOverviewItemForWindow(windows[7].get());
3302 
3303   const gfx::RectF screen_bounds(GetGridBounds());
3304   const gfx::RectF item0_bounds = item0->target_bounds();
3305   const gfx::RectF item1_bounds = item1->target_bounds();
3306   const gfx::RectF item6_bounds = item6->target_bounds();
3307   const gfx::RectF item7_bounds = item7->target_bounds();
3308 
3309   // |item6| should be in the same row of windows as |item0|, but offscreen
3310   // (one screen length away).
3311   EXPECT_FALSE(screen_bounds.Contains(item6_bounds));
3312   EXPECT_EQ(item0_bounds.y(), item6_bounds.y());
3313   // |item7| should be in the same row of windows as |item1|, but offscreen
3314   // and below |item6|.
3315   EXPECT_FALSE(screen_bounds.Contains(item7_bounds));
3316   EXPECT_EQ(item1_bounds.y(), item7_bounds.y());
3317   EXPECT_LT(item6_bounds.y(), item7_bounds.y());
3318 }
3319 
3320 // Tests to see if windows are not shifted if all already available windows
3321 // fit on screen.
TEST_P(TabletModeOverviewSessionTest,CheckNoOverviewItemShift)3322 TEST_P(TabletModeOverviewSessionTest, CheckNoOverviewItemShift) {
3323   auto windows = CreateTestWindows(4);
3324   ToggleOverview();
3325   ASSERT_TRUE(InOverviewSession());
3326 
3327   OverviewItem* item0 = GetOverviewItemForWindow(windows[0].get());
3328   const gfx::RectF before_shift_bounds = item0->target_bounds();
3329 
3330   GenerateScrollSequence(gfx::Point(100, 50), gfx::Point(0, 50));
3331   EXPECT_EQ(before_shift_bounds, item0->target_bounds());
3332 }
3333 
3334 // Tests to see if windows are shifted if at least one window is
3335 // partially/completely positioned offscreen.
TEST_P(TabletModeOverviewSessionTest,CheckOverviewItemShift)3336 TEST_P(TabletModeOverviewSessionTest, CheckOverviewItemShift) {
3337   auto windows = CreateTestWindows(7);
3338   ToggleOverview();
3339   ASSERT_TRUE(InOverviewSession());
3340 
3341   OverviewItem* item0 = GetOverviewItemForWindow(windows[0].get());
3342   const gfx::RectF before_shift_bounds = item0->target_bounds();
3343 
3344   GenerateScrollSequence(gfx::Point(100, 50), gfx::Point(0, 50));
3345   EXPECT_LT(item0->target_bounds(), before_shift_bounds);
3346 }
3347 
3348 // Tests to see if windows remain in bounds after scrolling extremely far.
TEST_P(TabletModeOverviewSessionTest,CheckOverviewItemScrollingBounds)3349 TEST_P(TabletModeOverviewSessionTest, CheckOverviewItemScrollingBounds) {
3350   auto windows = CreateTestWindows(8);
3351   ToggleOverview();
3352   ASSERT_TRUE(InOverviewSession());
3353 
3354   // Scroll an extreme amount to see if windows on the far left are still in
3355   // bounds. First, align the left-most window (|windows[0]|) to the left-hand
3356   // bound and store the item's location. Then, scroll a far amount and check to
3357   // see if the item moved at all.
3358   OverviewItem* leftmost_window = GetOverviewItemForWindow(windows[0].get());
3359 
3360   GenerateScrollSequence(
3361       gfx::Point(BackGestureEventHandler::kStartGoingBackLeftEdgeInset + 5, 50),
3362       gfx::Point(5000, 50));
3363   const gfx::RectF left_bounds = leftmost_window->target_bounds();
3364   GenerateScrollSequence(
3365       gfx::Point(BackGestureEventHandler::kStartGoingBackLeftEdgeInset + 5, 50),
3366       gfx::Point(5000, 50));
3367   EXPECT_EQ(left_bounds, leftmost_window->target_bounds());
3368 
3369   // Scroll an extreme amount to see if windows on the far right are still in
3370   // bounds. First, align the right-most window (|windows[7]|) to the right-hand
3371   // bound and store the item's location. Then, scroll a far amount and check to
3372   // see if the item moved at all.
3373   OverviewItem* rightmost_window = GetOverviewItemForWindow(windows[7].get());
3374   GenerateScrollSequence(gfx::Point(5000, 50), gfx::Point(0, 50));
3375   const gfx::RectF right_bounds = rightmost_window->target_bounds();
3376   GenerateScrollSequence(gfx::Point(5000, 50), gfx::Point(0, 50));
3377   EXPECT_EQ(right_bounds, rightmost_window->target_bounds());
3378 }
3379 
3380 // Tests the windows are stacked correctly when entering or exiting splitview
3381 // while the new overivew layout is enabled.
TEST_P(TabletModeOverviewSessionTest,StackingOrderSplitviewWindow)3382 TEST_P(TabletModeOverviewSessionTest, StackingOrderSplitviewWindow) {
3383   std::unique_ptr<aura::Window> window1 = CreateTestWindow();
3384   std::unique_ptr<aura::Window> window2 = CreateUnsnappableWindow();
3385   std::unique_ptr<aura::Window> window3 = CreateTestWindow();
3386 
3387   ToggleOverview();
3388   ASSERT_TRUE(InOverviewSession());
3389 
3390   // Snap |window1| to the left and exit overview. |window3| should have higher
3391   // z-order now, since it is the MRU window.
3392   split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
3393   ToggleOverview();
3394   ASSERT_EQ(SplitViewController::State::kBothSnapped,
3395             split_view_controller()->state());
3396   ASSERT_GT(IndexOf(window3.get(), window3->parent()),
3397             IndexOf(window1.get(), window1->parent()));
3398 
3399   // Test that on entering overview, |window3| is of a lower z-order, so that
3400   // when we scroll the grid, it will be seen under |window1|.
3401   ToggleOverview();
3402   EXPECT_LT(IndexOf(window3.get(), window3->parent()),
3403             IndexOf(window1.get(), window1->parent()));
3404 
3405   // Test that |window2| has a cannot snap widget indicating that it cannot be
3406   // snapped, and that both |window2| and the widget are lower z-order than
3407   // |window1|.
3408   views::Widget* cannot_snap_widget =
3409       static_cast<views::Widget*>(GetOverviewItemForWindow(window2.get())
3410                                       ->cannot_snap_widget_for_testing());
3411   ASSERT_TRUE(cannot_snap_widget);
3412   aura::Window* cannot_snap_window = cannot_snap_widget->GetNativeWindow();
3413   ASSERT_EQ(window1->parent(), cannot_snap_window->parent());
3414   EXPECT_LT(IndexOf(window2.get(), window2->parent()),
3415             IndexOf(window1.get(), window1->parent()));
3416   EXPECT_LT(IndexOf(cannot_snap_window, cannot_snap_window->parent()),
3417             IndexOf(window1.get(), window1->parent()));
3418 
3419   // Test that on exiting overview, |window3| becomes activated, so it returns
3420   // to being higher on the z-order than |window1|.
3421   ToggleOverview();
3422   EXPECT_GT(IndexOf(window3.get(), window3->parent()),
3423             IndexOf(window1.get(), window1->parent()));
3424 }
3425 
3426 // Tests the windows are remain stacked underneath the split view window after
3427 // dragging or long pressing.
TEST_P(TabletModeOverviewSessionTest,StackingOrderAfterGestureEvent)3428 TEST_P(TabletModeOverviewSessionTest, StackingOrderAfterGestureEvent) {
3429   std::unique_ptr<aura::Window> window1 = CreateTestWindow();
3430   std::unique_ptr<aura::Window> window2 = CreateTestWindow();
3431 
3432   ToggleOverview();
3433   ASSERT_TRUE(InOverviewSession());
3434   split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
3435 
3436   // Tests that if we long press, but cancel the event, the window stays stacked
3437   // under the snapped window.
3438   OverviewItem* item = GetOverviewItemForWindow(window2.get());
3439   const gfx::PointF item_center = item->target_bounds().CenterPoint();
3440   DispatchLongPress(item);
3441   ui::GestureEvent gesture_end(item_center.x(), item_center.y(), 0,
3442                                ui::EventTimeForNow(),
3443                                ui::GestureEventDetails(ui::ET_GESTURE_END));
3444   item->HandleGestureEvent(&gesture_end);
3445   EXPECT_GT(IndexOf(window1.get(), window1->parent()),
3446             IndexOf(window2.get(), window2->parent()));
3447 
3448   // Tests that if we drag the window around, then release, the window also
3449   // stays stacked under the snapped window.
3450   ASSERT_TRUE(InOverviewSession());
3451   const gfx::Vector2dF delta(15.f, 15.f);
3452   DispatchLongPress(item);
3453   overview_session()->Drag(item, item_center + delta);
3454   overview_session()->CompleteDrag(item, item_center + delta);
3455   EXPECT_GT(IndexOf(window1.get(), window1->parent()),
3456             IndexOf(window2.get(), window2->parent()));
3457 }
3458 
3459 // Test that scrolling occurs if started on top of a window using the window's
3460 // center-point as a start.
TEST_P(TabletModeOverviewSessionTest,HorizontalScrollingOnOverviewItem)3461 TEST_P(TabletModeOverviewSessionTest, HorizontalScrollingOnOverviewItem) {
3462   auto windows = CreateTestWindows(8);
3463   ToggleOverview();
3464   ASSERT_TRUE(InOverviewSession());
3465 
3466   OverviewItem* leftmost_window = GetOverviewItemForWindow(windows[0].get());
3467   const gfx::Point topleft_window_center =
3468       gfx::ToRoundedPoint(leftmost_window->target_bounds().CenterPoint());
3469   const gfx::RectF left_bounds = leftmost_window->target_bounds();
3470 
3471   GenerateScrollSequence(topleft_window_center, gfx::Point(-500, 50));
3472   EXPECT_LT(leftmost_window->target_bounds(), left_bounds);
3473 }
3474 
3475 // A unique test class for testing flings in overview as those rely on observing
3476 // compositor animations which require a mock time task environment.
3477 class OverviewSessionFlingTest : public AshTestBase {
3478  public:
OverviewSessionFlingTest()3479   OverviewSessionFlingTest()
3480       : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
3481   ~OverviewSessionFlingTest() override = default;
3482 
3483   OverviewSessionFlingTest(const OverviewSessionFlingTest&) = delete;
3484   OverviewSessionFlingTest& operator=(const OverviewSessionFlingTest&) = delete;
3485 
3486   // AshTestBase:
SetUp()3487   void SetUp() override {
3488     AshTestBase::SetUp();
3489 
3490     // Overview flinging is only available in tablet mode.
3491     base::RunLoop().RunUntilIdle();
3492     TabletModeControllerTestApi().EnterTabletMode();
3493     base::RunLoop().RunUntilIdle();
3494   }
3495 };
3496 
TEST_F(OverviewSessionFlingTest,BasicFling)3497 TEST_F(OverviewSessionFlingTest, BasicFling) {
3498   std::vector<std::unique_ptr<aura::Window>> windows(16);
3499   for (int i = 15; i >= 0; --i)
3500     windows[i] = CreateTestWindow();
3501 
3502   ToggleOverview();
3503   OverviewGrid* grid = GetOverviewSession()->grid_list()[0].get();
3504   OverviewGridEventHandler* grid_event_handler = grid->grid_event_handler();
3505 
3506   OverviewItem* item = GetOverviewItemForWindow(windows[2].get());
3507   const gfx::Point item_center =
3508       gfx::ToRoundedPoint(item->target_bounds().CenterPoint());
3509 
3510   // Create a scroll sequence which results in a fling.
3511   const gfx::Vector2d shift(-200, 0);
3512   GetEventGenerator()->GestureScrollSequence(
3513       item_center, item_center + shift, base::TimeDelta::FromMilliseconds(10),
3514       10);
3515 
3516   ui::Compositor* const compositor =
3517       windows[0]->GetRootWindow()->layer()->GetCompositor();
3518   ui::DrawWaiterForTest::WaitForCompositingStarted(compositor);
3519   ASSERT_TRUE(grid_event_handler->IsFlingInProgressForTesting());
3520 
3521   // Test that the scroll offset decreases as we advance the clock. Check the
3522   // scroll offset instead of the item bounds as there is an optimization which
3523   // does not update the item bounds of invisible elements. On some iterations,
3524   // there may not be enough time passed to decay the velocity so the scroll
3525   // offset will not change, but the overall change should be substantial.
3526   constexpr int kMaxLoops = 10;
3527   const float initial_scroll_offset = grid->scroll_offset();
3528   float previous_scroll_offset = initial_scroll_offset;
3529   for (int i = 0;
3530        i < kMaxLoops && grid_event_handler->IsFlingInProgressForTesting();
3531        ++i) {
3532     task_environment()->FastForwardBy(base::TimeDelta::FromMilliseconds(50));
3533     ui::DrawWaiterForTest::WaitForCompositingStarted(compositor);
3534 
3535     float scroll_offset = grid->scroll_offset();
3536     EXPECT_LE(scroll_offset, previous_scroll_offset);
3537     previous_scroll_offset = scroll_offset;
3538   }
3539 
3540   EXPECT_LT(grid->scroll_offset(), initial_scroll_offset - 100.f);
3541 }
3542 
3543 // Tests that a vertical scroll sequence will close the window it is scrolled
3544 // on.
TEST_P(TabletModeOverviewSessionTest,VerticalScrollingOnOverviewItem)3545 TEST_P(TabletModeOverviewSessionTest, VerticalScrollingOnOverviewItem) {
3546   constexpr int kNumWidgets = 8;
3547   std::vector<std::unique_ptr<views::Widget>> widgets(kNumWidgets);
3548   for (int i = kNumWidgets - 1; i >= 0; --i)
3549     widgets[i] = CreateTestWidget();
3550   ToggleOverview();
3551   ASSERT_TRUE(InOverviewSession());
3552 
3553   OverviewItem* leftmost_window =
3554       GetOverviewItemForWindow(widgets[0]->GetNativeWindow());
3555   const gfx::Point topleft_window_center =
3556       gfx::ToRoundedPoint(leftmost_window->target_bounds().CenterPoint());
3557   const gfx::Point end_point = topleft_window_center - gfx::Vector2d(0, 300);
3558 
3559   GenerateScrollSequence(topleft_window_center, end_point);
3560   EXPECT_TRUE(widgets[0]->IsClosed());
3561 }
3562 
3563 // Test that scrolling occurs if we hit the associated keyboard shortcut.
TEST_P(TabletModeOverviewSessionTest,CheckScrollingWithKeyboardShortcut)3564 TEST_P(TabletModeOverviewSessionTest, CheckScrollingWithKeyboardShortcut) {
3565   auto windows = CreateTestWindows(8);
3566   ToggleOverview();
3567   ASSERT_TRUE(InOverviewSession());
3568 
3569   OverviewItem* leftmost_window = GetOverviewItemForWindow(windows[0].get());
3570   const gfx::RectF left_bounds = leftmost_window->target_bounds();
3571 
3572   SendKey(ui::VKEY_RIGHT, ui::EF_CONTROL_DOWN);
3573   EXPECT_LT(leftmost_window->target_bounds(), left_bounds);
3574 }
3575 
3576 // Test that tapping a window in overview closes overview mode.
TEST_P(TabletModeOverviewSessionTest,CheckWindowActivateOnTap)3577 TEST_P(TabletModeOverviewSessionTest, CheckWindowActivateOnTap) {
3578   base::UserActionTester user_action_tester;
3579   auto windows = CreateTestWindows(8);
3580   wm::ActivateWindow(windows[1].get());
3581 
3582   ToggleOverview();
3583   ASSERT_TRUE(InOverviewSession());
3584 
3585   // Tap on |windows[1]| to exit overview.
3586   GetEventGenerator()->GestureTapAt(
3587       GetTransformedTargetBounds(windows[1].get()).CenterPoint());
3588   EXPECT_EQ(
3589       0, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview));
3590 
3591   // |windows[1]| remains active. Click on it to exit overview.
3592   ASSERT_EQ(windows[1].get(), window_util::GetFocusedWindow());
3593   ToggleOverview();
3594   ClickWindow(windows[1].get());
3595   EXPECT_EQ(
3596       0, user_action_tester.GetActionCount(kActiveWindowChangedFromOverview));
3597 }
3598 
TEST_P(TabletModeOverviewSessionTest,LayoutValidAfterRotation)3599 TEST_P(TabletModeOverviewSessionTest, LayoutValidAfterRotation) {
3600   UpdateDisplay("1366x768");
3601   display::test::ScopedSetInternalDisplayId set_internal(
3602       Shell::Get()->display_manager(),
3603       display::Screen::GetScreen()->GetPrimaryDisplay().id());
3604   auto windows = CreateTestWindows(7);
3605 
3606   // Helper to determine whether a grid layout is valid. It is considered valid
3607   // if the left edge of the first item is close enough to the left edge of the
3608   // grid bounds and if the right edge of the last item is close enough to the
3609   // right edge of the grid bounds. Either of these being false would mean there
3610   // is a large padding which shouldn't be there.
3611   auto layout_valid = [&windows, this](int expected_padding) {
3612     OverviewItem* first_item = GetOverviewItemForWindow(windows.front().get());
3613     OverviewItem* last_item = GetOverviewItemForWindow(windows.back().get());
3614 
3615     const gfx::Rect first_bounds =
3616         gfx::ToEnclosedRect(first_item->target_bounds());
3617     const gfx::Rect last_bounds =
3618         gfx::ToEnclosedRect(last_item->target_bounds());
3619 
3620     const gfx::Rect grid_bounds = GetGridBounds();
3621     const bool first_bounds_valid =
3622         first_bounds.x() <= (grid_bounds.x() + expected_padding);
3623     const bool last_bounds_valid =
3624         last_bounds.right() >= (grid_bounds.right() - expected_padding);
3625     return first_bounds_valid && last_bounds_valid;
3626   };
3627 
3628   // Enter overview and scroll to the edge of the grid. The layout should remain
3629   // valid.
3630   ToggleOverview();
3631   ASSERT_TRUE(InOverviewSession());
3632   // The expected padding should be the x position of the first item, before the
3633   // grid gets shifted.
3634   const int expected_padding =
3635       GetOverviewItemForWindow(windows.front().get())->target_bounds().x();
3636   GenerateScrollSequence(gfx::Point(1300, 10), gfx::Point(100, 10));
3637   EXPECT_TRUE(layout_valid(expected_padding));
3638 
3639   // Tests that the layout is still valid after a couple rotations.
3640   ScreenOrientationControllerTestApi test_api(
3641       Shell::Get()->screen_orientation_controller());
3642   test_api.SetDisplayRotation(display::Display::ROTATE_90,
3643                               display::Display::RotationSource::ACTIVE);
3644   EXPECT_TRUE(layout_valid(expected_padding));
3645 
3646   test_api.SetDisplayRotation(display::Display::ROTATE_180,
3647                               display::Display::RotationSource::ACTIVE);
3648   EXPECT_TRUE(layout_valid(expected_padding));
3649 }
3650 
3651 // Tests that windows snap through long press and drag to left or right side of
3652 // the screen.
TEST_P(TabletModeOverviewSessionTest,DragOverviewWindowToSnap)3653 TEST_P(TabletModeOverviewSessionTest, DragOverviewWindowToSnap) {
3654   const gfx::Rect bounds(400, 400);
3655   std::unique_ptr<aura::Window> window1(CreateTestWindow(bounds));
3656   std::unique_ptr<aura::Window> window2(CreateTestWindow(bounds));
3657   std::unique_ptr<aura::Window> window3(CreateTestWindow(bounds));
3658 
3659   ToggleOverview();
3660   ASSERT_TRUE(overview_controller()->InOverviewSession());
3661   ASSERT_FALSE(split_view_controller()->InSplitViewMode());
3662 
3663   // Dispatches a long press event at the |overview_item1|'s current location to
3664   // start dragging in SplitView. Drags |overview_item1| to the left border of
3665   // the screen. SplitView should trigger and upon completing drag,
3666   // |overview_item1| should snap to the left.
3667   OverviewItem* overview_item1 = GetOverviewItemForWindow(window1.get());
3668   const gfx::PointF snap_left_location =
3669       gfx::PointF(GetGridBounds().left_center());
3670 
3671   DispatchLongPress(overview_item1);
3672   overview_session()->Drag(
3673       overview_item1,
3674       gfx::PointF(overview_item1->target_bounds().left_center()));
3675   overview_session()->CompleteDrag(overview_item1, snap_left_location);
3676 
3677   ASSERT_TRUE(split_view_controller()->InSplitViewMode());
3678   EXPECT_EQ(split_view_controller()->state(),
3679             SplitViewController::State::kLeftSnapped);
3680   EXPECT_EQ(split_view_controller()->left_window(), window1.get());
3681 
3682   // Dispatches a long press event at the |overview_item2|'s current location to
3683   // start dragging in SplitView. Drags |overview_item2| to the right border of
3684   // the screen. Upon completing drag, |overview_item2| should snap to the
3685   // right.
3686   OverviewItem* overview_item2 = GetOverviewItemForWindow(window2.get());
3687   const gfx::PointF snap_right_location =
3688       gfx::PointF(GetGridBounds().right_center());
3689 
3690   DispatchLongPress(overview_item2);
3691   overview_session()->Drag(
3692       overview_item2,
3693       gfx::PointF(overview_item2->target_bounds().right_center()));
3694   overview_session()->CompleteDrag(overview_item2, snap_right_location);
3695 
3696   EXPECT_FALSE(InOverviewSession());
3697   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
3698   EXPECT_EQ(split_view_controller()->state(),
3699             SplitViewController::State::kBothSnapped);
3700   EXPECT_EQ(split_view_controller()->right_window(), window2.get());
3701 }
3702 
3703 // Verify that if the window item has been dragged enough vertically, the window
3704 // will be closed.
TEST_P(TabletModeOverviewSessionTest,DragToClose)3705 TEST_P(TabletModeOverviewSessionTest, DragToClose) {
3706   // This test requires a widget.
3707   std::unique_ptr<views::Widget> widget(CreateTestWidget());
3708 
3709   ToggleOverview();
3710   ASSERT_TRUE(overview_controller()->InOverviewSession());
3711 
3712   OverviewItem* item = GetOverviewItemForWindow(widget->GetNativeWindow());
3713   const gfx::PointF start = item->target_bounds().CenterPoint();
3714   ASSERT_TRUE(item);
3715 
3716   // This drag has not covered enough distance, so the widget is not closed and
3717   // we remain in overview mode.
3718   overview_session()->InitiateDrag(item, start, /*is_touch_dragging=*/true);
3719   overview_session()->Drag(item, start + gfx::Vector2dF(0, 80));
3720   overview_session()->CompleteDrag(item, start + gfx::Vector2dF(0, 80));
3721   ASSERT_TRUE(overview_session());
3722 
3723   // Verify that the second drag has enough vertical distance, so the widget
3724   // will be closed and overview mode will be exited.
3725   overview_session()->InitiateDrag(item, start, /*is_touch_dragging=*/true);
3726   overview_session()->Drag(item, start + gfx::Vector2dF(0, 180));
3727   overview_session()->CompleteDrag(item, start + gfx::Vector2dF(0, 180));
3728   base::RunLoop().RunUntilIdle();
3729   EXPECT_FALSE(overview_session());
3730   EXPECT_TRUE(widget->IsClosed());
3731 }
3732 
3733 // Verify that if the window item has been flung enough vertically, the window
3734 // will be closed.
TEST_P(TabletModeOverviewSessionTest,FlingToClose)3735 TEST_P(TabletModeOverviewSessionTest, FlingToClose) {
3736   // This test requires a widget.
3737   std::unique_ptr<views::Widget> widget(CreateTestWidget());
3738 
3739   ToggleOverview();
3740   ASSERT_TRUE(overview_controller()->InOverviewSession());
3741   EXPECT_EQ(1u, overview_session()->grid_list()[0]->size());
3742 
3743   OverviewItem* item = GetOverviewItemForWindow(widget->GetNativeWindow());
3744   const gfx::PointF start = item->target_bounds().CenterPoint();
3745   ASSERT_TRUE(item);
3746 
3747   // Verify that items flung horizontally do not close the item.
3748   overview_session()->InitiateDrag(item, start, /*is_touch_dragging=*/true);
3749   overview_session()->Drag(item, start + gfx::Vector2dF(0, 50));
3750   overview_session()->Fling(item, start, 2500, 0);
3751   ASSERT_TRUE(overview_session());
3752 
3753   // Verify that items flung vertically but without enough velocity do not
3754   // close the item.
3755   overview_session()->InitiateDrag(item, start, /*is_touch_dragging=*/true);
3756   overview_session()->Drag(item, start + gfx::Vector2dF(0, 50));
3757   overview_session()->Fling(item, start, 0, 1500);
3758   ASSERT_TRUE(overview_session());
3759 
3760   // Verify that flinging the item closes it, and since it is the last item in
3761   // overview mode, overview mode is exited.
3762   overview_session()->InitiateDrag(item, start, /*is_touch_dragging=*/true);
3763   overview_session()->Drag(item, start + gfx::Vector2dF(0, 50));
3764   overview_session()->Fling(item, start, 0, 2500);
3765   base::RunLoop().RunUntilIdle();
3766   EXPECT_FALSE(overview_session());
3767   EXPECT_TRUE(widget->IsClosed());
3768 }
3769 
3770 // Tests that nudging occurs in the most basic case, which is we have one row
3771 // and one item which is about to be deleted by dragging. If the item is deleted
3772 // we still only have one row, so the other items should nudge while the item is
3773 // being dragged.
TEST_P(TabletModeOverviewSessionTest,BasicNudging)3774 TEST_P(TabletModeOverviewSessionTest, BasicNudging) {
3775   // Set up three equal windows, which take up one row on the overview grid.
3776   // When one of them is deleted we are still left with all the windows on one
3777   // row.
3778   std::unique_ptr<aura::Window> window1 = CreateTestWindow();
3779   std::unique_ptr<aura::Window> window2 = CreateTestWindow();
3780   std::unique_ptr<aura::Window> window3 = CreateTestWindow();
3781 
3782   ToggleOverview();
3783   ASSERT_TRUE(overview_controller()->InOverviewSession());
3784 
3785   OverviewItem* item1 = GetOverviewItemForWindow(window1.get());
3786   OverviewItem* item2 = GetOverviewItemForWindow(window2.get());
3787   OverviewItem* item3 = GetOverviewItemForWindow(window3.get());
3788 
3789   const gfx::RectF item1_bounds = item1->target_bounds();
3790   const gfx::RectF item2_bounds = item2->target_bounds();
3791   const gfx::RectF item3_bounds = item3->target_bounds();
3792 
3793   // Drag |item1| vertically. |item2| and |item3| bounds should change as they
3794   // should be nudging towards their final bounds.
3795   overview_session()->InitiateDrag(item1, item1_bounds.CenterPoint(),
3796                                    /*is_touch_dragging=*/true);
3797   overview_session()->Drag(item1,
3798                            item1_bounds.CenterPoint() + gfx::Vector2dF(0, 160));
3799   EXPECT_NE(item2_bounds, item2->target_bounds());
3800   EXPECT_NE(item3_bounds, item3->target_bounds());
3801 
3802   // Drag |item1| back to its start drag location and release, so that it does
3803   // not get deleted.
3804   overview_session()->Drag(item1, item1_bounds.CenterPoint());
3805   overview_session()->CompleteDrag(item1, item1_bounds.CenterPoint());
3806 
3807   // Drag |item3| vertically. |item1| and |item2| bounds should change as they
3808   // should be nudging towards their final bounds.
3809   overview_session()->InitiateDrag(item3, item3_bounds.CenterPoint(),
3810                                    /*is_touch_dragging=*/true);
3811   overview_session()->Drag(item3,
3812                            item3_bounds.CenterPoint() + gfx::Vector2dF(0, 160));
3813   EXPECT_NE(item1_bounds, item1->target_bounds());
3814   EXPECT_NE(item2_bounds, item2->target_bounds());
3815 }
3816 
3817 // Tests that no nudging occurs when the number of rows in overview mode change
3818 // if the item to be deleted results in the overview grid to change number of
3819 // rows.
TEST_P(TabletModeOverviewSessionTest,NoNudgingWhenNumRowsChange)3820 TEST_P(TabletModeOverviewSessionTest, NoNudgingWhenNumRowsChange) {
3821   // Set up four equal windows, which would split into two rows in overview
3822   // mode. Removing one window would leave us with three windows, which only
3823   // takes a single row in overview.
3824   std::unique_ptr<aura::Window> window1 = CreateTestWindow();
3825   std::unique_ptr<aura::Window> window2 = CreateTestWindow();
3826   std::unique_ptr<aura::Window> window3 = CreateTestWindow();
3827   std::unique_ptr<aura::Window> window4 = CreateTestWindow();
3828 
3829   ToggleOverview();
3830   ASSERT_TRUE(overview_controller()->InOverviewSession());
3831 
3832   OverviewItem* item1 = GetOverviewItemForWindow(window1.get());
3833   OverviewItem* item2 = GetOverviewItemForWindow(window2.get());
3834   OverviewItem* item3 = GetOverviewItemForWindow(window3.get());
3835   OverviewItem* item4 = GetOverviewItemForWindow(window4.get());
3836 
3837   const gfx::RectF item1_bounds = item1->target_bounds();
3838   const gfx::RectF item2_bounds = item2->target_bounds();
3839   const gfx::RectF item3_bounds = item3->target_bounds();
3840   const gfx::RectF item4_bounds = item4->target_bounds();
3841 
3842   // Drag |item1| past the drag to swipe threshold. None of the other window
3843   // bounds should change, as none of them should be nudged.
3844   overview_session()->InitiateDrag(item1, item1_bounds.CenterPoint(),
3845                                    /*is_touch_dragging=*/true);
3846   overview_session()->Drag(item1,
3847                            item1_bounds.CenterPoint() + gfx::Vector2dF(0, 160));
3848   EXPECT_EQ(item2_bounds, item2->target_bounds());
3849   EXPECT_EQ(item3_bounds, item3->target_bounds());
3850   EXPECT_EQ(item4_bounds, item4->target_bounds());
3851 }
3852 
3853 // Tests that no nudging occurs when the item to be deleted results in an item
3854 // from the previous row to drop down to the current row, thus causing the items
3855 // to the right of the item to be shifted right, which is visually unacceptable.
TEST_P(TabletModeOverviewSessionTest,NoNudgingWhenLastItemOnPreviousRowDrops)3856 TEST_P(TabletModeOverviewSessionTest, NoNudgingWhenLastItemOnPreviousRowDrops) {
3857   // Set up five equal windows, which would split into two rows in overview
3858   // mode. Removing one window would cause the rows to rearrange, with the third
3859   // item dropping down from the first row to the second row. Create the windows
3860   // backward so the the window indexs match the order seen in overview, as
3861   // overview windows are ordered by MRU.
3862   const int kWindows = 5;
3863   std::unique_ptr<aura::Window> windows[kWindows];
3864   for (int i = kWindows - 1; i >= 0; --i)
3865     windows[i] = CreateTestWindow();
3866 
3867   ToggleOverview();
3868   ASSERT_TRUE(overview_controller()->InOverviewSession());
3869 
3870   OverviewItem* items[kWindows];
3871   gfx::RectF item_bounds[kWindows];
3872   for (int i = 0; i < kWindows; ++i) {
3873     items[i] = GetOverviewItemForWindow(windows[i].get());
3874     item_bounds[i] = items[i]->target_bounds();
3875   }
3876 
3877   // Drag the forth item past the drag to swipe threshold. None of the other
3878   // window bounds should change, as none of them should be nudged, because
3879   // deleting the fourth item will cause the third item to drop down from the
3880   // first row to the second.
3881   overview_session()->InitiateDrag(items[3], item_bounds[3].CenterPoint(),
3882                                    /*is_touch_dragging=*/true);
3883   overview_session()->Drag(
3884       items[3], item_bounds[3].CenterPoint() + gfx::Vector2dF(0, 160));
3885   EXPECT_EQ(item_bounds[0], items[0]->target_bounds());
3886   EXPECT_EQ(item_bounds[1], items[1]->target_bounds());
3887   EXPECT_EQ(item_bounds[2], items[2]->target_bounds());
3888   EXPECT_EQ(item_bounds[4], items[4]->target_bounds());
3889 
3890   // Drag the fourth item back to its start drag location and release, so that
3891   // it does not get deleted.
3892   overview_session()->Drag(items[3], item_bounds[3].CenterPoint());
3893   overview_session()->CompleteDrag(items[3], item_bounds[3].CenterPoint());
3894 
3895   // Drag the first item past the drag to swipe threshold. The second and third
3896   // items should nudge as expected as there is no item dropping down to their
3897   // row. The fourth and fifth items should not nudge as they are in a different
3898   // row than the first item.
3899   overview_session()->InitiateDrag(items[0], item_bounds[0].CenterPoint(),
3900                                    /*is_touch_dragging=*/true);
3901   overview_session()->Drag(
3902       items[0], item_bounds[0].CenterPoint() + gfx::Vector2dF(0, 160));
3903   EXPECT_NE(item_bounds[1], items[1]->target_bounds());
3904   EXPECT_NE(item_bounds[2], items[2]->target_bounds());
3905   EXPECT_EQ(item_bounds[3], items[3]->target_bounds());
3906   EXPECT_EQ(item_bounds[4], items[4]->target_bounds());
3907 }
3908 
3909 // Tests that there is no crash when destroying a window during a nudge drag.
3910 // Regression test for https://crbug.com/997335.
TEST_P(TabletModeOverviewSessionTest,DestroyWindowDuringNudge)3911 TEST_P(TabletModeOverviewSessionTest, DestroyWindowDuringNudge) {
3912   std::unique_ptr<aura::Window> window1 = CreateTestWindow();
3913   std::unique_ptr<aura::Window> window2 = CreateTestWindow();
3914   std::unique_ptr<aura::Window> window3 = CreateTestWindow();
3915 
3916   ToggleOverview();
3917   ASSERT_TRUE(overview_controller()->InOverviewSession());
3918 
3919   OverviewItem* item = GetOverviewItemForWindow(window1.get());
3920   const gfx::PointF item_center = item->target_bounds().CenterPoint();
3921 
3922   // Drag |item1| vertically to start nudging.
3923   overview_session()->InitiateDrag(item, item_center,
3924                                    /*is_touch_dragging=*/true);
3925   overview_session()->Drag(item, item_center + gfx::Vector2dF(0, 160));
3926 
3927   // Destroy |window2| and |window3|,then keep dragging. There should be no
3928   // crash.
3929   window2.reset();
3930   window3.reset();
3931   overview_session()->Drag(item, item_center + gfx::Vector2dF(0, 260));
3932 }
3933 
TEST_P(TabletModeOverviewSessionTest,MultiTouch)3934 TEST_P(TabletModeOverviewSessionTest, MultiTouch) {
3935   const gfx::Rect bounds(400, 400);
3936   std::unique_ptr<aura::Window> window1(CreateTestWindow(bounds));
3937   std::unique_ptr<aura::Window> window2(CreateTestWindow(bounds));
3938 
3939   ToggleOverview();
3940   ASSERT_TRUE(overview_controller()->InOverviewSession());
3941 
3942   // Dispatches a long press event to start drag mode.
3943   OverviewItem* item = GetOverviewItemForWindow(window1.get());
3944   DispatchLongPress(item);
3945   overview_session()->Drag(item, gfx::PointF(10.f, 500.f));
3946   const gfx::Rect item_bounds = item->GetWindow()->GetBoundsInScreen();
3947 
3948   // Tap on a point on the wallpaper. Normally this would exit overview, but not
3949   // while a drag is underway.
3950   GetEventGenerator()->set_current_screen_location(gfx::Point(10, 10));
3951   GetEventGenerator()->PressTouch();
3952   GetEventGenerator()->ReleaseTouch();
3953   ASSERT_TRUE(overview_controller()->InOverviewSession());
3954   EXPECT_EQ(item_bounds, item->GetWindow()->GetBoundsInScreen());
3955 
3956   // Long press on another item, the bounds of both items should be unchanged.
3957   OverviewItem* item2 = GetOverviewItemForWindow(window2.get());
3958   const gfx::Rect item2_bounds = item2->GetWindow()->GetBoundsInScreen();
3959   DispatchLongPress(item2);
3960   EXPECT_EQ(item_bounds, item->GetWindow()->GetBoundsInScreen());
3961   EXPECT_EQ(item2_bounds, item2->GetWindow()->GetBoundsInScreen());
3962 
3963   // Clicking on a point on the wallpaper should still exit overview.
3964   GetEventGenerator()->set_current_screen_location(gfx::Point(10, 10));
3965   GetEventGenerator()->ClickLeftButton();
3966   EXPECT_FALSE(overview_controller()->InOverviewSession());
3967 }
3968 
3969 // Tests that when exiting overview in a way that causes windows to minimize,
3970 // rounded corners are removed, otherwise they will be visible after
3971 // unminimizing. Regression test for https://crbug.com/1146240.
TEST_P(TabletModeOverviewSessionTest,MinimizedRoundedCorners)3972 TEST_P(TabletModeOverviewSessionTest, MinimizedRoundedCorners) {
3973   const gfx::Rect bounds(400, 400);
3974   std::unique_ptr<aura::Window> window(CreateTestWindow(bounds));
3975 
3976   // Enter overview. Spin the run loop since rounded corners are applied on a
3977   // post task.
3978   ToggleOverview();
3979   base::RunLoop().RunUntilIdle();
3980   ASSERT_TRUE(overview_controller()->InOverviewSession());
3981 
3982   // Tap on a point on the wallpaper to minimize the window and exit overview.
3983   GetEventGenerator()->set_current_screen_location(gfx::Point(10, 10));
3984   GetEventGenerator()->ClickLeftButton();
3985 
3986   // Tests that the window layer has rounded corners removed after exiting
3987   // overview.
3988   EXPECT_FALSE(overview_controller()->InOverviewSession());
3989   EXPECT_TRUE(WindowState::Get(window.get())->IsMinimized());
3990   EXPECT_EQ(gfx::RoundedCornersF(), window->layer()->rounded_corner_radii());
3991 }
3992 
3993 // Test the split view and overview functionalities in tablet mode.
3994 class SplitViewOverviewSessionTest : public OverviewSessionTest {
3995  public:
3996   SplitViewOverviewSessionTest() = default;
3997   ~SplitViewOverviewSessionTest() override = default;
3998 
3999   enum class SelectorItemLocation {
4000     CENTER,
4001     ORIGIN,
4002     TOP_RIGHT,
4003     BOTTOM_RIGHT,
4004     BOTTOM_LEFT,
4005   };
4006 
SetUp()4007   void SetUp() override {
4008     OverviewSessionTest::SetUp();
4009     EnterTabletMode();
4010   }
4011 
split_view_controller()4012   SplitViewController* split_view_controller() {
4013     return SplitViewController::Get(Shell::GetPrimaryRootWindow());
4014   }
4015 
IsDividerAnimating()4016   bool IsDividerAnimating() {
4017     return split_view_controller()->IsDividerAnimating();
4018   }
4019 
SkipDividerSnapAnimation()4020   void SkipDividerSnapAnimation() {
4021     if (!IsDividerAnimating())
4022       return;
4023     split_view_controller()->StopAndShoveAnimatedDivider();
4024     split_view_controller()->EndResizeImpl();
4025     split_view_controller()->EndTabletSplitViewAfterResizingIfAppropriate();
4026   }
4027 
EndSplitView()4028   void EndSplitView() { split_view_controller()->EndSplitView(); }
4029 
CheckWindowResizingPerformanceHistograms(const char * trace,int with_empty_overview_grid,int max_latency_with_empty_overview_grid,int with_nonempty_overview_grid,int max_latency_with_nonempty_overview_grid)4030   void CheckWindowResizingPerformanceHistograms(
4031       const char* trace,
4032       int with_empty_overview_grid,
4033       int max_latency_with_empty_overview_grid,
4034       int with_nonempty_overview_grid,
4035       int max_latency_with_nonempty_overview_grid) {
4036     CheckForDuplicateTraceName(trace);
4037     SCOPED_TRACE(trace);
4038 
4039     histograms_.ExpectTotalCount(
4040         "Ash.SplitViewResize.PresentationTime.ClamshellMode.SingleWindow",
4041         with_empty_overview_grid);
4042     histograms_.ExpectTotalCount(
4043         "Ash.SplitViewResize.PresentationTime.MaxLatency.ClamshellMode."
4044         "SingleWindow",
4045         max_latency_with_empty_overview_grid);
4046     histograms_.ExpectTotalCount(
4047         "Ash.SplitViewResize.PresentationTime.ClamshellMode.WithOverview",
4048         with_nonempty_overview_grid);
4049     histograms_.ExpectTotalCount(
4050         "Ash.SplitViewResize.PresentationTime.MaxLatency.ClamshellMode."
4051         "WithOverview",
4052         max_latency_with_nonempty_overview_grid);
4053   }
4054 
4055  protected:
CreateWindow(const gfx::Rect & bounds)4056   aura::Window* CreateWindow(const gfx::Rect& bounds) {
4057     aura::Window* window = CreateTestWindowInShellWithDelegate(
4058         new SplitViewTestWindowDelegate, -1, bounds);
4059     return window;
4060   }
4061 
CreateWindowWithMinimumSize(const gfx::Rect & bounds,const gfx::Size & size)4062   aura::Window* CreateWindowWithMinimumSize(const gfx::Rect& bounds,
4063                                             const gfx::Size& size) {
4064     SplitViewTestWindowDelegate* delegate = new SplitViewTestWindowDelegate();
4065     aura::Window* window =
4066         CreateTestWindowInShellWithDelegate(delegate, -1, bounds);
4067     delegate->set_minimum_size(size);
4068     return window;
4069   }
4070 
GetSplitViewLeftWindowBounds()4071   gfx::Rect GetSplitViewLeftWindowBounds() {
4072     return split_view_controller()->GetSnappedWindowBoundsInScreen(
4073         SplitViewController::LEFT, split_view_controller()->left_window());
4074   }
4075 
GetSplitViewRightWindowBounds()4076   gfx::Rect GetSplitViewRightWindowBounds() {
4077     return split_view_controller()->GetSnappedWindowBoundsInScreen(
4078         SplitViewController::RIGHT, split_view_controller()->right_window());
4079   }
4080 
GetSplitViewDividerBounds(bool is_dragging)4081   gfx::Rect GetSplitViewDividerBounds(bool is_dragging) {
4082     if (!split_view_controller()->InSplitViewMode())
4083       return gfx::Rect();
4084     return split_view_controller()
4085         ->split_view_divider_->GetDividerBoundsInScreen(is_dragging);
4086   }
4087 
GetWorkAreaInScreen(aura::Window * window)4088   gfx::Rect GetWorkAreaInScreen(aura::Window* window) {
4089     return screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
4090         window);
4091   }
4092 
4093   // Drags a overview item |item| from its center or one of its corners
4094   // to |end_location|. This should be used over
4095   // DragWindowTo(OverviewItem*, gfx::Point) when testing snapping a
4096   // window, but the windows centerpoint may be inside a snap region, thus the
4097   // window will not snapped. This function is mostly used to test splitview so
4098   // |long_press| is default to true. Set |long_press| to false if we do not
4099   // want to long press after every press, which enables dragging vertically to
4100   // close an item.
DragWindowTo(OverviewItem * item,const gfx::PointF & end_location,SelectorItemLocation location,bool long_press=true)4101   void DragWindowTo(OverviewItem* item,
4102                     const gfx::PointF& end_location,
4103                     SelectorItemLocation location,
4104                     bool long_press = true) {
4105     gfx::PointF start_location;
4106     switch (location) {
4107       case SelectorItemLocation::CENTER:
4108         start_location = item->target_bounds().CenterPoint();
4109         break;
4110       case SelectorItemLocation::ORIGIN:
4111         start_location = item->target_bounds().origin();
4112         break;
4113       case SelectorItemLocation::TOP_RIGHT:
4114         start_location = item->target_bounds().top_right();
4115         break;
4116       case SelectorItemLocation::BOTTOM_RIGHT:
4117         start_location = item->target_bounds().bottom_right();
4118         break;
4119       case SelectorItemLocation::BOTTOM_LEFT:
4120         start_location = item->target_bounds().bottom_left();
4121         break;
4122       default:
4123         NOTREACHED();
4124         break;
4125     }
4126     overview_session()->InitiateDrag(item, start_location,
4127                                      /*is_touch_dragging=*/true);
4128     if (long_press)
4129       overview_session()->StartNormalDragMode(start_location);
4130     overview_session()->Drag(item, end_location);
4131     overview_session()->CompleteDrag(item, end_location);
4132   }
4133 
4134   // Drags a overview item |item| from its center point to |end_location|.
DragWindowTo(OverviewItem * item,const gfx::PointF & end_location)4135   void DragWindowTo(OverviewItem* item, const gfx::PointF& end_location) {
4136     DragWindowTo(item, end_location, SelectorItemLocation::CENTER, true);
4137   }
4138 
4139  private:
4140   class SplitViewTestWindowDelegate : public aura::test::TestWindowDelegate {
4141    public:
4142     SplitViewTestWindowDelegate() = default;
4143     ~SplitViewTestWindowDelegate() override = default;
4144 
4145     // aura::test::TestWindowDelegate:
OnWindowDestroying(aura::Window * window)4146     void OnWindowDestroying(aura::Window* window) override { window->Hide(); }
OnWindowDestroyed(aura::Window * window)4147     void OnWindowDestroyed(aura::Window* window) override { delete this; }
4148   };
4149 
4150   DISALLOW_COPY_AND_ASSIGN(SplitViewOverviewSessionTest);
4151 };
4152 
4153 // Tests that dragging an overview item to the edge of the screen snaps the
4154 // window. If two windows are snapped to left and right side of the screen, exit
4155 // the overview mode.
TEST_P(SplitViewOverviewSessionTest,DragOverviewWindowToSnap)4156 TEST_P(SplitViewOverviewSessionTest, DragOverviewWindowToSnap) {
4157   const gfx::Rect bounds(400, 400);
4158   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
4159   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
4160   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
4161 
4162   ToggleOverview();
4163   EXPECT_TRUE(overview_controller()->InOverviewSession());
4164   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
4165 
4166   // Drag |window1| selector item to snap to left.
4167   OverviewItem* overview_item1 = GetOverviewItemForWindow(window1.get());
4168   DragWindowTo(overview_item1, gfx::PointF(0, 0));
4169 
4170   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
4171   EXPECT_EQ(split_view_controller()->state(),
4172             SplitViewController::State::kLeftSnapped);
4173   EXPECT_EQ(split_view_controller()->left_window(), window1.get());
4174 
4175   // Drag |window2| selector item to attempt to snap to left. Since there is
4176   // already one left snapped window |window1|, |window1| will be put in
4177   // overview mode.
4178   OverviewItem* overview_item2 = GetOverviewItemForWindow(window2.get());
4179   DragWindowTo(overview_item2, gfx::PointF(0, 0));
4180 
4181   EXPECT_EQ(split_view_controller()->state(),
4182             SplitViewController::State::kLeftSnapped);
4183   EXPECT_EQ(split_view_controller()->left_window(), window2.get());
4184   EXPECT_TRUE(overview_controller()->overview_session()->IsWindowInOverview(
4185       window1.get()));
4186 
4187   // Drag |window3| selector item to snap to right.
4188   OverviewItem* overview_item3 = GetOverviewItemForWindow(window3.get());
4189   const gfx::PointF end_location3(GetWorkAreaInScreen(window3.get()).width(),
4190                                   0.f);
4191   DragWindowTo(overview_item3, end_location3);
4192 
4193   EXPECT_EQ(split_view_controller()->state(),
4194             SplitViewController::State::kBothSnapped);
4195   EXPECT_EQ(split_view_controller()->right_window(), window3.get());
4196   EXPECT_FALSE(overview_controller()->InOverviewSession());
4197 }
4198 
4199 // Verify the correct behavior when dragging windows in overview mode.
TEST_P(SplitViewOverviewSessionTest,OverviewDragControllerBehavior)4200 TEST_P(SplitViewOverviewSessionTest, OverviewDragControllerBehavior) {
4201   ui::GestureConfiguration* gesture_config =
4202       ui::GestureConfiguration::GetInstance();
4203   gesture_config->set_long_press_time_in_ms(1);
4204   gesture_config->set_show_press_delay_in_ms(1);
4205 
4206   std::unique_ptr<aura::Window> window1 = CreateTestWindow();
4207   std::unique_ptr<aura::Window> window2 = CreateTestWindow();
4208 
4209   ToggleOverview();
4210   ASSERT_TRUE(overview_controller()->InOverviewSession());
4211 
4212   OverviewItem* window_item1 = GetOverviewItemForWindow(window1.get());
4213   OverviewItem* window_item2 = GetOverviewItemForWindow(window2.get());
4214 
4215   // Verify that if a drag is orginally horizontal, the drag behavior is drag to
4216   // snap.
4217   using DragBehavior = OverviewWindowDragController::DragBehavior;
4218   ui::test::EventGenerator* generator = GetEventGenerator();
4219   generator->set_current_screen_location(
4220       gfx::ToRoundedPoint(window_item1->target_bounds().CenterPoint()));
4221   generator->PressTouch();
4222 
4223   // Simulate a long press, which is required to snap windows.
4224   base::RunLoop run_loop;
4225   base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
4226       FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromMilliseconds(2));
4227   run_loop.Run();
4228 
4229   OverviewWindowDragController* drag_controller =
4230       overview_session()->window_drag_controller();
4231   ASSERT_TRUE(drag_controller);
4232   EXPECT_EQ(DragBehavior::kNormalDrag,
4233             drag_controller->current_drag_behavior());
4234   generator->MoveTouchBy(20, 0);
4235   EXPECT_EQ(DragBehavior::kNormalDrag,
4236             drag_controller->current_drag_behavior());
4237   generator->ReleaseTouch();
4238   EXPECT_EQ(DragBehavior::kNoDrag, drag_controller->current_drag_behavior());
4239 
4240   // Verify that if a drag is orginally vertical, the drag behavior is drag to
4241   // close.
4242   generator->set_current_screen_location(
4243       gfx::ToRoundedPoint(window_item2->target_bounds().CenterPoint()));
4244   generator->PressTouch();
4245 
4246   // Use small increments otherwise a fling event will be fired.
4247   for (int j = 0; j < 20; ++j)
4248     generator->MoveTouchBy(0, 1);
4249 
4250   // A new instance of drag controller gets created each time a drag starts.
4251   drag_controller = overview_session()->window_drag_controller();
4252   EXPECT_EQ(DragBehavior::kDragToClose,
4253             drag_controller->current_drag_behavior());
4254 }
4255 
4256 // Verify the window grid size changes as expected when dragging items around in
4257 // overview mode when split view is enabled.
TEST_P(SplitViewOverviewSessionTest,OverviewGridSizeWhileDraggingWithSplitView)4258 TEST_P(SplitViewOverviewSessionTest,
4259        OverviewGridSizeWhileDraggingWithSplitView) {
4260   // Add three windows and enter overview mode.
4261   std::unique_ptr<aura::Window> window1(CreateTestWindow());
4262   std::unique_ptr<aura::Window> window2(CreateTestWindow());
4263   std::unique_ptr<aura::Window> window3(CreateTestWindow());
4264 
4265   ToggleOverview();
4266   ASSERT_TRUE(overview_controller()->InOverviewSession());
4267 
4268   // Select window one and start the drag.
4269   const int window_width =
4270       Shell::Get()->GetPrimaryRootWindow()->GetBoundsInScreen().width();
4271   OverviewItem* overview_item = GetOverviewItemForWindow(window1.get());
4272   gfx::RectF overview_item_bounds = overview_item->target_bounds();
4273   gfx::PointF start_location(overview_item_bounds.CenterPoint());
4274   overview_session()->InitiateDrag(overview_item, start_location,
4275                                    /*is_touch_dragging=*/false);
4276 
4277   // Verify that when dragged to the left, the window grid is located where the
4278   // right window of split view mode should be.
4279   const gfx::PointF left(0, 0);
4280   overview_session()->Drag(overview_item, left);
4281   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
4282   EXPECT_EQ(SplitViewController::State::kNoSnap,
4283             split_view_controller()->state());
4284   EXPECT_TRUE(split_view_controller()->left_window() == nullptr);
4285   EXPECT_EQ(ShrinkBoundsByHotseatInset(GetSplitViewRightWindowBounds()),
4286             GetGridBounds());
4287 
4288   // Verify that when dragged to the right, the window grid is located where the
4289   // left window of split view mode should be.
4290   const gfx::PointF right(window_width, 0);
4291   overview_session()->Drag(overview_item, right);
4292   EXPECT_EQ(SplitViewController::State::kNoSnap,
4293             split_view_controller()->state());
4294   EXPECT_TRUE(split_view_controller()->right_window() == nullptr);
4295   EXPECT_EQ(ShrinkBoundsByHotseatInset(GetSplitViewLeftWindowBounds()),
4296             GetGridBounds());
4297 
4298   // Verify that when dragged to the center, the window grid is has the
4299   // dimensions of the work area.
4300   const gfx::PointF center(window_width / 2, 0);
4301   overview_session()->Drag(overview_item, center);
4302   EXPECT_EQ(SplitViewController::State::kNoSnap,
4303             split_view_controller()->state());
4304   EXPECT_EQ(ShrinkBoundsByHotseatInset(GetWorkAreaInScreen(window1.get())),
4305             GetGridBounds());
4306 
4307   // Snap window1 to the left and initialize dragging for window2.
4308   overview_session()->Drag(overview_item, left);
4309   overview_session()->CompleteDrag(overview_item, left);
4310   ASSERT_EQ(SplitViewController::State::kLeftSnapped,
4311             split_view_controller()->state());
4312   ASSERT_EQ(window1.get(), split_view_controller()->left_window());
4313   overview_item = GetOverviewItemForWindow(window2.get());
4314   overview_item_bounds = overview_item->target_bounds();
4315   start_location = overview_item_bounds.CenterPoint();
4316   overview_session()->InitiateDrag(overview_item, start_location,
4317                                    /*is_touch_dragging=*/false);
4318 
4319   // Verify that when there is a snapped window, the window grid bounds remain
4320   // constant despite overview items being dragged left and right.
4321   overview_session()->Drag(overview_item, left);
4322   EXPECT_EQ(GetSplitViewRightWindowBounds(), GetGridBounds());
4323   overview_session()->Drag(overview_item, right);
4324   EXPECT_EQ(GetSplitViewRightWindowBounds(), GetGridBounds());
4325   overview_session()->Drag(overview_item, center);
4326   EXPECT_EQ(GetSplitViewRightWindowBounds(), GetGridBounds());
4327 }
4328 
4329 // Tests dragging a unsnappable window.
TEST_P(SplitViewOverviewSessionTest,DraggingUnsnappableAppWithSplitView)4330 TEST_P(SplitViewOverviewSessionTest, DraggingUnsnappableAppWithSplitView) {
4331   std::unique_ptr<aura::Window> unsnappable_window = CreateUnsnappableWindow();
4332 
4333   // The grid bounds should be the size of the root window minus the shelf.
4334   const gfx::Rect root_window_bounds =
4335       Shell::Get()->GetPrimaryRootWindow()->GetBoundsInScreen();
4336   const gfx::Rect shelf_bounds =
4337       Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow())->GetIdealBounds();
4338   const gfx::Rect expected_grid_bounds = ShrinkBoundsByHotseatInset(
4339       SubtractRects(root_window_bounds, shelf_bounds));
4340 
4341   ToggleOverview();
4342   ASSERT_TRUE(overview_controller()->InOverviewSession());
4343 
4344   // Verify that after dragging the unsnappable window to the left and right,
4345   // the window grid bounds do not change.
4346   OverviewItem* overview_item =
4347       GetOverviewItemForWindow(unsnappable_window.get());
4348   overview_session()->InitiateDrag(overview_item,
4349                                    overview_item->target_bounds().CenterPoint(),
4350                                    /*is_touch_dragging=*/false);
4351   overview_session()->Drag(overview_item, gfx::PointF());
4352   EXPECT_EQ(expected_grid_bounds, GetGridBounds());
4353   overview_session()->Drag(overview_item,
4354                            gfx::PointF(root_window_bounds.right(), 0.f));
4355   EXPECT_EQ(expected_grid_bounds, GetGridBounds());
4356   overview_session()->Drag(overview_item,
4357                            gfx::PointF(root_window_bounds.right() / 2.f, 0.f));
4358   EXPECT_EQ(expected_grid_bounds, GetGridBounds());
4359 }
4360 
4361 // Test that if an unsnappable window is dragged from overview to where another
4362 // window is already snapped, then there is no snap preview, and if the drag
4363 // ends there, then there is no DCHECK failure (or crash).
TEST_P(SplitViewOverviewSessionTest,DragUnsnappableWindowFromOverviewToSnappedWindow)4364 TEST_P(SplitViewOverviewSessionTest,
4365        DragUnsnappableWindowFromOverviewToSnappedWindow) {
4366   std::unique_ptr<aura::Window> snapped_window = CreateTestWindow();
4367   std::unique_ptr<aura::Window> unsnappable_window = CreateUnsnappableWindow();
4368   ToggleOverview();
4369   split_view_controller()->SnapWindow(snapped_window.get(),
4370                                       SplitViewController::LEFT);
4371   ASSERT_EQ(1u, overview_session()->grid_list().size());
4372   OverviewGrid* overview_grid = overview_session()->grid_list()[0].get();
4373   OverviewItem* overview_item =
4374       overview_grid->GetOverviewItemContaining(unsnappable_window.get());
4375   overview_session()->InitiateDrag(overview_item,
4376                                    overview_item->target_bounds().CenterPoint(),
4377                                    /*is_touch_dragging=*/false);
4378   overview_session()->Drag(overview_item, gfx::PointF());
4379   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kFromOverview,
4380             overview_grid->split_view_drag_indicators()
4381                 ->current_window_dragging_state());
4382   overview_session()->CompleteDrag(overview_item, gfx::PointF());
4383 }
4384 
TEST_P(SplitViewOverviewSessionTest,Clipping)4385 TEST_P(SplitViewOverviewSessionTest, Clipping) {
4386   // Helper to check if two rectangles have roughly the same aspect ratio. They
4387   // may be off by a bit due to insets but should have roughly the same shape.
4388   auto aspect_ratio_near = [](const gfx::Rect& rect1, const gfx::Rect& rect2) {
4389     DCHECK_GT(rect1.height(), 0);
4390     DCHECK_GT(rect2.height(), 0);
4391     constexpr float kEpsilon = 0.05f;
4392     const float rect1_aspect_ratio =
4393         float{rect1.width()} / float{rect1.height()};
4394     const float rect2_aspect_ratio =
4395         float{rect2.width()} / float{rect2.height()};
4396     return std::abs(rect2_aspect_ratio - rect1_aspect_ratio) < kEpsilon;
4397   };
4398 
4399   std::unique_ptr<aura::Window> window1 = CreateTestWindow();
4400   std::unique_ptr<aura::Window> window2 = CreateTestWindow();
4401   std::unique_ptr<aura::Window> window3 = CreateTestWindow();  // Minimized.
4402   std::unique_ptr<aura::Window> window4 = CreateTestWindow();  // Has top inset.
4403   WindowState::Get(window3.get())->Minimize();
4404   window4->SetProperty(aura::client::kTopViewInset, 32);
4405 
4406   for (bool portrait : {false, true}) {
4407     SCOPED_TRACE(portrait ? "Portrait" : "Landscape");
4408     if (portrait) {
4409       ScreenOrientationControllerTestApi test_api(
4410           Shell::Get()->screen_orientation_controller());
4411       test_api.SetDisplayRotation(display::Display::ROTATE_90,
4412                                   display::Display::RotationSource::ACTIVE);
4413     }
4414 
4415     const gfx::Rect clipping1 = window1->layer()->clip_rect();
4416     const gfx::Rect clipping2 = window2->layer()->clip_rect();
4417     const gfx::Rect clipping3 = window3->layer()->clip_rect();
4418     const gfx::Rect clipping4 = window4->layer()->clip_rect();
4419     const gfx::Rect maximized_bounds =
4420         screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
4421             window1.get());
4422     const gfx::Rect split_view_bounds_right =
4423         split_view_controller()->GetSnappedWindowBoundsInScreen(
4424             SplitViewController::SnapPosition::RIGHT,
4425             /*window_for_minimum_size=*/nullptr);
4426 
4427     ToggleOverview();
4428 
4429     // Tests that after entering overview, windows with no top inset and
4430     // minimized windows still have no clip.
4431     ASSERT_TRUE(overview_controller()->InOverviewSession());
4432     EXPECT_EQ(clipping1, window1->layer()->clip_rect());
4433     EXPECT_EQ(clipping2, window2->layer()->clip_rect());
4434     EXPECT_EQ(clipping3, window3->layer()->clip_rect());
4435     EXPECT_NE(clipping4, window4->layer()->clip_rect());
4436     const gfx::Rect overview_clipping4 = window4->layer()->clip_rect();
4437 
4438     OverviewItem* item1 = GetOverviewItemForWindow(window1.get());
4439     OverviewItem* item2 = GetOverviewItemForWindow(window2.get());
4440     OverviewItem* item3 = GetOverviewItemForWindow(window3.get());
4441     OverviewItem* item4 = GetOverviewItemForWindow(window4.get());
4442     overview_session()->InitiateDrag(item1,
4443                                      item1->target_bounds().CenterPoint(),
4444                                      /*is_touch_dragging=*/false);
4445 
4446     // Tests that after we drag to a preview area, the items target bounds have
4447     // a matching aspect ratio to what the window would have if it were to be
4448     // snapped in splitview. The window clipping should match this, but the
4449     // windows regular bounds remain unchanged (maximized).
4450     overview_session()->Drag(item1, gfx::PointF());
4451     EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapLeft,
4452               overview_session()
4453                   ->grid_list()[0]
4454                   ->split_view_drag_indicators()
4455                   ->current_window_dragging_state());
4456     EXPECT_FALSE(window2->layer()->clip_rect().IsEmpty());
4457     EXPECT_TRUE(aspect_ratio_near(window2->layer()->clip_rect(),
4458                                   split_view_bounds_right));
4459     EXPECT_TRUE(aspect_ratio_near(
4460         gfx::ToEnclosedRect(item2->GetWindowTargetBoundsWithInsets()),
4461         split_view_bounds_right));
4462     EXPECT_TRUE(
4463         aspect_ratio_near(window2->GetBoundsInScreen(), maximized_bounds));
4464 
4465     // The actual window of a minimized window should not be clipped. The
4466     // clipped layer will be the WindowPreviewView of the associated
4467     // OverviewItemView.
4468     EXPECT_TRUE(window3->layer()->clip_rect().IsEmpty());
4469     ui::Layer* preview_layer =
4470         item3->overview_item_view()->preview_view()->layer();
4471     EXPECT_FALSE(preview_layer->clip_rect().IsEmpty());
4472     EXPECT_FALSE(preview_layer->transform().IsIdentity());
4473     // The clip rect is affected by |preview_layer|'s transform so apply it.
4474     gfx::RectF clip_rect3_f(preview_layer->clip_rect());
4475     preview_layer->transform().TransformRect(&clip_rect3_f);
4476     const gfx::Rect clip_rects3 = gfx::ToEnclosedRect(clip_rect3_f);
4477     EXPECT_TRUE(aspect_ratio_near(clip_rects3, split_view_bounds_right));
4478     EXPECT_TRUE(aspect_ratio_near(
4479         gfx::ToEnclosedRect(item3->GetWindowTargetBoundsWithInsets()),
4480         split_view_bounds_right));
4481     EXPECT_TRUE(
4482         aspect_ratio_near(window3->GetBoundsInScreen(), maximized_bounds));
4483 
4484     // A window with top view inset should be clipped, but with a new clipping
4485     // than the original overview clipping.
4486     EXPECT_FALSE(window4->layer()->clip_rect().IsEmpty());
4487     EXPECT_NE(overview_clipping4, window4->layer()->clip_rect());
4488     EXPECT_TRUE(aspect_ratio_near(window4->layer()->clip_rect(),
4489                                   split_view_bounds_right));
4490     EXPECT_TRUE(aspect_ratio_near(
4491         gfx::ToEnclosedRect(item4->GetWindowTargetBoundsWithInsets()),
4492         split_view_bounds_right));
4493     EXPECT_TRUE(
4494         aspect_ratio_near(window4->GetBoundsInScreen(), maximized_bounds));
4495 
4496     // Tests that after snapping, the aspect ratios should be the same as being
4497     // in the preview area.
4498     overview_session()->CompleteDrag(item1, gfx::PointF());
4499     ASSERT_EQ(SplitViewController::State::kLeftSnapped,
4500               split_view_controller()->state());
4501     EXPECT_FALSE(window2->layer()->clip_rect().IsEmpty());
4502     EXPECT_TRUE(aspect_ratio_near(window2->layer()->clip_rect(),
4503                                   split_view_bounds_right));
4504     EXPECT_TRUE(aspect_ratio_near(
4505         gfx::ToEnclosedRect(item2->GetWindowTargetBoundsWithInsets()),
4506         split_view_bounds_right));
4507     EXPECT_TRUE(
4508         aspect_ratio_near(window2->GetBoundsInScreen(), maximized_bounds));
4509 
4510     EXPECT_TRUE(window3->layer()->clip_rect().IsEmpty());
4511     EXPECT_TRUE(aspect_ratio_near(clip_rects3, split_view_bounds_right));
4512     EXPECT_TRUE(aspect_ratio_near(
4513         gfx::ToEnclosedRect(item3->GetWindowTargetBoundsWithInsets()),
4514         split_view_bounds_right));
4515     EXPECT_TRUE(
4516         aspect_ratio_near(window3->GetBoundsInScreen(), maximized_bounds));
4517 
4518     EXPECT_FALSE(window4->layer()->clip_rect().IsEmpty());
4519     EXPECT_NE(overview_clipping4, window4->layer()->clip_rect());
4520     EXPECT_TRUE(aspect_ratio_near(window4->layer()->clip_rect(),
4521                                   split_view_bounds_right));
4522     EXPECT_TRUE(aspect_ratio_near(
4523         gfx::ToEnclosedRect(item4->GetWindowTargetBoundsWithInsets()),
4524         split_view_bounds_right));
4525     EXPECT_TRUE(
4526         aspect_ratio_near(window4->GetBoundsInScreen(), maximized_bounds));
4527 
4528     // Tests that the clipping is reset after exiting overview.
4529     EndSplitView();
4530     ToggleOverview();
4531     EXPECT_EQ(clipping1, window1->layer()->clip_rect());
4532     EXPECT_EQ(clipping2, window2->layer()->clip_rect());
4533     EXPECT_EQ(clipping3, window3->layer()->clip_rect());
4534     EXPECT_EQ(clipping4, window4->layer()->clip_rect());
4535   }
4536 }
4537 
4538 // Tests that when splitview is inactive, there is no need for aspect ratio
4539 // changes, so there is no clipping on the overview windows. Regression test for
4540 // crbug.com/1020440.
TEST_P(SplitViewOverviewSessionTest,NoClippingWhenSplitviewDisabled)4541 TEST_P(SplitViewOverviewSessionTest, NoClippingWhenSplitviewDisabled) {
4542   std::unique_ptr<aura::Window> window1 = CreateTestWindow();
4543   std::unique_ptr<aura::Window> window2 = CreateTestWindow();
4544 
4545   // Splitview is disabled when chromeVox is enabled.
4546   Shell::Get()->accessibility_controller()->SetSpokenFeedbackEnabled(
4547       true, A11Y_NOTIFICATION_NONE);
4548   ASSERT_FALSE(ShouldAllowSplitView());
4549   const gfx::Rect clipping1 = window1->layer()->clip_rect();
4550   const gfx::Rect clipping2 = window2->layer()->clip_rect();
4551 
4552   ToggleOverview();
4553   ASSERT_TRUE(overview_controller()->InOverviewSession());
4554   EXPECT_EQ(clipping1, window1->layer()->clip_rect());
4555   EXPECT_EQ(clipping2, window2->layer()->clip_rect());
4556 
4557   // Drag to the edge of the screen. There should be no clipping and no crash.
4558   OverviewItem* item1 = GetOverviewItemForWindow(window1.get());
4559   overview_session()->InitiateDrag(item1, item1->target_bounds().CenterPoint(),
4560                                    /*is_touch_dragging=*/false);
4561   overview_session()->Drag(item1, gfx::PointF());
4562   EXPECT_EQ(clipping1, window1->layer()->clip_rect());
4563   EXPECT_EQ(clipping2, window2->layer()->clip_rect());
4564 }
4565 
4566 // Tests that if there is only one window in the MRU window list in the overview
4567 // mode, snapping the window to one side of the screen will not end the overview
4568 // mode even if there is no more window left in the overview window grid.
TEST_P(SplitViewOverviewSessionTest,EmptyWindowsListNotExitOverview)4569 TEST_P(SplitViewOverviewSessionTest, EmptyWindowsListNotExitOverview) {
4570   const gfx::Rect bounds(400, 400);
4571   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
4572 
4573   ToggleOverview();
4574   EXPECT_TRUE(overview_controller()->InOverviewSession());
4575 
4576   // Drag |window1| selector item to snap to left.
4577   OverviewItem* overview_item1 = GetOverviewItemForWindow(window1.get());
4578   DragWindowTo(overview_item1, gfx::PointF());
4579 
4580   // Test that overview mode is active in this single window case.
4581   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
4582   EXPECT_EQ(split_view_controller()->state(),
4583             SplitViewController::State::kLeftSnapped);
4584   EXPECT_TRUE(overview_controller()->InOverviewSession());
4585 
4586   // Create a new window should exit the overview mode.
4587   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
4588   wm::ActivateWindow(window2.get());
4589   EXPECT_FALSE(overview_controller()->InOverviewSession());
4590   EXPECT_EQ(split_view_controller()->state(),
4591             SplitViewController::State::kBothSnapped);
4592   // If there are only 2 snapped windows, close one of them should enter
4593   // overview mode.
4594   window2.reset();
4595   EXPECT_TRUE(overview_controller()->InOverviewSession());
4596 
4597   // If there are more than 2 windows in overview
4598   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
4599   std::unique_ptr<aura::Window> window4(CreateWindow(bounds));
4600   wm::ActivateWindow(window3.get());
4601   wm::ActivateWindow(window4.get());
4602   EXPECT_FALSE(overview_controller()->InOverviewSession());
4603   EXPECT_EQ(split_view_controller()->state(),
4604             SplitViewController::State::kBothSnapped);
4605   ToggleOverview();
4606   EXPECT_TRUE(overview_controller()->InOverviewSession());
4607   window3.reset();
4608   EXPECT_TRUE(overview_controller()->InOverviewSession());
4609   window4.reset();
4610   EXPECT_TRUE(overview_controller()->InOverviewSession());
4611 
4612   // Test that if there is only 1 snapped window, and no window in the overview
4613   // grid, ToggleOverview() can't end overview.
4614   ToggleOverview();
4615   EXPECT_TRUE(overview_controller()->InOverviewSession());
4616 
4617   EndSplitView();
4618   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
4619   EXPECT_TRUE(overview_controller()->InOverviewSession());
4620 
4621   // Test that ToggleOverview() can end overview if we're not in split view
4622   // mode.
4623   ToggleOverview();
4624   EXPECT_FALSE(overview_controller()->InOverviewSession());
4625 
4626   // Now enter overview and split view again. Test that exiting tablet mode can
4627   // end split view and overview correctly.
4628   ToggleOverview();
4629   overview_item1 = GetOverviewItemForWindow(window1.get());
4630   DragWindowTo(overview_item1, gfx::PointF());
4631   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
4632   EXPECT_TRUE(overview_controller()->InOverviewSession());
4633   Shell::Get()->tablet_mode_controller()->SetEnabledForTest(false);
4634   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
4635   EXPECT_FALSE(overview_controller()->InOverviewSession());
4636 
4637   // Test that closing all windows in overview can end overview if we're not in
4638   // split view mode.
4639   ToggleOverview();
4640   EXPECT_TRUE(overview_controller()->InOverviewSession());
4641   window1.reset();
4642   EXPECT_FALSE(overview_controller()->InOverviewSession());
4643 }
4644 
4645 // Tests using Alt+[ on a maximized window.
TEST_P(SplitViewOverviewSessionTest,AltLeftSquareBracketOnMaximizedWindow)4646 TEST_P(SplitViewOverviewSessionTest, AltLeftSquareBracketOnMaximizedWindow) {
4647   std::unique_ptr<aura::Window> snapped_window = CreateTestWindow();
4648   std::unique_ptr<aura::Window> overview_window = CreateTestWindow();
4649   wm::ActivateWindow(snapped_window.get());
4650   WindowState* snapped_window_state = WindowState::Get(snapped_window.get());
4651   EXPECT_EQ(WindowStateType::kMaximized, snapped_window_state->GetStateType());
4652   EXPECT_EQ(SplitViewController::State::kNoSnap,
4653             split_view_controller()->state());
4654   EXPECT_FALSE(InOverviewSession());
4655   const WMEvent alt_left_square_bracket(WM_EVENT_CYCLE_SNAP_LEFT);
4656   snapped_window_state->OnWMEvent(&alt_left_square_bracket);
4657   EXPECT_TRUE(wm::IsActiveWindow(snapped_window.get()));
4658   EXPECT_EQ(WindowStateType::kLeftSnapped,
4659             snapped_window_state->GetStateType());
4660   EXPECT_EQ(SplitViewController::State::kLeftSnapped,
4661             split_view_controller()->state());
4662   EXPECT_EQ(snapped_window.get(), split_view_controller()->left_window());
4663   EXPECT_TRUE(InOverviewSession());
4664 }
4665 
4666 // Tests using Alt+] on a maximized window.
TEST_P(SplitViewOverviewSessionTest,AltRightSquareBracketOnMaximizedWindow)4667 TEST_P(SplitViewOverviewSessionTest, AltRightSquareBracketOnMaximizedWindow) {
4668   std::unique_ptr<aura::Window> snapped_window = CreateTestWindow();
4669   std::unique_ptr<aura::Window> overview_window = CreateTestWindow();
4670   wm::ActivateWindow(snapped_window.get());
4671   WindowState* snapped_window_state = WindowState::Get(snapped_window.get());
4672   EXPECT_EQ(WindowStateType::kMaximized, snapped_window_state->GetStateType());
4673   EXPECT_EQ(SplitViewController::State::kNoSnap,
4674             split_view_controller()->state());
4675   EXPECT_FALSE(InOverviewSession());
4676   const WMEvent alt_right_square_bracket(WM_EVENT_CYCLE_SNAP_RIGHT);
4677   snapped_window_state->OnWMEvent(&alt_right_square_bracket);
4678   EXPECT_TRUE(wm::IsActiveWindow(snapped_window.get()));
4679   EXPECT_EQ(WindowStateType::kRightSnapped,
4680             snapped_window_state->GetStateType());
4681   EXPECT_EQ(SplitViewController::State::kRightSnapped,
4682             split_view_controller()->state());
4683   EXPECT_EQ(snapped_window.get(), split_view_controller()->right_window());
4684   EXPECT_TRUE(InOverviewSession());
4685 }
4686 
4687 // Tests using Alt+[ and Alt+] on an unsnappable window.
TEST_P(SplitViewOverviewSessionTest,AltSquareBracketOnUnsnappableWindow)4688 TEST_P(SplitViewOverviewSessionTest, AltSquareBracketOnUnsnappableWindow) {
4689   std::unique_ptr<aura::Window> unsnappable_window = CreateUnsnappableWindow();
4690   std::unique_ptr<aura::Window> other_window = CreateTestWindow();
4691   wm::ActivateWindow(unsnappable_window.get());
4692   WindowState* unsnappable_window_state =
4693       WindowState::Get(unsnappable_window.get());
4694   const auto expect_unsnappable_window_is_active_and_maximized =
4695       [this, &unsnappable_window, unsnappable_window_state]() {
4696         EXPECT_TRUE(wm::IsActiveWindow(unsnappable_window.get()));
4697         EXPECT_EQ(WindowStateType::kMaximized,
4698                   unsnappable_window_state->GetStateType());
4699         EXPECT_FALSE(split_view_controller()->InSplitViewMode());
4700         EXPECT_FALSE(InOverviewSession());
4701       };
4702   expect_unsnappable_window_is_active_and_maximized();
4703   const WMEvent alt_left_square_bracket(WM_EVENT_CYCLE_SNAP_LEFT);
4704   unsnappable_window_state->OnWMEvent(&alt_left_square_bracket);
4705   expect_unsnappable_window_is_active_and_maximized();
4706   const WMEvent alt_right_square_bracket(WM_EVENT_CYCLE_SNAP_RIGHT);
4707   unsnappable_window_state->OnWMEvent(&alt_right_square_bracket);
4708   expect_unsnappable_window_is_active_and_maximized();
4709 }
4710 
4711 // Tests using Alt+[ on a left snapped window, and Alt+] on a right snapped
4712 // window.
TEST_P(SplitViewOverviewSessionTest,AltSquareBracketOnSameSideSnappedWindow)4713 TEST_P(SplitViewOverviewSessionTest, AltSquareBracketOnSameSideSnappedWindow) {
4714   std::unique_ptr<aura::Window> window1 = CreateTestWindow();
4715   std::unique_ptr<aura::Window> window2 = CreateTestWindow();
4716   const auto test_unsnapping_window1 = [this,
4717                                         &window1](WMEventType event_type) {
4718     wm::ActivateWindow(window1.get());
4719     WindowState* window1_state = WindowState::Get(window1.get());
4720     const WMEvent event(event_type);
4721     window1_state->OnWMEvent(&event);
4722     EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
4723     EXPECT_EQ(WindowStateType::kMaximized, window1_state->GetStateType());
4724     EXPECT_FALSE(split_view_controller()->InSplitViewMode());
4725     EXPECT_FALSE(InOverviewSession());
4726   };
4727   // Test Alt+[ with active window snapped on left and overview on right.
4728   ToggleOverview();
4729   split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
4730   test_unsnapping_window1(WM_EVENT_CYCLE_SNAP_LEFT);
4731   // Test Alt+] with active window snapped on right and overview on left.
4732   ToggleOverview();
4733   split_view_controller()->SnapWindow(window1.get(),
4734                                       SplitViewController::RIGHT);
4735   test_unsnapping_window1(WM_EVENT_CYCLE_SNAP_RIGHT);
4736   // Test Alt+[ with active window snapped on left and other window snapped on
4737   // right, if the left window is the default snapped window.
4738   split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
4739   split_view_controller()->SnapWindow(window2.get(),
4740                                       SplitViewController::RIGHT);
4741   test_unsnapping_window1(WM_EVENT_CYCLE_SNAP_LEFT);
4742   // Test Alt+[ with active window snapped on left and other window snapped on
4743   // right, if the right window is the default snapped window.
4744   split_view_controller()->SnapWindow(window2.get(),
4745                                       SplitViewController::RIGHT);
4746   split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
4747   test_unsnapping_window1(WM_EVENT_CYCLE_SNAP_LEFT);
4748   // Test Alt+] with active window snapped on right and other window snapped on
4749   // left, if the left window is the default snapped window.
4750   split_view_controller()->SnapWindow(window2.get(), SplitViewController::LEFT);
4751   split_view_controller()->SnapWindow(window1.get(),
4752                                       SplitViewController::RIGHT);
4753   test_unsnapping_window1(WM_EVENT_CYCLE_SNAP_RIGHT);
4754   // Test Alt+] with active window snapped on right and other window snapped on
4755   // left, if the right window is the default snapped window.
4756   split_view_controller()->SnapWindow(window1.get(),
4757                                       SplitViewController::RIGHT);
4758   split_view_controller()->SnapWindow(window2.get(), SplitViewController::LEFT);
4759   test_unsnapping_window1(WM_EVENT_CYCLE_SNAP_RIGHT);
4760 }
4761 
4762 // Tests using Alt+[ on a right snapped window, and Alt+] on a left snapped
4763 // window.
TEST_P(SplitViewOverviewSessionTest,AltSquareBracketOnOppositeSideSnappedWindow)4764 TEST_P(SplitViewOverviewSessionTest,
4765        AltSquareBracketOnOppositeSideSnappedWindow) {
4766   std::unique_ptr<aura::Window> window1 = CreateTestWindow();
4767   std::unique_ptr<aura::Window> window2 = CreateTestWindow();
4768   const auto test_left_snapping_window1 = [this, &window1, &window2]() {
4769     wm::ActivateWindow(window1.get());
4770     WindowState* window1_state = WindowState::Get(window1.get());
4771     const WMEvent alt_left_square_bracket(WM_EVENT_CYCLE_SNAP_LEFT);
4772     window1_state->OnWMEvent(&alt_left_square_bracket);
4773     EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
4774     EXPECT_EQ(WindowStateType::kLeftSnapped, window1_state->GetStateType());
4775     EXPECT_EQ(SplitViewController::State::kLeftSnapped,
4776               split_view_controller()->state());
4777     EXPECT_EQ(window1.get(), split_view_controller()->left_window());
4778     ASSERT_TRUE(InOverviewSession());
4779     EXPECT_TRUE(GetOverviewItemForWindow(window2.get()));
4780   };
4781   const auto test_right_snapping_window1 = [this, &window1, &window2]() {
4782     wm::ActivateWindow(window1.get());
4783     WindowState* window1_state = WindowState::Get(window1.get());
4784     const WMEvent alt_right_square_bracket(WM_EVENT_CYCLE_SNAP_RIGHT);
4785     window1_state->OnWMEvent(&alt_right_square_bracket);
4786     EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
4787     EXPECT_EQ(WindowStateType::kRightSnapped, window1_state->GetStateType());
4788     EXPECT_EQ(SplitViewController::State::kRightSnapped,
4789               split_view_controller()->state());
4790     EXPECT_EQ(window1.get(), split_view_controller()->right_window());
4791     ASSERT_TRUE(InOverviewSession());
4792     EXPECT_TRUE(GetOverviewItemForWindow(window2.get()));
4793   };
4794   // Test Alt+[ with active window snapped on right and overview on left.
4795   ToggleOverview();
4796   split_view_controller()->SnapWindow(window1.get(),
4797                                       SplitViewController::RIGHT);
4798   test_left_snapping_window1();
4799   // Test Alt+] with active window snapped on left and overview on right.
4800   test_right_snapping_window1();
4801   // Test Alt+[ with active window snapped on right and other window snapped on
4802   // left, if the right window is the default snapped window.
4803   split_view_controller()->SnapWindow(window2.get(), SplitViewController::LEFT);
4804   test_left_snapping_window1();
4805   // Test Alt+] with active window snapped on left and other window snapped on
4806   // right, if the left window is the default snapped window.
4807   split_view_controller()->SnapWindow(window2.get(),
4808                                       SplitViewController::RIGHT);
4809   test_right_snapping_window1();
4810   // Test Alt+[ with active window snapped on right and other window snapped on
4811   // left, if the left window is the default snapped window.
4812   EndSplitView();
4813   split_view_controller()->SnapWindow(window2.get(), SplitViewController::LEFT);
4814   split_view_controller()->SnapWindow(window1.get(),
4815                                       SplitViewController::RIGHT);
4816   test_left_snapping_window1();
4817   // Test Alt+] with active window snapped on left and other window snapped on
4818   // right, if the right window is the default snapped window.
4819   EndSplitView();
4820   split_view_controller()->SnapWindow(window2.get(),
4821                                       SplitViewController::RIGHT);
4822   split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
4823   test_right_snapping_window1();
4824 }
4825 
4826 // Test the overview window drag functionalities when screen rotates.
TEST_P(SplitViewOverviewSessionTest,SplitViewRotationTest)4827 TEST_P(SplitViewOverviewSessionTest, SplitViewRotationTest) {
4828   UpdateDisplay("807x407");
4829   int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id();
4830   display::DisplayManager* display_manager = Shell::Get()->display_manager();
4831   display::test::ScopedSetInternalDisplayId set_internal(display_manager,
4832                                                          display_id);
4833   ScreenOrientationControllerTestApi test_api(
4834       Shell::Get()->screen_orientation_controller());
4835 
4836   // Set the screen orientation to LANDSCAPE_PRIMARY.
4837   test_api.SetDisplayRotation(display::Display::ROTATE_0,
4838                               display::Display::RotationSource::ACTIVE);
4839   EXPECT_EQ(test_api.GetCurrentOrientation(),
4840             OrientationLockType::kLandscapePrimary);
4841 
4842   const gfx::Rect bounds(400, 400);
4843   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
4844   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
4845 
4846   ToggleOverview();
4847   // Test that dragging |window1| to the left of the screen snaps it to left.
4848   OverviewItem* overview_item1 = GetOverviewItemForWindow(window1.get());
4849   DragWindowTo(overview_item1, gfx::PointF());
4850   EXPECT_EQ(split_view_controller()->state(),
4851             SplitViewController::State::kLeftSnapped);
4852   EXPECT_EQ(split_view_controller()->left_window(), window1.get());
4853 
4854   // Test that dragging |window2| to the right of the screen snaps it to right.
4855   OverviewItem* overview_item2 = GetOverviewItemForWindow(window2.get());
4856   gfx::Rect work_area_rect = GetWorkAreaInScreen(window2.get());
4857   gfx::PointF end_location2(work_area_rect.width(), work_area_rect.height());
4858   DragWindowTo(overview_item2, end_location2);
4859   EXPECT_EQ(split_view_controller()->state(),
4860             SplitViewController::State::kBothSnapped);
4861   EXPECT_EQ(split_view_controller()->right_window(), window2.get());
4862 
4863   // Test that |left_window_| was snapped to left after rotated 0 degree.
4864   gfx::Rect left_window_bounds =
4865       split_view_controller()->left_window()->GetBoundsInScreen();
4866   EXPECT_EQ(left_window_bounds.x(), work_area_rect.x());
4867   EXPECT_EQ(left_window_bounds.y(), work_area_rect.y());
4868   EndSplitView();
4869 
4870   // Rotate the screen by 270 degree.
4871   test_api.SetDisplayRotation(display::Display::ROTATE_270,
4872                               display::Display::RotationSource::ACTIVE);
4873   EXPECT_EQ(test_api.GetCurrentOrientation(),
4874             OrientationLockType::kPortraitPrimary);
4875   ToggleOverview();
4876 
4877   // Test that dragging |window1| to the top of the screen snaps it to left.
4878   overview_item1 = GetOverviewItemForWindow(window1.get());
4879   DragWindowTo(overview_item1, gfx::PointF(0, 0));
4880   EXPECT_EQ(split_view_controller()->state(),
4881             SplitViewController::State::kLeftSnapped);
4882   EXPECT_EQ(split_view_controller()->left_window(), window1.get());
4883 
4884   // Test that dragging |window2| to the bottom of the screen snaps it to right.
4885   overview_item2 = GetOverviewItemForWindow(window2.get());
4886   work_area_rect = GetWorkAreaInScreen(window2.get());
4887   end_location2 = gfx::PointF(work_area_rect.width(), work_area_rect.height());
4888   DragWindowTo(overview_item2, end_location2, SelectorItemLocation::ORIGIN);
4889   EXPECT_EQ(split_view_controller()->state(),
4890             SplitViewController::State::kBothSnapped);
4891   EXPECT_EQ(split_view_controller()->right_window(), window2.get());
4892 
4893   // Test that |left_window_| was snapped to top after rotated 270 degree.
4894   left_window_bounds =
4895       split_view_controller()->left_window()->GetBoundsInScreen();
4896   EXPECT_EQ(left_window_bounds.x(), work_area_rect.x());
4897   EXPECT_EQ(left_window_bounds.y(), work_area_rect.y());
4898   EndSplitView();
4899 
4900   // Rotate the screen by 180 degree.
4901   test_api.SetDisplayRotation(display::Display::ROTATE_180,
4902                               display::Display::RotationSource::ACTIVE);
4903   EXPECT_EQ(test_api.GetCurrentOrientation(),
4904             OrientationLockType::kLandscapeSecondary);
4905   ToggleOverview();
4906 
4907   // Test that dragging |window1| to the left of the screen snaps it to right.
4908   overview_item1 = GetOverviewItemForWindow(window1.get());
4909   DragWindowTo(overview_item1, gfx::PointF());
4910   EXPECT_EQ(split_view_controller()->state(),
4911             SplitViewController::State::kRightSnapped);
4912   EXPECT_EQ(split_view_controller()->right_window(), window1.get());
4913 
4914   // Test that dragging |window2| to the right of the screen snaps it to left.
4915   overview_item2 = GetOverviewItemForWindow(window2.get());
4916   work_area_rect = GetWorkAreaInScreen(window2.get());
4917   end_location2 = gfx::PointF(work_area_rect.width(), work_area_rect.height());
4918   DragWindowTo(overview_item2, end_location2, SelectorItemLocation::ORIGIN);
4919   EXPECT_EQ(split_view_controller()->state(),
4920             SplitViewController::State::kBothSnapped);
4921   EXPECT_EQ(split_view_controller()->left_window(), window2.get());
4922 
4923   // Test that |right_window_| was snapped to left after rotated 180 degree.
4924   gfx::Rect right_window_bounds =
4925       split_view_controller()->right_window()->GetBoundsInScreen();
4926   EXPECT_EQ(right_window_bounds.x(), work_area_rect.x());
4927   EXPECT_EQ(right_window_bounds.y(), work_area_rect.y());
4928   EndSplitView();
4929 
4930   // Rotate the screen by 90 degree.
4931   test_api.SetDisplayRotation(display::Display::ROTATE_90,
4932                               display::Display::RotationSource::ACTIVE);
4933   EXPECT_EQ(test_api.GetCurrentOrientation(),
4934             OrientationLockType::kPortraitSecondary);
4935   ToggleOverview();
4936 
4937   // Test that dragging |window1| to the top of the screen snaps it to right.
4938   overview_item1 = GetOverviewItemForWindow(window1.get());
4939   DragWindowTo(overview_item1, gfx::PointF(0, 0));
4940   EXPECT_EQ(split_view_controller()->state(),
4941             SplitViewController::State::kRightSnapped);
4942   EXPECT_EQ(split_view_controller()->right_window(), window1.get());
4943 
4944   // Test that dragging |window2| to the bottom of the screen snaps it to left.
4945   overview_item2 = GetOverviewItemForWindow(window2.get());
4946   work_area_rect = GetWorkAreaInScreen(window2.get());
4947   end_location2 = gfx::PointF(work_area_rect.width(), work_area_rect.height());
4948   DragWindowTo(overview_item2, end_location2);
4949   EXPECT_EQ(split_view_controller()->state(),
4950             SplitViewController::State::kBothSnapped);
4951   EXPECT_EQ(split_view_controller()->left_window(), window2.get());
4952 
4953   // Test that |right_window_| was snapped to top after rotated 90 degree.
4954   right_window_bounds =
4955       split_view_controller()->right_window()->GetBoundsInScreen();
4956   EXPECT_EQ(right_window_bounds.x(), work_area_rect.x());
4957   EXPECT_EQ(right_window_bounds.y(), work_area_rect.y());
4958   EndSplitView();
4959 }
4960 
4961 // Test that when split view mode and overview mode are both active at the same
4962 // time, dragging the split view divider resizes the bounds of snapped window
4963 // and the bounds of overview window grids at the same time.
TEST_P(SplitViewOverviewSessionTest,SplitViewOverviewBothActiveTest)4964 TEST_P(SplitViewOverviewSessionTest, SplitViewOverviewBothActiveTest) {
4965   UpdateDisplay("907x407");
4966 
4967   const gfx::Rect bounds(400, 400);
4968   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
4969   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
4970   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
4971 
4972   ToggleOverview();
4973 
4974   // Drag |window1| selector item to snap to left.
4975   OverviewItem* overview_item1 = GetOverviewItemForWindow(window1.get());
4976   DragWindowTo(overview_item1, gfx::PointF());
4977 
4978   EXPECT_EQ(split_view_controller()->state(),
4979             SplitViewController::State::kLeftSnapped);
4980   const gfx::Rect window1_bounds = window1->GetBoundsInScreen();
4981   const gfx::Rect overview_grid_bounds = GetGridBounds();
4982   const gfx::Rect divider_bounds =
4983       GetSplitViewDividerBounds(false /* is_dragging */);
4984 
4985   // Test that window1, divider, overview grid are aligned horizontally.
4986   EXPECT_EQ(window1_bounds.right(), divider_bounds.x());
4987   EXPECT_EQ(divider_bounds.right(), overview_grid_bounds.x());
4988 
4989   const gfx::Point resize_start_location(divider_bounds.CenterPoint());
4990   split_view_controller()->StartResize(resize_start_location);
4991   const gfx::Point resize_end_location(300, 0);
4992   split_view_controller()->EndResize(resize_end_location);
4993   SkipDividerSnapAnimation();
4994 
4995   const gfx::Rect window1_bounds_after_resize = window1->GetBoundsInScreen();
4996   const gfx::Rect overview_grid_bounds_after_resize = GetGridBounds();
4997   const gfx::Rect divider_bounds_after_resize =
4998       GetSplitViewDividerBounds(false /* is_dragging */);
4999 
5000   // Test that window1, divider, overview grid are still aligned horizontally
5001   // after resizing.
5002   EXPECT_EQ(window1_bounds.right(), divider_bounds.x());
5003   EXPECT_EQ(divider_bounds.right(), overview_grid_bounds.x());
5004 
5005   // Test that window1, divider, overview grid's bounds are changed after
5006   // resizing.
5007   EXPECT_NE(window1_bounds, window1_bounds_after_resize);
5008   EXPECT_NE(overview_grid_bounds, overview_grid_bounds_after_resize);
5009   EXPECT_NE(divider_bounds, divider_bounds_after_resize);
5010 }
5011 
5012 // Verify that selecting an unsnappable window while in split view works as
5013 // intended.
TEST_P(SplitViewOverviewSessionTest,SelectUnsnappableWindowInSplitView)5014 TEST_P(SplitViewOverviewSessionTest, SelectUnsnappableWindowInSplitView) {
5015   // Create one snappable and one unsnappable window.
5016   std::unique_ptr<aura::Window> window = CreateTestWindow();
5017   std::unique_ptr<aura::Window> unsnappable_window = CreateUnsnappableWindow();
5018 
5019   ToggleOverview();
5020   ASSERT_TRUE(overview_controller()->InOverviewSession());
5021 
5022   // Snap the snappable window to enter split view mode.
5023   split_view_controller()->SnapWindow(window.get(), SplitViewController::LEFT);
5024   ASSERT_TRUE(split_view_controller()->InSplitViewMode());
5025 
5026   // Select the unsnappable window.
5027   OverviewItem* overview_item =
5028       GetOverviewItemForWindow(unsnappable_window.get());
5029   ui::test::EventGenerator* generator = GetEventGenerator();
5030   generator->set_current_screen_location(
5031       gfx::ToRoundedPoint(overview_item->target_bounds().CenterPoint()));
5032   generator->ClickLeftButton();
5033 
5034   // Verify that we are out of split view and overview mode, and that the active
5035   // window is the unsnappable window.
5036   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
5037   EXPECT_FALSE(overview_controller()->InOverviewSession());
5038   EXPECT_EQ(unsnappable_window.get(), window_util::GetActiveWindow());
5039 
5040   std::unique_ptr<aura::Window> window2 = CreateTestWindow();
5041   ToggleOverview();
5042   split_view_controller()->SnapWindow(window.get(), SplitViewController::LEFT);
5043   split_view_controller()->SnapWindow(window2.get(),
5044                                       SplitViewController::RIGHT);
5045 
5046   // Split view mode should be active. Overview mode should be ended.
5047   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
5048   EXPECT_EQ(SplitViewController::State::kBothSnapped,
5049             split_view_controller()->state());
5050   EXPECT_FALSE(overview_controller()->InOverviewSession());
5051 
5052   ToggleOverview();
5053   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
5054   EXPECT_EQ(SplitViewController::State::kLeftSnapped,
5055             split_view_controller()->state());
5056   EXPECT_TRUE(overview_controller()->InOverviewSession());
5057 
5058   // Now select the unsnappable window.
5059   overview_item = GetOverviewItemForWindow(unsnappable_window.get());
5060   generator->set_current_screen_location(
5061       gfx::ToRoundedPoint(overview_item->target_bounds().CenterPoint()));
5062   generator->ClickLeftButton();
5063 
5064   // Split view mode should be ended. And the unsnappable window should be the
5065   // active window now.
5066   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
5067   EXPECT_FALSE(overview_controller()->InOverviewSession());
5068   EXPECT_EQ(unsnappable_window.get(), window_util::GetActiveWindow());
5069 }
5070 
5071 // Verify that when in overview mode, the selector items unsnappable indicator
5072 // shows up when expected.
TEST_P(SplitViewOverviewSessionTest,OverviewUnsnappableIndicatorVisibility)5073 TEST_P(SplitViewOverviewSessionTest, OverviewUnsnappableIndicatorVisibility) {
5074   // Create three windows; two normal and one unsnappable, so that when after
5075   // snapping |window1| to enter split view we can test the state of each normal
5076   // and unsnappable windows.
5077   std::unique_ptr<aura::Window> window1(CreateTestWindow());
5078   std::unique_ptr<aura::Window> window2(CreateTestWindow());
5079   std::unique_ptr<aura::Window> unsnappable_window = CreateUnsnappableWindow();
5080 
5081   ToggleOverview();
5082   ASSERT_TRUE(overview_controller()->InOverviewSession());
5083 
5084   OverviewItem* snappable_overview_item =
5085       GetOverviewItemForWindow(window2.get());
5086   OverviewItem* unsnappable_overview_item =
5087       GetOverviewItemForWindow(unsnappable_window.get());
5088 
5089   // Note: |cannot_snap_label_view_| and its parent will be created on demand.
5090   EXPECT_FALSE(snappable_overview_item->cannot_snap_widget_for_testing());
5091   ASSERT_FALSE(unsnappable_overview_item->cannot_snap_widget_for_testing());
5092 
5093   // Snap the extra snappable window to enter split view mode.
5094   split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
5095   ASSERT_TRUE(split_view_controller()->InSplitViewMode());
5096   EXPECT_FALSE(snappable_overview_item->cannot_snap_widget_for_testing());
5097   ASSERT_TRUE(unsnappable_overview_item->cannot_snap_widget_for_testing());
5098   ui::Layer* unsnappable_layer =
5099       unsnappable_overview_item->cannot_snap_widget_for_testing()
5100           ->GetNativeWindow()
5101           ->layer();
5102   EXPECT_EQ(1.f, unsnappable_layer->opacity());
5103 
5104   // Exiting the splitview will hide the unsnappable label.
5105   const gfx::Rect divider_bounds =
5106       GetSplitViewDividerBounds(/*is_dragging=*/false);
5107   GetEventGenerator()->set_current_screen_location(
5108       divider_bounds.CenterPoint());
5109   GetEventGenerator()->DragMouseTo(0, 0);
5110   SkipDividerSnapAnimation();
5111 
5112   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
5113   EXPECT_EQ(0.f, unsnappable_layer->opacity());
5114 }
5115 
5116 // Verify that during "normal" dragging from overview (not drag-to-close), the
5117 // dragged item's unsnappable indicator is temporarily suppressed.
TEST_P(SplitViewOverviewSessionTest,OverviewUnsnappableIndicatorVisibilityWhileDragging)5118 TEST_P(SplitViewOverviewSessionTest,
5119        OverviewUnsnappableIndicatorVisibilityWhileDragging) {
5120   ui::GestureConfiguration* gesture_config =
5121       ui::GestureConfiguration::GetInstance();
5122   gesture_config->set_long_press_time_in_ms(1);
5123   gesture_config->set_show_press_delay_in_ms(1);
5124 
5125   std::unique_ptr<aura::Window> snapped_window = CreateTestWindow();
5126   std::unique_ptr<aura::Window> unsnappable_window = CreateUnsnappableWindow();
5127   ToggleOverview();
5128   ASSERT_TRUE(overview_controller()->InOverviewSession());
5129   split_view_controller()->SnapWindow(snapped_window.get(),
5130                                       SplitViewController::LEFT);
5131   ASSERT_TRUE(split_view_controller()->InSplitViewMode());
5132   OverviewItem* unsnappable_overview_item =
5133       GetOverviewItemForWindow(unsnappable_window.get());
5134   ASSERT_TRUE(unsnappable_overview_item->cannot_snap_widget_for_testing());
5135   ui::Layer* unsnappable_layer =
5136       unsnappable_overview_item->cannot_snap_widget_for_testing()
5137           ->GetNativeWindow()
5138           ->layer();
5139   ASSERT_EQ(1.f, unsnappable_layer->opacity());
5140 
5141   // Test that the unsnappable label is temporarily suppressed during mouse
5142   // dragging.
5143   ui::test::EventGenerator* generator = GetEventGenerator();
5144   const gfx::Point drag_starting_point = gfx::ToRoundedPoint(
5145       unsnappable_overview_item->target_bounds().CenterPoint());
5146   generator->set_current_screen_location(drag_starting_point);
5147   generator->PressLeftButton();
5148   using DragBehavior = OverviewWindowDragController::DragBehavior;
5149   EXPECT_EQ(
5150       DragBehavior::kUndefined,
5151       overview_session()->window_drag_controller()->current_drag_behavior());
5152   EXPECT_EQ(1.f, unsnappable_layer->opacity());
5153   generator->MoveMouseBy(0, 20);
5154   EXPECT_EQ(
5155       DragBehavior::kNormalDrag,
5156       overview_session()->window_drag_controller()->current_drag_behavior());
5157   EXPECT_EQ(0.f, unsnappable_layer->opacity());
5158   generator->ReleaseLeftButton();
5159   EXPECT_EQ(1.f, unsnappable_layer->opacity());
5160 
5161   // Test that the unsnappable label is temporarily suppressed during "normal"
5162   // touch dragging (not drag-to-close).
5163   generator->set_current_screen_location(drag_starting_point);
5164   generator->PressTouch();
5165   {
5166     base::RunLoop run_loop;
5167     base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
5168         FROM_HERE, run_loop.QuitClosure(),
5169         base::TimeDelta::FromMilliseconds(2));
5170     run_loop.Run();
5171   }
5172   EXPECT_EQ(
5173       DragBehavior::kNormalDrag,
5174       overview_session()->window_drag_controller()->current_drag_behavior());
5175   EXPECT_EQ(0.f, unsnappable_layer->opacity());
5176   generator->MoveTouchBy(20, 0);
5177   generator->ReleaseTouch();
5178   EXPECT_EQ(1.f, unsnappable_layer->opacity());
5179 
5180   // Test that the unsnappable label reappears if "normal" touch dragging (not
5181   // drag-to-close) ends when the item has not been actually dragged anywhere.
5182   // This case improves test coverage because it is handled in
5183   // |OverviewWindowDragController::ResetGesture| instead of
5184   // |OverviewWindowDragController::CompleteNormalDrag|.
5185   generator->set_current_screen_location(drag_starting_point);
5186   generator->PressTouch();
5187   {
5188     base::RunLoop run_loop;
5189     base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
5190         FROM_HERE, run_loop.QuitClosure(),
5191         base::TimeDelta::FromMilliseconds(2));
5192     run_loop.Run();
5193   }
5194   EXPECT_EQ(
5195       DragBehavior::kNormalDrag,
5196       overview_session()->window_drag_controller()->current_drag_behavior());
5197   EXPECT_EQ(0.f, unsnappable_layer->opacity());
5198   generator->ReleaseTouch();
5199   EXPECT_EQ(1.f, unsnappable_layer->opacity());
5200 
5201   // Test that the unsnappable label persists in drag-to-close mode.
5202   generator->set_current_screen_location(drag_starting_point);
5203   generator->PressTouch();
5204   // Use small increments otherwise a fling event will be fired.
5205   for (int j = 0; j < 20; ++j)
5206     generator->MoveTouchBy(0, 1);
5207   EXPECT_EQ(
5208       DragBehavior::kDragToClose,
5209       overview_session()->window_drag_controller()->current_drag_behavior());
5210   // Drag-to-close mode affects the opacity of the whole overview item,
5211   // including the unsnappable label.
5212   EXPECT_EQ(unsnappable_overview_item->GetWindow()->layer()->opacity(),
5213             unsnappable_layer->opacity());
5214   generator->ReleaseTouch();
5215   EXPECT_EQ(1.f, unsnappable_layer->opacity());
5216 }
5217 
5218 // Verify that an item's unsnappable indicator is updated for display rotation.
TEST_P(SplitViewOverviewSessionTest,OverviewUnsnappableIndicatorVisibilityAfterDisplayRotation)5219 TEST_P(SplitViewOverviewSessionTest,
5220        OverviewUnsnappableIndicatorVisibilityAfterDisplayRotation) {
5221   UpdateDisplay("800x800");
5222   std::unique_ptr<aura::Window> snapped_window = CreateTestWindow();
5223   // Because of its minimum size, |overview_window| is snappable in horizontal
5224   // split view but not in vertical split view.
5225   std::unique_ptr<aura::Window> overview_window(
5226       CreateWindowWithMinimumSize(gfx::Rect(400, 600), gfx::Size(300, 500)));
5227   ToggleOverview();
5228   ASSERT_TRUE(overview_controller()->InOverviewSession());
5229   split_view_controller()->SnapWindow(snapped_window.get(),
5230                                       SplitViewController::LEFT);
5231   ASSERT_TRUE(split_view_controller()->InSplitViewMode());
5232   OverviewItem* overview_item = GetOverviewItemForWindow(overview_window.get());
5233   // Note: |cannot_snap_label_view_| and its parent will be created on demand.
5234   EXPECT_FALSE(overview_item->cannot_snap_widget_for_testing());
5235 
5236   // Rotate to primary portrait orientation. The unsnappable indicator appears.
5237   display::test::DisplayManagerTestApi(Shell::Get()->display_manager())
5238       .SetFirstDisplayAsInternalDisplay();
5239   ScreenOrientationControllerTestApi test_api(
5240       Shell::Get()->screen_orientation_controller());
5241   test_api.SetDisplayRotation(display::Display::ROTATE_270,
5242                               display::Display::RotationSource::ACTIVE);
5243   ASSERT_TRUE(overview_item->cannot_snap_widget_for_testing());
5244   ui::Layer* unsnappable_layer =
5245       overview_item->cannot_snap_widget_for_testing()->GetLayer();
5246   EXPECT_EQ(1.f, unsnappable_layer->opacity());
5247 
5248   // Rotate to primary landscape orientation. The unsnappable indicator hides.
5249   test_api.SetDisplayRotation(display::Display::ROTATE_0,
5250                               display::Display::RotationSource::ACTIVE);
5251   EXPECT_EQ(0.f, unsnappable_layer->opacity());
5252 }
5253 
5254 // Test that when splitview mode and overview mode are both active at the same
5255 // time, dragging divider behaviors are correct.
TEST_P(SplitViewOverviewSessionTest,DragDividerToExitTest)5256 TEST_P(SplitViewOverviewSessionTest, DragDividerToExitTest) {
5257   UpdateDisplay("907x407");
5258 
5259   const gfx::Rect bounds(400, 400);
5260   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
5261   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
5262   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
5263 
5264   ToggleOverview();
5265 
5266   // Drag |window1| selector item to snap to left.
5267   OverviewItem* overview_item1 = GetOverviewItemForWindow(window1.get());
5268   DragWindowTo(overview_item1, gfx::PointF());
5269   // Test that overview mode and split view mode are both active.
5270   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
5271   EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
5272 
5273   // Drag the divider toward closing the snapped window.
5274   gfx::Rect divider_bounds = GetSplitViewDividerBounds(false /* is_dragging */);
5275   split_view_controller()->StartResize(divider_bounds.CenterPoint());
5276   split_view_controller()->EndResize(gfx::Point(0, 0));
5277   SkipDividerSnapAnimation();
5278 
5279   // Test that split view mode is ended. Overview mode is still active.
5280   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
5281   EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
5282 
5283   // Now drag |window2| selector item to snap to left.
5284   OverviewItem* overview_item2 = GetOverviewItemForWindow(window2.get());
5285   DragWindowTo(overview_item2, gfx::PointF());
5286   // Test that overview mode and split view mode are both active.
5287   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
5288   EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
5289 
5290   // Drag the divider toward closing the overview window grid.
5291   divider_bounds = GetSplitViewDividerBounds(false /*is_dragging=*/);
5292   const gfx::Rect display_bounds = GetWorkAreaInScreen(window2.get());
5293   split_view_controller()->StartResize(divider_bounds.CenterPoint());
5294   split_view_controller()->EndResize(display_bounds.bottom_right());
5295   SkipDividerSnapAnimation();
5296 
5297   // Test that split view mode is ended. Overview mode is also ended. |window2|
5298   // should be activated.
5299   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
5300   EXPECT_FALSE(Shell::Get()->overview_controller()->InOverviewSession());
5301   EXPECT_EQ(window2.get(), window_util::GetActiveWindow());
5302 }
5303 
TEST_P(SplitViewOverviewSessionTest,OverviewItemLongPressed)5304 TEST_P(SplitViewOverviewSessionTest, OverviewItemLongPressed) {
5305   std::unique_ptr<aura::Window> window1 = CreateTestWindow();
5306   std::unique_ptr<aura::Window> window2 = CreateTestWindow();
5307 
5308   ToggleOverview();
5309   ASSERT_TRUE(overview_controller()->InOverviewSession());
5310 
5311   OverviewItem* overview_item = GetOverviewItemForWindow(window1.get());
5312   gfx::PointF start_location(overview_item->target_bounds().CenterPoint());
5313   const gfx::RectF original_bounds(overview_item->target_bounds());
5314 
5315   // Verify that when a overview item receives a resetting gesture, we
5316   // stay in overview mode and the bounds of the item are the same as they were
5317   // before the press sequence started.
5318   overview_session()->InitiateDrag(overview_item, start_location,
5319                                    /*is_touch_dragging=*/true);
5320   overview_session()->ResetDraggedWindowGesture();
5321   EXPECT_TRUE(overview_controller()->InOverviewSession());
5322   EXPECT_EQ(original_bounds, overview_item->target_bounds());
5323 
5324   // Verify that when a overview item is tapped, we exit overview mode,
5325   // and the current active window is the item.
5326   overview_session()->InitiateDrag(overview_item, start_location,
5327                                    /*is_touch_dragging=*/true);
5328   overview_session()->ActivateDraggedWindow();
5329   EXPECT_FALSE(overview_controller()->InOverviewSession());
5330   EXPECT_EQ(window1.get(), window_util::GetActiveWindow());
5331 }
5332 
TEST_P(SplitViewOverviewSessionTest,SnappedWindowBoundsTest)5333 TEST_P(SplitViewOverviewSessionTest, SnappedWindowBoundsTest) {
5334   const gfx::Rect bounds(400, 400);
5335   const int kMinimumBoundSize = 100;
5336   const gfx::Size size(kMinimumBoundSize, kMinimumBoundSize);
5337 
5338   std::unique_ptr<aura::Window> window1(
5339       CreateWindowWithMinimumSize(bounds, size));
5340   std::unique_ptr<aura::Window> window2(
5341       CreateWindowWithMinimumSize(bounds, size));
5342   std::unique_ptr<aura::Window> window3(
5343       CreateWindowWithMinimumSize(bounds, size));
5344   const int screen_width =
5345       screen_util::GetDisplayWorkAreaBoundsInParent(window1.get()).width();
5346   ToggleOverview();
5347 
5348   // Drag |window1| selector item to snap to left.
5349   OverviewItem* overview_item1 = GetOverviewItemForWindow(window1.get());
5350   DragWindowTo(overview_item1, gfx::PointF());
5351   EXPECT_EQ(SplitViewController::State::kLeftSnapped,
5352             split_view_controller()->state());
5353   EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
5354 
5355   // Then drag the divider to left toward closing the snapped window.
5356   gfx::Rect divider_bounds = GetSplitViewDividerBounds(false /*is_dragging=*/);
5357   split_view_controller()->StartResize(divider_bounds.CenterPoint());
5358   // Drag the divider to a point that is close enough but still have a short
5359   // distance to the edge of the screen.
5360   split_view_controller()->EndResize(gfx::Point(20, 20));
5361   SkipDividerSnapAnimation();
5362 
5363   // Test that split view mode is ended. Overview mode is still active.
5364   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
5365   EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
5366   // Test that |window1| has the dimensions of a tablet mode maxed window, so
5367   // that when it is placed back on the grid it will not look skinny.
5368   EXPECT_LE(window1->bounds().x(), 0);
5369   EXPECT_EQ(window1->bounds().width(), screen_width);
5370 
5371   // Drag |window2| selector item to snap to right.
5372   OverviewItem* overview_item2 = GetOverviewItemForWindow(window2.get());
5373   const gfx::Rect work_area_rect = GetWorkAreaInScreen(window2.get());
5374   gfx::Point end_location2 =
5375       gfx::Point(work_area_rect.width(), work_area_rect.height());
5376   DragWindowTo(overview_item2, gfx::PointF(end_location2));
5377   EXPECT_EQ(SplitViewController::State::kRightSnapped,
5378             split_view_controller()->state());
5379   EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
5380 
5381   // Then drag the divider to right toward closing the snapped window.
5382   divider_bounds = GetSplitViewDividerBounds(false /* is_dragging */);
5383   split_view_controller()->StartResize(divider_bounds.CenterPoint());
5384   // Drag the divider to a point that is close enough but still have a short
5385   // distance to the edge of the screen.
5386   end_location2.Offset(-20, -20);
5387   split_view_controller()->EndResize(end_location2);
5388   SkipDividerSnapAnimation();
5389 
5390   // Test that split view mode is ended. Overview mode is still active.
5391   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
5392   EXPECT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
5393   // Test that |window2| has the dimensions of a tablet mode maxed window, so
5394   // that when it is placed back on the grid it will not look skinny.
5395   EXPECT_GE(window2->bounds().x(), 0);
5396   EXPECT_EQ(window2->bounds().width(), screen_width);
5397 }
5398 
5399 // Test snapped window bounds with adjustment for the minimum size of a window.
TEST_P(SplitViewOverviewSessionTest,SnappedWindowBoundsWithMinimumSizeTest)5400 TEST_P(SplitViewOverviewSessionTest, SnappedWindowBoundsWithMinimumSizeTest) {
5401   const gfx::Rect bounds(400, 400);
5402   std::unique_ptr<aura::Window> window1(CreateTestWindow(bounds));
5403   const int work_area_length =
5404       screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
5405           Shell::GetPrimaryRootWindow())
5406           .width();
5407   std::unique_ptr<aura::Window> window2(CreateWindowWithMinimumSize(
5408       bounds, gfx::Size(work_area_length / 3 + 20, 0)));
5409 
5410   ToggleOverview();
5411   split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
5412   split_view_controller()->StartResize(
5413       GetSplitViewDividerBounds(/*is_dragging=*/false).CenterPoint());
5414   split_view_controller()->EndResize(gfx::Point(work_area_length / 3, 10));
5415   SkipDividerSnapAnimation();
5416   // Use |EXPECT_NEAR| for reasons related to rounding and divider thickness.
5417   EXPECT_NEAR(
5418       work_area_length / 3,
5419       split_view_controller()
5420           ->GetSnappedWindowBoundsInScreen(SplitViewController::LEFT,
5421                                            /*window_for_minimum_size=*/nullptr)
5422           .width(),
5423       8);
5424   EXPECT_NEAR(work_area_length / 2,
5425               split_view_controller()
5426                   ->GetSnappedWindowBoundsInScreen(SplitViewController::LEFT,
5427                                                    window2.get())
5428                   .width(),
5429               8);
5430   EXPECT_NEAR(
5431       work_area_length * 2 / 3,
5432       split_view_controller()
5433           ->GetSnappedWindowBoundsInScreen(SplitViewController::RIGHT,
5434                                            /*window_for_minimum_size=*/nullptr)
5435           .width(),
5436       8);
5437   EXPECT_NEAR(work_area_length * 2 / 3,
5438               split_view_controller()
5439                   ->GetSnappedWindowBoundsInScreen(SplitViewController::RIGHT,
5440                                                    window2.get())
5441                   .width(),
5442               8);
5443   split_view_controller()->StartResize(
5444       GetSplitViewDividerBounds(/*is_dragging=*/false).CenterPoint());
5445   split_view_controller()->EndResize(gfx::Point(work_area_length * 2 / 3, 10));
5446   EXPECT_NEAR(
5447       work_area_length * 2 / 3,
5448       split_view_controller()
5449           ->GetSnappedWindowBoundsInScreen(SplitViewController::LEFT,
5450                                            /*window_for_minimum_size=*/nullptr)
5451           .width(),
5452       8);
5453   EXPECT_NEAR(work_area_length * 2 / 3,
5454               split_view_controller()
5455                   ->GetSnappedWindowBoundsInScreen(SplitViewController::LEFT,
5456                                                    window2.get())
5457                   .width(),
5458               8);
5459   EXPECT_NEAR(
5460       work_area_length / 3,
5461       split_view_controller()
5462           ->GetSnappedWindowBoundsInScreen(SplitViewController::RIGHT,
5463                                            /*window_for_minimum_size=*/nullptr)
5464           .width(),
5465       8);
5466   EXPECT_NEAR(work_area_length / 2,
5467               split_view_controller()
5468                   ->GetSnappedWindowBoundsInScreen(SplitViewController::RIGHT,
5469                                                    window2.get())
5470                   .width(),
5471               8);
5472 }
5473 
5474 // Verify that if the split view divider is dragged all the way to the edge, the
5475 // window being dragged gets returned to the overview list, if overview mode is
5476 // still active.
TEST_P(SplitViewOverviewSessionTest,DividerDraggedToEdgeReturnsWindowToOverviewList)5477 TEST_P(SplitViewOverviewSessionTest,
5478        DividerDraggedToEdgeReturnsWindowToOverviewList) {
5479   const gfx::Rect bounds(400, 400);
5480   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
5481   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
5482   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
5483 
5484   ToggleOverview();
5485   // Drag |window1| selector item to snap to left. There should be two items on
5486   // the overview grid afterwards, |window2| and |window3|.
5487   OverviewItem* overview_item1 = GetOverviewItemForWindow(window1.get());
5488   DragWindowTo(overview_item1, gfx::PointF());
5489   EXPECT_EQ(SplitViewController::State::kLeftSnapped,
5490             split_view_controller()->state());
5491   EXPECT_TRUE(InOverviewSession());
5492   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
5493   ASSERT_TRUE(split_view_controller()->split_view_divider());
5494   std::vector<aura::Window*> window_list =
5495       overview_controller()->GetWindowsListInOverviewGridsForTest();
5496   EXPECT_EQ(2u, window_list.size());
5497   EXPECT_FALSE(base::Contains(window_list, window1.get()));
5498   EXPECT_TRUE(wm::IsActiveWindow(window1.get()));
5499 
5500   // Drag the divider to the left edge.
5501   const gfx::Rect divider_bounds =
5502       GetSplitViewDividerBounds(/*is_dragging=*/false);
5503   GetEventGenerator()->set_current_screen_location(
5504       divider_bounds.CenterPoint());
5505   GetEventGenerator()->DragMouseTo(0, 0);
5506   SkipDividerSnapAnimation();
5507 
5508   // Verify that it is still in overview mode and that |window1| is returned to
5509   // the overview list.
5510   EXPECT_TRUE(InOverviewSession());
5511   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
5512   window_list = overview_controller()->GetWindowsListInOverviewGridsForTest();
5513   EXPECT_EQ(3u, window_list.size());
5514   EXPECT_TRUE(base::Contains(window_list, window1.get()));
5515   EXPECT_FALSE(wm::IsActiveWindow(window1.get()));
5516 }
5517 
5518 // Verify that if overview mode is active and the split view divider is dragged
5519 // all the way to the opposite edge, then the split view window is reinserted
5520 // into the overview grid at the correct position according to MRU order, and
5521 // the stacking order is also correct.
TEST_P(SplitViewOverviewSessionTest,SplitViewWindowReinsertedToOverviewAtCorrectPositionWhenSplitViewIsEnded)5522 TEST_P(
5523     SplitViewOverviewSessionTest,
5524     SplitViewWindowReinsertedToOverviewAtCorrectPositionWhenSplitViewIsEnded) {
5525   const gfx::Rect bounds(400, 400);
5526   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
5527   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
5528   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
5529   ToggleOverview();
5530   DragWindowTo(GetOverviewItemForWindow(window1.get()), gfx::PointF());
5531   DragWindowTo(GetOverviewItemForWindow(window2.get()),
5532                gfx::PointF(799.f, 0.f));
5533   EXPECT_EQ(window1.get(), split_view_controller()->left_window());
5534   EXPECT_EQ(window2.get(), split_view_controller()->right_window());
5535   ToggleOverview();
5536   // Drag the divider to the left edge.
5537   const gfx::Rect divider_bounds =
5538       GetSplitViewDividerBounds(/*is_dragging=*/false);
5539   GetEventGenerator()->set_current_screen_location(
5540       divider_bounds.CenterPoint());
5541   GetEventGenerator()->DragMouseTo(0, 0);
5542   SkipDividerSnapAnimation();
5543 
5544   // Verify the grid arrangement.
5545   ASSERT_TRUE(InOverviewSession());
5546   const std::vector<aura::Window*> expected_mru_list = {
5547       window2.get(), window1.get(), window3.get()};
5548   const std::vector<aura::Window*> expected_overview_list = {
5549       window2.get(), window1.get(), window3.get()};
5550   EXPECT_EQ(
5551       expected_mru_list,
5552       Shell::Get()->mru_window_tracker()->BuildMruWindowList(kActiveDesk));
5553   EXPECT_EQ(expected_overview_list,
5554             overview_controller()->GetWindowsListInOverviewGridsForTest());
5555 
5556   // Verify the stacking order.
5557   aura::Window* parent = window1->parent();
5558   ASSERT_EQ(parent, window2->parent());
5559   ASSERT_EQ(parent, window3->parent());
5560   EXPECT_GT(IndexOf(GetOverviewItemForWindow(window2.get())
5561                         ->item_widget()
5562                         ->GetNativeWindow(),
5563                     parent),
5564             IndexOf(GetOverviewItemForWindow(window1.get())
5565                         ->item_widget()
5566                         ->GetNativeWindow(),
5567                     parent));
5568   EXPECT_GT(IndexOf(GetOverviewItemForWindow(window1.get())
5569                         ->item_widget()
5570                         ->GetNativeWindow(),
5571                     parent),
5572             IndexOf(GetOverviewItemForWindow(window3.get())
5573                         ->item_widget()
5574                         ->GetNativeWindow(),
5575                     parent));
5576 }
5577 
5578 // Verify that if a window is dragged from overview and snapped in place of
5579 // another split view window, then the old split view window is reinserted into
5580 // the overview grid at the correct position according to MRU order, and the
5581 // stacking order is also correct.
TEST_P(SplitViewOverviewSessionTest,SplitViewWindowReinsertedToOverviewAtCorrectPositionWhenAnotherWindowTakesItsPlace)5582 TEST_P(
5583     SplitViewOverviewSessionTest,
5584     SplitViewWindowReinsertedToOverviewAtCorrectPositionWhenAnotherWindowTakesItsPlace) {
5585   const gfx::Rect bounds(400, 400);
5586   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
5587   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
5588   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
5589   std::unique_ptr<aura::Window> window4(CreateWindow(bounds));
5590   ToggleOverview();
5591   DragWindowTo(GetOverviewItemForWindow(window1.get()), gfx::PointF());
5592   DragWindowTo(GetOverviewItemForWindow(window2.get()),
5593                gfx::PointF(799.f, 0.f));
5594   EXPECT_EQ(window1.get(), split_view_controller()->left_window());
5595   EXPECT_EQ(window2.get(), split_view_controller()->right_window());
5596   ToggleOverview();
5597   DragWindowTo(GetOverviewItemForWindow(window3.get()), gfx::PointF());
5598   EXPECT_EQ(window3.get(), split_view_controller()->left_window());
5599 
5600   // Verify the grid arrangement.
5601   ASSERT_TRUE(InOverviewSession());
5602   const std::vector<aura::Window*> expected_mru_list = {
5603       window3.get(), window2.get(), window1.get(), window4.get()};
5604   const std::vector<aura::Window*> expected_overview_list = {
5605       window2.get(), window1.get(), window4.get()};
5606   EXPECT_EQ(
5607       expected_mru_list,
5608       Shell::Get()->mru_window_tracker()->BuildMruWindowList(kActiveDesk));
5609   EXPECT_EQ(expected_overview_list,
5610             overview_controller()->GetWindowsListInOverviewGridsForTest());
5611 
5612   // Verify the stacking order.
5613   aura::Window* parent = window1->parent();
5614   ASSERT_EQ(parent, window2->parent());
5615   ASSERT_EQ(parent, window4->parent());
5616   EXPECT_GT(IndexOf(GetOverviewItemForWindow(window2.get())
5617                         ->item_widget()
5618                         ->GetNativeWindow(),
5619                     parent),
5620             IndexOf(GetOverviewItemForWindow(window1.get())
5621                         ->item_widget()
5622                         ->GetNativeWindow(),
5623                     parent));
5624   EXPECT_GT(IndexOf(GetOverviewItemForWindow(window1.get())
5625                         ->item_widget()
5626                         ->GetNativeWindow(),
5627                     parent),
5628             IndexOf(GetOverviewItemForWindow(window4.get())
5629                         ->item_widget()
5630                         ->GetNativeWindow(),
5631                     parent));
5632 }
5633 
5634 // Verify that if the split view divider is dragged close to the edge, the grid
5635 // bounds will be fixed to a third of the work area width and start sliding off
5636 // the screen instead of continuing to shrink.
TEST_P(SplitViewOverviewSessionTest,OverviewHasMinimumBoundsWhenDividerDragged)5637 TEST_P(SplitViewOverviewSessionTest,
5638        OverviewHasMinimumBoundsWhenDividerDragged) {
5639   UpdateDisplay("600x400");
5640 
5641   const gfx::Rect bounds(400, 400);
5642   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
5643   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
5644 
5645   ToggleOverview();
5646   // Snap a window to the left and test dragging the divider towards the right
5647   // edge of the screen.
5648   split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
5649   OverviewGrid* grid = overview_session()->grid_list()[0].get();
5650   ASSERT_TRUE(grid);
5651 
5652   // Drag the divider to the right edge.
5653   gfx::Rect divider_bounds = GetSplitViewDividerBounds(/*is_dragging=*/false);
5654   ui::test::EventGenerator* generator = GetEventGenerator();
5655   generator->set_current_screen_location(divider_bounds.CenterPoint());
5656   generator->PressLeftButton();
5657 
5658   // Tests that near the right edge, the grid bounds are fixed at 200 and are
5659   // partially off screen to the right.
5660   generator->MoveMouseTo(580, 0);
5661   EXPECT_EQ(200, grid->bounds().width());
5662   EXPECT_GT(grid->bounds().right(), 600);
5663   generator->ReleaseLeftButton();
5664   SkipDividerSnapAnimation();
5665 
5666   // Releasing close to the edge will activate the left window and exit
5667   // overview.
5668   ASSERT_FALSE(InOverviewSession());
5669   ToggleOverview();
5670   // Snap a window to the right and test dragging the divider towards the left
5671   // edge of the screen.
5672   split_view_controller()->SnapWindow(window1.get(),
5673                                       SplitViewController::RIGHT);
5674   grid = overview_session()->grid_list()[0].get();
5675   ASSERT_TRUE(grid);
5676 
5677   // Drag the divider to the left edge.
5678   divider_bounds = GetSplitViewDividerBounds(/*is_dragging=*/false);
5679   generator->set_current_screen_location(divider_bounds.CenterPoint());
5680   generator->PressLeftButton();
5681 
5682   generator->MoveMouseTo(20, 0);
5683   // Tests that near the left edge, the grid bounds are fixed at 200 and are
5684   // partially off screen to the left.
5685   EXPECT_EQ(200, grid->bounds().width());
5686   EXPECT_LT(grid->bounds().x(), 0);
5687   generator->ReleaseLeftButton();
5688   SkipDividerSnapAnimation();
5689 }
5690 
5691 // Test that when splitview mode is active, minimizing one of the snapped window
5692 // will insert the minimized window back to overview mode if overview mode is
5693 // active at the moment.
TEST_P(SplitViewOverviewSessionTest,InsertMinimizedWindowBackToOverview)5694 TEST_P(SplitViewOverviewSessionTest, InsertMinimizedWindowBackToOverview) {
5695   const gfx::Rect bounds(400, 400);
5696   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
5697   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
5698 
5699   ToggleOverview();
5700   OverviewItem* overview_item1 = GetOverviewItemForWindow(window1.get());
5701   DragWindowTo(overview_item1, gfx::PointF());
5702   EXPECT_EQ(split_view_controller()->state(),
5703             SplitViewController::State::kLeftSnapped);
5704   EXPECT_EQ(split_view_controller()->left_window(), window1.get());
5705   EXPECT_TRUE(InOverviewSession());
5706 
5707   // Minimize |window1| will put |window1| back to overview grid.
5708   WindowState::Get(window1.get())->Minimize();
5709   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
5710   EXPECT_TRUE(InOverviewSession());
5711   EXPECT_TRUE(GetOverviewItemForWindow(window1.get()));
5712 
5713   // Now snap both |window1| and |window2|.
5714   overview_item1 = GetOverviewItemForWindow(window1.get());
5715   DragWindowTo(overview_item1, gfx::PointF());
5716   wm::ActivateWindow(window2.get());
5717   EXPECT_FALSE(InOverviewSession());
5718   EXPECT_EQ(split_view_controller()->state(),
5719             SplitViewController::State::kBothSnapped);
5720   EXPECT_EQ(split_view_controller()->left_window(), window1.get());
5721   EXPECT_EQ(split_view_controller()->right_window(), window2.get());
5722 
5723   // Minimize |window1| will open overview and put |window1| to overview grid.
5724   WindowState::Get(window1.get())->Minimize();
5725   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
5726   EXPECT_EQ(split_view_controller()->state(),
5727             SplitViewController::State::kRightSnapped);
5728   EXPECT_TRUE(InOverviewSession());
5729   EXPECT_TRUE(GetOverviewItemForWindow(window1.get()));
5730 
5731   // Minimize |window2| also put |window2| to overview grid.
5732   WindowState::Get(window2.get())->Minimize();
5733   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
5734   EXPECT_TRUE(InOverviewSession());
5735   EXPECT_TRUE(GetOverviewItemForWindow(window1.get()));
5736   EXPECT_TRUE(GetOverviewItemForWindow(window2.get()));
5737 }
5738 
5739 // Test that when splitview and overview are both active at the same time, if
5740 // overview is ended due to snapping a window in splitview, the tranform of each
5741 // window in the overview grid is restored.
TEST_P(SplitViewOverviewSessionTest,SnappedWindowAnimationObserverTest)5742 TEST_P(SplitViewOverviewSessionTest, SnappedWindowAnimationObserverTest) {
5743   const gfx::Rect bounds(400, 400);
5744   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
5745   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
5746   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
5747 
5748   // There are four ways to exit overview mode. Verify in each case the
5749   // tranform of each window in the overview window grid has been restored.
5750 
5751   // 1. Overview is ended by dragging a item in overview to snap to splitview.
5752   // Drag |window1| selector item to snap to left. There should be two items on
5753   // the overview grid afterwards, |window2| and |window3|.
5754   ToggleOverview();
5755   EXPECT_FALSE(window1->layer()->GetTargetTransform().IsIdentity());
5756   EXPECT_FALSE(window2->layer()->GetTargetTransform().IsIdentity());
5757   EXPECT_FALSE(window3->layer()->GetTargetTransform().IsIdentity());
5758   OverviewItem* overview_item1 = GetOverviewItemForWindow(window1.get());
5759   DragWindowTo(overview_item1, gfx::PointF());
5760   EXPECT_EQ(SplitViewController::State::kLeftSnapped,
5761             split_view_controller()->state());
5762   // Drag |window2| to snap to right.
5763   OverviewItem* overview_item2 = GetOverviewItemForWindow(window2.get());
5764   const gfx::Rect work_area_rect =
5765       screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
5766           window2.get());
5767   const gfx::PointF end_location2(work_area_rect.width(), 0);
5768   DragWindowTo(overview_item2, end_location2);
5769   EXPECT_EQ(SplitViewController::State::kBothSnapped,
5770             split_view_controller()->state());
5771   EXPECT_FALSE(overview_controller()->InOverviewSession());
5772   EXPECT_TRUE(window1->layer()->GetTargetTransform().IsIdentity());
5773   EXPECT_TRUE(window2->layer()->GetTargetTransform().IsIdentity());
5774   EXPECT_TRUE(window3->layer()->GetTargetTransform().IsIdentity());
5775 
5776   // 2. Overview is ended by ToggleOverview() directly.
5777   // ToggleOverview() will open overview grid in the non-default side of the
5778   // split screen.
5779   ToggleOverview();
5780   EXPECT_TRUE(window1->layer()->GetTargetTransform().IsIdentity());
5781   EXPECT_FALSE(window2->layer()->GetTargetTransform().IsIdentity());
5782   EXPECT_FALSE(window3->layer()->GetTargetTransform().IsIdentity());
5783   EXPECT_EQ(SplitViewController::State::kLeftSnapped,
5784             split_view_controller()->state());
5785   // ToggleOverview() directly.
5786   ToggleOverview();
5787   EXPECT_EQ(SplitViewController::State::kBothSnapped,
5788             split_view_controller()->state());
5789   EXPECT_FALSE(overview_controller()->InOverviewSession());
5790   EXPECT_TRUE(window1->layer()->GetTargetTransform().IsIdentity());
5791   EXPECT_TRUE(window2->layer()->GetTargetTransform().IsIdentity());
5792   EXPECT_TRUE(window3->layer()->GetTargetTransform().IsIdentity());
5793 
5794   // 3. Overview is ended by actviating an existing window.
5795   ToggleOverview();
5796   EXPECT_TRUE(window1->layer()->GetTargetTransform().IsIdentity());
5797   EXPECT_FALSE(window2->layer()->GetTargetTransform().IsIdentity());
5798   EXPECT_FALSE(window3->layer()->GetTargetTransform().IsIdentity());
5799   EXPECT_EQ(SplitViewController::State::kLeftSnapped,
5800             split_view_controller()->state());
5801   wm::ActivateWindow(window2.get());
5802   EXPECT_EQ(SplitViewController::State::kBothSnapped,
5803             split_view_controller()->state());
5804   EXPECT_FALSE(overview_controller()->InOverviewSession());
5805   EXPECT_TRUE(window1->layer()->GetTargetTransform().IsIdentity());
5806   EXPECT_TRUE(window2->layer()->GetTargetTransform().IsIdentity());
5807   EXPECT_TRUE(window3->layer()->GetTargetTransform().IsIdentity());
5808 
5809   // 4. Overview is ended by activating a new window.
5810   ToggleOverview();
5811   EXPECT_TRUE(window1->layer()->GetTargetTransform().IsIdentity());
5812   EXPECT_FALSE(window2->layer()->GetTargetTransform().IsIdentity());
5813   EXPECT_FALSE(window3->layer()->GetTargetTransform().IsIdentity());
5814   EXPECT_EQ(SplitViewController::State::kLeftSnapped,
5815             split_view_controller()->state());
5816   std::unique_ptr<aura::Window> window4(CreateWindow(bounds));
5817   wm::ActivateWindow(window4.get());
5818   EXPECT_EQ(SplitViewController::State::kBothSnapped,
5819             split_view_controller()->state());
5820   EXPECT_FALSE(overview_controller()->InOverviewSession());
5821   EXPECT_TRUE(window1->layer()->GetTargetTransform().IsIdentity());
5822   EXPECT_TRUE(window2->layer()->GetTargetTransform().IsIdentity());
5823   EXPECT_TRUE(window3->layer()->GetTargetTransform().IsIdentity());
5824   EXPECT_TRUE(window4->layer()->GetTargetTransform().IsIdentity());
5825 }
5826 
5827 // Test that when split view and overview are both active at the same time,
5828 // double tapping on the divider can swap the window's position with the
5829 // overview window grid's postion.
TEST_P(SplitViewOverviewSessionTest,SwapWindowAndOverviewGrid)5830 TEST_P(SplitViewOverviewSessionTest, SwapWindowAndOverviewGrid) {
5831   const gfx::Rect bounds(400, 400);
5832   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
5833   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
5834 
5835   ToggleOverview();
5836   OverviewItem* overview_item1 = GetOverviewItemForWindow(window1.get());
5837   DragWindowTo(overview_item1, gfx::PointF());
5838   EXPECT_EQ(split_view_controller()->state(),
5839             SplitViewController::State::kLeftSnapped);
5840   EXPECT_EQ(split_view_controller()->default_snap_position(),
5841             SplitViewController::LEFT);
5842   EXPECT_TRUE(overview_controller()->InOverviewSession());
5843   EXPECT_EQ(
5844       GetGridBounds(),
5845       split_view_controller()->GetSnappedWindowBoundsInScreen(
5846           SplitViewController::RIGHT, /*window_for_minimum_size=*/nullptr));
5847 
5848   split_view_controller()->SwapWindows();
5849   EXPECT_EQ(split_view_controller()->state(),
5850             SplitViewController::State::kRightSnapped);
5851   EXPECT_EQ(split_view_controller()->default_snap_position(),
5852             SplitViewController::RIGHT);
5853   EXPECT_EQ(
5854       GetGridBounds(),
5855       split_view_controller()->GetSnappedWindowBoundsInScreen(
5856           SplitViewController::LEFT, /*window_for_minimum_size=*/nullptr));
5857 }
5858 
5859 // Test that in tablet mode, pressing tab key in overview should not crash.
TEST_P(SplitViewOverviewSessionTest,NoCrashWhenPressTabKey)5860 TEST_P(SplitViewOverviewSessionTest, NoCrashWhenPressTabKey) {
5861   std::unique_ptr<aura::Window> window(CreateWindow(gfx::Rect(400, 400)));
5862   std::unique_ptr<aura::Window> window2(CreateWindow(gfx::Rect(400, 400)));
5863 
5864   // In overview, there should be no crash when pressing tab key.
5865   ToggleOverview();
5866   EXPECT_TRUE(InOverviewSession());
5867   SendKey(ui::VKEY_TAB);
5868   EXPECT_TRUE(InOverviewSession());
5869 
5870   // When splitview and overview are both active, there should be no crash when
5871   // pressing tab key.
5872   split_view_controller()->SnapWindow(window.get(), SplitViewController::LEFT);
5873   EXPECT_TRUE(InOverviewSession());
5874   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
5875 
5876   SendKey(ui::VKEY_TAB);
5877   EXPECT_TRUE(InOverviewSession());
5878 }
5879 
5880 // Tests closing a snapped window while in overview mode.
TEST_P(SplitViewOverviewSessionTest,ClosingSplitViewWindow)5881 TEST_P(SplitViewOverviewSessionTest, ClosingSplitViewWindow) {
5882   const gfx::Rect bounds(400, 400);
5883   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
5884   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
5885 
5886   ToggleOverview();
5887   // Drag |window1| selector item to snap to left.
5888   OverviewItem* overview_item1 = GetOverviewItemForWindow(window1.get());
5889   DragWindowTo(overview_item1, gfx::PointF(0, 0));
5890   EXPECT_TRUE(overview_controller()->InOverviewSession());
5891   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
5892 
5893   // Now close the snapped |window1|. We should remain in overview mode and the
5894   // overview focus window should regain focus.
5895   window1.reset();
5896   EXPECT_TRUE(overview_controller()->InOverviewSession());
5897   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
5898   EXPECT_EQ(overview_session()->GetOverviewFocusWindow(),
5899             window_util::GetFocusedWindow());
5900 }
5901 
5902 // Test that you cannot drag from overview during the split view divider
5903 // animation.
TEST_P(SplitViewOverviewSessionTest,CannotDragFromOverviewDuringSplitViewDividerAnimation)5904 TEST_P(SplitViewOverviewSessionTest,
5905        CannotDragFromOverviewDuringSplitViewDividerAnimation) {
5906   std::unique_ptr<aura::Window> snapped_window = CreateTestWindow();
5907   std::unique_ptr<aura::Window> overview_window = CreateTestWindow();
5908   ToggleOverview();
5909   split_view_controller()->SnapWindow(snapped_window.get(),
5910                                       SplitViewController::LEFT);
5911 
5912   gfx::Point divider_drag_point =
5913       split_view_controller()
5914           ->split_view_divider()
5915           ->GetDividerBoundsInScreen(/*is_dragging=*/false)
5916           .CenterPoint();
5917   split_view_controller()->StartResize(divider_drag_point);
5918   divider_drag_point.Offset(20, 0);
5919   split_view_controller()->Resize(divider_drag_point);
5920   split_view_controller()->EndResize(divider_drag_point);
5921   ASSERT_TRUE(IsDividerAnimating());
5922 
5923   OverviewItem* overview_item = GetOverviewItemForWindow(overview_window.get());
5924   overview_session()->InitiateDrag(overview_item,
5925                                    overview_item->target_bounds().CenterPoint(),
5926                                    /*is_touch_dragging=*/true);
5927   EXPECT_FALSE(overview_item->IsDragItem());
5928 }
5929 
5930 // Tests that a window which is dragged to a splitview zone is destroyed, the
5931 // grid bounds return to a non-splitview bounds.
TEST_P(SplitViewOverviewSessionTest,GridBoundsAfterWindowDestroyed)5932 TEST_P(SplitViewOverviewSessionTest, GridBoundsAfterWindowDestroyed) {
5933   // Create two windows otherwise we exit overview after one window is
5934   // destroyed.
5935   std::unique_ptr<aura::Window> window1 = CreateTestWindow();
5936   std::unique_ptr<aura::Window> window2 = CreateTestWindow();
5937 
5938   ToggleOverview();
5939   const gfx::Rect grid_bounds = GetGridBounds();
5940   // Drag the item such that the splitview preview area shows up and the grid
5941   // bounds shrink.
5942   OverviewItem* overview_item = GetOverviewItemForWindow(window1.get());
5943   overview_session()->InitiateDrag(overview_item,
5944                                    overview_item->target_bounds().CenterPoint(),
5945                                    /*is_touch_dragging=*/true);
5946   overview_session()->Drag(overview_item, gfx::PointF(1.f, 1.f));
5947   EXPECT_NE(grid_bounds, GetGridBounds());
5948 
5949   // Tests that when the dragged window is destroyed, the grid bounds return to
5950   // their normal size.
5951   window1.reset();
5952   EXPECT_EQ(grid_bounds, GetGridBounds());
5953 }
5954 
5955 // Tests that overview stays active if we have a snapped window.
TEST_P(SplitViewOverviewSessionTest,OnScreenLock)5956 TEST_P(SplitViewOverviewSessionTest, OnScreenLock) {
5957   std::unique_ptr<aura::Window> window1 = CreateTestWindow();
5958   std::unique_ptr<aura::Window> window2 = CreateTestWindow();
5959 
5960   // Overview should exit if no snapped window after locking/unlocking.
5961   ToggleOverview();
5962   GetSessionControllerClient()->LockScreen();
5963   GetSessionControllerClient()->UnlockScreen();
5964   ASSERT_FALSE(InOverviewSession());
5965 
5966   ToggleOverview();
5967   split_view_controller()->SnapWindow(window2.get(), SplitViewController::LEFT);
5968 
5969   // Lock and unlock the machine. Test that we are still in overview and
5970   // splitview.
5971   GetSessionControllerClient()->LockScreen();
5972   GetSessionControllerClient()->UnlockScreen();
5973   EXPECT_TRUE(InOverviewSession());
5974   EXPECT_EQ(SplitViewController::State::kLeftSnapped,
5975             split_view_controller()->state());
5976 }
5977 
5978 // Verify that selecting an minimized snappable window while in split view
5979 // triggers auto snapping.
TEST_P(SplitViewOverviewSessionTest,SelectMinimizedSnappableWindowInSplitView)5980 TEST_P(SplitViewOverviewSessionTest,
5981        SelectMinimizedSnappableWindowInSplitView) {
5982   // Create two snappable windows.
5983   std::unique_ptr<aura::Window> snapped_window = CreateTestWindow();
5984   std::unique_ptr<aura::Window> minimized_window = CreateTestWindow();
5985   WindowState::Get(minimized_window.get())->Minimize();
5986 
5987   ToggleOverview();
5988   ASSERT_TRUE(overview_controller()->InOverviewSession());
5989 
5990   // Snap a window to enter split view mode.
5991   split_view_controller()->SnapWindow(snapped_window.get(),
5992                                       SplitViewController::LEFT);
5993   EXPECT_EQ(SplitViewController::State::kLeftSnapped,
5994             split_view_controller()->state());
5995 
5996   // Select the minimized window.
5997   OverviewItem* overview_item =
5998       GetOverviewItemForWindow(minimized_window.get());
5999   ui::test::EventGenerator* generator = GetEventGenerator();
6000   generator->set_current_screen_location(
6001       gfx::ToRoundedPoint(overview_item->target_bounds().CenterPoint()));
6002   generator->ClickLeftButton();
6003 
6004   // Verify that both windows are in a snapped state and overview mode is ended.
6005   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
6006   EXPECT_TRUE(
6007       split_view_controller()->IsWindowInSplitView(snapped_window.get()));
6008   EXPECT_EQ(
6009       split_view_controller()->GetPositionOfSnappedWindow(snapped_window.get()),
6010       SplitViewController::LEFT);
6011   EXPECT_TRUE(
6012       split_view_controller()->IsWindowInSplitView(minimized_window.get()));
6013   EXPECT_EQ(split_view_controller()->GetPositionOfSnappedWindow(
6014                 minimized_window.get()),
6015             SplitViewController::RIGHT);
6016   EXPECT_FALSE(overview_controller()->InOverviewSession());
6017   EXPECT_EQ(minimized_window.get(), window_util::GetActiveWindow());
6018 }
6019 
6020 // Verify no crash (or DCHECK failure) if you exit and re-enter mirror mode
6021 // while in tablet split view with empty overview.
TEST_P(SplitViewOverviewSessionTest,ExitAndReenterMirrorModeWithEmptyOverview)6022 TEST_P(SplitViewOverviewSessionTest,
6023        ExitAndReenterMirrorModeWithEmptyOverview) {
6024   UpdateDisplay("800x600,800x600");
6025   std::unique_ptr<aura::Window> window = CreateTestWindow();
6026   ToggleOverview();
6027   split_view_controller()->SnapWindow(window.get(), SplitViewController::LEFT);
6028   display_manager()->SetMirrorMode(display::MirrorMode::kOff, base::nullopt);
6029   display_manager()->SetMirrorMode(display::MirrorMode::kNormal, base::nullopt);
6030 }
6031 
6032 // Test the split view and overview functionalities in clamshell mode. Split
6033 // view is only active when overview is active in clamshell mode.
6034 class SplitViewOverviewSessionInClamshellTest
6035     : public SplitViewOverviewSessionTest {
6036  public:
6037   SplitViewOverviewSessionInClamshellTest() = default;
6038   ~SplitViewOverviewSessionInClamshellTest() override = default;
6039 
6040   // AshTestBase:
SetUp()6041   void SetUp() override {
6042     scoped_feature_list_.InitAndEnableFeature(
6043         features::kDragToSnapInClamshellMode);
6044     OverviewSessionTest::SetUp();
6045     Shell::Get()->tablet_mode_controller()->SetEnabledForTest(false);
6046     DCHECK(ShouldAllowSplitView());
6047   }
6048 
CreateWindowWithHitTestComponent(int hit_test_component,const gfx::Rect & bounds)6049   aura::Window* CreateWindowWithHitTestComponent(int hit_test_component,
6050                                                  const gfx::Rect& bounds) {
6051     return CreateTestWindowInShellWithDelegate(
6052         new TestWindowHitTestDelegate(hit_test_component), 0, bounds);
6053   }
6054 
6055  private:
6056   class TestWindowHitTestDelegate : public aura::test::TestWindowDelegate {
6057    public:
TestWindowHitTestDelegate(int hit_test_component)6058     explicit TestWindowHitTestDelegate(int hit_test_component) {
6059       set_window_component(hit_test_component);
6060     }
6061     ~TestWindowHitTestDelegate() override = default;
6062 
6063    private:
6064     // aura::Test::TestWindowDelegate:
OnWindowDestroyed(aura::Window * window)6065     void OnWindowDestroyed(aura::Window* window) override { delete this; }
6066 
6067     DISALLOW_COPY_AND_ASSIGN(TestWindowHitTestDelegate);
6068   };
6069 
6070   base::test::ScopedFeatureList scoped_feature_list_;
6071   DISALLOW_COPY_AND_ASSIGN(SplitViewOverviewSessionInClamshellTest);
6072 };
6073 
6074 // Test some basic functionalities in clamshell splitview mode.
TEST_P(SplitViewOverviewSessionInClamshellTest,BasicFunctionalitiesTest)6075 TEST_P(SplitViewOverviewSessionInClamshellTest, BasicFunctionalitiesTest) {
6076   UpdateDisplay("600x400");
6077   EXPECT_FALSE(Shell::Get()->tablet_mode_controller()->InTabletMode());
6078 
6079   // 1. Test the 1 window scenario.
6080   const gfx::Rect bounds(400, 400);
6081   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
6082   WindowState* window_state1 = WindowState::Get(window1.get());
6083   EXPECT_FALSE(window_state1->IsSnapped());
6084   ToggleOverview();
6085   EXPECT_TRUE(overview_controller()->InOverviewSession());
6086   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6087   // Drag |window1| selector item to snap to left.
6088   OverviewItem* overview_item1 = GetOverviewItemForWindow(window1.get());
6089   DragWindowTo(overview_item1, gfx::PointF(0, 0));
6090   // Since the only window is snapped, overview and splitview should be both
6091   // ended.
6092   EXPECT_EQ(window_state1->GetStateType(), WindowStateType::kLeftSnapped);
6093   EXPECT_FALSE(overview_controller()->InOverviewSession());
6094   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6095 
6096   // 2. Test if one window is snapped, the other windows are showing in
6097   // overview, close all windows in overview will end overview and also
6098   // splitview.
6099   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
6100   ToggleOverview();
6101   EXPECT_TRUE(overview_controller()->InOverviewSession());
6102   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6103   overview_item1 = GetOverviewItemForWindow(window1.get());
6104   DragWindowTo(overview_item1, gfx::PointF(600, 300));
6105   // SplitView and overview are both active at the moment.
6106   EXPECT_TRUE(overview_controller()->InOverviewSession());
6107   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
6108   EXPECT_TRUE(split_view_controller()->IsWindowInSplitView(window1.get()));
6109   EXPECT_TRUE(overview_controller()->overview_session()->IsWindowInOverview(
6110       window2.get()));
6111   EXPECT_EQ(window_state1->GetStateType(), WindowStateType::kRightSnapped);
6112   // Close |window2| will end overview and splitview.
6113   window2.reset();
6114   EXPECT_FALSE(overview_controller()->InOverviewSession());
6115   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6116 
6117   // 3. Test that snap 2 windows will end overview and splitview.
6118   std::unique_ptr<aura::Window> window3(CreateWindow(bounds));
6119   ToggleOverview();
6120   overview_item1 = GetOverviewItemForWindow(window1.get());
6121   DragWindowTo(overview_item1, gfx::PointF(0, 0));
6122   OverviewItem* overview_item3 = GetOverviewItemForWindow(window3.get());
6123   DragWindowTo(overview_item3, gfx::PointF(600, 300));
6124   EXPECT_EQ(window_state1->GetStateType(), WindowStateType::kLeftSnapped);
6125   EXPECT_EQ(WindowState::Get(window3.get())->GetStateType(),
6126             WindowStateType::kRightSnapped);
6127   EXPECT_FALSE(overview_controller()->InOverviewSession());
6128   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6129 
6130   // 4. Test if one window is snapped, the other windows are showing in
6131   // overview, we can drag another window in overview to snap in splitview, and
6132   // the previous snapped window will be put back into overview.
6133   std::unique_ptr<aura::Window> window4(CreateWindow(bounds));
6134   ToggleOverview();
6135   overview_item1 = GetOverviewItemForWindow(window1.get());
6136   DragWindowTo(overview_item1, gfx::PointF(0, 0));
6137   EXPECT_FALSE(overview_controller()->overview_session()->IsWindowInOverview(
6138       window1.get()));
6139   overview_item3 = GetOverviewItemForWindow(window3.get());
6140   DragWindowTo(overview_item3, gfx::PointF(0, 0));
6141   EXPECT_FALSE(overview_controller()->overview_session()->IsWindowInOverview(
6142       window3.get()));
6143   EXPECT_TRUE(overview_controller()->overview_session()->IsWindowInOverview(
6144       window1.get()));
6145   EXPECT_EQ(window_state1->GetStateType(), WindowStateType::kLeftSnapped);
6146   EXPECT_EQ(WindowState::Get(window3.get())->GetStateType(),
6147             WindowStateType::kLeftSnapped);
6148   EXPECT_TRUE(overview_controller()->InOverviewSession());
6149   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
6150   // End overview, test that we'll not auto-snap a window to the right side of
6151   // the screen.
6152   EXPECT_EQ(WindowState::Get(window4.get())->GetStateType(),
6153             WindowStateType::kDefault);
6154   ToggleOverview();
6155   EXPECT_EQ(WindowState::Get(window4.get())->GetStateType(),
6156             WindowStateType::kDefault);
6157   EXPECT_FALSE(overview_controller()->InOverviewSession());
6158   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6159 
6160   // 5. Test if one window is snapped, the other window are showing in overview,
6161   // activating an new window will not auto-snap the new window. Overview and
6162   // splitview should be ended.
6163   ToggleOverview();
6164   overview_item1 = GetOverviewItemForWindow(window1.get());
6165   DragWindowTo(overview_item1, gfx::PointF(0, 0));
6166   EXPECT_TRUE(overview_controller()->InOverviewSession());
6167   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
6168   std::unique_ptr<aura::Window> window5(CreateWindow(bounds));
6169   EXPECT_EQ(WindowState::Get(window5.get())->GetStateType(),
6170             WindowStateType::kDefault);
6171   wm::ActivateWindow(window5.get());
6172   EXPECT_EQ(WindowState::Get(window5.get())->GetStateType(),
6173             WindowStateType::kDefault);
6174   EXPECT_FALSE(overview_controller()->InOverviewSession());
6175   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6176 
6177   // 6. Test if one window is snapped, the other window is showing in overview,
6178   // close the snapped window will end split view, but overview is still active.
6179   ToggleOverview();
6180   const gfx::Rect overview_bounds = GetGridBounds();
6181   overview_item1 = GetOverviewItemForWindow(window1.get());
6182   DragWindowTo(overview_item1, gfx::PointF(0, 0));
6183   EXPECT_TRUE(overview_controller()->InOverviewSession());
6184   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
6185   EXPECT_NE(GetGridBounds(), overview_bounds);
6186   EXPECT_EQ(GetGridBounds(), GetSplitViewRightWindowBounds());
6187   window1.reset();
6188   EXPECT_TRUE(overview_controller()->InOverviewSession());
6189   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6190   // Overview bounds will adjust from snapped bounds to fullscreen bounds.
6191   EXPECT_EQ(GetGridBounds(), overview_bounds);
6192 
6193   // 7. Test if split view mode is active, open the app list will end both
6194   // overview and splitview.
6195   overview_item3 = GetOverviewItemForWindow(window3.get());
6196   DragWindowTo(overview_item3, gfx::PointF(0, 0));
6197   EXPECT_TRUE(overview_controller()->InOverviewSession());
6198   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
6199   // Open app list.
6200   AppListControllerImpl* app_list_controller =
6201       Shell::Get()->app_list_controller();
6202   app_list_controller->ToggleAppList(
6203       display::Screen::GetScreen()->GetDisplayNearestWindow(window3.get()).id(),
6204       AppListShowSource::kSearchKey, base::TimeTicks());
6205   base::RunLoop().RunUntilIdle();
6206   EXPECT_FALSE(overview_controller()->InOverviewSession());
6207   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6208 
6209   // 8. Test if splitview is not active, open the app list will end overview if
6210   // overview is active.
6211   ToggleOverview();
6212   // Open app list.
6213   app_list_controller->ToggleAppList(
6214       display::Screen::GetScreen()->GetDisplayNearestWindow(window3.get()).id(),
6215       AppListShowSource::kSearchKey, base::TimeTicks());
6216   base::RunLoop().RunUntilIdle();
6217   EXPECT_FALSE(overview_controller()->InOverviewSession());
6218   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6219 }
6220 
6221 // Test overview exit animation histograms when you drag to snap two windows on
6222 // opposite sides.
TEST_P(SplitViewOverviewSessionInClamshellTest,BothSnappedOverviewExitAnimationHistogramTest)6223 TEST_P(SplitViewOverviewSessionInClamshellTest,
6224        BothSnappedOverviewExitAnimationHistogramTest) {
6225   ui::ScopedAnimationDurationScaleMode anmatin_scale(
6226       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
6227   const gfx::Rect bounds(400, 400);
6228   std::unique_ptr<aura::Window> left_window(CreateWindow(bounds));
6229   std::unique_ptr<aura::Window> right_window(CreateWindow(bounds));
6230   CheckOverviewEnterExitHistogram("Init", {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0});
6231 
6232   ToggleOverview();
6233   WaitForOverviewEnterAnimation();
6234   CheckOverviewEnterExitHistogram("EnterOverview", {1, 0, 0, 0, 0},
6235                                   {0, 0, 0, 0, 0});
6236 
6237   DragWindowTo(GetOverviewItemForWindow(left_window.get()), gfx::PointF(0, 0));
6238   DragWindowTo(GetOverviewItemForWindow(right_window.get()),
6239                gfx::PointF(799, 300));
6240   WaitForOverviewExitAnimation();
6241   CheckOverviewEnterExitHistogram("SnapBothSides", {1, 0, 0, 0, 0},
6242                                   {1, 0, 0, 0, 1});
6243 }
6244 
6245 // Test that when overview and splitview are both active, only resize that
6246 // happens on eligible window components will change snapped window bounds and
6247 // overview bounds at the same time.
TEST_P(SplitViewOverviewSessionInClamshellTest,ResizeWindowTest)6248 TEST_P(SplitViewOverviewSessionInClamshellTest, ResizeWindowTest) {
6249   UpdateDisplay("600x400");
6250   const gfx::Rect bounds(400, 400);
6251   std::unique_ptr<aura::Window> window1(
6252       CreateWindowWithHitTestComponent(HTRIGHT, bounds));
6253   std::unique_ptr<aura::Window> window2(
6254       CreateWindowWithHitTestComponent(HTLEFT, bounds));
6255   std::unique_ptr<aura::Window> window3(
6256       CreateWindowWithHitTestComponent(HTTOP, bounds));
6257   std::unique_ptr<aura::Window> window4(
6258       CreateWindowWithHitTestComponent(HTBOTTOM, bounds));
6259 
6260   ToggleOverview();
6261   gfx::Rect overview_full_bounds = GetGridBounds();
6262   OverviewItem* overview_item1 = GetOverviewItemForWindow(window1.get());
6263   DragWindowTo(overview_item1, gfx::PointF(0, 0));
6264   EXPECT_NE(GetGridBounds(), overview_full_bounds);
6265   EXPECT_EQ(GetGridBounds(), GetSplitViewRightWindowBounds());
6266   gfx::Rect overview_snapped_bounds = GetGridBounds();
6267 
6268   // Resize that happens on the right edge of the left snapped window will
6269   // resize the window and overview at the same time.
6270   ui::test::EventGenerator generator1(Shell::GetPrimaryRootWindow(),
6271                                       window1.get());
6272   generator1.PressLeftButton();
6273   CheckWindowResizingPerformanceHistograms("BeforeResizingLeftSnappedWindow1",
6274                                            0, 0, 0, 0);
6275   generator1.MoveMouseBy(50, 50);
6276   CheckWindowResizingPerformanceHistograms("WhileResizingLeftSnappedWindow1", 0,
6277                                            0, 1, 0);
6278   generator1.ReleaseLeftButton();
6279   CheckWindowResizingPerformanceHistograms("AfterResizingLeftSnappedWindow1", 0,
6280                                            0, 1, 1);
6281   EXPECT_TRUE(overview_controller()->InOverviewSession());
6282   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
6283   EXPECT_NE(GetGridBounds(), overview_full_bounds);
6284   EXPECT_NE(GetGridBounds(), overview_snapped_bounds);
6285   EXPECT_EQ(GetGridBounds(), GetSplitViewRightWindowBounds());
6286 
6287   // Resize that happens on the left edge of the left snapped window will end
6288   // overview. The same for the resize that happens on the top or bottom edge of
6289   // the left snapped window.
6290   OverviewItem* overview_item2 = GetOverviewItemForWindow(window2.get());
6291   DragWindowTo(overview_item2, gfx::PointF(0, 0));
6292   EXPECT_TRUE(overview_controller()->InOverviewSession());
6293   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
6294   ui::test::EventGenerator generator2(Shell::GetPrimaryRootWindow(),
6295                                       window2.get());
6296   generator2.DragMouseBy(50, 50);
6297   CheckWindowResizingPerformanceHistograms("AfterResizingLeftSnappedWindow2", 0,
6298                                            0, 1, 1);
6299   EXPECT_FALSE(overview_controller()->InOverviewSession());
6300   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6301 
6302   ToggleOverview();
6303   OverviewItem* overview_item3 = GetOverviewItemForWindow(window3.get());
6304   DragWindowTo(overview_item3, gfx::PointF(0, 0));
6305   ui::test::EventGenerator generator3(Shell::GetPrimaryRootWindow(),
6306                                       window3.get());
6307   generator3.DragMouseBy(50, 50);
6308   CheckWindowResizingPerformanceHistograms("AfterResizingLeftSnappedWindow3", 0,
6309                                            0, 1, 1);
6310   EXPECT_FALSE(overview_controller()->InOverviewSession());
6311   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6312 
6313   ToggleOverview();
6314   OverviewItem* overview_item4 = GetOverviewItemForWindow(window4.get());
6315   DragWindowTo(overview_item4, gfx::PointF(0, 0));
6316   ui::test::EventGenerator generator4(Shell::GetPrimaryRootWindow(),
6317                                       window4.get());
6318   generator4.DragMouseBy(50, 50);
6319   CheckWindowResizingPerformanceHistograms("AfterResizingLeftSnappedWindow4", 0,
6320                                            0, 1, 1);
6321   EXPECT_FALSE(overview_controller()->InOverviewSession());
6322   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6323 
6324   // Now try snapping on the right.
6325   ToggleOverview();
6326   overview_full_bounds = GetGridBounds();
6327   overview_item2 = GetOverviewItemForWindow(window2.get());
6328   DragWindowTo(overview_item2, gfx::PointF(599, 0));
6329   EXPECT_NE(GetGridBounds(), overview_full_bounds);
6330   EXPECT_EQ(GetGridBounds(), GetSplitViewLeftWindowBounds());
6331   overview_snapped_bounds = GetGridBounds();
6332 
6333   ui::test::EventGenerator generator5(Shell::GetPrimaryRootWindow(),
6334                                       window2.get());
6335   generator5.PressLeftButton();
6336   CheckWindowResizingPerformanceHistograms("BeforeResizingRightSnappedWindow2",
6337                                            0, 0, 1, 1);
6338   generator5.MoveMouseBy(50, 50);
6339   CheckWindowResizingPerformanceHistograms("WhileResizingRightSnappedWindow2",
6340                                            0, 0, 2, 1);
6341   generator5.ReleaseLeftButton();
6342   CheckWindowResizingPerformanceHistograms("AfterResizingRightSnappedWindow2",
6343                                            0, 0, 2, 2);
6344   EXPECT_TRUE(overview_controller()->InOverviewSession());
6345   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
6346   EXPECT_NE(GetGridBounds(), overview_full_bounds);
6347   EXPECT_NE(GetGridBounds(), overview_snapped_bounds);
6348   EXPECT_EQ(GetGridBounds(), GetSplitViewLeftWindowBounds());
6349 
6350   overview_item1 = GetOverviewItemForWindow(window1.get());
6351   DragWindowTo(overview_item1, gfx::PointF(599, 0));
6352   EXPECT_TRUE(overview_controller()->InOverviewSession());
6353   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
6354   ui::test::EventGenerator generator6(Shell::GetPrimaryRootWindow(),
6355                                       window1.get());
6356   generator6.DragMouseBy(50, 50);
6357   CheckWindowResizingPerformanceHistograms("AfterResizingRightSnappedWindow1",
6358                                            0, 0, 2, 2);
6359   EXPECT_FALSE(overview_controller()->InOverviewSession());
6360   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6361 
6362   ToggleOverview();
6363   overview_item3 = GetOverviewItemForWindow(window3.get());
6364   DragWindowTo(overview_item3, gfx::PointF(599, 0));
6365   ui::test::EventGenerator generator7(Shell::GetPrimaryRootWindow(),
6366                                       window3.get());
6367   generator7.DragMouseBy(50, 50);
6368   CheckWindowResizingPerformanceHistograms("AfterResizingRightSnappedWindow3",
6369                                            0, 0, 2, 2);
6370   EXPECT_FALSE(overview_controller()->InOverviewSession());
6371   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6372 
6373   ToggleOverview();
6374   overview_item4 = GetOverviewItemForWindow(window4.get());
6375   DragWindowTo(overview_item4, gfx::PointF(599, 0));
6376   ui::test::EventGenerator generator8(Shell::GetPrimaryRootWindow(),
6377                                       window4.get());
6378   generator8.DragMouseBy(50, 50);
6379   CheckWindowResizingPerformanceHistograms("AfterResizingRightSnappedWindow4",
6380                                            0, 0, 2, 2);
6381   EXPECT_FALSE(overview_controller()->InOverviewSession());
6382   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6383 }
6384 
6385 // Test closing the split view window while resizing it.
TEST_P(SplitViewOverviewSessionInClamshellTest,CloseWindowWhileResizingItTest)6386 TEST_P(SplitViewOverviewSessionInClamshellTest,
6387        CloseWindowWhileResizingItTest) {
6388   UpdateDisplay("600x400");
6389   const gfx::Rect bounds(400, 400);
6390   std::unique_ptr<aura::Window> split_view_window(
6391       CreateWindowWithHitTestComponent(HTRIGHT, bounds));
6392   std::unique_ptr<aura::Window> overview_window(CreateWindow(bounds));
6393   ToggleOverview();
6394   DragWindowTo(GetOverviewItemForWindow(split_view_window.get()),
6395                gfx::PointF(0.f, 0.f));
6396   EXPECT_TRUE(overview_controller()->InOverviewSession());
6397   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
6398   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
6399                                      split_view_window.get());
6400   generator.PressLeftButton();
6401   CheckWindowResizingPerformanceHistograms("AfterPressingMouseButton", 0, 0, 0,
6402                                            0);
6403   generator.MoveMouseBy(50, 50);
6404   CheckWindowResizingPerformanceHistograms("WhileResizing", 0, 0, 1, 0);
6405   split_view_window.reset();
6406   CheckWindowResizingPerformanceHistograms("AfterClosing", 0, 0, 1, 1);
6407   EXPECT_TRUE(overview_controller()->InOverviewSession());
6408   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6409   generator.ReleaseLeftButton();
6410   CheckWindowResizingPerformanceHistograms("AfterReleasingMouseButton", 0, 0, 1,
6411                                            1);
6412   EXPECT_TRUE(overview_controller()->InOverviewSession());
6413   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6414 }
6415 
6416 class TestWindowStateDelegate : public WindowStateDelegate {
6417  public:
6418   TestWindowStateDelegate() = default;
6419   TestWindowStateDelegate(const TestWindowStateDelegate&) = delete;
6420   TestWindowStateDelegate& operator=(const TestWindowStateDelegate&) = delete;
6421   ~TestWindowStateDelegate() override = default;
6422 
6423   // WindowStateDelegate:
OnDragStarted(int component)6424   void OnDragStarted(int component) override { drag_in_progress_ = true; }
OnDragFinished(bool cancel,const gfx::PointF & location)6425   void OnDragFinished(bool cancel, const gfx::PointF& location) override {
6426     drag_in_progress_ = false;
6427   }
6428 
drag_in_progress()6429   bool drag_in_progress() { return drag_in_progress_; }
6430 
6431  private:
6432   bool drag_in_progress_ = false;
6433 };
6434 
6435 // Tests that when a split view window carries over to clamshell split view
6436 // while the divider is being dragged, the window resize is properly completed.
TEST_P(SplitViewOverviewSessionInClamshellTest,CarryOverToClamshellSplitViewWhileResizing)6437 TEST_P(SplitViewOverviewSessionInClamshellTest,
6438        CarryOverToClamshellSplitViewWhileResizing) {
6439   std::unique_ptr<aura::Window> snapped_window = CreateTestWindow();
6440   std::unique_ptr<aura::Window> overview_window = CreateTestWindow();
6441   WindowState* snapped_window_state = WindowState::Get(snapped_window.get());
6442   TestWindowStateDelegate* snapped_window_state_delegate =
6443       new TestWindowStateDelegate();
6444   snapped_window_state->SetDelegate(
6445       base::WrapUnique(snapped_window_state_delegate));
6446 
6447   // Enter clamshell split view and then switch to tablet mode.
6448   ToggleOverview();
6449   split_view_controller()->SnapWindow(snapped_window.get(),
6450                                       SplitViewController::LEFT);
6451   EnterTabletMode();
6452   ASSERT_EQ(SplitViewController::State::kLeftSnapped,
6453             split_view_controller()->state());
6454   ASSERT_EQ(snapped_window.get(), split_view_controller()->left_window());
6455 
6456   // Start dragging the divider.
6457   ui::test::EventGenerator* generator = GetEventGenerator();
6458   generator->set_current_screen_location(
6459       split_view_controller()
6460           ->split_view_divider()
6461           ->GetDividerBoundsInScreen(/*is_dragging=*/false)
6462           .CenterPoint());
6463   generator->PressTouch();
6464   generator->MoveTouchBy(5, 0);
6465   EXPECT_TRUE(snapped_window_state_delegate->drag_in_progress());
6466   EXPECT_NE(nullptr, snapped_window_state->drag_details());
6467 
6468   // End tablet mode.
6469   Shell::Get()->tablet_mode_controller()->SetEnabledForTest(false);
6470   ASSERT_EQ(SplitViewController::State::kLeftSnapped,
6471             split_view_controller()->state());
6472   ASSERT_EQ(snapped_window.get(), split_view_controller()->left_window());
6473   EXPECT_FALSE(snapped_window_state_delegate->drag_in_progress());
6474   EXPECT_EQ(nullptr, snapped_window_state->drag_details());
6475 }
6476 
6477 // Test that overview and clamshell split view end if you double click the edge
6478 // of the split view window where it meets the overview grid.
TEST_P(SplitViewOverviewSessionInClamshellTest,HorizontalMaximizeTest)6479 TEST_P(SplitViewOverviewSessionInClamshellTest, HorizontalMaximizeTest) {
6480   const gfx::Rect bounds(400, 400);
6481   std::unique_ptr<aura::Window> snapped_window(
6482       CreateWindowWithHitTestComponent(HTRIGHT, bounds));
6483   std::unique_ptr<aura::Window> overview_window = CreateTestWindow(bounds);
6484   ToggleOverview();
6485   split_view_controller()->SnapWindow(snapped_window.get(),
6486                                       SplitViewController::LEFT);
6487   EXPECT_TRUE(overview_controller()->InOverviewSession());
6488   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
6489   ui::test::EventGenerator(Shell::GetPrimaryRootWindow(), snapped_window.get())
6490       .DoubleClickLeftButton();
6491   EXPECT_FALSE(overview_controller()->InOverviewSession());
6492   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6493 }
6494 
6495 // Test that when laptop splitview mode is active, moving the snapped window
6496 // will end splitview and overview at the same time.
TEST_P(SplitViewOverviewSessionInClamshellTest,MoveWindowTest)6497 TEST_P(SplitViewOverviewSessionInClamshellTest, MoveWindowTest) {
6498   const gfx::Rect bounds(400, 400);
6499   std::unique_ptr<aura::Window> window1(
6500       CreateWindowWithHitTestComponent(HTCAPTION, bounds));
6501   std::unique_ptr<aura::Window> window2(
6502       CreateWindowWithHitTestComponent(HTCAPTION, bounds));
6503 
6504   ToggleOverview();
6505   OverviewItem* overview_item1 = GetOverviewItemForWindow(window1.get());
6506   DragWindowTo(overview_item1, gfx::PointF(0, 0));
6507   EXPECT_TRUE(overview_controller()->InOverviewSession());
6508   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
6509 
6510   ui::test::EventGenerator generator1(Shell::GetPrimaryRootWindow(),
6511                                       window1.get());
6512   generator1.DragMouseBy(50, 50);
6513   EXPECT_FALSE(overview_controller()->InOverviewSession());
6514   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6515 }
6516 
6517 // Test that in clamshell splitview mode, if the snapped window is minimized,
6518 // splitview mode and overview mode are both ended.
TEST_P(SplitViewOverviewSessionInClamshellTest,MinimizedWindowTest)6519 TEST_P(SplitViewOverviewSessionInClamshellTest, MinimizedWindowTest) {
6520   const gfx::Rect bounds(400, 400);
6521   std::unique_ptr<aura::Window> window1(CreateWindow(bounds));
6522   std::unique_ptr<aura::Window> window2(CreateWindow(bounds));
6523 
6524   ToggleOverview();
6525   // Drag |window1| selector item to snap to left.
6526   OverviewItem* overview_item1 = GetOverviewItemForWindow(window1.get());
6527   DragWindowTo(overview_item1, gfx::PointF(0, 0));
6528   EXPECT_TRUE(overview_controller()->InOverviewSession());
6529   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
6530 
6531   // Now minimize the snapped |window1|.
6532   WindowState::Get(window1.get())->Minimize();
6533   EXPECT_FALSE(overview_controller()->InOverviewSession());
6534   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6535 }
6536 
6537 // Test snapped window bounds with adjustment for the minimum size of a window.
TEST_P(SplitViewOverviewSessionInClamshellTest,SnappedWindowBoundsWithMinimumSizeTest)6538 TEST_P(SplitViewOverviewSessionInClamshellTest,
6539        SnappedWindowBoundsWithMinimumSizeTest) {
6540   const gfx::Rect bounds(400, 400);
6541   std::unique_ptr<aura::Window> window1(
6542       CreateWindowWithHitTestComponent(HTRIGHT, bounds));
6543   const int window2_minimum_size = 350;
6544   std::unique_ptr<aura::Window> window2(
6545       CreateWindowWithMinimumSize(bounds, gfx::Size(window2_minimum_size, 0)));
6546 
6547   ToggleOverview();
6548   split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT);
6549   ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow(),
6550                                      window1.get());
6551   int divider_position = split_view_controller()->divider_position();
6552   generator.MoveMouseTo(divider_position, 10);
6553   divider_position = 300;
6554   generator.DragMouseTo(divider_position, 10);
6555   EXPECT_EQ(divider_position, split_view_controller()
6556                                   ->GetSnappedWindowBoundsInScreen(
6557                                       SplitViewController::LEFT,
6558                                       /*window_for_minimum_size=*/nullptr)
6559                                   .width());
6560   EXPECT_EQ(window2_minimum_size,
6561             split_view_controller()
6562                 ->GetSnappedWindowBoundsInScreen(SplitViewController::LEFT,
6563                                                  window2.get())
6564                 .width());
6565   const int work_area_length =
6566       screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
6567           window1.get())
6568           .width();
6569   EXPECT_EQ(
6570       work_area_length - divider_position,
6571       split_view_controller()
6572           ->GetSnappedWindowBoundsInScreen(SplitViewController::RIGHT,
6573                                            /*window_for_minimum_size=*/nullptr)
6574           .width());
6575   EXPECT_EQ(work_area_length - divider_position,
6576             split_view_controller()
6577                 ->GetSnappedWindowBoundsInScreen(SplitViewController::RIGHT,
6578                                                  window2.get())
6579                 .width());
6580   divider_position = 500;
6581   generator.DragMouseTo(divider_position, 10);
6582   EXPECT_EQ(divider_position, split_view_controller()
6583                                   ->GetSnappedWindowBoundsInScreen(
6584                                       SplitViewController::LEFT,
6585                                       /*window_for_minimum_size=*/nullptr)
6586                                   .width());
6587   EXPECT_EQ(divider_position, split_view_controller()
6588                                   ->GetSnappedWindowBoundsInScreen(
6589                                       SplitViewController::LEFT, window2.get())
6590                                   .width());
6591   EXPECT_EQ(
6592       work_area_length - divider_position,
6593       split_view_controller()
6594           ->GetSnappedWindowBoundsInScreen(SplitViewController::RIGHT,
6595                                            /*window_for_minimum_size=*/nullptr)
6596           .width());
6597   EXPECT_EQ(window2_minimum_size,
6598             split_view_controller()
6599                 ->GetSnappedWindowBoundsInScreen(SplitViewController::RIGHT,
6600                                                  window2.get())
6601                 .width());
6602 }
6603 
6604 // Tests that on a display in portrait orientation, clamshell split view still
6605 // uses snap positions on the left and right.
TEST_P(SplitViewOverviewSessionInClamshellTest,PortraitClamshellSplitViewSnapPositionsTest)6606 TEST_P(SplitViewOverviewSessionInClamshellTest,
6607        PortraitClamshellSplitViewSnapPositionsTest) {
6608   UpdateDisplay("800x600/l");
6609   const int height = 800 - ShelfConfig::Get()->shelf_size();
6610   ASSERT_EQ(gfx::Rect(0, 0, 600, height),
6611             screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
6612                 Shell::GetPrimaryRootWindow()));
6613   // Check that snapped window bounds represent snapping on the left and right.
6614   const gfx::Rect left_snapped_bounds(0, 0, 300, height);
6615   EXPECT_EQ(
6616       left_snapped_bounds,
6617       split_view_controller()->GetSnappedWindowBoundsInScreen(
6618           SplitViewController::LEFT, /*window_for_minimum_size=*/nullptr));
6619   const gfx::Rect right_snapped_bounds(300, 0, 300, height);
6620   EXPECT_EQ(
6621       right_snapped_bounds,
6622       split_view_controller()->GetSnappedWindowBoundsInScreen(
6623           SplitViewController::RIGHT, /*window_for_minimum_size=*/nullptr));
6624   // Switch from clamshell mode to tablet mode and then back to clamshell mode.
6625   display::test::DisplayManagerTestApi(Shell::Get()->display_manager())
6626       .SetFirstDisplayAsInternalDisplay();
6627   TabletModeControllerTestApi tablet_mode_controller_test_api;
6628   tablet_mode_controller_test_api.DetachAllMice();
6629   EXPECT_FALSE(tablet_mode_controller_test_api.IsTabletModeStarted());
6630   tablet_mode_controller_test_api.OpenLidToAngle(315.0f);
6631   EXPECT_TRUE(tablet_mode_controller_test_api.IsTabletModeStarted());
6632   tablet_mode_controller_test_api.OpenLidToAngle(90.0f);
6633   EXPECT_FALSE(tablet_mode_controller_test_api.IsTabletModeStarted());
6634   // Check the snapped window bounds again. They should be the same as before.
6635   EXPECT_EQ(
6636       left_snapped_bounds,
6637       split_view_controller()->GetSnappedWindowBoundsInScreen(
6638           SplitViewController::LEFT, /*window_for_minimum_size=*/nullptr));
6639   EXPECT_EQ(
6640       right_snapped_bounds,
6641       split_view_controller()->GetSnappedWindowBoundsInScreen(
6642           SplitViewController::RIGHT, /*window_for_minimum_size=*/nullptr));
6643 }
6644 
6645 // Tests that the ratio between the divider position and the work area width is
6646 // the same before and after changing the display orientation in clamshell mode.
TEST_P(SplitViewOverviewSessionInClamshellTest,DisplayOrientationChangeTest)6647 TEST_P(SplitViewOverviewSessionInClamshellTest, DisplayOrientationChangeTest) {
6648   UpdateDisplay("600x400");
6649   const gfx::Rect bounds(400, 400);
6650   std::unique_ptr<aura::Window> split_view_window(
6651       CreateWindowWithHitTestComponent(HTRIGHT, bounds));
6652   std::unique_ptr<aura::Window> overview_window(CreateWindow(bounds));
6653   ToggleOverview();
6654   split_view_controller()->SnapWindow(split_view_window.get(),
6655                                       SplitViewController::LEFT);
6656   const auto test_many_orientation_changes =
6657       [this](const std::string& description) {
6658         SCOPED_TRACE(description);
6659         for (display::Display::Rotation rotation :
6660              {display::Display::ROTATE_270, display::Display::ROTATE_180,
6661               display::Display::ROTATE_90, display::Display::ROTATE_0,
6662               display::Display::ROTATE_180, display::Display::ROTATE_0}) {
6663           const auto compute_divider_position_ratio = [this]() {
6664             return static_cast<float>(
6665                        split_view_controller()->divider_position()) /
6666                    static_cast<float>(display::Screen::GetScreen()
6667                                           ->GetPrimaryDisplay()
6668                                           .work_area()
6669                                           .width());
6670           };
6671           const float before = compute_divider_position_ratio();
6672           Shell::Get()->display_manager()->SetDisplayRotation(
6673               display::Screen::GetScreen()->GetPrimaryDisplay().id(), rotation,
6674               display::Display::RotationSource::ACTIVE);
6675           const float after = compute_divider_position_ratio();
6676           EXPECT_NEAR(before, after, 0.001f);
6677         }
6678       };
6679   EXPECT_EQ(split_view_controller()->GetDefaultDividerPosition(),
6680             split_view_controller()->divider_position());
6681   test_many_orientation_changes("centered divider");
6682   EXPECT_EQ(split_view_controller()->GetDefaultDividerPosition(),
6683             split_view_controller()->divider_position());
6684   ui::test::EventGenerator(Shell::GetPrimaryRootWindow(),
6685                            split_view_window.get())
6686       .DragMouseBy(50, 50);
6687   EXPECT_NE(split_view_controller()->GetDefaultDividerPosition(),
6688             split_view_controller()->divider_position());
6689   test_many_orientation_changes("off-center divider");
6690 }
6691 
6692 // Verify that an item's unsnappable indicator is updated for display rotation.
TEST_P(SplitViewOverviewSessionInClamshellTest,OverviewUnsnappableIndicatorVisibilityAfterDisplayRotation)6693 TEST_P(SplitViewOverviewSessionInClamshellTest,
6694        OverviewUnsnappableIndicatorVisibilityAfterDisplayRotation) {
6695   UpdateDisplay("900x600");
6696   std::unique_ptr<aura::Window> snapped_window = CreateTestWindow();
6697   // Because of its minimum size, |overview_window| is snappable in clamshell
6698   // split view with landscape display orientation but not with portrait display
6699   // orientation.
6700   std::unique_ptr<aura::Window> overview_window(
6701       CreateWindowWithMinimumSize(gfx::Rect(400, 400), gfx::Size(400, 0)));
6702   ToggleOverview();
6703   ASSERT_TRUE(overview_controller()->InOverviewSession());
6704   split_view_controller()->SnapWindow(snapped_window.get(),
6705                                       SplitViewController::LEFT);
6706   ASSERT_TRUE(split_view_controller()->InSplitViewMode());
6707   OverviewItem* overview_item = GetOverviewItemForWindow(overview_window.get());
6708   // Note: |cannot_snap_label_view_| and its parent will be created on demand.
6709   EXPECT_FALSE(overview_item->cannot_snap_widget_for_testing());
6710 
6711   // Rotate to primary portrait orientation. The unsnappable indicator appears.
6712   display::DisplayManager* display_manager = Shell::Get()->display_manager();
6713   const int64_t display_id =
6714       display::Screen::GetScreen()->GetPrimaryDisplay().id();
6715   display_manager->SetDisplayRotation(display_id, display::Display::ROTATE_270,
6716                                       display::Display::RotationSource::ACTIVE);
6717   ASSERT_TRUE(overview_item->cannot_snap_widget_for_testing());
6718   ui::Layer* unsnappable_layer =
6719       overview_item->cannot_snap_widget_for_testing()->GetLayer();
6720   EXPECT_EQ(1.f, unsnappable_layer->opacity());
6721 
6722   // Rotate to primary landscape orientation. The unsnappable indicator hides.
6723   display_manager->SetDisplayRotation(display_id, display::Display::ROTATE_0,
6724                                       display::Display::RotationSource::ACTIVE);
6725   EXPECT_EQ(0.f, unsnappable_layer->opacity());
6726 }
6727 
6728 // Tests that dragging a window from overview creates a drop target on the same
6729 // display, even if the window bounds are mostly on another display.
TEST_P(SplitViewOverviewSessionInClamshellTest,DragFromOverviewWithBoundsMostlyOnAnotherDisplay)6730 TEST_P(SplitViewOverviewSessionInClamshellTest,
6731        DragFromOverviewWithBoundsMostlyOnAnotherDisplay) {
6732   UpdateDisplay("600x600,600x600");
6733   const aura::Window::Windows root_windows = Shell::Get()->GetAllRootWindows();
6734   ASSERT_EQ(2u, root_windows.size());
6735   const display::DisplayIdList display_ids =
6736       display_manager()->GetCurrentDisplayIdList();
6737   ASSERT_EQ(2u, display_ids.size());
6738   ASSERT_EQ(root_windows[0], Shell::GetRootWindowForDisplayId(display_ids[0]));
6739   ASSERT_EQ(root_windows[1], Shell::GetRootWindowForDisplayId(display_ids[1]));
6740 
6741   display::Screen* screen = display::Screen::GetScreen();
6742   const gfx::Rect creation_bounds(0, 0, 600, 600);
6743   ASSERT_EQ(display_ids[0], screen->GetDisplayMatching(creation_bounds).id());
6744   const gfx::Rect bounds(550, 0, 600, 600);
6745   ASSERT_EQ(display_ids[1], screen->GetDisplayMatching(bounds).id());
6746   std::unique_ptr<aura::Window> window = CreateTestWindow(creation_bounds);
6747   window->SetBoundsInScreen(bounds,
6748                             display_manager()->GetDisplayForId(display_ids[0]));
6749 
6750   ToggleOverview();
6751   OverviewItem* overview_item = GetOverviewItemForWindow(window.get());
6752   EXPECT_FALSE(GetDropTarget(0));
6753   EXPECT_FALSE(GetDropTarget(1));
6754   gfx::PointF drag_point = overview_item->target_bounds().CenterPoint();
6755   overview_session()->InitiateDrag(overview_item, drag_point,
6756                                    /*is_touch_dragging=*/false);
6757   EXPECT_FALSE(GetDropTarget(0));
6758   EXPECT_FALSE(GetDropTarget(1));
6759   drag_point.Offset(5.f, 0.f);
6760   overview_session()->Drag(overview_item, drag_point);
6761   EXPECT_FALSE(GetDropTarget(1));
6762   ASSERT_TRUE(GetDropTarget(0));
6763   EXPECT_EQ(root_windows[0], GetDropTarget(0)->root_window());
6764   overview_session()->CompleteDrag(overview_item, drag_point);
6765   EXPECT_FALSE(GetDropTarget(0));
6766   EXPECT_FALSE(GetDropTarget(1));
6767 }
6768 
6769 // Tests that Alt+[ and Alt+] do not start overview.
TEST_P(SplitViewOverviewSessionInClamshellTest,AltSquareBracketNotStartOverview)6770 TEST_P(SplitViewOverviewSessionInClamshellTest,
6771        AltSquareBracketNotStartOverview) {
6772   std::unique_ptr<aura::Window> window1 = CreateTestWindow();
6773   std::unique_ptr<aura::Window> window2 = CreateTestWindow();
6774   wm::ActivateWindow(window1.get());
6775   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6776   EXPECT_FALSE(InOverviewSession());
6777   // Alt+[
6778   const WMEvent alt_left_square_bracket(WM_EVENT_CYCLE_SNAP_LEFT);
6779   WindowState* window1_state = WindowState::Get(window1.get());
6780   window1_state->OnWMEvent(&alt_left_square_bracket);
6781   EXPECT_EQ(WindowStateType::kLeftSnapped, window1_state->GetStateType());
6782   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6783   EXPECT_FALSE(InOverviewSession());
6784   // Alt+]
6785   const WMEvent alt_right_square_bracket(WM_EVENT_CYCLE_SNAP_RIGHT);
6786   window1_state->OnWMEvent(&alt_right_square_bracket);
6787   EXPECT_EQ(WindowStateType::kRightSnapped, window1_state->GetStateType());
6788   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6789   EXPECT_FALSE(InOverviewSession());
6790 }
6791 
6792 // Tests using Alt+[ on a left split view window.
TEST_P(SplitViewOverviewSessionInClamshellTest,AltLeftSquareBracketOnLeftSplitViewWindow)6793 TEST_P(SplitViewOverviewSessionInClamshellTest,
6794        AltLeftSquareBracketOnLeftSplitViewWindow) {
6795   std::unique_ptr<aura::Window> snapped_window = CreateTestWindow();
6796   std::unique_ptr<aura::Window> overview_window = CreateTestWindow();
6797   ToggleOverview();
6798   split_view_controller()->SnapWindow(snapped_window.get(),
6799                                       SplitViewController::LEFT);
6800   WindowState* snapped_window_state = WindowState::Get(snapped_window.get());
6801   EXPECT_EQ(WindowStateType::kLeftSnapped,
6802             snapped_window_state->GetStateType());
6803   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
6804   EXPECT_TRUE(InOverviewSession());
6805   const WMEvent alt_left_square_bracket(WM_EVENT_CYCLE_SNAP_LEFT);
6806   snapped_window_state->OnWMEvent(&alt_left_square_bracket);
6807   EXPECT_EQ(WindowStateType::kNormal, snapped_window_state->GetStateType());
6808   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6809   EXPECT_FALSE(InOverviewSession());
6810 }
6811 
6812 // Tests using Alt+] on a right split view window.
TEST_P(SplitViewOverviewSessionInClamshellTest,AltRightSquareBracketOnRightSplitViewWindow)6813 TEST_P(SplitViewOverviewSessionInClamshellTest,
6814        AltRightSquareBracketOnRightSplitViewWindow) {
6815   std::unique_ptr<aura::Window> snapped_window = CreateTestWindow();
6816   std::unique_ptr<aura::Window> overview_window = CreateTestWindow();
6817   ToggleOverview();
6818   split_view_controller()->SnapWindow(snapped_window.get(),
6819                                       SplitViewController::RIGHT);
6820   WindowState* snapped_window_state = WindowState::Get(snapped_window.get());
6821   EXPECT_EQ(WindowStateType::kRightSnapped,
6822             snapped_window_state->GetStateType());
6823   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
6824   EXPECT_TRUE(InOverviewSession());
6825   const WMEvent alt_right_square_bracket(WM_EVENT_CYCLE_SNAP_RIGHT);
6826   snapped_window_state->OnWMEvent(&alt_right_square_bracket);
6827   EXPECT_EQ(WindowStateType::kNormal, snapped_window_state->GetStateType());
6828   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
6829   EXPECT_FALSE(InOverviewSession());
6830 }
6831 
6832 // Tests using Alt+[ on a right split view window, and Alt+] on a left split
6833 // view window.
TEST_P(SplitViewOverviewSessionInClamshellTest,AltSquareBracketOnSplitViewWindow)6834 TEST_P(SplitViewOverviewSessionInClamshellTest,
6835        AltSquareBracketOnSplitViewWindow) {
6836   std::unique_ptr<aura::Window> snapped_window = CreateTestWindow();
6837   std::unique_ptr<aura::Window> overview_window = CreateTestWindow();
6838   // Enter clamshell split view with |snapped_window| on the right.
6839   ToggleOverview();
6840   split_view_controller()->SnapWindow(snapped_window.get(),
6841                                       SplitViewController::RIGHT);
6842   wm::ActivateWindow(snapped_window.get());
6843   WindowState* snapped_window_state = WindowState::Get(snapped_window.get());
6844   EXPECT_EQ(WindowStateType::kRightSnapped,
6845             snapped_window_state->GetStateType());
6846   EXPECT_EQ(SplitViewController::State::kRightSnapped,
6847             split_view_controller()->state());
6848   EXPECT_EQ(snapped_window.get(), split_view_controller()->right_window());
6849   EXPECT_TRUE(InOverviewSession());
6850   // Test using Alt+[ to put |snapped_window| on the left.
6851   const WMEvent alt_left_square_bracket(WM_EVENT_CYCLE_SNAP_LEFT);
6852   snapped_window_state->OnWMEvent(&alt_left_square_bracket);
6853   EXPECT_TRUE(wm::IsActiveWindow(snapped_window.get()));
6854   EXPECT_EQ(WindowStateType::kLeftSnapped,
6855             snapped_window_state->GetStateType());
6856   EXPECT_EQ(SplitViewController::State::kLeftSnapped,
6857             split_view_controller()->state());
6858   EXPECT_EQ(snapped_window.get(), split_view_controller()->left_window());
6859   EXPECT_TRUE(InOverviewSession());
6860   // Test using Alt+] to put |snapped_window| on the right.
6861   const WMEvent alt_right_square_bracket(WM_EVENT_CYCLE_SNAP_RIGHT);
6862   snapped_window_state->OnWMEvent(&alt_right_square_bracket);
6863   EXPECT_TRUE(wm::IsActiveWindow(snapped_window.get()));
6864   EXPECT_EQ(WindowStateType::kRightSnapped,
6865             snapped_window_state->GetStateType());
6866   EXPECT_EQ(SplitViewController::State::kRightSnapped,
6867             split_view_controller()->state());
6868   EXPECT_EQ(snapped_window.get(), split_view_controller()->right_window());
6869   EXPECT_TRUE(InOverviewSession());
6870 }
6871 
6872 using SplitViewOverviewSessionInClamshellTestMultiDisplayOnly =
6873     SplitViewOverviewSessionInClamshellTest;
6874 
6875 // Test |SplitViewController::Get|.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,GetSplitViewController)6876 TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
6877        GetSplitViewController) {
6878   UpdateDisplay("800x600,800x600");
6879   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
6880   ASSERT_EQ(2u, root_windows.size());
6881   const gfx::Rect bounds_within_root1(0, 0, 400, 400);
6882   const gfx::Rect bounds_within_root2(800, 0, 400, 400);
6883   std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds_within_root1);
6884   std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds_within_root2);
6885   EXPECT_EQ(root_windows[0],
6886             SplitViewController::Get(window1.get())->root_window());
6887   EXPECT_EQ(root_windows[1],
6888             SplitViewController::Get(window2.get())->root_window());
6889 }
6890 
6891 // Test |SplitViewController::GetSnappedWindowBoundsInScreen|.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,GetSnappedBounds)6892 TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
6893        GetSnappedBounds) {
6894   UpdateDisplay("800x600,800x600");
6895   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
6896   ASSERT_EQ(2u, root_windows.size());
6897   const int height = 600 - ShelfConfig::Get()->shelf_size();
6898   ASSERT_EQ(gfx::Rect(0, 0, 800, height),
6899             screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
6900                 root_windows[0]));
6901   ASSERT_EQ(gfx::Rect(800, 0, 800, height),
6902             screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
6903                 root_windows[1]));
6904 
6905   EXPECT_EQ(
6906       gfx::Rect(0, 0, 400, height),
6907       SplitViewController::Get(root_windows[0])
6908           ->GetSnappedWindowBoundsInScreen(
6909               SplitViewController::LEFT, /*window_for_minimum_size=*/nullptr));
6910   EXPECT_EQ(
6911       gfx::Rect(400, 0, 400, height),
6912       SplitViewController::Get(root_windows[0])
6913           ->GetSnappedWindowBoundsInScreen(
6914               SplitViewController::RIGHT, /*window_for_minimum_size=*/nullptr));
6915   EXPECT_EQ(
6916       gfx::Rect(800, 0, 400, height),
6917       SplitViewController::Get(root_windows[1])
6918           ->GetSnappedWindowBoundsInScreen(
6919               SplitViewController::LEFT, /*window_for_minimum_size=*/nullptr));
6920   EXPECT_EQ(
6921       gfx::Rect(1200, 0, 400, height),
6922       SplitViewController::Get(root_windows[1])
6923           ->GetSnappedWindowBoundsInScreen(
6924               SplitViewController::RIGHT, /*window_for_minimum_size=*/nullptr));
6925 }
6926 
6927 // Test that if clamshell split view is started by snapping a window that is the
6928 // only overview window, then split view ends as soon as it starts, and overview
6929 // ends along with it.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,SplitViewEndsImmediatelyIfOverviewIsEmpty)6930 TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
6931        SplitViewEndsImmediatelyIfOverviewIsEmpty) {
6932   UpdateDisplay("800x600,800x600");
6933   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
6934   ASSERT_EQ(2u, root_windows.size());
6935   const gfx::Rect bounds_within_root1(0, 0, 400, 400);
6936   std::unique_ptr<aura::Window> window = CreateTestWindow(bounds_within_root1);
6937   ToggleOverview();
6938   SplitViewController::Get(root_windows[0])
6939       ->SnapWindow(window.get(), SplitViewController::LEFT);
6940   EXPECT_FALSE(InOverviewSession());
6941   EXPECT_FALSE(SplitViewController::Get(root_windows[0])->InSplitViewMode());
6942 }
6943 
6944 // Test that if clamshell split view is started by snapping a window on one
6945 // display while there is an overview window on another display, then split view
6946 // stays active (instead of ending as soon as it starts), and overview also
6947 // stays active. Then close the overview window and verify that split view and
6948 // overview are ended.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,SplitViewViableWithOverviewWindowOnOtherDisplay)6949 TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
6950        SplitViewViableWithOverviewWindowOnOtherDisplay) {
6951   UpdateDisplay("800x600,800x600");
6952   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
6953   ASSERT_EQ(2u, root_windows.size());
6954   const gfx::Rect bounds_within_root1(0, 0, 400, 400);
6955   const gfx::Rect bounds_within_root2(800, 0, 400, 400);
6956   std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds_within_root1);
6957   std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds_within_root2);
6958   ToggleOverview();
6959   SplitViewController::Get(root_windows[0])
6960       ->SnapWindow(window1.get(), SplitViewController::LEFT);
6961   EXPECT_TRUE(SplitViewController::Get(root_windows[0])->InSplitViewMode());
6962   EXPECT_TRUE(InOverviewSession());
6963   window2.reset();
6964   EXPECT_FALSE(SplitViewController::Get(root_windows[0])->InSplitViewMode());
6965   EXPECT_FALSE(InOverviewSession());
6966 }
6967 
6968 // Test dragging to snap an overview item on an external display.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,DraggingOnExternalDisplay)6969 TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
6970        DraggingOnExternalDisplay) {
6971   UpdateDisplay("800x600,800x600");
6972   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
6973   ASSERT_EQ(2u, root_windows.size());
6974   const gfx::Rect bounds_within_root2(800, 0, 400, 400);
6975   std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds_within_root2);
6976   std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds_within_root2);
6977   ToggleOverview();
6978   OverviewGrid* grid_on_root2 =
6979       overview_session()->GetGridWithRootWindow(root_windows[1]);
6980   OverviewItem* item1 = grid_on_root2->GetOverviewItemContaining(window1.get());
6981   OverviewItem* item2 = grid_on_root2->GetOverviewItemContaining(window2.get());
6982   SplitViewController* split_view_controller =
6983       SplitViewController::Get(root_windows[1]);
6984   SplitViewDragIndicators* indicators =
6985       grid_on_root2->split_view_drag_indicators();
6986 
6987   Shell::Get()->cursor_manager()->SetDisplay(
6988       display::Screen::GetScreen()->GetDisplayNearestWindow(root_windows[1]));
6989   overview_session()->InitiateDrag(item1, item1->target_bounds().CenterPoint(),
6990                                    /*is_touch_dragging=*/false);
6991   const gfx::PointF right_snap_point(1599.f, 300.f);
6992   overview_session()->Drag(item1, right_snap_point);
6993   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapRight,
6994             indicators->current_window_dragging_state());
6995   EXPECT_EQ(
6996       SplitViewController::Get(root_windows[1])
6997           ->GetSnappedWindowBoundsInScreen(SplitViewController::LEFT,
6998                                            /*window_for_minimum_size=*/nullptr),
6999       grid_on_root2->bounds());
7000   overview_session()->CompleteDrag(item1, right_snap_point);
7001   EXPECT_EQ(SplitViewController::State::kRightSnapped,
7002             split_view_controller->state());
7003   EXPECT_EQ(window1.get(), split_view_controller->right_window());
7004 
7005   overview_session()->InitiateDrag(item2, item2->target_bounds().CenterPoint(),
7006                                    /*is_touch_dragging=*/false);
7007   const gfx::PointF left_of_middle(1150.f, 300.f);
7008   overview_session()->Drag(item2, left_of_middle);
7009   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kFromOverview,
7010             indicators->current_window_dragging_state());
7011   overview_session()->CompleteDrag(item2, left_of_middle);
7012   EXPECT_EQ(SplitViewController::State::kRightSnapped,
7013             split_view_controller->state());
7014   EXPECT_EQ(window1.get(), split_view_controller->right_window());
7015 
7016   overview_session()->InitiateDrag(item2, item2->target_bounds().CenterPoint(),
7017                                    /*is_touch_dragging=*/false);
7018   const gfx::PointF left_snap_point(810.f, 300.f);
7019   overview_session()->Drag(item2, left_snap_point);
7020   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapLeft,
7021             indicators->current_window_dragging_state());
7022   overview_session()->CompleteDrag(item2, left_snap_point);
7023   EXPECT_EQ(SplitViewController::State::kNoSnap,
7024             split_view_controller->state());
7025 }
7026 
7027 // Test dragging from one display to another.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,MultiDisplayDragging)7028 TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
7029        MultiDisplayDragging) {
7030   wm::CursorManager* cursor_manager = Shell::Get()->cursor_manager();
7031   UpdateDisplay("800x600,800x600");
7032   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
7033   ASSERT_EQ(2u, root_windows.size());
7034   const display::Display display_with_root1 =
7035       display::Screen::GetScreen()->GetDisplayNearestWindow(root_windows[0]);
7036   const display::Display display_with_root2 =
7037       display::Screen::GetScreen()->GetDisplayNearestWindow(root_windows[1]);
7038   const gfx::Rect bounds_within_root1(0, 0, 400, 400);
7039   const gfx::Rect bounds_within_root2(800, 0, 400, 400);
7040   std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds_within_root1);
7041   std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds_within_root1);
7042   std::unique_ptr<aura::Window> window3 = CreateTestWindow(bounds_within_root2);
7043   ToggleOverview();
7044   OverviewGrid* grid_on_root1 =
7045       overview_session()->GetGridWithRootWindow(root_windows[0]);
7046   OverviewGrid* grid_on_root2 =
7047       overview_session()->GetGridWithRootWindow(root_windows[1]);
7048   OverviewItem* item1 = grid_on_root1->GetOverviewItemContaining(window1.get());
7049   SplitViewDragIndicators* indicators_on_root1 =
7050       grid_on_root1->split_view_drag_indicators();
7051   SplitViewDragIndicators* indicators_on_root2 =
7052       grid_on_root2->split_view_drag_indicators();
7053 
7054   ASSERT_EQ(display_with_root1.id(), cursor_manager->GetDisplay().id());
7055   overview_session()->InitiateDrag(item1, item1->target_bounds().CenterPoint(),
7056                                    /*is_touch_dragging=*/false);
7057   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kNoDrag,
7058             indicators_on_root1->current_window_dragging_state());
7059   EXPECT_EQ(display_with_root1.work_area(), grid_on_root1->bounds());
7060   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kNoDrag,
7061             indicators_on_root2->current_window_dragging_state());
7062   EXPECT_EQ(display_with_root2.work_area(), grid_on_root2->bounds());
7063 
7064   const gfx::PointF root1_left_snap_point(0.f, 300.f);
7065   overview_session()->Drag(item1, root1_left_snap_point);
7066   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapLeft,
7067             indicators_on_root1->current_window_dragging_state());
7068   EXPECT_EQ(
7069       SplitViewController::Get(root_windows[0])
7070           ->GetSnappedWindowBoundsInScreen(SplitViewController::RIGHT,
7071                                            /*window_for_minimum_size=*/nullptr),
7072       grid_on_root1->bounds());
7073   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kOtherDisplay,
7074             indicators_on_root2->current_window_dragging_state());
7075   EXPECT_EQ(display_with_root2.work_area(), grid_on_root2->bounds());
7076 
7077   const gfx::PointF root1_middle_point(400.f, 300.f);
7078   overview_session()->Drag(item1, root1_middle_point);
7079   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kFromOverview,
7080             indicators_on_root1->current_window_dragging_state());
7081   EXPECT_EQ(display_with_root1.work_area(), grid_on_root1->bounds());
7082   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kOtherDisplay,
7083             indicators_on_root2->current_window_dragging_state());
7084   EXPECT_EQ(display_with_root2.work_area(), grid_on_root2->bounds());
7085 
7086   const gfx::PointF root1_right_snap_point(799.f, 300.f);
7087   overview_session()->Drag(item1, root1_right_snap_point);
7088   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapRight,
7089             indicators_on_root1->current_window_dragging_state());
7090   EXPECT_EQ(
7091       SplitViewController::Get(root_windows[0])
7092           ->GetSnappedWindowBoundsInScreen(SplitViewController::LEFT,
7093                                            /*window_for_minimum_size=*/nullptr),
7094       grid_on_root1->bounds());
7095   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kOtherDisplay,
7096             indicators_on_root2->current_window_dragging_state());
7097   EXPECT_EQ(display_with_root2.work_area(), grid_on_root2->bounds());
7098 
7099   const gfx::PointF root2_left_snap_point(800.f, 300.f);
7100   cursor_manager->SetDisplay(display_with_root2);
7101   overview_session()->Drag(item1, root2_left_snap_point);
7102   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kOtherDisplay,
7103             indicators_on_root1->current_window_dragging_state());
7104   EXPECT_EQ(display_with_root1.work_area(), grid_on_root1->bounds());
7105   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapLeft,
7106             indicators_on_root2->current_window_dragging_state());
7107   EXPECT_EQ(
7108       SplitViewController::Get(root_windows[1])
7109           ->GetSnappedWindowBoundsInScreen(SplitViewController::RIGHT,
7110                                            /*window_for_minimum_size=*/nullptr),
7111       grid_on_root2->bounds());
7112 
7113   const gfx::PointF root2_left_snap_point_away_from_edge(816.f, 300.f);
7114   overview_session()->Drag(item1, root2_left_snap_point_away_from_edge);
7115   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kOtherDisplay,
7116             indicators_on_root1->current_window_dragging_state());
7117   EXPECT_EQ(display_with_root1.work_area(), grid_on_root1->bounds());
7118   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapLeft,
7119             indicators_on_root2->current_window_dragging_state());
7120   EXPECT_EQ(
7121       SplitViewController::Get(root_windows[1])
7122           ->GetSnappedWindowBoundsInScreen(SplitViewController::RIGHT,
7123                                            /*window_for_minimum_size=*/nullptr),
7124       grid_on_root2->bounds());
7125 
7126   const gfx::PointF root2_right_snap_point(1599.f, 300.f);
7127   overview_session()->Drag(item1, root2_right_snap_point);
7128   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kOtherDisplay,
7129             indicators_on_root1->current_window_dragging_state());
7130   EXPECT_EQ(display_with_root1.work_area(), grid_on_root1->bounds());
7131   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kToSnapRight,
7132             indicators_on_root2->current_window_dragging_state());
7133   EXPECT_EQ(
7134       SplitViewController::Get(root_windows[1])
7135           ->GetSnappedWindowBoundsInScreen(SplitViewController::LEFT,
7136                                            /*window_for_minimum_size=*/nullptr),
7137       grid_on_root2->bounds());
7138 
7139   const gfx::PointF root2_middle_point(1200.f, 300.f);
7140   overview_session()->Drag(item1, root2_middle_point);
7141   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kOtherDisplay,
7142             indicators_on_root1->current_window_dragging_state());
7143   EXPECT_EQ(display_with_root1.work_area(), grid_on_root1->bounds());
7144   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kFromOverview,
7145             indicators_on_root2->current_window_dragging_state());
7146   EXPECT_EQ(display_with_root2.work_area(), grid_on_root2->bounds());
7147 
7148   overview_session()->CompleteDrag(item1, root2_middle_point);
7149   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kNoDrag,
7150             indicators_on_root1->current_window_dragging_state());
7151   EXPECT_EQ(display_with_root1.work_area(), grid_on_root1->bounds());
7152   EXPECT_EQ(SplitViewDragIndicators::WindowDraggingState::kNoDrag,
7153             indicators_on_root2->current_window_dragging_state());
7154   EXPECT_EQ(display_with_root2.work_area(), grid_on_root2->bounds());
7155 }
7156 
7157 // Verify the drop target positions for multi-display dragging.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,DropTargetPositionTest)7158 TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
7159        DropTargetPositionTest) {
7160   wm::CursorManager* cursor_manager = Shell::Get()->cursor_manager();
7161   UpdateDisplay("800x600,800x600");
7162   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
7163   ASSERT_EQ(2u, root_windows.size());
7164   const display::Display display_with_root1 =
7165       display::Screen::GetScreen()->GetDisplayNearestWindow(root_windows[0]);
7166   const display::Display display_with_root2 =
7167       display::Screen::GetScreen()->GetDisplayNearestWindow(root_windows[1]);
7168   const gfx::Rect bounds_within_root1(0, 0, 400, 400);
7169   const gfx::Rect bounds_within_root2(800, 0, 400, 400);
7170   // Named for MRU order, which is in reverse of creation order.
7171   std::unique_ptr<aura::Window> window6 = CreateTestWindow(bounds_within_root2);
7172   std::unique_ptr<aura::Window> window5 = CreateTestWindow(bounds_within_root1);
7173   std::unique_ptr<aura::Window> window4 = CreateTestWindow(bounds_within_root2);
7174   std::unique_ptr<aura::Window> window3 = CreateTestWindow(bounds_within_root1);
7175   std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds_within_root2);
7176   std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds_within_root1);
7177   ToggleOverview();
7178   OverviewGrid* grid1 =
7179       overview_session()->GetGridWithRootWindow(root_windows[0]);
7180   OverviewGrid* grid2 =
7181       overview_session()->GetGridWithRootWindow(root_windows[1]);
7182   OverviewItem* item4 = grid2->GetOverviewItemContaining(window4.get());
7183   // Start dragging |item4| from |grid2|.
7184   cursor_manager->SetDisplay(display_with_root2);
7185   overview_session()->InitiateDrag(item4, item4->target_bounds().CenterPoint(),
7186                                    /*is_touch_dragging=*/false);
7187   overview_session()->Drag(item4, gfx::PointF(1200.f, 0.f));
7188   // On the grid where the drag starts (|grid2|), the drop target is inserted at
7189   // the index immediately following the dragged item (|item4|).
7190   ASSERT_EQ(4u, grid2->window_list().size());
7191   EXPECT_EQ(grid2->GetDropTarget(), grid2->window_list()[2].get());
7192   // Drag over |grid1|.
7193   cursor_manager->SetDisplay(display_with_root1);
7194   overview_session()->Drag(item4, gfx::PointF(400.f, 0.f));
7195   // On other grids (such as |grid1|), the drop target is inserted at the
7196   // correct position according to MRU order (between the overview items for
7197   // |window3| and |window5|).
7198   ASSERT_EQ(4u, grid1->window_list().size());
7199   EXPECT_EQ(grid1->GetDropTarget(), grid1->window_list()[2].get());
7200 }
7201 
7202 // Verify that the drop target in each overview grid has the correct bounds when
7203 // a maximized window is being dragged.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,DropTargetBoundsForMaximizedWindowDraggedToOtherDisplay)7204 TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
7205        DropTargetBoundsForMaximizedWindowDraggedToOtherDisplay) {
7206   UpdateDisplay("1000x400,1000x400/l");
7207   std::unique_ptr<aura::Window> window = CreateTestWindow();
7208   WindowState::Get(window.get())->Maximize();
7209   ToggleOverview();
7210   OverviewItem* item = GetOverviewItemForWindow(window.get());
7211   // Verify that |item| is letter boxed. The bounds of |item|, minus the margin
7212   // should have an aspect ratio of 2 : 1.
7213   gfx::RectF item_bounds = item->target_bounds();
7214   item_bounds.Inset(gfx::InsetsF(kWindowMargin));
7215   EXPECT_EQ(OverviewGridWindowFillMode::kLetterBoxed,
7216             item->GetWindowDimensionsType());
7217   EXPECT_EQ(2.f, item_bounds.width() / item_bounds.height());
7218   overview_session()->InitiateDrag(item, item->target_bounds().CenterPoint(),
7219                                    /*is_touch_dragging=*/false);
7220   Shell::Get()->cursor_manager()->SetDisplay(
7221       display::test::DisplayManagerTestApi(display_manager())
7222           .GetSecondaryDisplay());
7223   overview_session()->Drag(item, gfx::PointF(1200.f, 0.f));
7224   OverviewItem* drop_target = GetDropTarget(1);
7225   ASSERT_TRUE(drop_target);
7226   // Verify that |drop_target| is effectively pillar boxed. Avoid calling
7227   // |OverviewItem::GetWindowDimensionsType|, because it does not work for drop
7228   // targets (and that is okay). The bounds of |drop_target|, minus the margin
7229   // should have an aspect ratio of 1 : 2.
7230   gfx::RectF drop_target_bounds = drop_target->target_bounds();
7231   drop_target_bounds.Inset(gfx::InsetsF(kWindowMargin));
7232   EXPECT_EQ(0.5f, drop_target_bounds.width() / drop_target_bounds.height());
7233 }
7234 
7235 // Verify that the drop target in each overview grid has bounds representing
7236 // anticipation that if the dragged window is dropped into that grid, it will
7237 // shrink to fit into the corresponding work area.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,DropTargetBoundsOnDisplayWhereDraggedWindowDoesNotFitIntoWorkArea)7238 TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
7239        DropTargetBoundsOnDisplayWhereDraggedWindowDoesNotFitIntoWorkArea) {
7240   UpdateDisplay("600x600,1200x1200");
7241   // Drags |item| from the right display to the left display and back, and
7242   // returns the bounds of the drop target that appears on the left display.
7243   const auto root1_drop_target_bounds = [this](OverviewItem* item) {
7244     wm::CursorManager* cursor_manager = Shell::Get()->cursor_manager();
7245     const gfx::PointF drag_starting_point = item->target_bounds().CenterPoint();
7246     display::test::DisplayManagerTestApi display_manager_test(
7247         display_manager());
7248     cursor_manager->SetDisplay(display_manager_test.GetSecondaryDisplay());
7249     overview_session()->InitiateDrag(item, drag_starting_point,
7250                                      /*is_touch_dragging=*/false);
7251     cursor_manager->SetDisplay(
7252         display::Screen::GetScreen()->GetPrimaryDisplay());
7253     overview_session()->Drag(item, gfx::PointF(300.f, 0.f));
7254     cursor_manager->SetDisplay(display_manager_test.GetSecondaryDisplay());
7255     overview_session()->Drag(item, drag_starting_point);
7256     DCHECK(GetDropTarget(0));
7257     const gfx::RectF result = GetDropTarget(0)->target_bounds();
7258     overview_session()->CompleteDrag(item, drag_starting_point);
7259     return result;
7260   };
7261 
7262   // |window1| has the size that |window2| would become if moved to the left
7263   // display.
7264   std::unique_ptr<aura::Window> window1 =
7265       CreateTestWindow(gfx::Rect(600, 0, 600, 400));
7266   std::unique_ptr<aura::Window> window2 =
7267       CreateTestWindow(gfx::Rect(600, 0, 1000, 400));
7268   // |window3| has the size that |window4| would become if moved to the left
7269   // display.
7270   std::unique_ptr<aura::Window> window3 = CreateTestWindow(
7271       gfx::Rect(600, 0, 400, 600 - ShelfConfig::Get()->shelf_size()));
7272   std::unique_ptr<aura::Window> window4 =
7273       CreateTestWindow(gfx::Rect(600, 0, 400, 1000));
7274 
7275   ToggleOverview();
7276   OverviewItem* item1 = GetOverviewItemForWindow(window1.get());
7277   OverviewItem* item2 = GetOverviewItemForWindow(window2.get());
7278   OverviewItem* item3 = GetOverviewItemForWindow(window3.get());
7279   OverviewItem* item4 = GetOverviewItemForWindow(window4.get());
7280 
7281   // For good test coverage in each case, the dragged window and the drop target
7282   // have different |OverviewGridWindowFillMode| values.
7283   EXPECT_EQ(OverviewGridWindowFillMode::kNormal,
7284             item1->GetWindowDimensionsType());
7285   EXPECT_EQ(OverviewGridWindowFillMode::kLetterBoxed,
7286             item2->GetWindowDimensionsType());
7287   EXPECT_EQ(OverviewGridWindowFillMode::kNormal,
7288             item3->GetWindowDimensionsType());
7289   EXPECT_EQ(OverviewGridWindowFillMode::kPillarBoxed,
7290             item4->GetWindowDimensionsType());
7291 
7292   EXPECT_EQ(root1_drop_target_bounds(item1), root1_drop_target_bounds(item2));
7293   EXPECT_EQ(root1_drop_target_bounds(item3), root1_drop_target_bounds(item4));
7294 }
7295 
7296 // Test dragging from one overview grid and dropping into another overview grid.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,DragAndDropIntoAnotherOverviewGrid)7297 TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
7298        DragAndDropIntoAnotherOverviewGrid) {
7299   UpdateDisplay("800x600,800x600");
7300   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
7301   ASSERT_EQ(2u, root_windows.size());
7302   std::unique_ptr<aura::Window> window = CreateTestWindow();
7303   ASSERT_EQ(root_windows[0], window->GetRootWindow());
7304   ToggleOverview();
7305   OverviewGrid* grid1 =
7306       overview_session()->GetGridWithRootWindow(root_windows[0]);
7307   OverviewGrid* grid2 =
7308       overview_session()->GetGridWithRootWindow(root_windows[1]);
7309 
7310   // Drag |window| from |grid1| and drop into |grid2|.
7311   ui::test::EventGenerator* generator = GetEventGenerator();
7312   generator->MoveMouseTo(
7313       gfx::ToRoundedPoint(grid1->GetOverviewItemContaining(window.get())
7314                               ->target_bounds()
7315                               .CenterPoint()));
7316   generator->PressLeftButton();
7317   Shell::Get()->cursor_manager()->SetDisplay(
7318       display::Screen::GetScreen()->GetDisplayNearestWindow(root_windows[1]));
7319   generator->MoveMouseTo(1200, 300);
7320   generator->ReleaseLeftButton();
7321 
7322   EXPECT_EQ(root_windows[1], window->GetRootWindow());
7323   EXPECT_TRUE(grid1->empty());
7324   OverviewItem* item = grid2->GetOverviewItemContaining(window.get());
7325   ASSERT_TRUE(item);
7326   EXPECT_EQ(root_windows[1], item->root_window());
7327 }
7328 
7329 // Test that overview widgets are stacked in the correct order after an overview
7330 // window is dragged from one overview grid and dropped into another. Also test
7331 // that the destination overview grid is arranged in the correct order.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,OverviewWidgetStackingOrderAndGridOrderWithMultiDisplayDragging)7332 TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
7333        OverviewWidgetStackingOrderAndGridOrderWithMultiDisplayDragging) {
7334   UpdateDisplay("800x600,800x600");
7335   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
7336   ASSERT_EQ(2u, root_windows.size());
7337   const gfx::Rect bounds_within_root1(0, 0, 400, 400);
7338   const gfx::Rect bounds_within_root2(800, 0, 400, 400);
7339   std::unique_ptr<aura::Window> window3 = CreateTestWindow(bounds_within_root2);
7340   std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds_within_root1);
7341   std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds_within_root2);
7342   aura::Window* parent_on_root1 = window2->parent();
7343   aura::Window* parent_on_root2 = window1->parent();
7344   ASSERT_NE(parent_on_root1, parent_on_root2);
7345   ASSERT_EQ(window3->parent(), parent_on_root2);
7346   ToggleOverview();
7347   OverviewItem* item1 = GetOverviewItemForWindow(window1.get());
7348   OverviewItem* item2 = GetOverviewItemForWindow(window2.get());
7349   OverviewItem* item3 = GetOverviewItemForWindow(window3.get());
7350 
7351   ASSERT_EQ(root_windows[0], item2->root_window());
7352   // Verify that |item1| is stacked above |item3| (because we created |window1|
7353   // after |window3|).
7354   EXPECT_GT(IndexOf(item1->item_widget()->GetNativeWindow(), parent_on_root2),
7355             IndexOf(item3->item_widget()->GetNativeWindow(), parent_on_root2));
7356   // Verify that the item widget for each window is stacked below that window.
7357   EXPECT_LT(IndexOf(item1->item_widget()->GetNativeWindow(), parent_on_root2),
7358             IndexOf(window1.get(), parent_on_root2));
7359   EXPECT_LT(IndexOf(item2->item_widget()->GetNativeWindow(), parent_on_root1),
7360             IndexOf(window2.get(), parent_on_root1));
7361   EXPECT_LT(IndexOf(item3->item_widget()->GetNativeWindow(), parent_on_root2),
7362             IndexOf(window3.get(), parent_on_root2));
7363 
7364   // Drag |item2| from the left display and drop into the right display.
7365   ui::test::EventGenerator* generator = GetEventGenerator();
7366   generator->MoveMouseTo(
7367       gfx::ToRoundedPoint(item2->target_bounds().CenterPoint()));
7368   generator->PressLeftButton();
7369   Shell::Get()->cursor_manager()->SetDisplay(
7370       display::Screen::GetScreen()->GetDisplayNearestWindow(root_windows[1]));
7371   generator->MoveMouseTo(1200, 300);
7372   generator->ReleaseLeftButton();
7373   // |item2| is now a dangling pointer and we have to refresh it, because when
7374   // an overview window is dragged from one grid and dropped into another, the
7375   // original item is destroyed and a new one is created.
7376   item2 = GetOverviewItemForWindow(window2.get());
7377 
7378   ASSERT_EQ(window2->parent(), parent_on_root2);
7379   ASSERT_EQ(root_windows[1], item2->root_window());
7380   // With all three items on one grid, verify that their stacking order
7381   // corresponds to the MRU order of the windows. The new |item2| is sandwiched
7382   // between |item1| and |item3|.
7383   EXPECT_GT(IndexOf(item1->item_widget()->GetNativeWindow(), parent_on_root2),
7384             IndexOf(item2->item_widget()->GetNativeWindow(), parent_on_root2));
7385   EXPECT_GT(IndexOf(item2->item_widget()->GetNativeWindow(), parent_on_root2),
7386             IndexOf(item3->item_widget()->GetNativeWindow(), parent_on_root2));
7387   // Verify that the item widget for the new |item2| is stacked below |window2|.
7388   EXPECT_LT(IndexOf(item2->item_widget()->GetNativeWindow(), parent_on_root2),
7389             IndexOf(window2.get(), parent_on_root2));
7390 
7391   // Verify that the right grid is in MRU order.
7392   const std::vector<aura::Window*> expected_order = {
7393       window1.get(), window2.get(), window3.get()};
7394   EXPECT_EQ(expected_order,
7395             overview_controller()->GetWindowsListInOverviewGridsForTest());
7396 }
7397 
7398 // Test dragging from one display to another and then snapping.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,DragFromOneDisplayToAnotherAndSnap)7399 TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
7400        DragFromOneDisplayToAnotherAndSnap) {
7401   UpdateDisplay("800x600,800x600");
7402   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
7403   ASSERT_EQ(2u, root_windows.size());
7404   SplitViewController* split_view_controller1 =
7405       SplitViewController::Get(root_windows[0]);
7406   SplitViewController* split_view_controller2 =
7407       SplitViewController::Get(root_windows[1]);
7408   const gfx::Rect bounds_within_root1(0, 0, 400, 400);
7409   std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds_within_root1);
7410   std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds_within_root1);
7411   ToggleOverview();
7412   ui::test::EventGenerator* generator = GetEventGenerator();
7413   generator->MoveMouseTo(gfx::ToRoundedPoint(
7414       GetOverviewItemForWindow(window2.get())->target_bounds().CenterPoint()));
7415   generator->PressLeftButton();
7416   Shell::Get()->cursor_manager()->SetDisplay(
7417       display::Screen::GetScreen()->GetDisplayNearestWindow(root_windows[1]));
7418   generator->MoveMouseTo(800, 300);
7419   generator->ReleaseLeftButton();
7420   EXPECT_EQ(SplitViewController::State::kNoSnap,
7421             split_view_controller1->state());
7422   EXPECT_EQ(SplitViewController::State::kLeftSnapped,
7423             split_view_controller2->state());
7424   EXPECT_EQ(window2.get(), split_view_controller2->left_window());
7425   EXPECT_EQ(root_windows[1], window2->GetRootWindow());
7426   EXPECT_TRUE(InOverviewSession());
7427 }
7428 
7429 // Verify that window resizing performance is recorded to the correct histogram
7430 // depending on whether the overview grid is empty.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,WindowResizingPerformanceHistogramsTest)7431 TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
7432        WindowResizingPerformanceHistogramsTest) {
7433   UpdateDisplay("800x600,800x600");
7434   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
7435   ASSERT_EQ(2u, root_windows.size());
7436   const gfx::Rect bounds_within_root1(0, 0, 400, 400);
7437   const gfx::Rect bounds_within_root2(800, 0, 400, 400);
7438   std::unique_ptr<aura::Window> window1(
7439       CreateWindowWithHitTestComponent(HTRIGHT, bounds_within_root1));
7440   std::unique_ptr<aura::Window> window2(
7441       CreateWindowWithHitTestComponent(HTRIGHT, bounds_within_root2));
7442   std::unique_ptr<aura::Window> window3 = CreateTestWindow(bounds_within_root2);
7443   ToggleOverview();
7444   SplitViewController::Get(root_windows[0])
7445       ->SnapWindow(window1.get(), SplitViewController::LEFT);
7446   SplitViewController::Get(root_windows[1])
7447       ->SnapWindow(window2.get(), SplitViewController::LEFT);
7448   // Resize |window1|, which is in split view with an empty overview grid.
7449   ui::test::EventGenerator generator1(root_windows[0], window1.get());
7450   generator1.PressLeftButton();
7451   CheckWindowResizingPerformanceHistograms("BeforeResizingWindow1", 0, 0, 0, 0);
7452   generator1.MoveMouseBy(50, 50);
7453   CheckWindowResizingPerformanceHistograms("WhileResizingWindow1", 1, 0, 0, 0);
7454   generator1.ReleaseLeftButton();
7455   CheckWindowResizingPerformanceHistograms("AfterResizingWindow1", 1, 1, 0, 0);
7456   // Resize |window2|, which is in split view with a nonempty overview grid.
7457   Shell::Get()->cursor_manager()->SetDisplay(
7458       display::Screen::GetScreen()->GetDisplayNearestWindow(root_windows[1]));
7459   ui::test::EventGenerator generator2(root_windows[1], window2.get());
7460   generator2.PressLeftButton();
7461   CheckWindowResizingPerformanceHistograms("BeforeResizingWindow2", 1, 1, 0, 0);
7462   generator2.MoveMouseBy(50, 50);
7463   CheckWindowResizingPerformanceHistograms("WhileResizingWindow2", 1, 1, 1, 0);
7464   generator2.ReleaseLeftButton();
7465   CheckWindowResizingPerformanceHistograms("AfterResizingWindow2", 1, 1, 1, 1);
7466 }
7467 
7468 // Verify that the user action "SplitView_MultiDisplaySplitView" is recorded
7469 // when multi-display split view starts, and that a value is recorded to the
7470 // histogram "Ash.SplitView.TimeInMultiDisplaySplitView" when multi-display
7471 // split view ends. This test does not actually examine the timing values
7472 // recorded to the histogram, but this test does provide evidence of timing
7473 // accuracy as the time in multi-display split view is measured from the time
7474 // when the user action "SplitView_MultiDisplaySplitView" is recorded.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,MultiDisplaySplitViewMetrics)7475 TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
7476        MultiDisplaySplitViewMetrics) {
7477   base::UserActionTester user_action_tester;
7478   base::HistogramTester histogram_tester;
7479   // Verifies that multi-display split view has started exactly |start_count|
7480   // times and ended exactly |end_count| times. If not, then the output will
7481   // include |description| to indicate where the test failed.
7482   const auto verify = [&user_action_tester, &histogram_tester](
7483                           const char* description, int start_count,
7484                           int end_count) {
7485     SCOPED_TRACE(description);
7486     EXPECT_EQ(start_count, user_action_tester.GetActionCount(
7487                                "SplitView_MultiDisplaySplitView"));
7488     histogram_tester.ExpectTotalCount(
7489         "Ash.SplitView.TimeInMultiDisplaySplitView", end_count);
7490   };
7491 
7492   UpdateDisplay("800x600,800x600,800x600");
7493   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
7494   ASSERT_EQ(3u, root_windows.size());
7495   const gfx::Rect bounds_within_root1(0, 0, 400, 400);
7496   const gfx::Rect bounds_within_root2(800, 0, 400, 400);
7497   const gfx::Rect bounds_within_root3(1600, 0, 400, 400);
7498   std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds_within_root1);
7499   std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds_within_root1);
7500   std::unique_ptr<aura::Window> window3 = CreateTestWindow(bounds_within_root2);
7501   std::unique_ptr<aura::Window> window4 = CreateTestWindow(bounds_within_root2);
7502   std::unique_ptr<aura::Window> window5 = CreateTestWindow(bounds_within_root3);
7503   SplitViewController* split_view_controller1 =
7504       SplitViewController::Get(root_windows[0]);
7505   SplitViewController* split_view_controller2 =
7506       SplitViewController::Get(root_windows[1]);
7507   SplitViewController* split_view_controller3 =
7508       SplitViewController::Get(root_windows[2]);
7509   verify("1. Unit test set up", 0, 0);
7510   ToggleOverview();
7511   split_view_controller1->SnapWindow(window1.get(), SplitViewController::LEFT);
7512   verify("2. Number of displays in split view changed from 0 to 1", 0, 0);
7513   split_view_controller2->SnapWindow(window3.get(), SplitViewController::LEFT);
7514   verify("3. Number of displays in split view changed from 1 to 2", 1, 0);
7515   ToggleOverview();
7516   verify("4. Number of displays in split view changed from 2 to 0", 1, 1);
7517   ToggleOverview();
7518   split_view_controller1->SnapWindow(window1.get(), SplitViewController::LEFT);
7519   verify("5. Number of displays in split view changed from 0 to 1", 1, 1);
7520   split_view_controller2->SnapWindow(window3.get(), SplitViewController::LEFT);
7521   verify("6. Number of displays in split view changed from 1 to 2", 2, 1);
7522   split_view_controller3->SnapWindow(window5.get(), SplitViewController::LEFT);
7523   verify("7. Number of displays in split view changed from 2 to 3", 2, 1);
7524   ToggleOverview();
7525   verify("8. Number of displays in split view changed from 3 to 0", 2, 2);
7526   ToggleOverview();
7527   split_view_controller1->SnapWindow(window1.get(), SplitViewController::LEFT);
7528   verify("9. Number of displays in split view changed from 0 to 1", 2, 2);
7529   split_view_controller2->SnapWindow(window3.get(), SplitViewController::LEFT);
7530   verify("10. Number of displays in split view changed from 1 to 2", 3, 2);
7531   split_view_controller3->SnapWindow(window5.get(), SplitViewController::LEFT);
7532   verify("11. Number of displays in split view changed from 2 to 3", 3, 2);
7533   // For good test coverage, after multi-display split view started with
7534   // |split_view_controller2|, now we end split view on |split_view_controller2|
7535   // first, and then end multi-display split view with |split_view_controller3|.
7536   window3.reset();
7537   verify("12. Number of displays in split view changed from 3 to 2", 3, 2);
7538   window5.reset();
7539   verify("13. Number of displays in split view changed from 2 to 1", 3, 3);
7540   window1.reset();
7541   verify("14. Number of displays in split view changed from 1 to 0", 3, 3);
7542   split_view_controller1->SnapWindow(window2.get(), SplitViewController::LEFT);
7543   verify("15. Number of displays in split view changed from 0 to 1", 3, 3);
7544   // In this case, multi-display split view ends as soon as it starts. The
7545   // metrics should report that as starting and ending multi-display split view.
7546   split_view_controller2->SnapWindow(window4.get(), SplitViewController::LEFT);
7547   verify(
7548       "16. Multi-display split view started by snapping last overview window",
7549       4, 4);
7550 }
7551 
7552 // Verify that |SplitViewController::CanSnapWindow| checks that the minimum size
7553 // of the window fits into the left or top, with the default divider position.
7554 // (If the work area length is odd, then the right or bottom will be one pixel
7555 // larger.)
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,SnapWindowWithMinimumSizeTest)7556 TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
7557        SnapWindowWithMinimumSizeTest) {
7558   // The divider is 8 thick. For the default divider position, the remaining 792
7559   // of the work area on the first root window is divided into 396 on each side,
7560   // and the remaining 791 of the work area on the second root window is divided
7561   // into 395 on the left and 396 on the right (the left side is what matters).
7562   UpdateDisplay("800x600,799x600");
7563   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
7564   ASSERT_EQ(2u, root_windows.size());
7565   const gfx::Rect bounds_within_root1(0, 0, 400, 400);
7566   const gfx::Rect bounds_within_root2(800, 0, 400, 400);
7567   // It should make no difference which root window has the window passed to
7568   // |SplitViewController::CanSnapWindow|. What should matter is the root window
7569   // of the |SplitViewController|. To verify, we test with |bounds_within_root1|
7570   // and |bounds_within_root2|, and expect the same results.
7571   for (const gfx::Rect& bounds : {bounds_within_root1, bounds_within_root2}) {
7572     SCOPED_TRACE(bounds.ToString());
7573     aura::test::TestWindowDelegate* delegate =
7574         aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate();
7575     std::unique_ptr<aura::Window> window(
7576         CreateTestWindowInShellWithDelegate(delegate, /*id=*/-1, bounds));
7577     // Before setting a minimum size, expect that |window| can be snapped in
7578     // split view on either root window.
7579     EXPECT_TRUE(
7580         SplitViewController::Get(root_windows[0])->CanSnapWindow(window.get()));
7581     EXPECT_TRUE(
7582         SplitViewController::Get(root_windows[1])->CanSnapWindow(window.get()));
7583     // Either root window can accommodate a minimum size 395 wide.
7584     delegate->set_minimum_size(gfx::Size(395, 0));
7585     EXPECT_TRUE(
7586         SplitViewController::Get(root_windows[0])->CanSnapWindow(window.get()));
7587     EXPECT_TRUE(
7588         SplitViewController::Get(root_windows[1])->CanSnapWindow(window.get()));
7589     // Only the first root window can accommodate a minimum size 396 wide.
7590     delegate->set_minimum_size(gfx::Size(396, 0));
7591     EXPECT_TRUE(
7592         SplitViewController::Get(root_windows[0])->CanSnapWindow(window.get()));
7593     EXPECT_FALSE(
7594         SplitViewController::Get(root_windows[1])->CanSnapWindow(window.get()));
7595     // Neither root window can accommodate a minimum size 397 wide.
7596     delegate->set_minimum_size(gfx::Size(397, 0));
7597     EXPECT_FALSE(
7598         SplitViewController::Get(root_windows[0])->CanSnapWindow(window.get()));
7599     EXPECT_FALSE(
7600         SplitViewController::Get(root_windows[1])->CanSnapWindow(window.get()));
7601   }
7602 }
7603 
7604 // Verify that when in overview mode, the selector items unsnappable indicator
7605 // shows up when expected.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,OverviewUnsnappableIndicatorVisibility)7606 TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
7607        OverviewUnsnappableIndicatorVisibility) {
7608   UpdateDisplay("800x600,800x600");
7609   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
7610   ASSERT_EQ(2u, root_windows.size());
7611   const gfx::Rect bounds_within_root1(0, 0, 400, 400);
7612   const gfx::Rect bounds_within_root2(800, 0, 400, 400);
7613   std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds_within_root1);
7614   std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds_within_root1);
7615   std::unique_ptr<aura::Window> window3 =
7616       CreateUnsnappableWindow(bounds_within_root1);
7617   std::unique_ptr<aura::Window> window4 = CreateTestWindow(bounds_within_root2);
7618   std::unique_ptr<aura::Window> window5 = CreateTestWindow(bounds_within_root2);
7619   std::unique_ptr<aura::Window> window6 =
7620       CreateUnsnappableWindow(bounds_within_root2);
7621   ToggleOverview();
7622   OverviewItem* item2 = GetOverviewItemForWindow(window2.get());
7623   OverviewItem* item3 = GetOverviewItemForWindow(window3.get());
7624   OverviewItem* item5 = GetOverviewItemForWindow(window5.get());
7625   OverviewItem* item6 = GetOverviewItemForWindow(window6.get());
7626 
7627   // Note: |cannot_snap_label_view_| and its parent will be created on demand.
7628   ASSERT_FALSE(SplitViewController::Get(root_windows[0])->InSplitViewMode());
7629   ASSERT_FALSE(SplitViewController::Get(root_windows[1])->InSplitViewMode());
7630   EXPECT_FALSE(item2->cannot_snap_widget_for_testing());
7631   EXPECT_FALSE(item3->cannot_snap_widget_for_testing());
7632   EXPECT_FALSE(item5->cannot_snap_widget_for_testing());
7633   EXPECT_FALSE(item6->cannot_snap_widget_for_testing());
7634 
7635   SplitViewController::Get(root_windows[0])
7636       ->SnapWindow(window1.get(), SplitViewController::LEFT);
7637   ASSERT_TRUE(SplitViewController::Get(root_windows[0])->InSplitViewMode());
7638   ASSERT_FALSE(SplitViewController::Get(root_windows[1])->InSplitViewMode());
7639   EXPECT_FALSE(item2->cannot_snap_widget_for_testing());
7640   ASSERT_TRUE(item3->cannot_snap_widget_for_testing());
7641   ui::Layer* item3_unsnappable_layer =
7642       item3->cannot_snap_widget_for_testing()->GetNativeWindow()->layer();
7643   EXPECT_EQ(1.f, item3_unsnappable_layer->opacity());
7644   EXPECT_FALSE(item5->cannot_snap_widget_for_testing());
7645   EXPECT_FALSE(item6->cannot_snap_widget_for_testing());
7646 
7647   SplitViewController::Get(root_windows[1])
7648       ->SnapWindow(window4.get(), SplitViewController::LEFT);
7649   ASSERT_TRUE(SplitViewController::Get(root_windows[0])->InSplitViewMode());
7650   ASSERT_TRUE(SplitViewController::Get(root_windows[1])->InSplitViewMode());
7651   EXPECT_FALSE(item2->cannot_snap_widget_for_testing());
7652   EXPECT_EQ(1.f, item3_unsnappable_layer->opacity());
7653   EXPECT_FALSE(item5->cannot_snap_widget_for_testing());
7654   ASSERT_TRUE(item6->cannot_snap_widget_for_testing());
7655   ui::Layer* item6_unsnappable_layer =
7656       item6->cannot_snap_widget_for_testing()->GetNativeWindow()->layer();
7657   EXPECT_EQ(1.f, item6_unsnappable_layer->opacity());
7658 
7659   SplitViewController::Get(root_windows[0])->EndSplitView();
7660   ASSERT_FALSE(SplitViewController::Get(root_windows[0])->InSplitViewMode());
7661   ASSERT_TRUE(SplitViewController::Get(root_windows[1])->InSplitViewMode());
7662   EXPECT_FALSE(item2->cannot_snap_widget_for_testing());
7663   EXPECT_EQ(0.f, item3_unsnappable_layer->opacity());
7664   EXPECT_FALSE(item5->cannot_snap_widget_for_testing());
7665   EXPECT_EQ(1.f, item6_unsnappable_layer->opacity());
7666 
7667   SplitViewController::Get(root_windows[1])->EndSplitView();
7668   ASSERT_FALSE(SplitViewController::Get(root_windows[0])->InSplitViewMode());
7669   ASSERT_FALSE(SplitViewController::Get(root_windows[1])->InSplitViewMode());
7670   EXPECT_FALSE(item2->cannot_snap_widget_for_testing());
7671   EXPECT_EQ(0.f, item3_unsnappable_layer->opacity());
7672   EXPECT_FALSE(item5->cannot_snap_widget_for_testing());
7673   EXPECT_EQ(0.f, item6_unsnappable_layer->opacity());
7674 }
7675 
7676 // Test that enabling the docked magnifier ends clamshell split view on all
7677 // displays.
TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,DockedMagnifierEndsClamshellSplitView)7678 TEST_P(SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
7679        DockedMagnifierEndsClamshellSplitView) {
7680   UpdateDisplay("800x600,800x600");
7681   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
7682   ASSERT_EQ(2u, root_windows.size());
7683   const gfx::Rect bounds_within_root1(0, 0, 400, 400);
7684   const gfx::Rect bounds_within_root2(800, 0, 400, 400);
7685   std::unique_ptr<aura::Window> window1 = CreateTestWindow(bounds_within_root1);
7686   std::unique_ptr<aura::Window> window2 = CreateTestWindow(bounds_within_root1);
7687   std::unique_ptr<aura::Window> window3 = CreateTestWindow(bounds_within_root2);
7688   ToggleOverview();
7689   SplitViewController::Get(root_windows[0])
7690       ->SnapWindow(window1.get(), SplitViewController::LEFT);
7691   SplitViewController::Get(root_windows[1])
7692       ->SnapWindow(window3.get(), SplitViewController::LEFT);
7693   EXPECT_TRUE(InOverviewSession());
7694   EXPECT_TRUE(SplitViewController::Get(root_windows[0])->InSplitViewMode());
7695   EXPECT_TRUE(SplitViewController::Get(root_windows[1])->InSplitViewMode());
7696   Shell::Get()->docked_magnifier_controller()->SetEnabled(true);
7697   EXPECT_FALSE(InOverviewSession());
7698   EXPECT_FALSE(SplitViewController::Get(root_windows[0])->InSplitViewMode());
7699   EXPECT_FALSE(SplitViewController::Get(root_windows[1])->InSplitViewMode());
7700 }
7701 
7702 INSTANTIATE_TEST_SUITE_P(All, OverviewSessionTest, testing::Bool());
7703 INSTANTIATE_TEST_SUITE_P(All, TabletModeOverviewSessionTest, testing::Bool());
7704 INSTANTIATE_TEST_SUITE_P(All, SplitViewOverviewSessionTest, testing::Bool());
7705 INSTANTIATE_TEST_SUITE_P(All,
7706                          SplitViewOverviewSessionInClamshellTest,
7707                          testing::Bool());
7708 INSTANTIATE_TEST_SUITE_P(
7709     All,
7710     SplitViewOverviewSessionInClamshellTestMultiDisplayOnly,
7711     testing::Values(true));
7712 
7713 }  // namespace ash
7714