OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "services/window_manager/focus_controller.h" | 5 #include "services/window_manager/focus_controller.h" |
6 | 6 |
7 #include "mojo/converters/geometry/geometry_type_converters.h" | 7 #include "mojo/converters/geometry/geometry_type_converters.h" |
8 #include "services/window_manager/basic_focus_rules.h" | 8 #include "services/window_manager/basic_focus_rules.h" |
9 #include "services/window_manager/focus_controller_observer.h" | 9 #include "services/window_manager/focus_controller_observer.h" |
10 #include "services/window_manager/view_event_dispatcher.h" | 10 #include "services/window_manager/view_event_dispatcher.h" |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 event->SetHandled(); | 132 event->SetHandled(); |
133 } | 133 } |
134 void OnGestureEvent(ui::GestureEvent* event) override { | 134 void OnGestureEvent(ui::GestureEvent* event) override { |
135 event->SetHandled(); | 135 event->SetHandled(); |
136 } | 136 } |
137 | 137 |
138 private: | 138 private: |
139 DISALLOW_COPY_AND_ASSIGN(SimpleEventHandler); | 139 DISALLOW_COPY_AND_ASSIGN(SimpleEventHandler); |
140 }; | 140 }; |
141 | 141 |
| 142 class FocusShiftingActivationObserver |
| 143 : public FocusControllerObserver { |
| 144 public: |
| 145 explicit FocusShiftingActivationObserver(FocusController* focus_controller, |
| 146 View* activated_view) |
| 147 : focus_controller_(focus_controller), |
| 148 activated_view_(activated_view), |
| 149 shift_focus_to_(NULL) {} |
| 150 ~FocusShiftingActivationObserver() override {} |
| 151 |
| 152 void set_shift_focus_to(View* shift_focus_to) { |
| 153 shift_focus_to_ = shift_focus_to; |
| 154 } |
| 155 |
| 156 private: |
| 157 // Overridden from FocusControllerObserver: |
| 158 void OnViewActivated(View* gained_active, |
| 159 View* lost_active) override { |
| 160 // Shift focus to a child. This should prevent the default focusing from |
| 161 // occurring in FocusController::FocusView(). |
| 162 if (gained_active == activated_view_) |
| 163 focus_controller_->FocusView(shift_focus_to_); |
| 164 } |
| 165 |
| 166 void OnViewFocused(View* gained_focus, View* lost_focus) override {} |
| 167 |
| 168 FocusController* focus_controller_; |
| 169 View* activated_view_; |
| 170 View* shift_focus_to_; |
| 171 |
| 172 DISALLOW_COPY_AND_ASSIGN(FocusShiftingActivationObserver); |
| 173 }; |
| 174 |
142 // BasicFocusRules subclass that allows basic overrides of focus/activation to | 175 // BasicFocusRules subclass that allows basic overrides of focus/activation to |
143 // be tested. This is intended more as a test that the override system works at | 176 // be tested. This is intended more as a test that the override system works at |
144 // all, rather than as an exhaustive set of use cases, those should be covered | 177 // all, rather than as an exhaustive set of use cases, those should be covered |
145 // in tests for those FocusRules implementations. | 178 // in tests for those FocusRules implementations. |
146 class TestFocusRules : public BasicFocusRules { | 179 class TestFocusRules : public BasicFocusRules { |
147 public: | 180 public: |
148 TestFocusRules(View* root) | 181 TestFocusRules(View* root) |
149 : BasicFocusRules(root), focus_restriction_(NULL) {} | 182 : BasicFocusRules(root), focus_restriction_(NULL) {} |
150 | 183 |
151 // Restricts focus and activation to this window and its child hierarchy. | 184 // Restricts focus and activation to this window and its child hierarchy. |
152 void set_focus_restriction(View* focus_restriction) { | 185 void set_focus_restriction(View* focus_restriction) { |
153 focus_restriction_ = focus_restriction; | 186 focus_restriction_ = focus_restriction; |
154 } | 187 } |
155 | 188 |
156 // Overridden from BasicFocusRules: | 189 // Overridden from BasicFocusRules: |
| 190 bool SupportsChildActivation(View* view) const override { |
| 191 // In FocusControllerTests, only the Root has activatable children. |
| 192 return view->GetRoot() == view; |
| 193 } |
157 bool CanActivateView(View* view) const override { | 194 bool CanActivateView(View* view) const override { |
158 // Restricting focus to a non-activatable child view means the activatable | 195 // Restricting focus to a non-activatable child view means the activatable |
159 // parent outside the focus restriction is activatable. | 196 // parent outside the focus restriction is activatable. |
160 bool can_activate = | 197 bool can_activate = |
161 CanFocusOrActivate(view) || view->Contains(focus_restriction_); | 198 CanFocusOrActivate(view) || view->Contains(focus_restriction_); |
162 return can_activate ? BasicFocusRules::CanActivateView(view) : false; | 199 return can_activate ? BasicFocusRules::CanActivateView(view) : false; |
163 } | 200 } |
164 bool CanFocusView(View* view) const override { | 201 bool CanFocusView(View* view) const override { |
165 return CanFocusOrActivate(view) ? BasicFocusRules::CanFocusView(view) | 202 return CanFocusOrActivate(view) ? BasicFocusRules::CanFocusView(view) |
166 : false; | 203 : false; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
278 } | 315 } |
279 | 316 |
280 View* root_view() { return &root_view_; } | 317 View* root_view() { return &root_view_; } |
281 TestFocusRules* test_focus_rules() { return test_focus_rules_; } | 318 TestFocusRules* test_focus_rules() { return test_focus_rules_; } |
282 FocusController* focus_controller() { return focus_controller_.get(); } | 319 FocusController* focus_controller() { return focus_controller_.get(); } |
283 | 320 |
284 // Test functions. | 321 // Test functions. |
285 virtual void BasicFocus() = 0; | 322 virtual void BasicFocus() = 0; |
286 virtual void BasicActivation() = 0; | 323 virtual void BasicActivation() = 0; |
287 virtual void FocusEvents() = 0; | 324 virtual void FocusEvents() = 0; |
| 325 virtual void DuplicateFocusEvents() {} |
| 326 virtual void ActivationEvents() = 0; |
| 327 virtual void ReactivationEvents() {} |
| 328 virtual void DuplicateActivationEvents() {} |
| 329 virtual void ShiftFocusWithinActiveView() {} |
| 330 virtual void ShiftFocusToChildOfInactiveView() {} |
| 331 virtual void ShiftFocusToParentOfFocusedView() {} |
| 332 virtual void FocusRulesOverride() = 0; |
| 333 virtual void ActivationRulesOverride() = 0; |
| 334 virtual void ShiftFocusOnActivation() {} |
288 | 335 |
289 private: | 336 private: |
290 TestView root_view_; | 337 TestView root_view_; |
291 scoped_ptr<FocusController> focus_controller_; | 338 scoped_ptr<FocusController> focus_controller_; |
292 TestFocusRules* test_focus_rules_; | 339 TestFocusRules* test_focus_rules_; |
293 // TODO(erg): The aura version of this class also keeps track of WMState. Do | 340 // TODO(erg): The aura version of this class also keeps track of WMState. Do |
294 // we need something analogous here? | 341 // we need something analogous here? |
295 | 342 |
296 scoped_ptr<ViewEventDispatcher> view_event_dispatcher_; | 343 scoped_ptr<ViewEventDispatcher> view_event_dispatcher_; |
297 | 344 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
365 FocusViewById(1); | 412 FocusViewById(1); |
366 root_observer.ExpectCounts(1, 1); | 413 root_observer.ExpectCounts(1, 1); |
367 observer1.ExpectCounts(1, 1); | 414 observer1.ExpectCounts(1, 1); |
368 observer2.ExpectCounts(0, 0); | 415 observer2.ExpectCounts(0, 0); |
369 | 416 |
370 FocusViewById(2); | 417 FocusViewById(2); |
371 root_observer.ExpectCounts(2, 2); | 418 root_observer.ExpectCounts(2, 2); |
372 observer1.ExpectCounts(2, 2); | 419 observer1.ExpectCounts(2, 2); |
373 observer2.ExpectCounts(1, 1); | 420 observer2.ExpectCounts(1, 1); |
374 } | 421 } |
| 422 void DuplicateFocusEvents() override { |
| 423 // Focusing an existing focused window should not resend focus events. |
| 424 ScopedFocusNotificationObserver root_observer(focus_controller()); |
| 425 ScopedFilteringFocusNotificationObserver observer1(focus_controller(), |
| 426 GetViewById(1)); |
| 427 |
| 428 root_observer.ExpectCounts(0, 0); |
| 429 observer1.ExpectCounts(0, 0); |
| 430 |
| 431 FocusViewById(1); |
| 432 root_observer.ExpectCounts(1, 1); |
| 433 observer1.ExpectCounts(1, 1); |
| 434 |
| 435 FocusViewById(1); |
| 436 root_observer.ExpectCounts(1, 1); |
| 437 observer1.ExpectCounts(1, 1); |
| 438 } |
| 439 void ActivationEvents() override { |
| 440 ActivateViewById(1); |
| 441 |
| 442 ScopedFocusNotificationObserver root_observer(focus_controller()); |
| 443 ScopedFilteringFocusNotificationObserver observer1(focus_controller(), |
| 444 GetViewById(1)); |
| 445 ScopedFilteringFocusNotificationObserver observer2(focus_controller(), |
| 446 GetViewById(2)); |
| 447 |
| 448 root_observer.ExpectCounts(0, 0); |
| 449 observer1.ExpectCounts(0, 0); |
| 450 observer2.ExpectCounts(0, 0); |
| 451 |
| 452 ActivateViewById(2); |
| 453 root_observer.ExpectCounts(1, 1); |
| 454 observer1.ExpectCounts(1, 1); |
| 455 observer2.ExpectCounts(1, 1); |
| 456 } |
| 457 void ReactivationEvents() override { |
| 458 ActivateViewById(1); |
| 459 ScopedFocusNotificationObserver root_observer(focus_controller()); |
| 460 EXPECT_EQ(0, root_observer.reactivation_count()); |
| 461 GetViewById(2)->SetVisible(false); |
| 462 // When we attempt to activate "2", which cannot be activated because it |
| 463 // is not visible, "1" will be reactivated. |
| 464 ActivateViewById(2); |
| 465 EXPECT_EQ(1, root_observer.reactivation_count()); |
| 466 EXPECT_EQ(GetViewById(2), |
| 467 root_observer.reactivation_requested_window()); |
| 468 EXPECT_EQ(GetViewById(1), |
| 469 root_observer.reactivation_actual_window()); |
| 470 } |
| 471 void DuplicateActivationEvents() override { |
| 472 // Activating an existing active window should not resend activation events. |
| 473 ActivateViewById(1); |
| 474 |
| 475 ScopedFocusNotificationObserver root_observer(focus_controller()); |
| 476 ScopedFilteringFocusNotificationObserver observer1(focus_controller(), |
| 477 GetViewById(1)); |
| 478 ScopedFilteringFocusNotificationObserver observer2(focus_controller(), |
| 479 GetViewById(2)); |
| 480 |
| 481 root_observer.ExpectCounts(0, 0); |
| 482 observer1.ExpectCounts(0, 0); |
| 483 observer2.ExpectCounts(0, 0); |
| 484 |
| 485 ActivateViewById(2); |
| 486 root_observer.ExpectCounts(1, 1); |
| 487 observer1.ExpectCounts(1, 1); |
| 488 observer2.ExpectCounts(1, 1); |
| 489 |
| 490 ActivateViewById(2); |
| 491 root_observer.ExpectCounts(1, 1); |
| 492 observer1.ExpectCounts(1, 1); |
| 493 observer2.ExpectCounts(1, 1); |
| 494 } |
| 495 void ShiftFocusWithinActiveView() override { |
| 496 ActivateViewById(1); |
| 497 EXPECT_EQ(1, GetActiveViewId()); |
| 498 EXPECT_EQ(1, GetFocusedViewId()); |
| 499 FocusViewById(11); |
| 500 EXPECT_EQ(11, GetFocusedViewId()); |
| 501 FocusViewById(12); |
| 502 EXPECT_EQ(12, GetFocusedViewId()); |
| 503 } |
| 504 void ShiftFocusToChildOfInactiveView() override { |
| 505 ActivateViewById(2); |
| 506 EXPECT_EQ(2, GetActiveViewId()); |
| 507 EXPECT_EQ(2, GetFocusedViewId()); |
| 508 FocusViewById(11); |
| 509 EXPECT_EQ(1, GetActiveViewId()); |
| 510 EXPECT_EQ(11, GetFocusedViewId()); |
| 511 } |
| 512 void ShiftFocusToParentOfFocusedView() override { |
| 513 ActivateViewById(1); |
| 514 EXPECT_EQ(1, GetFocusedViewId()); |
| 515 FocusViewById(11); |
| 516 EXPECT_EQ(11, GetFocusedViewId()); |
| 517 FocusViewById(1); |
| 518 // Focus should _not_ shift to the parent of the already-focused window. |
| 519 EXPECT_EQ(11, GetFocusedViewId()); |
| 520 } |
| 521 void FocusRulesOverride() override { |
| 522 EXPECT_EQ(NULL, GetFocusedView()); |
| 523 FocusViewById(11); |
| 524 EXPECT_EQ(11, GetFocusedViewId()); |
| 525 |
| 526 test_focus_rules()->set_focus_restriction(GetViewById(211)); |
| 527 FocusViewById(12); |
| 528 // Input events leave focus unchanged; direct API calls will change focus |
| 529 // to the restricted view. |
| 530 int focused_view = IsInputEvent() ? 11 : 211; |
| 531 EXPECT_EQ(focused_view, GetFocusedViewId()); |
| 532 |
| 533 test_focus_rules()->set_focus_restriction(NULL); |
| 534 FocusViewById(12); |
| 535 EXPECT_EQ(12, GetFocusedViewId()); |
| 536 } |
| 537 void ActivationRulesOverride() override { |
| 538 ActivateViewById(1); |
| 539 EXPECT_EQ(1, GetActiveViewId()); |
| 540 EXPECT_EQ(1, GetFocusedViewId()); |
| 541 |
| 542 View* v3 = GetViewById(3); |
| 543 test_focus_rules()->set_focus_restriction(v3); |
| 544 |
| 545 ActivateViewById(2); |
| 546 // Input events leave activation unchanged; direct API calls will activate |
| 547 // the restricted view. |
| 548 int active_view = IsInputEvent() ? 1 : 3; |
| 549 EXPECT_EQ(active_view, GetActiveViewId()); |
| 550 EXPECT_EQ(active_view, GetFocusedViewId()); |
| 551 |
| 552 test_focus_rules()->set_focus_restriction(NULL); |
| 553 ActivateViewById(2); |
| 554 EXPECT_EQ(2, GetActiveViewId()); |
| 555 EXPECT_EQ(2, GetFocusedViewId()); |
| 556 } |
| 557 void ShiftFocusOnActivation() override { |
| 558 // When a view is activated, by default that view is also focused. |
| 559 // An ActivationChangeObserver may shift focus to another view within the |
| 560 // same activatable view. |
| 561 ActivateViewById(2); |
| 562 EXPECT_EQ(2, GetFocusedViewId()); |
| 563 ActivateViewById(1); |
| 564 EXPECT_EQ(1, GetFocusedViewId()); |
| 565 |
| 566 ActivateViewById(2); |
| 567 |
| 568 View* target = GetViewById(1); |
| 569 |
| 570 scoped_ptr<FocusShiftingActivationObserver> observer( |
| 571 new FocusShiftingActivationObserver(focus_controller(), target)); |
| 572 observer->set_shift_focus_to(target->GetChildById(11)); |
| 573 focus_controller()->AddObserver(observer.get()); |
| 574 |
| 575 ActivateViewById(1); |
| 576 |
| 577 // w1's ActivationChangeObserver shifted focus to this child, pre-empting |
| 578 // FocusController's default setting. |
| 579 EXPECT_EQ(11, GetFocusedViewId()); |
| 580 |
| 581 ActivateViewById(2); |
| 582 EXPECT_EQ(2, GetFocusedViewId()); |
| 583 |
| 584 // Simulate a focus reset by the ActivationChangeObserver. This should |
| 585 // trigger the default setting in FocusController. |
| 586 observer->set_shift_focus_to(nullptr); |
| 587 ActivateViewById(1); |
| 588 EXPECT_EQ(1, GetFocusedViewId()); |
| 589 |
| 590 focus_controller()->RemoveObserver(observer.get()); |
| 591 |
| 592 ActivateViewById(2); |
| 593 EXPECT_EQ(2, GetFocusedViewId()); |
| 594 ActivateViewById(1); |
| 595 EXPECT_EQ(1, GetFocusedViewId()); |
| 596 } |
| 597 |
375 | 598 |
376 // TODO(erg): There are a whole bunch other tests here. Port them. | 599 // TODO(erg): There are a whole bunch other tests here. Port them. |
377 | 600 |
378 private: | 601 private: |
379 DISALLOW_COPY_AND_ASSIGN(FocusControllerDirectTestBase); | 602 DISALLOW_COPY_AND_ASSIGN(FocusControllerDirectTestBase); |
380 }; | 603 }; |
381 | 604 |
382 // Focus and Activation changes via the FocusController API. | 605 // Focus and Activation changes via the FocusController API. |
383 class FocusControllerApiTest : public FocusControllerDirectTestBase { | 606 class FocusControllerApiTest : public FocusControllerDirectTestBase { |
384 public: | 607 public: |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
429 #define FOCUS_CONTROLLER_TEST(TESTCLASS, TESTNAME) \ | 652 #define FOCUS_CONTROLLER_TEST(TESTCLASS, TESTNAME) \ |
430 TEST_F(TESTCLASS, TESTNAME) { TESTNAME(); } | 653 TEST_F(TESTCLASS, TESTNAME) { TESTNAME(); } |
431 | 654 |
432 // Runs direct focus change tests (input events and API calls). | 655 // Runs direct focus change tests (input events and API calls). |
433 // | 656 // |
434 // TODO(erg): Enable gesture events in the future. | 657 // TODO(erg): Enable gesture events in the future. |
435 #define DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \ | 658 #define DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \ |
436 FOCUS_CONTROLLER_TEST(FocusControllerApiTest, TESTNAME) \ | 659 FOCUS_CONTROLLER_TEST(FocusControllerApiTest, TESTNAME) \ |
437 FOCUS_CONTROLLER_TEST(FocusControllerMouseEventTest, TESTNAME) | 660 FOCUS_CONTROLLER_TEST(FocusControllerMouseEventTest, TESTNAME) |
438 | 661 |
| 662 // TODO(erg): Once all the basic tests are implemented, go through this list |
| 663 // and change the ones which are ALL_FOCUS_TESTS() to the correct macro. |
| 664 |
439 DIRECT_FOCUS_CHANGE_TESTS(BasicFocus); | 665 DIRECT_FOCUS_CHANGE_TESTS(BasicFocus); |
440 DIRECT_FOCUS_CHANGE_TESTS(BasicActivation); | 666 DIRECT_FOCUS_CHANGE_TESTS(BasicActivation); |
441 DIRECT_FOCUS_CHANGE_TESTS(FocusEvents); | 667 DIRECT_FOCUS_CHANGE_TESTS(FocusEvents); |
| 668 DIRECT_FOCUS_CHANGE_TESTS(DuplicateFocusEvents); |
| 669 DIRECT_FOCUS_CHANGE_TESTS(DuplicateActivationEvents); |
| 670 |
| 671 DIRECT_FOCUS_CHANGE_TESTS(ActivationEvents); |
| 672 |
| 673 // - Input events/API calls shift focus between focusable views within the |
| 674 // active view. |
| 675 DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusWithinActiveView); |
| 676 |
| 677 // - Input events/API calls to a child view of an inactive view shifts |
| 678 // activation to the activatable parent and focuses the child. |
| 679 DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusToChildOfInactiveView); |
| 680 |
| 681 // - Input events/API calls to focus the parent of the focused view do not |
| 682 // shift focus away from the child. |
| 683 DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusToParentOfFocusedView); |
| 684 |
| 685 // - Attempts to active a hidden window, verifies that current window is |
| 686 // attempted to be reactivated and the appropriate event dispatched. |
| 687 FOCUS_CONTROLLER_TEST(FocusControllerApiTest, ReactivationEvents); |
| 688 |
| 689 // - Verifies that FocusRules determine what can be focused. |
| 690 DIRECT_FOCUS_CHANGE_TESTS(FocusRulesOverride); |
| 691 |
| 692 // - Verifies that FocusRules determine what can be activated. |
| 693 DIRECT_FOCUS_CHANGE_TESTS(ActivationRulesOverride); |
| 694 |
| 695 // - Verifies that attempts to change focus or activation from a focus or |
| 696 // activation change observer are ignored. |
| 697 DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusOnActivation); |
442 | 698 |
443 // TODO(erg): Also port IMPLICIT_FOCUS_CHANGE_TARGET_TESTS / ALL_FOCUS_TESTS | 699 // TODO(erg): Also port IMPLICIT_FOCUS_CHANGE_TARGET_TESTS / ALL_FOCUS_TESTS |
444 // here, and replace the above direct testing list. | 700 // here, and replace the above direct testing list. |
445 | 701 |
446 // If a mouse event was handled, it should not activate a window. | 702 // If a mouse event was handled, it should not activate a window. |
447 FOCUS_CONTROLLER_TEST(FocusControllerMouseEventTest, IgnoreHandledEvent); | 703 FOCUS_CONTROLLER_TEST(FocusControllerMouseEventTest, IgnoreHandledEvent); |
448 | 704 |
449 } // namespace mojo | 705 } // namespace mojo |
OLD | NEW |