Chromium Code Reviews| 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() == gfx::Transform()); | |
|
flackr
2014/07/02 15:50:42
nit: GetTargetTransform().IsIdentity()
Nina
2014/07/02 17:39:05
Just another use of those linear algebra classes!
| |
| 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 |