Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(319)

Side by Side Diff: services/window_manager/focus_controller_unittest.cc

Issue 747163002: Port more focus controller unit tests and fix our focus rules. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Remove O(n) solution with O(1). Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « services/window_manager/basic_focus_rules.cc ('k') | services/window_manager/focus_rules.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « services/window_manager/basic_focus_rules.cc ('k') | services/window_manager/focus_rules.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698