OLD | NEW |
| (Empty) |
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/split_view_controller.h" | |
6 | |
7 #include "athena/screen/public/screen_manager.h" | |
8 #include "athena/test/base/athena_test_base.h" | |
9 #include "athena/test/base/test_windows.h" | |
10 #include "athena/wm/public/window_list_provider.h" | |
11 #include "athena/wm/test/window_manager_impl_test_api.h" | |
12 #include "base/memory/scoped_vector.h" | |
13 #include "ui/aura/test/test_window_delegate.h" | |
14 #include "ui/aura/window.h" | |
15 #include "ui/gfx/display.h" | |
16 #include "ui/gfx/screen.h" | |
17 #include "ui/wm/core/window_util.h" | |
18 | |
19 namespace athena { | |
20 | |
21 class SplitViewControllerTest : public test::AthenaTestBase { | |
22 public: | |
23 SplitViewControllerTest() {} | |
24 ~SplitViewControllerTest() override {} | |
25 | |
26 // test::AthenaTestBase: | |
27 void SetUp() override { | |
28 test::AthenaTestBase::SetUp(); | |
29 api_.reset(new test::WindowManagerImplTestApi); | |
30 } | |
31 | |
32 void TearDown() override { | |
33 api_.reset(); | |
34 test::AthenaTestBase::TearDown(); | |
35 } | |
36 | |
37 // Returns the topmost window in z-order. | |
38 const aura::Window* GetTopmostWindow() const { | |
39 return *api_->GetWindowListProvider()->GetWindowList().rbegin(); | |
40 } | |
41 | |
42 // Returns the second topmost window in z-order. | |
43 const aura::Window* GetSecondTopmostWindow() const { | |
44 const aura::Window::Windows& list = | |
45 api_->GetWindowListProvider()->GetWindowList(); | |
46 return *(list.rbegin() + 1); | |
47 } | |
48 | |
49 // Returns whether only the split view windows are visible. | |
50 bool OnlySplitViewWindowsVisible() const { | |
51 SplitViewController* controller = api_->GetSplitViewController(); | |
52 DCHECK(controller->IsSplitViewModeActive()); | |
53 aura::Window::Windows list = | |
54 api_->GetWindowListProvider()->GetWindowList(); | |
55 for (aura::Window::Windows::const_iterator it = list.begin(); | |
56 it != list.end(); ++it) { | |
57 bool in_split_view = (*it == controller->left_window() || | |
58 *it == controller->right_window()); | |
59 if (in_split_view != (*it)->IsVisible()) | |
60 return false; | |
61 } | |
62 return true; | |
63 } | |
64 | |
65 bool IsSplitViewAllowed() const { | |
66 return api_->GetSplitViewController()->CanActivateSplitViewMode(); | |
67 } | |
68 | |
69 test::WindowManagerImplTestApi* api() { | |
70 return api_.get(); | |
71 } | |
72 | |
73 void HandleScrollBegin(float delta) { | |
74 api_->GetSplitViewController()->HandleScrollBegin(delta); | |
75 } | |
76 | |
77 void HandleScrollUpdate(float delta) { | |
78 api_->GetSplitViewController()->HandleScrollUpdate(delta); | |
79 } | |
80 | |
81 void HandleScrollEnd(float velocity) { | |
82 api_->GetSplitViewController()->HandleScrollEnd(velocity); | |
83 } | |
84 | |
85 float GetMaxDistanceFromMiddleForTest() { | |
86 return api_->GetSplitViewController()->GetMaxDistanceFromMiddleForTest(); | |
87 } | |
88 | |
89 float GetMinFlingVelocityForTest() { | |
90 return api_->GetSplitViewController()->GetMinFlingVelocityForTest(); | |
91 } | |
92 | |
93 private: | |
94 scoped_ptr<test::WindowManagerImplTestApi> api_; | |
95 | |
96 DISALLOW_COPY_AND_ASSIGN(SplitViewControllerTest); | |
97 }; | |
98 | |
99 // Tests that when split mode is activated, the windows on the left and right | |
100 // are selected correctly. | |
101 TEST_F(SplitViewControllerTest, SplitModeActivation) { | |
102 aura::test::TestWindowDelegate delegate; | |
103 ScopedVector<aura::Window> windows; | |
104 const int kNumWindows = 6; | |
105 for (size_t i = 0; i < kNumWindows; ++i) { | |
106 scoped_ptr<aura::Window> window = | |
107 test::CreateNormalWindow(nullptr, nullptr); | |
108 windows.push_back(window.release()); | |
109 windows[i]->Hide(); | |
110 } | |
111 | |
112 windows[kNumWindows - 1]->Show(); | |
113 wm::ActivateWindow(windows[kNumWindows - 1]); | |
114 | |
115 SplitViewController* controller = api()->GetSplitViewController(); | |
116 ASSERT_FALSE(controller->IsSplitViewModeActive()); | |
117 | |
118 controller->ActivateSplitMode(nullptr, nullptr, nullptr); | |
119 ASSERT_TRUE(controller->IsSplitViewModeActive()); | |
120 // The last two windows should be on the left and right, respectively. | |
121 EXPECT_EQ(windows[kNumWindows - 1], controller->left_window()); | |
122 EXPECT_EQ(windows[kNumWindows - 2], controller->right_window()); | |
123 EXPECT_EQ(windows[kNumWindows - 1], GetTopmostWindow()); | |
124 EXPECT_EQ(windows[kNumWindows - 2], GetSecondTopmostWindow()); | |
125 EXPECT_TRUE(OnlySplitViewWindowsVisible()); | |
126 | |
127 // Select the window that is currently on the left for the right panel. The | |
128 // windows should switch. | |
129 controller->ActivateSplitMode( | |
130 nullptr, windows[kNumWindows - 1], windows[kNumWindows - 1]); | |
131 EXPECT_EQ(windows[kNumWindows - 2], controller->left_window()); | |
132 EXPECT_EQ(windows[kNumWindows - 1], controller->right_window()); | |
133 EXPECT_EQ(windows[kNumWindows - 1], GetTopmostWindow()); | |
134 EXPECT_EQ(windows[kNumWindows - 2], GetSecondTopmostWindow()); | |
135 EXPECT_TRUE(OnlySplitViewWindowsVisible()); | |
136 | |
137 controller->ActivateSplitMode( | |
138 windows[kNumWindows - 1], nullptr, windows[kNumWindows - 1]); | |
139 EXPECT_EQ(windows[kNumWindows - 1], controller->left_window()); | |
140 EXPECT_EQ(windows[kNumWindows - 2], controller->right_window()); | |
141 EXPECT_EQ(windows[kNumWindows - 1], GetTopmostWindow()); | |
142 EXPECT_EQ(windows[kNumWindows - 2], GetSecondTopmostWindow()); | |
143 EXPECT_TRUE(OnlySplitViewWindowsVisible()); | |
144 | |
145 // Select the same windows, but pass in a different window to activate. | |
146 controller->ActivateSplitMode(windows[kNumWindows - 1], | |
147 windows[kNumWindows - 2], | |
148 windows[kNumWindows - 2]); | |
149 EXPECT_EQ(windows[kNumWindows - 1], controller->left_window()); | |
150 EXPECT_EQ(windows[kNumWindows - 2], controller->right_window()); | |
151 EXPECT_EQ(windows[kNumWindows - 2], GetTopmostWindow()); | |
152 EXPECT_EQ(windows[kNumWindows - 1], GetSecondTopmostWindow()); | |
153 EXPECT_TRUE(OnlySplitViewWindowsVisible()); | |
154 | |
155 // Select one of the windows behind the stacks for the right panel. The window | |
156 // on the left should remain unchanged. | |
157 controller->ActivateSplitMode(nullptr, windows[0], windows[0]); | |
158 EXPECT_EQ(windows[kNumWindows - 1], controller->left_window()); | |
159 EXPECT_EQ(windows[0], controller->right_window()); | |
160 EXPECT_EQ(windows[0], GetTopmostWindow()); | |
161 EXPECT_EQ(windows[kNumWindows - 1], GetSecondTopmostWindow()); | |
162 EXPECT_TRUE(OnlySplitViewWindowsVisible()); | |
163 | |
164 controller->ActivateSplitMode(windows[1], nullptr, nullptr); | |
165 EXPECT_EQ(windows[1], controller->left_window()); | |
166 EXPECT_EQ(windows[0], controller->right_window()); | |
167 EXPECT_EQ(windows[0], GetTopmostWindow()); | |
168 EXPECT_EQ(windows[1], GetSecondTopmostWindow()); | |
169 EXPECT_TRUE(OnlySplitViewWindowsVisible()); | |
170 | |
171 controller->ActivateSplitMode(windows[4], windows[5], windows[5]); | |
172 EXPECT_EQ(windows[4], controller->left_window()); | |
173 EXPECT_EQ(windows[5], controller->right_window()); | |
174 EXPECT_EQ(windows[5], GetTopmostWindow()); | |
175 EXPECT_EQ(windows[4], GetSecondTopmostWindow()); | |
176 EXPECT_TRUE(OnlySplitViewWindowsVisible()); | |
177 | |
178 controller->ActivateSplitMode(windows[0], nullptr, windows[0]); | |
179 EXPECT_EQ(windows[0], controller->left_window()); | |
180 EXPECT_EQ(windows[5], controller->right_window()); | |
181 EXPECT_EQ(windows[0], GetTopmostWindow()); | |
182 EXPECT_EQ(windows[5], GetSecondTopmostWindow()); | |
183 EXPECT_TRUE(OnlySplitViewWindowsVisible()); | |
184 } | |
185 | |
186 // Helper function used to return the x-translation value of the layer | |
187 // containing |window|. | |
188 float XTranslationForWindow(aura::Window* window) { | |
189 return window->layer()->transform().To2dTranslation().x(); | |
190 } | |
191 | |
192 // Tests that calls to the methods of DragHandleScrollDelegate will disengage | |
193 // split view mode under the correct circumstances. | |
194 TEST_F(SplitViewControllerTest, ScrollDragHandle) { | |
195 aura::test::TestWindowDelegate delegate; | |
196 ScopedVector<aura::Window> windows; | |
197 const int kNumWindows = 2; | |
198 for (size_t i = 0; i < kNumWindows; ++i) { | |
199 scoped_ptr<aura::Window> window = | |
200 test::CreateNormalWindow(nullptr, nullptr); | |
201 windows.push_back(window.release()); | |
202 windows[i]->Hide(); | |
203 } | |
204 | |
205 SplitViewController* controller = api()->GetSplitViewController(); | |
206 ASSERT_FALSE(controller->IsSplitViewModeActive()); | |
207 | |
208 aura::Window* left_window = windows[0]; | |
209 aura::Window* right_window = windows[1]; | |
210 left_window->Show(); | |
211 wm::ActivateWindow(left_window); | |
212 | |
213 // Activate split view. | |
214 controller->ActivateSplitMode(left_window, right_window, left_window); | |
215 ASSERT_TRUE(controller->IsSplitViewModeActive()); | |
216 EXPECT_TRUE(OnlySplitViewWindowsVisible()); | |
217 EXPECT_EQ(left_window, controller->left_window()); | |
218 EXPECT_EQ(right_window, controller->right_window()); | |
219 | |
220 const float small_distance = GetMaxDistanceFromMiddleForTest() - 1.0f; | |
221 const float large_distance = GetMaxDistanceFromMiddleForTest() + 1.0f; | |
222 const float slow_velocity = GetMinFlingVelocityForTest() - 1.0f; | |
223 const float fast_velocity = GetMinFlingVelocityForTest() + 1.0f; | |
224 | |
225 // Only scroll a small distance to the right, but not enough to be able to | |
226 // disengage split view. | |
227 EXPECT_EQ(0.0f, XTranslationForWindow(right_window)); | |
228 HandleScrollBegin(small_distance - 1.0f); | |
229 EXPECT_EQ(small_distance - 1.0f, XTranslationForWindow(right_window)); | |
230 HandleScrollUpdate(small_distance); | |
231 EXPECT_EQ(small_distance, XTranslationForWindow(right_window)); | |
232 HandleScrollEnd(0.0f); | |
233 EXPECT_EQ(0.0f, XTranslationForWindow(right_window)); | |
234 ASSERT_TRUE(controller->IsSplitViewModeActive()); | |
235 EXPECT_EQ(left_window, controller->left_window()); | |
236 EXPECT_EQ(right_window, controller->right_window()); | |
237 | |
238 // Scroll far enough to the right to be able to disengage split view. Split | |
239 // view should be disengaged with the left window active. | |
240 HandleScrollBegin(small_distance); | |
241 HandleScrollUpdate(large_distance); | |
242 HandleScrollEnd(0.0f); | |
243 ASSERT_FALSE(controller->IsSplitViewModeActive()); | |
244 EXPECT_EQ(nullptr, controller->left_window()); | |
245 EXPECT_EQ(nullptr, controller->right_window()); | |
246 EXPECT_EQ(left_window, GetTopmostWindow()); | |
247 | |
248 // Re-activate split view mode. | |
249 controller->ActivateSplitMode(left_window, right_window, left_window); | |
250 | |
251 // Start scrolling a small distance and then fling, but not fast enough to | |
252 // disengage split view (see kMinFlingVelocity). Split view mode should | |
253 // remain engaged. Also verify that |right_window| is translated correctly. | |
254 EXPECT_EQ(0.0f, XTranslationForWindow(right_window)); | |
255 HandleScrollBegin(-small_distance + 1.0f); | |
256 EXPECT_EQ(-small_distance + 1.0f, XTranslationForWindow(right_window)); | |
257 HandleScrollUpdate(-small_distance); | |
258 EXPECT_EQ(-small_distance, XTranslationForWindow(right_window)); | |
259 HandleScrollEnd(slow_velocity); | |
260 EXPECT_EQ(0.0f, XTranslationForWindow(right_window)); | |
261 ASSERT_TRUE(controller->IsSplitViewModeActive()); | |
262 EXPECT_EQ(left_window, controller->left_window()); | |
263 EXPECT_EQ(right_window, controller->right_window()); | |
264 | |
265 // Scroll far enough to the left to be able to disengage split view, then | |
266 // fling to the right (but not faster than kMinFlingVelocity). Split view | |
267 // should be disengaged with the right window active. | |
268 HandleScrollBegin(-small_distance); | |
269 HandleScrollUpdate(-large_distance); | |
270 HandleScrollEnd(slow_velocity); | |
271 ASSERT_FALSE(controller->IsSplitViewModeActive()); | |
272 EXPECT_EQ(nullptr, controller->left_window()); | |
273 EXPECT_EQ(nullptr, controller->right_window()); | |
274 EXPECT_EQ(right_window, GetTopmostWindow()); | |
275 | |
276 // Re-activate split view mode. | |
277 controller->ActivateSplitMode(left_window, right_window, left_window); | |
278 | |
279 // Scroll far enough to the left to be able to disengage split view, then | |
280 // fling to the right, this time faster than kMinFlingVelocity). Split view | |
281 // should be disengaged with the left window active. | |
282 HandleScrollBegin(-small_distance); | |
283 HandleScrollUpdate(-large_distance); | |
284 HandleScrollEnd(fast_velocity); | |
285 ASSERT_FALSE(controller->IsSplitViewModeActive()); | |
286 EXPECT_EQ(nullptr, controller->left_window()); | |
287 EXPECT_EQ(nullptr, controller->right_window()); | |
288 EXPECT_EQ(left_window, GetTopmostWindow()); | |
289 } | |
290 | |
291 TEST_F(SplitViewControllerTest, LandscapeOnly) { | |
292 aura::test::TestWindowDelegate delegate; | |
293 ScopedVector<aura::Window> windows; | |
294 const int kNumWindows = 2; | |
295 for (size_t i = 0; i < kNumWindows; ++i) { | |
296 scoped_ptr<aura::Window> window = | |
297 test::CreateNormalWindow(nullptr, nullptr); | |
298 window->Hide(); | |
299 windows.push_back(window.release()); | |
300 } | |
301 windows[kNumWindows - 1]->Show(); | |
302 wm::ActivateWindow(windows[kNumWindows - 1]); | |
303 | |
304 ASSERT_EQ(gfx::Display::ROTATE_0, | |
305 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().rotation()); | |
306 | |
307 SplitViewController* controller = api()->GetSplitViewController(); | |
308 ASSERT_TRUE(IsSplitViewAllowed()); | |
309 ASSERT_FALSE(controller->IsSplitViewModeActive()); | |
310 | |
311 controller->ActivateSplitMode(nullptr, nullptr, nullptr); | |
312 ASSERT_TRUE(controller->IsSplitViewModeActive()); | |
313 | |
314 // Screen rotation should be locked while in splitview. | |
315 ScreenManager::Get()->SetRotation(gfx::Display::ROTATE_90); | |
316 EXPECT_EQ(gfx::Display::ROTATE_0, | |
317 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().rotation()); | |
318 | |
319 // Screen is rotated on exiting splitview. | |
320 controller->DeactivateSplitMode(); | |
321 ASSERT_EQ(gfx::Display::ROTATE_90, | |
322 gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().rotation()); | |
323 | |
324 // Entering splitview should now be disabled now that the screen is in a | |
325 // portrait orientation. | |
326 EXPECT_FALSE(IsSplitViewAllowed()); | |
327 | |
328 // Rotating back to 0 allows splitview again. | |
329 ScreenManager::Get()->SetRotation(gfx::Display::ROTATE_0); | |
330 EXPECT_TRUE(IsSplitViewAllowed()); | |
331 } | |
332 | |
333 } // namespace athena | |
OLD | NEW |