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

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

Issue 1049993002: Get mojo_shell building inside chromium checkout. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix presubmit Created 5 years, 8 months 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "mojo/services/window_manager/focus_controller.h"
6
7 #include "mojo/converters/geometry/geometry_type_converters.h"
8 #include "mojo/services/window_manager/basic_focus_rules.h"
9 #include "mojo/services/window_manager/capture_controller.h"
10 #include "mojo/services/window_manager/focus_controller_observer.h"
11 #include "mojo/services/window_manager/view_event_dispatcher.h"
12 #include "mojo/services/window_manager/view_targeter.h"
13 #include "mojo/services/window_manager/window_manager_test_util.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "ui/events/event_utils.h"
16 #include "ui/gfx/geometry/rect.h"
17
18 using mojo::View;
19
20 namespace window_manager {
21
22 // Counts the number of events that occur.
23 class FocusNotificationObserver : public FocusControllerObserver {
24 public:
25 FocusNotificationObserver()
26 : activation_changed_count_(0),
27 focus_changed_count_(0),
28 reactivation_count_(0),
29 reactivation_requested_view_(NULL),
30 reactivation_actual_view_(NULL) {}
31 ~FocusNotificationObserver() override {}
32
33 void ExpectCounts(int activation_changed_count, int focus_changed_count) {
34 EXPECT_EQ(activation_changed_count, activation_changed_count_);
35 EXPECT_EQ(focus_changed_count, focus_changed_count_);
36 }
37 int reactivation_count() const { return reactivation_count_; }
38 View* reactivation_requested_view() const {
39 return reactivation_requested_view_;
40 }
41 View* reactivation_actual_view() const {
42 return reactivation_actual_view_;
43 }
44
45 protected:
46 // Overridden from FocusControllerObserver:
47 void OnActivated(View* gained_active) override {
48 ++activation_changed_count_;
49 }
50
51 void OnFocused(View* gained_focus) override { ++focus_changed_count_; }
52
53 void OnAttemptToReactivateView(View* request_active,
54 View* actual_active) override {
55 ++reactivation_count_;
56 reactivation_requested_view_ = request_active;
57 reactivation_actual_view_ = actual_active;
58 }
59
60 private:
61 int activation_changed_count_;
62 int focus_changed_count_;
63 int reactivation_count_;
64 View* reactivation_requested_view_;
65 View* reactivation_actual_view_;
66
67 DISALLOW_COPY_AND_ASSIGN(FocusNotificationObserver);
68 };
69
70 class ViewDestroyer {
71 public:
72 virtual View* GetDestroyedView() = 0;
73
74 protected:
75 virtual ~ViewDestroyer() {}
76 };
77
78 // FocusNotificationObserver that keeps track of whether it was notified about
79 // activation changes or focus changes with a destroyed view.
80 class RecordingFocusNotificationObserver : public FocusNotificationObserver {
81 public:
82 RecordingFocusNotificationObserver(FocusController* focus_controller,
83 ViewDestroyer* destroyer)
84 : focus_controller_(focus_controller),
85 destroyer_(destroyer),
86 active_(nullptr),
87 focus_(nullptr),
88 was_notified_with_destroyed_view_(false) {
89 focus_controller_->AddObserver(this);
90 }
91 ~RecordingFocusNotificationObserver() override {
92 focus_controller_->RemoveObserver(this);
93 }
94
95 bool was_notified_with_destroyed_view() const {
96 return was_notified_with_destroyed_view_;
97 }
98
99 // Overridden from FocusNotificationObserver:
100 void OnActivated(View* gained_active) override {
101 if (active_ && active_ == destroyer_->GetDestroyedView())
102 was_notified_with_destroyed_view_ = true;
103 active_ = gained_active;
104 }
105
106 void OnFocused(View* gained_focus) override {
107 if (focus_ && focus_ == destroyer_->GetDestroyedView())
108 was_notified_with_destroyed_view_ = true;
109 focus_ = gained_focus;
110 }
111
112 private:
113 FocusController* focus_controller_;
114
115 // Not owned.
116 ViewDestroyer* destroyer_;
117 View* active_;
118 View* focus_;
119
120 // Whether the observer was notified about the loss of activation or the
121 // loss of focus with a view already destroyed by |destroyer_| as the
122 // |lost_active| or |lost_focus| parameter.
123 bool was_notified_with_destroyed_view_;
124
125 DISALLOW_COPY_AND_ASSIGN(RecordingFocusNotificationObserver);
126 };
127
128 class DestroyOnLoseActivationFocusNotificationObserver
129 : public FocusNotificationObserver,
130 public ViewDestroyer {
131 public:
132 DestroyOnLoseActivationFocusNotificationObserver(
133 FocusController* focus_controller,
134 View* view_to_destroy,
135 View* initial_active)
136 : focus_controller_(focus_controller),
137 view_to_destroy_(view_to_destroy),
138 active_(initial_active),
139 did_destroy_(false) {
140 focus_controller_->AddObserver(this);
141 }
142 ~DestroyOnLoseActivationFocusNotificationObserver() override {
143 focus_controller_->RemoveObserver(this);
144 }
145
146 // Overridden from FocusNotificationObserver:
147 void OnActivated(View* gained_active) override {
148 if (view_to_destroy_ && active_ == view_to_destroy_) {
149 view_to_destroy_->Destroy();
150 did_destroy_ = true;
151 }
152 active_ = gained_active;
153 }
154
155 // Overridden from ViewDestroyer:
156 View* GetDestroyedView() override {
157 return did_destroy_ ? view_to_destroy_ : nullptr;
158 }
159
160 private:
161 FocusController* focus_controller_;
162 View* view_to_destroy_;
163 View* active_;
164 bool did_destroy_;
165
166 DISALLOW_COPY_AND_ASSIGN(DestroyOnLoseActivationFocusNotificationObserver);
167 };
168
169 class ScopedFocusNotificationObserver : public FocusNotificationObserver {
170 public:
171 ScopedFocusNotificationObserver(FocusController* focus_controller)
172 : focus_controller_(focus_controller) {
173 focus_controller_->AddObserver(this);
174 }
175 ~ScopedFocusNotificationObserver() override {
176 focus_controller_->RemoveObserver(this);
177 }
178
179 private:
180 FocusController* focus_controller_;
181
182 DISALLOW_COPY_AND_ASSIGN(ScopedFocusNotificationObserver);
183 };
184
185 // Only responds to events if a message contains |target| as a parameter.
186 class ScopedFilteringFocusNotificationObserver
187 : public FocusNotificationObserver {
188 public:
189 ScopedFilteringFocusNotificationObserver(FocusController* focus_controller,
190 View* target,
191 View* initial_active,
192 View* initial_focus)
193 : focus_controller_(focus_controller),
194 target_(target),
195 active_(initial_active),
196 focus_(initial_focus) {
197 focus_controller_->AddObserver(this);
198 }
199 ~ScopedFilteringFocusNotificationObserver() override {
200 focus_controller_->RemoveObserver(this);
201 }
202
203 private:
204 // Overridden from FocusControllerObserver:
205 void OnActivated(View* gained_active) override {
206 if (gained_active == target_ || active_ == target_)
207 FocusNotificationObserver::OnActivated(gained_active);
208 active_ = gained_active;
209 }
210
211 void OnFocused(View* gained_focus) override {
212 if (gained_focus == target_ || focus_ == target_)
213 FocusNotificationObserver::OnFocused(gained_focus);
214 focus_ = gained_focus;
215 }
216
217 void OnAttemptToReactivateView(View* request_active,
218 View* actual_active) override {
219 if (request_active == target_ || actual_active == target_) {
220 FocusNotificationObserver::OnAttemptToReactivateView(request_active,
221 actual_active);
222 }
223 }
224
225 FocusController* focus_controller_;
226 View* target_;
227 View* active_;
228 View* focus_;
229
230 DISALLOW_COPY_AND_ASSIGN(ScopedFilteringFocusNotificationObserver);
231 };
232
233 // Used to fake the handling of events in the pre-target phase.
234 class SimpleEventHandler : public ui::EventHandler {
235 public:
236 SimpleEventHandler() {}
237 ~SimpleEventHandler() override {}
238
239 // Overridden from ui::EventHandler:
240 void OnMouseEvent(ui::MouseEvent* event) override {
241 event->SetHandled();
242 }
243 void OnGestureEvent(ui::GestureEvent* event) override {
244 event->SetHandled();
245 }
246
247 private:
248 DISALLOW_COPY_AND_ASSIGN(SimpleEventHandler);
249 };
250
251 class FocusShiftingActivationObserver
252 : public FocusControllerObserver {
253 public:
254 explicit FocusShiftingActivationObserver(FocusController* focus_controller,
255 View* activated_view)
256 : focus_controller_(focus_controller),
257 activated_view_(activated_view),
258 shift_focus_to_(NULL) {}
259 ~FocusShiftingActivationObserver() override {}
260
261 void set_shift_focus_to(View* shift_focus_to) {
262 shift_focus_to_ = shift_focus_to;
263 }
264
265 private:
266 // Overridden from FocusControllerObserver:
267 void OnActivated(View* gained_active) override {
268 // Shift focus to a child. This should prevent the default focusing from
269 // occurring in FocusController::FocusView().
270 if (gained_active == activated_view_)
271 focus_controller_->FocusView(shift_focus_to_);
272 }
273
274 void OnFocused(View* gained_focus) override {}
275
276 FocusController* focus_controller_;
277 View* activated_view_;
278 View* shift_focus_to_;
279
280 DISALLOW_COPY_AND_ASSIGN(FocusShiftingActivationObserver);
281 };
282
283 // BasicFocusRules subclass that allows basic overrides of focus/activation to
284 // be tested. This is intended more as a test that the override system works at
285 // all, rather than as an exhaustive set of use cases, those should be covered
286 // in tests for those FocusRules implementations.
287 class TestFocusRules : public BasicFocusRules {
288 public:
289 TestFocusRules(View* root)
290 : BasicFocusRules(root), focus_restriction_(NULL) {}
291
292 // Restricts focus and activation to this view and its child hierarchy.
293 void set_focus_restriction(View* focus_restriction) {
294 focus_restriction_ = focus_restriction;
295 }
296
297 // Overridden from BasicFocusRules:
298 bool SupportsChildActivation(View* view) const override {
299 // In FocusControllerTests, only the Root has activatable children.
300 return view->GetRoot() == view;
301 }
302 bool CanActivateView(View* view) const override {
303 // Restricting focus to a non-activatable child view means the activatable
304 // parent outside the focus restriction is activatable.
305 bool can_activate =
306 CanFocusOrActivate(view) || view->Contains(focus_restriction_);
307 return can_activate ? BasicFocusRules::CanActivateView(view) : false;
308 }
309 bool CanFocusView(View* view) const override {
310 return CanFocusOrActivate(view) ? BasicFocusRules::CanFocusView(view)
311 : false;
312 }
313 View* GetActivatableView(View* view) const override {
314 return BasicFocusRules::GetActivatableView(
315 CanFocusOrActivate(view) ? view : focus_restriction_);
316 }
317 View* GetFocusableView(View* view) const override {
318 return BasicFocusRules::GetFocusableView(
319 CanFocusOrActivate(view) ? view : focus_restriction_);
320 }
321 View* GetNextActivatableView(View* ignore) const override {
322 View* next_activatable = BasicFocusRules::GetNextActivatableView(ignore);
323 return CanFocusOrActivate(next_activatable)
324 ? next_activatable
325 : GetActivatableView(focus_restriction_);
326 }
327
328 private:
329 bool CanFocusOrActivate(View* view) const {
330 return !focus_restriction_ || focus_restriction_->Contains(view);
331 }
332
333 View* focus_restriction_;
334
335 DISALLOW_COPY_AND_ASSIGN(TestFocusRules);
336 };
337
338 // Common infrastructure shared by all FocusController test types.
339 class FocusControllerTestBase : public testing::Test {
340 protected:
341 // Hierarchy used by all tests:
342 // root_view
343 // +-- w1
344 // | +-- w11
345 // | +-- w12
346 // +-- w2
347 // | +-- w21
348 // | +-- w211
349 // +-- w3
350 FocusControllerTestBase()
351 : root_view_(TestView::Build(0, gfx::Rect(0, 0, 800, 600))),
352 v1(TestView::Build(1, gfx::Rect(0, 0, 50, 50), root_view())),
353 v11(TestView::Build(11, gfx::Rect(5, 5, 10, 10), v1)),
354 v12(TestView::Build(12, gfx::Rect(15, 15, 10, 10), v1)),
355 v2(TestView::Build(2, gfx::Rect(75, 75, 50, 50), root_view())),
356 v21(TestView::Build(21, gfx::Rect(5, 5, 10, 10), v2)),
357 v211(TestView::Build(211, gfx::Rect(1, 1, 5, 5), v21)),
358 v3(TestView::Build(3, gfx::Rect(125, 125, 50, 50), root_view())) {}
359
360 // Overridden from testing::Test:
361 void SetUp() override {
362 testing::Test::SetUp();
363
364 test_focus_rules_ = new TestFocusRules(root_view());
365 focus_controller_.reset(
366 new FocusController(scoped_ptr<FocusRules>(test_focus_rules_)));
367 SetFocusController(root_view(), focus_controller_.get());
368
369 capture_controller_.reset(new CaptureController);
370 SetCaptureController(root_view(), capture_controller_.get());
371
372 ViewTarget* root_target = root_view_->target();
373 root_target->SetEventTargeter(scoped_ptr<ViewTargeter>(new ViewTargeter()));
374 view_event_dispatcher_.reset(new ViewEventDispatcher());
375 view_event_dispatcher_->SetRootViewTarget(root_target);
376
377 GetRootViewTarget()->AddPreTargetHandler(focus_controller_.get());
378 }
379
380 void TearDown() override {
381 GetRootViewTarget()->RemovePreTargetHandler(focus_controller_.get());
382 view_event_dispatcher_.reset();
383
384 root_view_->Destroy();
385
386 capture_controller_.reset();
387 test_focus_rules_ = nullptr; // Owned by FocusController.
388 focus_controller_.reset();
389
390 testing::Test::TearDown();
391 }
392
393 void FocusView(View* view) { focus_controller_->FocusView(view); }
394 View* GetFocusedView() { return focus_controller_->GetFocusedView(); }
395 int GetFocusedViewId() {
396 View* focused_view = GetFocusedView();
397 return focused_view ? focused_view->id() : -1;
398 }
399 void ActivateView(View* view) { focus_controller_->ActivateView(view); }
400 void DeactivateView(View* view) { focus_controller_->DeactivateView(view); }
401 View* GetActiveView() { return focus_controller_->GetActiveView(); }
402 int GetActiveViewId() {
403 View* active_view = GetActiveView();
404 return active_view ? active_view->id() : -1;
405 }
406
407 View* GetViewById(int id) { return root_view_->GetChildById(id); }
408
409 void ClickLeftButton(View* view) {
410 // Get the center bounds of |target| in |root_view_| coordinate space.
411 gfx::Point center =
412 gfx::Rect(view->bounds().To<gfx::Rect>().size()).CenterPoint();
413 ViewTarget::ConvertPointToTarget(ViewTarget::TargetFromView(view),
414 root_view_->target(), &center);
415
416 ui::MouseEvent button_down(ui::ET_MOUSE_PRESSED, center, center,
417 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
418 ui::EF_NONE);
419 ui::EventDispatchDetails details =
420 view_event_dispatcher_->OnEventFromSource(&button_down);
421 CHECK(!details.dispatcher_destroyed);
422
423 ui::MouseEvent button_up(ui::ET_MOUSE_RELEASED, center, center,
424 ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
425 ui::EF_NONE);
426 details = view_event_dispatcher_->OnEventFromSource(&button_up);
427 CHECK(!details.dispatcher_destroyed);
428 }
429
430 ViewTarget* GetRootViewTarget() {
431 return ViewTarget::TargetFromView(root_view());
432 }
433
434 View* root_view() { return root_view_; }
435 TestFocusRules* test_focus_rules() { return test_focus_rules_; }
436 FocusController* focus_controller() { return focus_controller_.get(); }
437 CaptureController* capture_controller() { return capture_controller_.get(); }
438
439 // Test functions.
440 virtual void BasicFocus() = 0;
441 virtual void BasicActivation() = 0;
442 virtual void FocusEvents() = 0;
443 virtual void DuplicateFocusEvents() {}
444 virtual void ActivationEvents() = 0;
445 virtual void ReactivationEvents() {}
446 virtual void DuplicateActivationEvents() {}
447 virtual void ShiftFocusWithinActiveView() {}
448 virtual void ShiftFocusToChildOfInactiveView() {}
449 virtual void ShiftFocusToParentOfFocusedView() {}
450 virtual void FocusRulesOverride() = 0;
451 virtual void ActivationRulesOverride() = 0;
452 virtual void ShiftFocusOnActivation() {}
453 virtual void ShiftFocusOnActivationDueToHide() {}
454 virtual void NoShiftActiveOnActivation() {}
455 virtual void ChangeFocusWhenNothingFocusedAndCaptured() {}
456 virtual void DontPassDestroyedView() {}
457 // TODO(erg): Also, void FocusedTextInputClient() once we build the IME.
458
459 private:
460 TestView* root_view_;
461 scoped_ptr<FocusController> focus_controller_;
462 TestFocusRules* test_focus_rules_;
463 scoped_ptr<CaptureController> capture_controller_;
464 // TODO(erg): The aura version of this class also keeps track of WMState. Do
465 // we need something analogous here?
466
467 scoped_ptr<ViewEventDispatcher> view_event_dispatcher_;
468
469 TestView* v1;
470 TestView* v11;
471 TestView* v12;
472 TestView* v2;
473 TestView* v21;
474 TestView* v211;
475 TestView* v3;
476
477 DISALLOW_COPY_AND_ASSIGN(FocusControllerTestBase);
478 };
479
480 // Test base for tests where focus is directly set to a target view.
481 class FocusControllerDirectTestBase : public FocusControllerTestBase {
482 protected:
483 FocusControllerDirectTestBase() {}
484
485 // Different test types shift focus in different ways.
486 virtual void FocusViewDirect(View* view) = 0;
487 virtual void ActivateViewDirect(View* view) = 0;
488 virtual void DeactivateViewDirect(View* view) = 0;
489
490 // Input events do not change focus if the view can not be focused.
491 virtual bool IsInputEvent() = 0;
492
493 void FocusViewById(int id) {
494 View* view = root_view()->GetChildById(id);
495 DCHECK(view);
496 FocusViewDirect(view);
497 }
498 void ActivateViewById(int id) {
499 View* view = root_view()->GetChildById(id);
500 DCHECK(view);
501 ActivateViewDirect(view);
502 }
503
504 // Overridden from FocusControllerTestBase:
505 void BasicFocus() override {
506 EXPECT_EQ(nullptr, GetFocusedView());
507 FocusViewById(1);
508 EXPECT_EQ(1, GetFocusedViewId());
509 FocusViewById(2);
510 EXPECT_EQ(2, GetFocusedViewId());
511 }
512 void BasicActivation() override {
513 EXPECT_EQ(nullptr, GetActiveView());
514 ActivateViewById(1);
515 EXPECT_EQ(1, GetActiveViewId());
516 ActivateViewById(2);
517 EXPECT_EQ(2, GetActiveViewId());
518 // Verify that attempting to deactivate NULL does not crash and does not
519 // change activation.
520 DeactivateView(nullptr);
521 EXPECT_EQ(2, GetActiveViewId());
522 DeactivateView(GetActiveView());
523 EXPECT_EQ(1, GetActiveViewId());
524 }
525 void FocusEvents() override {
526 ScopedFocusNotificationObserver root_observer(focus_controller());
527 ScopedFilteringFocusNotificationObserver observer1(
528 focus_controller(), GetViewById(1), GetActiveView(), GetFocusedView());
529 ScopedFilteringFocusNotificationObserver observer2(
530 focus_controller(), GetViewById(2), GetActiveView(), GetFocusedView());
531
532 {
533 SCOPED_TRACE("initial state");
534 root_observer.ExpectCounts(0, 0);
535 observer1.ExpectCounts(0, 0);
536 observer2.ExpectCounts(0, 0);
537 }
538
539 FocusViewById(1);
540 {
541 SCOPED_TRACE("FocusViewById(1)");
542 root_observer.ExpectCounts(1, 1);
543 observer1.ExpectCounts(1, 1);
544 observer2.ExpectCounts(0, 0);
545 }
546
547 FocusViewById(2);
548 {
549 SCOPED_TRACE("FocusViewById(2)");
550 root_observer.ExpectCounts(2, 2);
551 observer1.ExpectCounts(2, 2);
552 observer2.ExpectCounts(1, 1);
553 }
554 }
555 void DuplicateFocusEvents() override {
556 // Focusing an existing focused view should not resend focus events.
557 ScopedFocusNotificationObserver root_observer(focus_controller());
558 ScopedFilteringFocusNotificationObserver observer1(
559 focus_controller(), GetViewById(1), GetActiveView(), GetFocusedView());
560
561 root_observer.ExpectCounts(0, 0);
562 observer1.ExpectCounts(0, 0);
563
564 FocusViewById(1);
565 root_observer.ExpectCounts(1, 1);
566 observer1.ExpectCounts(1, 1);
567
568 FocusViewById(1);
569 root_observer.ExpectCounts(1, 1);
570 observer1.ExpectCounts(1, 1);
571 }
572 void ActivationEvents() override {
573 ActivateViewById(1);
574
575 ScopedFocusNotificationObserver root_observer(focus_controller());
576 ScopedFilteringFocusNotificationObserver observer1(
577 focus_controller(), GetViewById(1), GetActiveView(), GetFocusedView());
578 ScopedFilteringFocusNotificationObserver observer2(
579 focus_controller(), GetViewById(2), GetActiveView(), GetFocusedView());
580
581 root_observer.ExpectCounts(0, 0);
582 observer1.ExpectCounts(0, 0);
583 observer2.ExpectCounts(0, 0);
584
585 ActivateViewById(2);
586 root_observer.ExpectCounts(1, 1);
587 observer1.ExpectCounts(1, 1);
588 observer2.ExpectCounts(1, 1);
589 }
590 void ReactivationEvents() override {
591 ActivateViewById(1);
592 ScopedFocusNotificationObserver root_observer(focus_controller());
593 EXPECT_EQ(0, root_observer.reactivation_count());
594 GetViewById(2)->SetVisible(false);
595 // When we attempt to activate "2", which cannot be activated because it
596 // is not visible, "1" will be reactivated.
597 ActivateViewById(2);
598 EXPECT_EQ(1, root_observer.reactivation_count());
599 EXPECT_EQ(GetViewById(2),
600 root_observer.reactivation_requested_view());
601 EXPECT_EQ(GetViewById(1),
602 root_observer.reactivation_actual_view());
603 }
604 void DuplicateActivationEvents() override {
605 ActivateViewById(1);
606
607 ScopedFocusNotificationObserver root_observer(focus_controller());
608 ScopedFilteringFocusNotificationObserver observer1(
609 focus_controller(), GetViewById(1), GetActiveView(), GetFocusedView());
610 ScopedFilteringFocusNotificationObserver observer2(
611 focus_controller(), GetViewById(2), GetActiveView(), GetFocusedView());
612
613 root_observer.ExpectCounts(0, 0);
614 observer1.ExpectCounts(0, 0);
615 observer2.ExpectCounts(0, 0);
616
617 ActivateViewById(2);
618 root_observer.ExpectCounts(1, 1);
619 observer1.ExpectCounts(1, 1);
620 observer2.ExpectCounts(1, 1);
621
622 // Activating an existing active view should not resend activation events.
623 ActivateViewById(2);
624 root_observer.ExpectCounts(1, 1);
625 observer1.ExpectCounts(1, 1);
626 observer2.ExpectCounts(1, 1);
627 }
628 void ShiftFocusWithinActiveView() override {
629 ActivateViewById(1);
630 EXPECT_EQ(1, GetActiveViewId());
631 EXPECT_EQ(1, GetFocusedViewId());
632 FocusViewById(11);
633 EXPECT_EQ(11, GetFocusedViewId());
634 FocusViewById(12);
635 EXPECT_EQ(12, GetFocusedViewId());
636 }
637 void ShiftFocusToChildOfInactiveView() override {
638 ActivateViewById(2);
639 EXPECT_EQ(2, GetActiveViewId());
640 EXPECT_EQ(2, GetFocusedViewId());
641 FocusViewById(11);
642 EXPECT_EQ(1, GetActiveViewId());
643 EXPECT_EQ(11, GetFocusedViewId());
644 }
645 void ShiftFocusToParentOfFocusedView() override {
646 ActivateViewById(1);
647 EXPECT_EQ(1, GetFocusedViewId());
648 FocusViewById(11);
649 EXPECT_EQ(11, GetFocusedViewId());
650 FocusViewById(1);
651 // Focus should _not_ shift to the parent of the already-focused view.
652 EXPECT_EQ(11, GetFocusedViewId());
653 }
654 void FocusRulesOverride() override {
655 EXPECT_EQ(NULL, GetFocusedView());
656 FocusViewById(11);
657 EXPECT_EQ(11, GetFocusedViewId());
658
659 test_focus_rules()->set_focus_restriction(GetViewById(211));
660 FocusViewById(12);
661 // Input events leave focus unchanged; direct API calls will change focus
662 // to the restricted view.
663 int focused_view = IsInputEvent() ? 11 : 211;
664 EXPECT_EQ(focused_view, GetFocusedViewId());
665
666 test_focus_rules()->set_focus_restriction(NULL);
667 FocusViewById(12);
668 EXPECT_EQ(12, GetFocusedViewId());
669 }
670 void ActivationRulesOverride() override {
671 ActivateViewById(1);
672 EXPECT_EQ(1, GetActiveViewId());
673 EXPECT_EQ(1, GetFocusedViewId());
674
675 View* v3 = GetViewById(3);
676 test_focus_rules()->set_focus_restriction(v3);
677
678 ActivateViewById(2);
679 // Input events leave activation unchanged; direct API calls will activate
680 // the restricted view.
681 int active_view = IsInputEvent() ? 1 : 3;
682 EXPECT_EQ(active_view, GetActiveViewId());
683 EXPECT_EQ(active_view, GetFocusedViewId());
684
685 test_focus_rules()->set_focus_restriction(NULL);
686 ActivateViewById(2);
687 EXPECT_EQ(2, GetActiveViewId());
688 EXPECT_EQ(2, GetFocusedViewId());
689 }
690 void ShiftFocusOnActivation() override {
691 // When a view is activated, by default that view is also focused.
692 // An ActivationChangeObserver may shift focus to another view within the
693 // same activatable view.
694 ActivateViewById(2);
695 EXPECT_EQ(2, GetFocusedViewId());
696 ActivateViewById(1);
697 EXPECT_EQ(1, GetFocusedViewId());
698
699 ActivateViewById(2);
700
701 View* target = GetViewById(1);
702
703 scoped_ptr<FocusShiftingActivationObserver> observer(
704 new FocusShiftingActivationObserver(focus_controller(), target));
705 observer->set_shift_focus_to(target->GetChildById(11));
706 focus_controller()->AddObserver(observer.get());
707
708 ActivateViewById(1);
709
710 // w1's ActivationChangeObserver shifted focus to this child, pre-empting
711 // FocusController's default setting.
712 EXPECT_EQ(11, GetFocusedViewId());
713
714 ActivateViewById(2);
715 EXPECT_EQ(2, GetFocusedViewId());
716
717 // Simulate a focus reset by the ActivationChangeObserver. This should
718 // trigger the default setting in FocusController.
719 observer->set_shift_focus_to(nullptr);
720 ActivateViewById(1);
721 EXPECT_EQ(1, GetFocusedViewId());
722
723 focus_controller()->RemoveObserver(observer.get());
724
725 ActivateViewById(2);
726 EXPECT_EQ(2, GetFocusedViewId());
727 ActivateViewById(1);
728 EXPECT_EQ(1, GetFocusedViewId());
729 }
730 void ShiftFocusOnActivationDueToHide() override {
731 // Similar to ShiftFocusOnActivation except the activation change is
732 // triggered by hiding the active view.
733 ActivateViewById(1);
734 EXPECT_EQ(1, GetFocusedViewId());
735
736 // Removes view 3 as candidate for next activatable view.
737 root_view()->GetChildById(3)->SetVisible(false);
738 EXPECT_EQ(1, GetFocusedViewId());
739
740 View* target = root_view()->GetChildById(2);
741
742 scoped_ptr<FocusShiftingActivationObserver> observer(
743 new FocusShiftingActivationObserver(focus_controller(), target));
744 observer->set_shift_focus_to(target->GetChildById(21));
745 focus_controller()->AddObserver(observer.get());
746
747 // Hide the active view.
748 root_view()->GetChildById(1)->SetVisible(false);
749
750 EXPECT_EQ(21, GetFocusedViewId());
751
752 focus_controller()->RemoveObserver(observer.get());
753 }
754 void NoShiftActiveOnActivation() override {
755 // When a view is activated, we need to prevent any change to activation
756 // from being made in response to an activation change notification.
757 }
758
759 // Verifies focus change is honored while capture held.
760 void ChangeFocusWhenNothingFocusedAndCaptured() override {
761 View* v1 = root_view()->GetChildById(1);
762 capture_controller()->SetCapture(v1);
763
764 EXPECT_EQ(-1, GetActiveViewId());
765 EXPECT_EQ(-1, GetFocusedViewId());
766
767 FocusViewById(1);
768
769 EXPECT_EQ(1, GetActiveViewId());
770 EXPECT_EQ(1, GetFocusedViewId());
771
772 capture_controller()->ReleaseCapture(v1);
773 }
774
775 // Verifies if a view that loses activation or focus is destroyed during
776 // observer notification we don't pass the destroyed view to other observers.
777 void DontPassDestroyedView() override {
778 FocusViewById(1);
779
780 EXPECT_EQ(1, GetActiveViewId());
781 EXPECT_EQ(1, GetFocusedViewId());
782
783 {
784 View* to_destroy = root_view()->GetChildById(1);
785 DestroyOnLoseActivationFocusNotificationObserver observer1(
786 focus_controller(), to_destroy, GetActiveView());
787 RecordingFocusNotificationObserver observer2(focus_controller(),
788 &observer1);
789
790 FocusViewById(2);
791
792 EXPECT_EQ(2, GetActiveViewId());
793 EXPECT_EQ(2, GetFocusedViewId());
794
795 EXPECT_EQ(to_destroy, observer1.GetDestroyedView());
796 EXPECT_FALSE(observer2.was_notified_with_destroyed_view());
797 }
798
799 {
800 View* to_destroy = root_view()->GetChildById(2);
801 DestroyOnLoseActivationFocusNotificationObserver observer1(
802 focus_controller(), to_destroy, GetActiveView());
803 RecordingFocusNotificationObserver observer2(focus_controller(),
804 &observer1);
805
806 FocusViewById(3);
807
808 EXPECT_EQ(3, GetActiveViewId());
809 EXPECT_EQ(3, GetFocusedViewId());
810
811 EXPECT_EQ(to_destroy, observer1.GetDestroyedView());
812 EXPECT_FALSE(observer2.was_notified_with_destroyed_view());
813 }
814 }
815
816 private:
817 DISALLOW_COPY_AND_ASSIGN(FocusControllerDirectTestBase);
818 };
819
820 // Focus and Activation changes via the FocusController API.
821 class FocusControllerApiTest : public FocusControllerDirectTestBase {
822 public:
823 FocusControllerApiTest() {}
824
825 private:
826 // Overridden from FocusControllerTestBase:
827 void FocusViewDirect(View* view) override { FocusView(view); }
828 void ActivateViewDirect(View* view) override { ActivateView(view); }
829 void DeactivateViewDirect(View* view) override { DeactivateView(view); }
830 bool IsInputEvent() override { return false; }
831
832 DISALLOW_COPY_AND_ASSIGN(FocusControllerApiTest);
833 };
834
835 // Focus and Activation changes via input events.
836 class FocusControllerMouseEventTest : public FocusControllerDirectTestBase {
837 public:
838 FocusControllerMouseEventTest() {}
839
840 // Tests that a handled mouse event does not trigger a view activation.
841 void IgnoreHandledEvent() {
842 EXPECT_EQ(NULL, GetActiveView());
843 View* v1 = root_view()->GetChildById(1);
844 SimpleEventHandler handler;
845 GetRootViewTarget()->PrependPreTargetHandler(&handler);
846 ClickLeftButton(v1);
847 EXPECT_EQ(NULL, GetActiveView());
848 // TODO(erg): Add gesture testing when we get gestures working.
849 GetRootViewTarget()->RemovePreTargetHandler(&handler);
850 ClickLeftButton(v1);
851 EXPECT_EQ(1, GetActiveViewId());
852 }
853
854 private:
855 // Overridden from FocusControllerTestBase:
856 void FocusViewDirect(View* view) override { ClickLeftButton(view); }
857 void ActivateViewDirect(View* view) override { ClickLeftButton(view); }
858 void DeactivateViewDirect(View* view) override {
859 View* next_activatable = test_focus_rules()->GetNextActivatableView(view);
860 ClickLeftButton(next_activatable);
861 }
862 bool IsInputEvent() override { return true; }
863
864 DISALLOW_COPY_AND_ASSIGN(FocusControllerMouseEventTest);
865 };
866
867 // TODO(erg): Add a FocusControllerGestureEventTest once we have working
868 // gesture forwarding and handling.
869
870 // Test base for tests where focus is implicitly set to a window as the result
871 // of a disposition change to the focused window or the hierarchy that contains
872 // it.
873 class FocusControllerImplicitTestBase : public FocusControllerTestBase {
874 protected:
875 explicit FocusControllerImplicitTestBase(bool parent) : parent_(parent) {}
876
877 View* GetDispositionView(View* view) {
878 return parent_ ? view->parent() : view;
879 }
880
881 // Change the disposition of |view| in such a way as it will lose focus.
882 virtual void ChangeViewDisposition(View* view) = 0;
883
884 // Allow each disposition change test to add additional post-disposition
885 // change expectations.
886 virtual void PostDispostionChangeExpectations() {}
887
888 // Overridden from FocusControllerTestBase:
889 void BasicFocus() override {
890 EXPECT_EQ(NULL, GetFocusedView());
891
892 View* w211 = root_view()->GetChildById(211);
893 FocusView(w211);
894 EXPECT_EQ(211, GetFocusedViewId());
895
896 ChangeViewDisposition(w211);
897 // BasicFocusRules passes focus to the parent.
898 EXPECT_EQ(parent_ ? 2 : 21, GetFocusedViewId());
899 }
900
901 void BasicActivation() override {
902 DCHECK(!parent_) << "Activation tests don't support parent changes.";
903
904 EXPECT_EQ(NULL, GetActiveView());
905
906 View* w2 = root_view()->GetChildById(2);
907 ActivateView(w2);
908 EXPECT_EQ(2, GetActiveViewId());
909
910 ChangeViewDisposition(w2);
911 EXPECT_EQ(3, GetActiveViewId());
912 PostDispostionChangeExpectations();
913 }
914
915 void FocusEvents() override {
916 View* w211 = root_view()->GetChildById(211);
917 FocusView(w211);
918
919 ScopedFocusNotificationObserver root_observer(focus_controller());
920 ScopedFilteringFocusNotificationObserver observer211(
921 focus_controller(), GetViewById(211), GetActiveView(),
922 GetFocusedView());
923
924 {
925 SCOPED_TRACE("first");
926 root_observer.ExpectCounts(0, 0);
927 observer211.ExpectCounts(0, 0);
928 }
929
930 ChangeViewDisposition(w211);
931 {
932 SCOPED_TRACE("second");
933 {
934 SCOPED_TRACE("root_observer");
935 root_observer.ExpectCounts(0, 1);
936 }
937 {
938 SCOPED_TRACE("observer211");
939 observer211.ExpectCounts(0, 1);
940 }
941 }
942 }
943
944 void ActivationEvents() override {
945 DCHECK(!parent_) << "Activation tests don't support parent changes.";
946
947 View* w2 = root_view()->GetChildById(2);
948 ActivateView(w2);
949
950 ScopedFocusNotificationObserver root_observer(focus_controller());
951 ScopedFilteringFocusNotificationObserver observer2(
952 focus_controller(), GetViewById(2), GetActiveView(), GetFocusedView());
953 ScopedFilteringFocusNotificationObserver observer3(
954 focus_controller(), GetViewById(3), GetActiveView(), GetFocusedView());
955 root_observer.ExpectCounts(0, 0);
956 observer2.ExpectCounts(0, 0);
957 observer3.ExpectCounts(0, 0);
958
959 ChangeViewDisposition(w2);
960 root_observer.ExpectCounts(1, 1);
961 observer2.ExpectCounts(1, 1);
962 observer3.ExpectCounts(1, 1);
963 }
964
965 void FocusRulesOverride() override {
966 EXPECT_EQ(NULL, GetFocusedView());
967 View* w211 = root_view()->GetChildById(211);
968 FocusView(w211);
969 EXPECT_EQ(211, GetFocusedViewId());
970
971 test_focus_rules()->set_focus_restriction(root_view()->GetChildById(11));
972 ChangeViewDisposition(w211);
973 // Normally, focus would shift to the parent (w21) but the override shifts
974 // it to 11.
975 EXPECT_EQ(11, GetFocusedViewId());
976
977 test_focus_rules()->set_focus_restriction(NULL);
978 }
979
980 void ActivationRulesOverride() override {
981 DCHECK(!parent_) << "Activation tests don't support parent changes.";
982
983 View* w1 = root_view()->GetChildById(1);
984 ActivateView(w1);
985
986 EXPECT_EQ(1, GetActiveViewId());
987 EXPECT_EQ(1, GetFocusedViewId());
988
989 View* w3 = root_view()->GetChildById(3);
990 test_focus_rules()->set_focus_restriction(w3);
991
992 // Normally, activation/focus would move to w2, but since we have a focus
993 // restriction, it should move to w3 instead.
994 ChangeViewDisposition(w1);
995 EXPECT_EQ(3, GetActiveViewId());
996 EXPECT_EQ(3, GetFocusedViewId());
997
998 test_focus_rules()->set_focus_restriction(NULL);
999 ActivateView(root_view()->GetChildById(2));
1000 EXPECT_EQ(2, GetActiveViewId());
1001 EXPECT_EQ(2, GetFocusedViewId());
1002 }
1003
1004 private:
1005 // When true, the disposition change occurs to the parent of the window
1006 // instead of to the window. This verifies that changes occurring in the
1007 // hierarchy that contains the window affect the window's focus.
1008 bool parent_;
1009
1010 DISALLOW_COPY_AND_ASSIGN(FocusControllerImplicitTestBase);
1011 };
1012
1013 // Focus and Activation changes in response to window visibility changes.
1014 class FocusControllerHideTest : public FocusControllerImplicitTestBase {
1015 public:
1016 FocusControllerHideTest() : FocusControllerImplicitTestBase(false) {}
1017
1018 protected:
1019 FocusControllerHideTest(bool parent)
1020 : FocusControllerImplicitTestBase(parent) {}
1021
1022 // Overridden from FocusControllerImplicitTestBase:
1023 void ChangeViewDisposition(View* view) override {
1024 GetDispositionView(view)->SetVisible(false);
1025 }
1026
1027 private:
1028 DISALLOW_COPY_AND_ASSIGN(FocusControllerHideTest);
1029 };
1030
1031 // Focus and Activation changes in response to window parent visibility
1032 // changes.
1033 class FocusControllerParentHideTest : public FocusControllerHideTest {
1034 public:
1035 FocusControllerParentHideTest() : FocusControllerHideTest(true) {}
1036
1037 private:
1038 DISALLOW_COPY_AND_ASSIGN(FocusControllerParentHideTest);
1039 };
1040
1041 // Focus and Activation changes in response to window destruction.
1042 class FocusControllerDestructionTest : public FocusControllerImplicitTestBase {
1043 public:
1044 FocusControllerDestructionTest() : FocusControllerImplicitTestBase(false) {}
1045
1046 protected:
1047 FocusControllerDestructionTest(bool parent)
1048 : FocusControllerImplicitTestBase(parent) {}
1049
1050 // Overridden from FocusControllerImplicitTestBase:
1051 void ChangeViewDisposition(View* view) override {
1052 GetDispositionView(view)->Destroy();
1053 }
1054
1055 private:
1056 DISALLOW_COPY_AND_ASSIGN(FocusControllerDestructionTest);
1057 };
1058
1059 // Focus and Activation changes in response to window removal.
1060 class FocusControllerRemovalTest : public FocusControllerImplicitTestBase {
1061 public:
1062 FocusControllerRemovalTest()
1063 : FocusControllerImplicitTestBase(false),
1064 window_to_destroy_(nullptr) {}
1065
1066 protected:
1067 FocusControllerRemovalTest(bool parent)
1068 : FocusControllerImplicitTestBase(parent),
1069 window_to_destroy_(nullptr) {}
1070
1071 // Overridden from FocusControllerImplicitTestBase:
1072 void ChangeViewDisposition(View* view) override {
1073 View* disposition_view = GetDispositionView(view);
1074 disposition_view->parent()->RemoveChild(disposition_view);
1075 window_to_destroy_ = disposition_view;
1076 }
1077 void TearDown() override {
1078 if (window_to_destroy_)
1079 window_to_destroy_->Destroy();
1080
1081 FocusControllerImplicitTestBase::TearDown();
1082 }
1083
1084 private:
1085 View* window_to_destroy_;
1086
1087 DISALLOW_COPY_AND_ASSIGN(FocusControllerRemovalTest);
1088 };
1089
1090 // Focus and Activation changes in response to window parent removal.
1091 class FocusControllerParentRemovalTest : public FocusControllerRemovalTest {
1092 public:
1093 FocusControllerParentRemovalTest() : FocusControllerRemovalTest(true) {}
1094
1095 private:
1096 DISALLOW_COPY_AND_ASSIGN(FocusControllerParentRemovalTest);
1097 };
1098
1099 #define FOCUS_CONTROLLER_TEST(TESTCLASS, TESTNAME) \
1100 TEST_F(TESTCLASS, TESTNAME) { TESTNAME(); }
1101
1102 // Runs direct focus change tests (input events and API calls).
1103 //
1104 // TODO(erg): Enable gesture events in the future.
1105 #define DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \
1106 FOCUS_CONTROLLER_TEST(FocusControllerApiTest, TESTNAME) \
1107 FOCUS_CONTROLLER_TEST(FocusControllerMouseEventTest, TESTNAME)
1108
1109 // Runs implicit focus change tests for disposition changes to target.
1110 #define IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME) \
1111 FOCUS_CONTROLLER_TEST(FocusControllerHideTest, TESTNAME) \
1112 FOCUS_CONTROLLER_TEST(FocusControllerDestructionTest, TESTNAME) \
1113 FOCUS_CONTROLLER_TEST(FocusControllerRemovalTest, TESTNAME)
1114
1115 // Runs implicit focus change tests for disposition changes to target's parent
1116 // hierarchy.
1117 #define IMPLICIT_FOCUS_CHANGE_PARENT_TESTS(TESTNAME) \
1118 FOCUS_CONTROLLER_TEST(FocusControllerParentHideTest, TESTNAME) \
1119 FOCUS_CONTROLLER_TEST(FocusControllerParentRemovalTest, TESTNAME)
1120 // TODO(erg): FocusControllerParentDestructionTest were commented out in the
1121 // aura version of this file, and don't work when I tried porting things over.
1122
1123 // Runs all implicit focus change tests (changes to the target and target's
1124 // parent hierarchy)
1125 #define IMPLICIT_FOCUS_CHANGE_TESTS(TESTNAME) \
1126 IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME) \
1127 IMPLICIT_FOCUS_CHANGE_PARENT_TESTS(TESTNAME)
1128
1129 // Runs all possible focus change tests.
1130 #define ALL_FOCUS_TESTS(TESTNAME) \
1131 DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \
1132 IMPLICIT_FOCUS_CHANGE_TESTS(TESTNAME)
1133
1134 // Runs focus change tests that apply only to the target. For example,
1135 // implicit activation changes caused by window disposition changes do not
1136 // occur when changes to the containing hierarchy happen.
1137 #define TARGET_FOCUS_TESTS(TESTNAME) \
1138 DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \
1139 IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME)
1140
1141 // - Focuses a window, verifies that focus changed.
1142 ALL_FOCUS_TESTS(BasicFocus);
1143
1144 // - Activates a window, verifies that activation changed.
1145 TARGET_FOCUS_TESTS(BasicActivation);
1146
1147 // - Focuses a window, verifies that focus events were dispatched.
1148 ALL_FOCUS_TESTS(FocusEvents);
1149
1150 // - Focuses or activates a window multiple times, verifies that events are only
1151 // dispatched when focus/activation actually changes.
1152 DIRECT_FOCUS_CHANGE_TESTS(DuplicateFocusEvents);
1153 DIRECT_FOCUS_CHANGE_TESTS(DuplicateActivationEvents);
1154
1155 // - Activates a window, verifies that activation events were dispatched.
1156 TARGET_FOCUS_TESTS(ActivationEvents);
1157
1158 // - Attempts to active a hidden view, verifies that current view is
1159 // attempted to be reactivated and the appropriate event dispatched.
1160 FOCUS_CONTROLLER_TEST(FocusControllerApiTest, ReactivationEvents);
1161
1162 // - Input events/API calls shift focus between focusable views within the
1163 // active view.
1164 DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusWithinActiveView);
1165
1166 // - Input events/API calls to a child view of an inactive view shifts
1167 // activation to the activatable parent and focuses the child.
1168 DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusToChildOfInactiveView);
1169
1170 // - Input events/API calls to focus the parent of the focused view do not
1171 // shift focus away from the child.
1172 DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusToParentOfFocusedView);
1173
1174 // - Verifies that FocusRules determine what can be focused.
1175 ALL_FOCUS_TESTS(FocusRulesOverride);
1176
1177 // - Verifies that FocusRules determine what can be activated.
1178 TARGET_FOCUS_TESTS(ActivationRulesOverride);
1179
1180 // - Verifies that attempts to change focus or activation from a focus or
1181 // activation change observer are ignored.
1182 DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusOnActivation);
1183 DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusOnActivationDueToHide);
1184 DIRECT_FOCUS_CHANGE_TESTS(NoShiftActiveOnActivation);
1185
1186 FOCUS_CONTROLLER_TEST(FocusControllerApiTest,
1187 ChangeFocusWhenNothingFocusedAndCaptured);
1188
1189 // See description above DontPassDestroyedView() for details.
1190 FOCUS_CONTROLLER_TEST(FocusControllerApiTest, DontPassDestroyedView);
1191
1192 // TODO(erg): Add the TextInputClient tests here.
1193
1194 // If a mouse event was handled, it should not activate a view.
1195 FOCUS_CONTROLLER_TEST(FocusControllerMouseEventTest, IgnoreHandledEvent);
1196
1197 } // namespace window_manager
OLDNEW
« no previous file with comments | « mojo/services/window_manager/focus_controller_observer.h ('k') | mojo/services/window_manager/focus_rules.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698