OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <algorithm> | 5 #include <algorithm> |
6 | 6 |
7 #include "ash/accessibility_delegate.h" | 7 #include "ash/accessibility_delegate.h" |
8 #include "ash/drag_drop/drag_drop_controller.h" | 8 #include "ash/drag_drop/drag_drop_controller.h" |
9 #include "ash/root_window_controller.h" | 9 #include "ash/root_window_controller.h" |
10 #include "ash/screen_util.h" | 10 #include "ash/screen_util.h" |
(...skipping 12 matching lines...) Expand all Loading... |
23 #include "ash/wm/overview/window_selector_controller.h" | 23 #include "ash/wm/overview/window_selector_controller.h" |
24 #include "ash/wm/overview/window_selector_item.h" | 24 #include "ash/wm/overview/window_selector_item.h" |
25 #include "ash/wm/panels/panel_layout_manager.h" | 25 #include "ash/wm/panels/panel_layout_manager.h" |
26 #include "ash/wm/window_state.h" | 26 #include "ash/wm/window_state.h" |
27 #include "ash/wm/window_util.h" | 27 #include "ash/wm/window_util.h" |
28 #include "ash/wm/wm_event.h" | 28 #include "ash/wm/wm_event.h" |
29 #include "base/basictypes.h" | 29 #include "base/basictypes.h" |
30 #include "base/compiler_specific.h" | 30 #include "base/compiler_specific.h" |
31 #include "base/memory/scoped_vector.h" | 31 #include "base/memory/scoped_vector.h" |
32 #include "base/run_loop.h" | 32 #include "base/run_loop.h" |
| 33 #include "base/strings/string_piece.h" |
33 #include "base/strings/utf_string_conversions.h" | 34 #include "base/strings/utf_string_conversions.h" |
34 #include "ui/aura/client/aura_constants.h" | 35 #include "ui/aura/client/aura_constants.h" |
35 #include "ui/aura/client/cursor_client.h" | 36 #include "ui/aura/client/cursor_client.h" |
36 #include "ui/aura/client/focus_client.h" | 37 #include "ui/aura/client/focus_client.h" |
37 #include "ui/aura/test/event_generator.h" | 38 #include "ui/aura/test/event_generator.h" |
38 #include "ui/aura/test/test_window_delegate.h" | 39 #include "ui/aura/test/test_window_delegate.h" |
39 #include "ui/aura/test/test_windows.h" | 40 #include "ui/aura/test/test_windows.h" |
40 #include "ui/aura/window.h" | 41 #include "ui/aura/window.h" |
41 #include "ui/aura/window_event_dispatcher.h" | 42 #include "ui/aura/window_event_dispatcher.h" |
42 #include "ui/compositor/scoped_animation_duration_scale_mode.h" | 43 #include "ui/compositor/scoped_animation_duration_scale_mode.h" |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 window_selector_->grid_list_[index]->window_list_.get(); | 196 window_selector_->grid_list_[index]->window_list_.get(); |
196 } | 197 } |
197 | 198 |
198 const aura::Window* GetSelectedWindow() { | 199 const aura::Window* GetSelectedWindow() { |
199 WindowSelector* ws = ash::Shell::GetInstance()-> | 200 WindowSelector* ws = ash::Shell::GetInstance()-> |
200 window_selector_controller()->window_selector_.get(); | 201 window_selector_controller()->window_selector_.get(); |
201 return ws->grid_list_[ws->selected_grid_index_]-> | 202 return ws->grid_list_[ws->selected_grid_index_]-> |
202 SelectedWindow()->SelectionWindow(); | 203 SelectedWindow()->SelectionWindow(); |
203 } | 204 } |
204 | 205 |
| 206 const bool selection_widget_active() { |
| 207 WindowSelector* ws = ash::Shell::GetInstance()-> |
| 208 window_selector_controller()->window_selector_.get(); |
| 209 return ws->grid_list_[ws->selected_grid_index_]->is_selecting(); |
| 210 } |
| 211 |
| 212 bool showing_filter_widget() { |
| 213 WindowSelector* ws = ash::Shell::GetInstance()-> |
| 214 window_selector_controller()->window_selector_.get(); |
| 215 return ws->text_filter_widget_->GetNativeWindow()->layer()-> |
| 216 GetTargetTransform().IsIdentity(); |
| 217 } |
| 218 |
205 views::Widget* GetCloseButton(ash::WindowSelectorItem* window) { | 219 views::Widget* GetCloseButton(ash::WindowSelectorItem* window) { |
206 return window->close_button_.get(); | 220 return window->close_button_.get(); |
207 } | 221 } |
208 | 222 |
209 views::Label* GetLabelView(ash::WindowSelectorItem* window) { | 223 views::Label* GetLabelView(ash::WindowSelectorItem* window) { |
210 return window->window_label_view_; | 224 return window->window_label_view_; |
211 } | 225 } |
212 | 226 |
213 // Tests that a window is contained within a given WindowSelectorItem, and | 227 // Tests that a window is contained within a given WindowSelectorItem, and |
214 // that both the window and its matching close button are within the same | 228 // that both the window and its matching close button are within the same |
215 // screen. | 229 // screen. |
216 void IsWindowAndCloseButtonInScreen(aura::Window* window, | 230 void IsWindowAndCloseButtonInScreen(aura::Window* window, |
217 WindowSelectorItem* window_item) { | 231 WindowSelectorItem* window_item) { |
218 aura::Window* root_window = window_item->GetRootWindow(); | 232 aura::Window* root_window = window_item->GetRootWindow(); |
219 EXPECT_TRUE(window_item->Contains(window)); | 233 EXPECT_TRUE(window_item->Contains(window)); |
220 EXPECT_TRUE(root_window->GetBoundsInScreen().Contains( | 234 EXPECT_TRUE(root_window->GetBoundsInScreen().Contains( |
221 ToEnclosingRect(GetTransformedTargetBounds(window)))); | 235 ToEnclosingRect(GetTransformedTargetBounds(window)))); |
222 EXPECT_TRUE(root_window->GetBoundsInScreen().Contains( | 236 EXPECT_TRUE(root_window->GetBoundsInScreen().Contains( |
223 ToEnclosingRect(GetTransformedTargetBounds( | 237 ToEnclosingRect(GetTransformedTargetBounds( |
224 GetCloseButton(window_item)->GetNativeView())))); | 238 GetCloseButton(window_item)->GetNativeView())))); |
225 } | 239 } |
226 | 240 |
| 241 void FilterItems(const base::StringPiece& pattern) { |
| 242 ash::Shell::GetInstance()-> |
| 243 window_selector_controller()->window_selector_.get()-> |
| 244 ContentsChanged(NULL, base::UTF8ToUTF16(pattern)); |
| 245 } |
| 246 |
227 test::ShelfViewTestAPI* shelf_view_test() { | 247 test::ShelfViewTestAPI* shelf_view_test() { |
228 return shelf_view_test_.get(); | 248 return shelf_view_test_.get(); |
229 } | 249 } |
230 | 250 |
| 251 views::Widget* text_filter_widget() { |
| 252 return ash::Shell::GetInstance()-> |
| 253 window_selector_controller()->window_selector_.get()-> |
| 254 text_filter_widget_.get(); |
| 255 } |
| 256 |
231 private: | 257 private: |
232 aura::test::TestWindowDelegate delegate_; | 258 aura::test::TestWindowDelegate delegate_; |
233 NonActivatableActivationDelegate non_activatable_activation_delegate_; | 259 NonActivatableActivationDelegate non_activatable_activation_delegate_; |
234 scoped_ptr<test::ShelfViewTestAPI> shelf_view_test_; | 260 scoped_ptr<test::ShelfViewTestAPI> shelf_view_test_; |
235 | 261 |
236 DISALLOW_COPY_AND_ASSIGN(WindowSelectorTest); | 262 DISALLOW_COPY_AND_ASSIGN(WindowSelectorTest); |
237 }; | 263 }; |
238 | 264 |
239 // Tests that an a11y alert is sent on entering overview mode. | 265 // Tests that an a11y alert is sent on entering overview mode. |
240 TEST_F(WindowSelectorTest, A11yAlertOnOverviewMode) { | 266 TEST_F(WindowSelectorTest, A11yAlertOnOverviewMode) { |
(...skipping 18 matching lines...) Expand all Loading... |
259 scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds)); | 285 scoped_ptr<aura::Window> panel2(CreatePanelWindow(bounds)); |
260 EXPECT_TRUE(WindowsOverlapping(window1.get(), window2.get())); | 286 EXPECT_TRUE(WindowsOverlapping(window1.get(), window2.get())); |
261 EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get())); | 287 EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get())); |
262 wm::ActivateWindow(window2.get()); | 288 wm::ActivateWindow(window2.get()); |
263 EXPECT_FALSE(wm::IsActiveWindow(window1.get())); | 289 EXPECT_FALSE(wm::IsActiveWindow(window1.get())); |
264 EXPECT_TRUE(wm::IsActiveWindow(window2.get())); | 290 EXPECT_TRUE(wm::IsActiveWindow(window2.get())); |
265 EXPECT_EQ(window2.get(), GetFocusedWindow()); | 291 EXPECT_EQ(window2.get(), GetFocusedWindow()); |
266 // Hide the cursor before entering overview to test that it will be shown. | 292 // Hide the cursor before entering overview to test that it will be shown. |
267 aura::client::GetCursorClient(root_window)->HideCursor(); | 293 aura::client::GetCursorClient(root_window)->HideCursor(); |
268 | 294 |
269 // In overview mode the windows should no longer overlap and focus should | 295 // In overview mode the windows should no longer overlap and the text filter |
270 // be removed from the window. | 296 // widget should be focused. |
271 ToggleOverview(); | 297 ToggleOverview(); |
272 EXPECT_EQ(NULL, GetFocusedWindow()); | 298 EXPECT_EQ(text_filter_widget()->GetNativeWindow(), GetFocusedWindow()); |
273 EXPECT_FALSE(WindowsOverlapping(window1.get(), window2.get())); | 299 EXPECT_FALSE(WindowsOverlapping(window1.get(), window2.get())); |
274 EXPECT_FALSE(WindowsOverlapping(window1.get(), panel1.get())); | 300 EXPECT_FALSE(WindowsOverlapping(window1.get(), panel1.get())); |
275 // Panels 1 and 2 should still be overlapping being in a single selector | 301 // Panels 1 and 2 should still be overlapping being in a single selector |
276 // item. | 302 // item. |
277 EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get())); | 303 EXPECT_TRUE(WindowsOverlapping(panel1.get(), panel2.get())); |
278 | 304 |
279 // Clicking window 1 should activate it. | 305 // Clicking window 1 should activate it. |
280 ClickWindow(window1.get()); | 306 ClickWindow(window1.get()); |
281 EXPECT_TRUE(wm::IsActiveWindow(window1.get())); | 307 EXPECT_TRUE(wm::IsActiveWindow(window1.get())); |
282 EXPECT_FALSE(wm::IsActiveWindow(window2.get())); | 308 EXPECT_FALSE(wm::IsActiveWindow(window2.get())); |
283 EXPECT_EQ(window1.get(), GetFocusedWindow()); | 309 EXPECT_EQ(window1.get(), GetFocusedWindow()); |
284 | 310 |
285 // Cursor should have been unlocked. | 311 // Cursor should have been unlocked. |
286 EXPECT_FALSE(aura::client::GetCursorClient(root_window)->IsCursorLocked()); | 312 EXPECT_FALSE(aura::client::GetCursorClient(root_window)->IsCursorLocked()); |
287 } | 313 } |
288 | 314 |
289 // Tests selecting a window by tapping on it. | 315 // Tests selecting a window by tapping on it. |
290 TEST_F(WindowSelectorTest, BasicGesture) { | 316 TEST_F(WindowSelectorTest, BasicGesture) { |
291 gfx::Rect bounds(0, 0, 400, 400); | 317 gfx::Rect bounds(0, 0, 400, 400); |
292 scoped_ptr<aura::Window> window1(CreateWindow(bounds)); | 318 scoped_ptr<aura::Window> window1(CreateWindow(bounds)); |
293 scoped_ptr<aura::Window> window2(CreateWindow(bounds)); | 319 scoped_ptr<aura::Window> window2(CreateWindow(bounds)); |
294 wm::ActivateWindow(window1.get()); | 320 wm::ActivateWindow(window1.get()); |
295 EXPECT_EQ(window1.get(), GetFocusedWindow()); | 321 EXPECT_EQ(window1.get(), GetFocusedWindow()); |
296 ToggleOverview(); | 322 ToggleOverview(); |
297 EXPECT_EQ(NULL, GetFocusedWindow()); | 323 EXPECT_EQ(text_filter_widget()->GetNativeWindow(), GetFocusedWindow()); |
298 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), | 324 aura::test::EventGenerator generator(Shell::GetPrimaryRootWindow(), |
299 window2.get()); | 325 window2.get()); |
300 generator.GestureTapAt(gfx::ToEnclosingRect( | 326 generator.GestureTapAt(gfx::ToEnclosingRect( |
301 GetTransformedTargetBounds(window2.get())).CenterPoint()); | 327 GetTransformedTargetBounds(window2.get())).CenterPoint()); |
302 EXPECT_EQ(window2.get(), GetFocusedWindow()); | 328 EXPECT_EQ(window2.get(), GetFocusedWindow()); |
303 } | 329 } |
304 | 330 |
305 // Tests that a window does not receive located events when in overview mode. | 331 // Tests that a window does not receive located events when in overview mode. |
306 TEST_F(WindowSelectorTest, WindowDoesNotReceiveEvents) { | 332 TEST_F(WindowSelectorTest, WindowDoesNotReceiveEvents) { |
307 gfx::Rect window_bounds(20, 10, 200, 300); | 333 gfx::Rect window_bounds(20, 10, 200, 300); |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 } | 521 } |
496 | 522 |
497 // Tests that exiting overview mode without selecting a window restores focus | 523 // Tests that exiting overview mode without selecting a window restores focus |
498 // to the previously focused window. | 524 // to the previously focused window. |
499 TEST_F(WindowSelectorTest, CancelRestoresFocus) { | 525 TEST_F(WindowSelectorTest, CancelRestoresFocus) { |
500 gfx::Rect bounds(0, 0, 400, 400); | 526 gfx::Rect bounds(0, 0, 400, 400); |
501 scoped_ptr<aura::Window> window(CreateWindow(bounds)); | 527 scoped_ptr<aura::Window> window(CreateWindow(bounds)); |
502 wm::ActivateWindow(window.get()); | 528 wm::ActivateWindow(window.get()); |
503 EXPECT_EQ(window.get(), GetFocusedWindow()); | 529 EXPECT_EQ(window.get(), GetFocusedWindow()); |
504 | 530 |
505 // In overview mode, focus should be removed. | 531 // In overview mode, the text filter widget should be focused. |
506 ToggleOverview(); | 532 ToggleOverview(); |
507 EXPECT_EQ(NULL, GetFocusedWindow()); | 533 EXPECT_EQ(text_filter_widget()->GetNativeWindow(), GetFocusedWindow()); |
508 | 534 |
509 // If canceling overview mode, focus should be restored. | 535 // If canceling overview mode, focus should be restored. |
510 ToggleOverview(); | 536 ToggleOverview(); |
511 EXPECT_EQ(window.get(), GetFocusedWindow()); | 537 EXPECT_EQ(window.get(), GetFocusedWindow()); |
512 } | 538 } |
513 | 539 |
514 // Tests that overview mode is exited if the last remaining window is destroyed. | 540 // Tests that overview mode is exited if the last remaining window is destroyed. |
515 TEST_F(WindowSelectorTest, LastWindowDestroyed) { | 541 TEST_F(WindowSelectorTest, LastWindowDestroyed) { |
516 gfx::Rect bounds(0, 0, 400, 400); | 542 gfx::Rect bounds(0, 0, 400, 400); |
517 scoped_ptr<aura::Window> window1(CreateWindow(bounds)); | 543 scoped_ptr<aura::Window> window1(CreateWindow(bounds)); |
(...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1007 gfx::Point point2(bounds2.top_right().x() - 1, bounds2.top_right().y() - 1); | 1033 gfx::Point point2(bounds2.top_right().x() - 1, bounds2.top_right().y() - 1); |
1008 aura::test::EventGenerator event_generator2(window2->GetRootWindow(), point2); | 1034 aura::test::EventGenerator event_generator2(window2->GetRootWindow(), point2); |
1009 | 1035 |
1010 EXPECT_FALSE(widget2->IsClosed()); | 1036 EXPECT_FALSE(widget2->IsClosed()); |
1011 event_generator2.ClickLeftButton(); | 1037 event_generator2.ClickLeftButton(); |
1012 EXPECT_TRUE(widget2->IsClosed()); | 1038 EXPECT_TRUE(widget2->IsClosed()); |
1013 RunAllPendingInMessageLoop(); | 1039 RunAllPendingInMessageLoop(); |
1014 EXPECT_FALSE(IsSelecting()); | 1040 EXPECT_FALSE(IsSelecting()); |
1015 } | 1041 } |
1016 | 1042 |
| 1043 // Creates three windows and tests filtering them by title. |
| 1044 TEST_F(WindowSelectorTest, BasicTextFiltering) { |
| 1045 gfx::Rect bounds(0, 0, 100, 100); |
| 1046 scoped_ptr<aura::Window> window2(CreateWindow(bounds)); |
| 1047 scoped_ptr<aura::Window> window1(CreateWindow(bounds)); |
| 1048 scoped_ptr<aura::Window> window0(CreateWindow(bounds)); |
| 1049 base::string16 window2_title = base::UTF8ToUTF16("Highway to test"); |
| 1050 base::string16 window1_title = base::UTF8ToUTF16("For those about to test"); |
| 1051 base::string16 window0_title = base::UTF8ToUTF16("We salute you"); |
| 1052 window0->SetTitle(window0_title); |
| 1053 window1->SetTitle(window1_title); |
| 1054 window2->SetTitle(window2_title); |
| 1055 ToggleOverview(); |
| 1056 EXPECT_FALSE(selection_widget_active()); |
| 1057 EXPECT_FALSE(showing_filter_widget()); |
| 1058 FilterItems("Test"); |
| 1059 |
| 1060 // The selection widget should appear when filtering starts, and should be |
| 1061 // selecting the first matching window. |
| 1062 EXPECT_TRUE(selection_widget_active()); |
| 1063 EXPECT_TRUE(showing_filter_widget()); |
| 1064 EXPECT_EQ(GetSelectedWindow(), window1.get()); |
| 1065 |
| 1066 // Window 0 has no "test" on it so it should be the only dimmed item. |
| 1067 std::vector<WindowSelectorItem*> items = GetWindowItemsForRoot(0); |
| 1068 EXPECT_TRUE(items[0]->dimmed()); |
| 1069 EXPECT_FALSE(items[1]->dimmed()); |
| 1070 EXPECT_FALSE(items[2]->dimmed()); |
| 1071 |
| 1072 // No items match the search. |
| 1073 FilterItems("I'm testing 'n testing"); |
| 1074 EXPECT_TRUE(items[0]->dimmed()); |
| 1075 EXPECT_TRUE(items[1]->dimmed()); |
| 1076 EXPECT_TRUE(items[2]->dimmed()); |
| 1077 |
| 1078 // All the items should match the empty string. The filter widget should also |
| 1079 // disappear. |
| 1080 FilterItems(""); |
| 1081 EXPECT_FALSE(showing_filter_widget()); |
| 1082 EXPECT_FALSE(items[0]->dimmed()); |
| 1083 EXPECT_FALSE(items[1]->dimmed()); |
| 1084 EXPECT_FALSE(items[2]->dimmed()); |
| 1085 } |
| 1086 |
| 1087 // Tests selecting in the overview with dimmed and undimmed items. |
| 1088 TEST_F(WindowSelectorTest, TextFilteringSelection) { |
| 1089 gfx::Rect bounds(0, 0, 100, 100); |
| 1090 scoped_ptr<aura::Window> window2(CreateWindow(bounds)); |
| 1091 scoped_ptr<aura::Window> window1(CreateWindow(bounds)); |
| 1092 scoped_ptr<aura::Window> window0(CreateWindow(bounds)); |
| 1093 base::string16 window2_title = base::UTF8ToUTF16("Rock and roll"); |
| 1094 base::string16 window1_title = base::UTF8ToUTF16("Rock and"); |
| 1095 base::string16 window0_title = base::UTF8ToUTF16("Rock"); |
| 1096 window0->SetTitle(window0_title); |
| 1097 window1->SetTitle(window1_title); |
| 1098 window2->SetTitle(window2_title); |
| 1099 ToggleOverview(); |
| 1100 SendKey(ui::VKEY_RIGHT); |
| 1101 EXPECT_TRUE(selection_widget_active()); |
| 1102 EXPECT_EQ(GetSelectedWindow(), window0.get()); |
| 1103 |
| 1104 // Dim the first item, the selection should jump to the next item. |
| 1105 std::vector<WindowSelectorItem*> items = GetWindowItemsForRoot(0); |
| 1106 FilterItems("Rock and"); |
| 1107 EXPECT_EQ(GetSelectedWindow(), window1.get()); |
| 1108 |
| 1109 // Cycle the selection, the dimmed window should not be selected. |
| 1110 SendKey(ui::VKEY_RIGHT); |
| 1111 EXPECT_EQ(GetSelectedWindow(), window2.get()); |
| 1112 SendKey(ui::VKEY_RIGHT); |
| 1113 EXPECT_EQ(GetSelectedWindow(), window1.get()); |
| 1114 |
| 1115 // Dimming all the items should hide the selection widget. |
| 1116 FilterItems("Pop"); |
| 1117 EXPECT_FALSE(selection_widget_active()); |
| 1118 |
| 1119 // Undimming one window should automatically select it. |
| 1120 FilterItems("Rock and roll"); |
| 1121 EXPECT_EQ(GetSelectedWindow(), window2.get()); |
| 1122 } |
| 1123 |
1017 } // namespace ash | 1124 } // namespace ash |
OLD | NEW |