1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "athena/wm/public/window_manager.h" 6 7 #include "athena/screen/public/screen_manager.h" 8 #include "athena/test/athena_test_base.h" 9 #include "athena/wm/public/window_list_provider.h" 10 #include "athena/wm/split_view_controller.h" 11 #include "athena/wm/test/window_manager_impl_test_api.h" 12 #include "athena/wm/window_manager_impl.h" 13 #include "ui/aura/client/window_tree_client.h" 14 #include "ui/aura/test/test_window_delegate.h" 15 #include "ui/aura/window.h" 16 #include "ui/base/hit_test.h" 17 #include "ui/events/test/event_generator.h" 18 #include "ui/gfx/display.h" 19 #include "ui/gfx/screen.h" 20 #include "ui/wm/core/window_util.h" 21 22 namespace athena { 23 24 class WindowManagerTest : public test::AthenaTestBase { 25 public: 26 WindowManagerTest() {} 27 virtual ~WindowManagerTest() {} 28 29 scoped_ptr<aura::Window> CreateAndActivateWindow( 30 aura::WindowDelegate* delegate) { 31 scoped_ptr<aura::Window> window(CreateTestWindow(delegate, gfx::Rect())); 32 window->Show(); 33 wm::ActivateWindow(window.get()); 34 return window.Pass(); 35 } 36 37 private: 38 DISALLOW_COPY_AND_ASSIGN(WindowManagerTest); 39 }; 40 41 TEST_F(WindowManagerTest, OverviewModeBasics) { 42 aura::test::TestWindowDelegate delegate; 43 scoped_ptr<aura::Window> first(CreateAndActivateWindow(&delegate)); 44 scoped_ptr<aura::Window> second(CreateAndActivateWindow(&delegate)); 45 46 test::WindowManagerImplTestApi wm_api; 47 wm::ActivateWindow(second.get()); 48 49 ASSERT_FALSE(WindowManager::Get()->IsOverviewModeActive()); 50 EXPECT_EQ(first->bounds().ToString(), second->bounds().ToString()); 51 EXPECT_EQ(gfx::Screen::GetNativeScreen() 52 ->GetPrimaryDisplay() 53 .work_area() 54 .size() 55 .ToString(), 56 first->bounds().size().ToString()); 57 EXPECT_FALSE(WindowManager::Get()->IsOverviewModeActive()); 58 59 // Tests that going into overview mode does not change the window bounds. 60 WindowManager::Get()->ToggleOverview(); 61 ASSERT_TRUE(WindowManager::Get()->IsOverviewModeActive()); 62 EXPECT_EQ(first->bounds().ToString(), second->bounds().ToString()); 63 EXPECT_EQ(gfx::Screen::GetNativeScreen() 64 ->GetPrimaryDisplay() 65 .work_area() 66 .size() 67 .ToString(), 68 first->bounds().size().ToString()); 69 EXPECT_TRUE(first->IsVisible()); 70 EXPECT_TRUE(second->IsVisible()); 71 72 // Terminate overview mode. |first| should be hidden, since it's not visible 73 // to the user anymore. 74 WindowManager::Get()->ToggleOverview(); 75 ASSERT_FALSE(WindowManager::Get()->IsOverviewModeActive()); 76 EXPECT_FALSE(first->IsVisible()); 77 EXPECT_TRUE(second->IsVisible()); 78 } 79 80 TEST_F(WindowManagerTest, OverviewToSplitViewMode) { 81 test::WindowManagerImplTestApi wm_api; 82 83 aura::test::TestWindowDelegate delegate; 84 scoped_ptr<aura::Window> w1(CreateAndActivateWindow(&delegate)); 85 scoped_ptr<aura::Window> w2(CreateAndActivateWindow(&delegate)); 86 scoped_ptr<aura::Window> w3(CreateAndActivateWindow(&delegate)); 87 wm::ActivateWindow(w3.get()); 88 89 WindowManager::Get()->ToggleOverview(); 90 EXPECT_TRUE(w1->IsVisible()); 91 EXPECT_TRUE(w2->IsVisible()); 92 EXPECT_TRUE(w3->IsVisible()); 93 94 // Go into split-view mode. 95 WindowOverviewModeDelegate* overview_delegate = wm_api.wm(); 96 overview_delegate->OnSelectSplitViewWindow(w3.get(), NULL, w3.get()); 97 EXPECT_TRUE(w3->IsVisible()); 98 EXPECT_TRUE(w2->IsVisible()); 99 EXPECT_FALSE(w1->IsVisible()); 100 } 101 102 TEST_F(WindowManagerTest, NewWindowFromOverview) { 103 aura::test::TestWindowDelegate delegate; 104 scoped_ptr<aura::Window> w1(CreateAndActivateWindow(&delegate)); 105 scoped_ptr<aura::Window> w2(CreateAndActivateWindow(&delegate)); 106 107 WindowManager::Get()->ToggleOverview(); 108 EXPECT_TRUE(w1->IsVisible()); 109 EXPECT_TRUE(w2->IsVisible()); 110 111 // Test that opening a new window exits overview mode. The new window could 112 // have been opened by JavaScript or by the home card. 113 scoped_ptr<aura::Window> w3(CreateAndActivateWindow(&delegate)); 114 115 ASSERT_FALSE(WindowManager::Get()->IsOverviewModeActive()); 116 EXPECT_TRUE(w3->IsVisible()); 117 EXPECT_TRUE(wm::IsActiveWindow(w3.get())); 118 EXPECT_FALSE(w1->IsVisible()); 119 EXPECT_FALSE(w2->IsVisible()); 120 } 121 122 TEST_F(WindowManagerTest, BezelGestureToSplitViewMode) { 123 aura::test::TestWindowDelegate delegate; 124 scoped_ptr<aura::Window> first(CreateAndActivateWindow(&delegate)); 125 scoped_ptr<aura::Window> second(CreateAndActivateWindow(&delegate)); 126 scoped_ptr<aura::Window> third(CreateAndActivateWindow(&delegate)); 127 128 test::WindowManagerImplTestApi wm_api; 129 130 // Test that going into split-view mode with two-finger gesture selects the 131 // correct windows on left and right splits. 132 ui::test::EventGenerator generator(root_window()); 133 const gfx::Point start_points[2] = { 134 gfx::Point(2, 10), gfx::Point(4, 20), 135 }; 136 const int kEventTimeSepration = 16; 137 int x_middle = root_window()->bounds().width() / 2; 138 generator.GestureMultiFingerScroll( 139 2, start_points, kEventTimeSepration, 1, x_middle, 0); 140 ASSERT_TRUE(wm_api.GetSplitViewController()->IsSplitViewModeActive()); 141 EXPECT_EQ(second.get(), wm_api.GetSplitViewController()->left_window()); 142 EXPECT_EQ(third.get(), wm_api.GetSplitViewController()->right_window()); 143 EXPECT_EQ(second->bounds().size().ToString(), 144 third->bounds().size().ToString()); 145 } 146 147 TEST_F(WindowManagerTest, BezelGestureToSwitchBetweenWindows) { 148 aura::test::TestWindowDelegate delegate; 149 scoped_ptr<aura::Window> first(CreateAndActivateWindow(&delegate)); 150 scoped_ptr<aura::Window> second(CreateAndActivateWindow(&delegate)); 151 scoped_ptr<aura::Window> third(CreateAndActivateWindow(&delegate)); 152 first->Hide(); 153 second->Hide(); 154 155 test::WindowManagerImplTestApi wm_api; 156 157 EXPECT_EQ(third.get(), 158 wm_api.GetWindowListProvider()->GetWindowList().back()); 159 160 // Do a two-finger swipe from the left bezel. 161 ui::test::EventGenerator generator(root_window()); 162 const gfx::Point left_bezel_points[2] = { 163 gfx::Point(2, 10), gfx::Point(4, 20), 164 }; 165 const int kEventTimeSeparation = 16; 166 int width = root_window()->bounds().width(); 167 generator.GestureMultiFingerScroll( 168 2, left_bezel_points, kEventTimeSeparation, 1, width, 0); 169 EXPECT_TRUE(wm::IsActiveWindow(second.get())); 170 EXPECT_EQ(second.get(), 171 wm_api.GetWindowListProvider()->GetWindowList().back()); 172 173 // Do a two-finger swipe from the right bezel. 174 const gfx::Point right_bezel_points[2] = { 175 gfx::Point(width - 5, 10), 176 gfx::Point(width - 10, 20) 177 }; 178 generator.GestureMultiFingerScroll( 179 2, right_bezel_points, kEventTimeSeparation, 1, -width, 0); 180 EXPECT_TRUE(wm::IsActiveWindow(third.get())); 181 EXPECT_EQ(third.get(), 182 wm_api.GetWindowListProvider()->GetWindowList().back()); 183 } 184 185 TEST_F(WindowManagerTest, TitleDragSwitchBetweenWindows) { 186 aura::test::TestWindowDelegate delegate; 187 delegate.set_window_component(HTCAPTION); 188 scoped_ptr<aura::Window> first(CreateAndActivateWindow(&delegate)); 189 scoped_ptr<aura::Window> second(CreateAndActivateWindow(&delegate)); 190 scoped_ptr<aura::Window> third(CreateAndActivateWindow(&delegate)); 191 192 test::WindowManagerImplTestApi wm_api; 193 194 EXPECT_EQ(third.get(), 195 wm_api.GetWindowListProvider()->GetWindowList().back()); 196 197 // Do a title-swipe from the top to switch to the previous window. 198 ui::test::EventGenerator generator(root_window()); 199 generator.GestureScrollSequence(gfx::Point(20, 10), 200 gfx::Point(20, 400), 201 base::TimeDelta::FromMilliseconds(20), 202 5); 203 EXPECT_TRUE(wm::IsActiveWindow(second.get())); 204 EXPECT_EQ(second.get(), 205 wm_api.GetWindowListProvider()->GetWindowList().back()); 206 EXPECT_TRUE(second->IsVisible()); 207 EXPECT_FALSE(third->IsVisible()); 208 209 // Performing the same gesture again will switch back to |third|. 210 generator.GestureScrollSequence(gfx::Point(20, 10), 211 gfx::Point(20, 400), 212 base::TimeDelta::FromMilliseconds(20), 213 5); 214 EXPECT_TRUE(wm::IsActiveWindow(third.get())); 215 EXPECT_EQ(third.get(), 216 wm_api.GetWindowListProvider()->GetWindowList().back()); 217 EXPECT_FALSE(second->IsVisible()); 218 EXPECT_TRUE(third->IsVisible()); 219 220 // Perform a swipe that doesn't go enough to perform the window switch. 221 generator.GestureScrollSequence(gfx::Point(20, 10), 222 gfx::Point(20, 90), 223 base::TimeDelta::FromMilliseconds(20), 224 5); 225 EXPECT_TRUE(wm::IsActiveWindow(third.get())); 226 EXPECT_EQ(third.get(), 227 wm_api.GetWindowListProvider()->GetWindowList().back()); 228 EXPECT_FALSE(second->IsVisible()); 229 EXPECT_TRUE(third->IsVisible()); 230 } 231 232 TEST_F(WindowManagerTest, TitleDragSwitchBetweenWindowsInSplitViewMode) { 233 aura::test::TestWindowDelegate delegate; 234 delegate.set_window_component(HTCAPTION); 235 scoped_ptr<aura::Window> first(CreateAndActivateWindow(&delegate)); 236 scoped_ptr<aura::Window> second(CreateAndActivateWindow(&delegate)); 237 scoped_ptr<aura::Window> third(CreateAndActivateWindow(&delegate)); 238 scoped_ptr<aura::Window> fourth(CreateAndActivateWindow(&delegate)); 239 240 test::WindowManagerImplTestApi wm_api; 241 242 // Test that going into split-view mode with two-finger gesture selects the 243 // correct windows on left and right splits. 244 ui::test::EventGenerator generator(root_window()); 245 const gfx::Point start_points[2] = { 246 gfx::Point(2, 10), gfx::Point(4, 20), 247 }; 248 const int kEventTimeSepration = 16; 249 int x_middle = root_window()->bounds().width() / 2; 250 generator.GestureMultiFingerScroll( 251 2, start_points, kEventTimeSepration, 1, x_middle, 0); 252 ASSERT_TRUE(wm_api.GetSplitViewController()->IsSplitViewModeActive()); 253 EXPECT_EQ(third.get(), wm_api.GetSplitViewController()->left_window()); 254 EXPECT_EQ(fourth.get(), wm_api.GetSplitViewController()->right_window()); 255 256 // Swipe the title of the left window. It should switch to |second|. 257 generator.GestureScrollSequence(gfx::Point(20, 10), 258 gfx::Point(20, 400), 259 base::TimeDelta::FromMilliseconds(20), 260 5); 261 EXPECT_EQ(second.get(), wm_api.GetSplitViewController()->left_window()); 262 EXPECT_EQ(fourth.get(), wm_api.GetSplitViewController()->right_window()); 263 aura::Window::Windows windows = 264 wm_api.GetWindowListProvider()->GetWindowList(); 265 ASSERT_EQ(4u, windows.size()); 266 EXPECT_EQ(second.get(), windows[3]); 267 EXPECT_EQ(fourth.get(), windows[2]); 268 269 // Swipe the title of the right window now. It should switch to |third|. 270 generator.GestureScrollSequence(gfx::Point(x_middle + 20, 10), 271 gfx::Point(x_middle + 20, 400), 272 base::TimeDelta::FromMilliseconds(20), 273 5); 274 EXPECT_EQ(second.get(), wm_api.GetSplitViewController()->left_window()); 275 EXPECT_EQ(third.get(), wm_api.GetSplitViewController()->right_window()); 276 windows = wm_api.GetWindowListProvider()->GetWindowList(); 277 ASSERT_EQ(4u, windows.size()); 278 EXPECT_EQ(third.get(), windows[3]); 279 EXPECT_EQ(second.get(), windows[2]); 280 } 281 282 TEST_F(WindowManagerTest, NewWindowBounds) { 283 aura::test::TestWindowDelegate delegate; 284 scoped_ptr<aura::Window> first(CreateAndActivateWindow(&delegate)); 285 286 test::WindowManagerImplTestApi wm_api; 287 // The window should have the same size as the container. 288 const gfx::Size work_area = 289 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().work_area().size(); 290 EXPECT_EQ(work_area.ToString(), 291 first->bounds().size().ToString()); 292 EXPECT_TRUE(first->bounds().origin().IsOrigin()); 293 294 // A second window should have the same bounds as the first one. 295 scoped_ptr<aura::Window> second(CreateAndActivateWindow(&delegate)); 296 EXPECT_EQ(first->bounds().ToString(), second->bounds().ToString()); 297 298 // Get into split view. 299 wm_api.GetSplitViewController()->ActivateSplitMode(NULL, NULL, NULL); 300 const gfx::Rect left_bounds = 301 wm_api.GetSplitViewController()->left_window()->bounds(); 302 EXPECT_NE(work_area.ToString(), 303 left_bounds.size().ToString()); 304 305 // A new window should replace the left window when in split view. 306 scoped_ptr<aura::Window> third(CreateAndActivateWindow(&delegate)); 307 EXPECT_EQ(wm_api.GetSplitViewController()->left_window(), third.get()); 308 EXPECT_EQ(left_bounds.ToString(), third->bounds().ToString()); 309 } 310 311 TEST_F(WindowManagerTest, SplitModeActivationByShortcut) { 312 test::WindowManagerImplTestApi wm_api; 313 314 aura::test::TestWindowDelegate delegate; 315 scoped_ptr<aura::Window> w1(CreateAndActivateWindow(&delegate)); 316 317 // Splitview mode needs at least two windows. 318 wm_api.wm()->ToggleSplitView(); 319 EXPECT_FALSE(wm_api.GetSplitViewController()->IsSplitViewModeActive()); 320 321 scoped_ptr<aura::Window> w2(CreateAndActivateWindow(&delegate)); 322 w2->Show(); 323 324 wm_api.wm()->ToggleSplitView(); 325 EXPECT_TRUE(wm_api.GetSplitViewController()->IsSplitViewModeActive()); 326 int width = 327 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().work_area().width(); 328 329 EXPECT_EQ(w1->bounds().width(), w2->bounds().width()); 330 EXPECT_GE(width / 2, w1->bounds().width()); 331 332 // Toggle back to normal mode. 333 wm_api.wm()->ToggleSplitView(); 334 EXPECT_FALSE(wm_api.GetSplitViewController()->IsSplitViewModeActive()); 335 336 EXPECT_EQ(width, w1->bounds().width()); 337 EXPECT_EQ(width, w2->bounds().width()); 338 } 339 340 TEST_F(WindowManagerTest, OverviewModeFromSplitMode) { 341 test::WindowManagerImplTestApi wm_api; 342 343 aura::test::TestWindowDelegate delegate; 344 scoped_ptr<aura::Window> w1(CreateAndActivateWindow(&delegate)); 345 scoped_ptr<aura::Window> w2(CreateAndActivateWindow(&delegate)); 346 scoped_ptr<aura::Window> w3(CreateAndActivateWindow(&delegate)); 347 348 // Get into split-view mode, and then turn on overview mode. 349 wm_api.GetSplitViewController()->ActivateSplitMode(NULL, NULL, NULL); 350 WindowManager::Get()->ToggleOverview(); 351 EXPECT_TRUE(wm_api.GetSplitViewController()->IsSplitViewModeActive()); 352 EXPECT_EQ(w3.get(), wm_api.GetSplitViewController()->left_window()); 353 EXPECT_EQ(w2.get(), wm_api.GetSplitViewController()->right_window()); 354 355 WindowOverviewModeDelegate* overview_delegate = wm_api.wm(); 356 overview_delegate->OnSelectWindow(w1.get()); 357 EXPECT_FALSE(wm_api.GetSplitViewController()->IsSplitViewModeActive()); 358 EXPECT_TRUE(w1->IsVisible()); 359 // Make sure the windows that were in split-view mode are hidden. 360 EXPECT_FALSE(w2->IsVisible()); 361 EXPECT_FALSE(w3->IsVisible()); 362 } 363 364 } // namespace athena 365