Add persisted preference for projection touch HUD
[chromium-blink-merge.git] / ui / views / corewm / focus_controller_unittest.cc
blob62062f875c496e32e77d28ed2954f50fa2711bc6
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.
5 #include "ui/views/corewm/focus_controller.h"
7 #include <map>
9 #include "ui/aura/client/activation_change_observer.h"
10 #include "ui/aura/client/activation_client.h"
11 #include "ui/aura/client/aura_constants.h"
12 #include "ui/aura/client/default_capture_client.h"
13 #include "ui/aura/client/focus_change_observer.h"
14 #include "ui/aura/root_window.h"
15 #include "ui/aura/test/aura_test_base.h"
16 #include "ui/aura/test/event_generator.h"
17 #include "ui/aura/test/test_window_delegate.h"
18 #include "ui/aura/test/test_windows.h"
19 #include "ui/aura/window.h"
20 #include "ui/aura/window_tracker.h"
21 #include "ui/base/events/event_handler.h"
22 #include "ui/views/corewm/base_focus_rules.h"
24 namespace views {
25 namespace corewm {
27 class FocusNotificationObserver : public aura::client::ActivationChangeObserver,
28 public aura::client::FocusChangeObserver {
29 public:
30 FocusNotificationObserver()
31 : activation_changed_count_(0),
32 focus_changed_count_(0),
33 reactivation_count_(0),
34 reactivation_requested_window_(NULL),
35 reactivation_actual_window_(NULL) {}
36 virtual ~FocusNotificationObserver() {}
38 void ExpectCounts(int activation_changed_count, int focus_changed_count) {
39 EXPECT_EQ(activation_changed_count, activation_changed_count_);
40 EXPECT_EQ(focus_changed_count, focus_changed_count_);
42 int reactivation_count() const {
43 return reactivation_count_;
45 aura::Window* reactivation_requested_window() const {
46 return reactivation_requested_window_;
48 aura::Window* reactivation_actual_window() const {
49 return reactivation_actual_window_;
52 private:
53 // Overridden from aura::client::ActivationChangeObserver:
54 virtual void OnWindowActivated(aura::Window* gained_active,
55 aura::Window* lost_active) OVERRIDE {
56 ++activation_changed_count_;
58 virtual void OnAttemptToReactivateWindow(
59 aura::Window* request_active,
60 aura::Window* actual_active) OVERRIDE {
61 ++reactivation_count_;
62 reactivation_requested_window_ = request_active;
63 reactivation_actual_window_ = actual_active;
66 // Overridden from aura::client::FocusChangeObserver:
67 virtual void OnWindowFocused(aura::Window* gained_focus,
68 aura::Window* lost_focus) OVERRIDE {
69 ++focus_changed_count_;
72 int activation_changed_count_;
73 int focus_changed_count_;
74 int reactivation_count_;
75 aura::Window* reactivation_requested_window_;
76 aura::Window* reactivation_actual_window_;
78 DISALLOW_COPY_AND_ASSIGN(FocusNotificationObserver);
81 class ScopedFocusNotificationObserver : public FocusNotificationObserver {
82 public:
83 ScopedFocusNotificationObserver(aura::RootWindow* root_window)
84 : root_window_(root_window) {
85 aura::client::GetActivationClient(root_window_)->AddObserver(this);
86 aura::client::GetFocusClient(root_window_)->AddObserver(this);
88 virtual ~ScopedFocusNotificationObserver() {
89 aura::client::GetActivationClient(root_window_)->RemoveObserver(this);
90 aura::client::GetFocusClient(root_window_)->RemoveObserver(this);
93 private:
94 aura::RootWindow* root_window_;
96 DISALLOW_COPY_AND_ASSIGN(ScopedFocusNotificationObserver);
99 class ScopedTargetFocusNotificationObserver : public FocusNotificationObserver {
100 public:
101 ScopedTargetFocusNotificationObserver(aura::RootWindow* root_window, int id)
102 : target_(root_window->GetChildById(id)) {
103 aura::client::SetActivationChangeObserver(target_, this);
104 aura::client::SetFocusChangeObserver(target_, this);
105 tracker_.Add(target_);
107 virtual ~ScopedTargetFocusNotificationObserver() {
108 if (tracker_.Contains(target_)) {
109 aura::client::SetActivationChangeObserver(target_, NULL);
110 aura::client::SetFocusChangeObserver(target_, NULL);
114 private:
115 aura::Window* target_;
116 aura::WindowTracker tracker_;
118 DISALLOW_COPY_AND_ASSIGN(ScopedTargetFocusNotificationObserver);
121 class FocusShiftingActivationObserver
122 : public aura::client::ActivationChangeObserver {
123 public:
124 explicit FocusShiftingActivationObserver(aura::Window* activated_window)
125 : activated_window_(activated_window),
126 shift_focus_to_(NULL) {}
127 virtual ~FocusShiftingActivationObserver() {}
129 void set_shift_focus_to(aura::Window* shift_focus_to) {
130 shift_focus_to_ = shift_focus_to;
133 private:
134 // Overridden from aura::client::ActivationChangeObserver:
135 virtual void OnWindowActivated(aura::Window* gained_active,
136 aura::Window* lost_active) OVERRIDE {
137 // Shift focus to a child. This should prevent the default focusing from
138 // occurring in FocusController::FocusWindow().
139 if (gained_active == activated_window_) {
140 aura::client::FocusClient* client =
141 aura::client::GetFocusClient(gained_active);
142 client->FocusWindow(shift_focus_to_);
146 aura::Window* activated_window_;
147 aura::Window* shift_focus_to_;
149 DISALLOW_COPY_AND_ASSIGN(FocusShiftingActivationObserver);
152 // BaseFocusRules subclass that allows basic overrides of focus/activation to
153 // be tested. This is intended more as a test that the override system works at
154 // all, rather than as an exhaustive set of use cases, those should be covered
155 // in tests for those FocusRules implementations.
156 class TestFocusRules : public BaseFocusRules {
157 public:
158 TestFocusRules() : focus_restriction_(NULL) {}
160 // Restricts focus and activation to this window and its child hierarchy.
161 void set_focus_restriction(aura::Window* focus_restriction) {
162 focus_restriction_ = focus_restriction;
165 // Overridden from BaseFocusRules:
166 virtual bool SupportsChildActivation(aura::Window* window) const OVERRIDE {
167 // In FocusControllerTests, only the RootWindow has activatable children.
168 return window->GetRootWindow() == window;
170 virtual bool CanActivateWindow(aura::Window* window) const OVERRIDE {
171 // Restricting focus to a non-activatable child window means the activatable
172 // parent outside the focus restriction is activatable.
173 bool can_activate =
174 CanFocusOrActivate(window) || window->Contains(focus_restriction_);
175 return can_activate ? BaseFocusRules::CanActivateWindow(window) : false;
177 virtual bool CanFocusWindow(aura::Window* window) const OVERRIDE {
178 return CanFocusOrActivate(window) ?
179 BaseFocusRules::CanFocusWindow(window) : false;
181 virtual aura::Window* GetActivatableWindow(
182 aura::Window* window) const OVERRIDE {
183 return BaseFocusRules::GetActivatableWindow(
184 CanFocusOrActivate(window) ? window : focus_restriction_);
186 virtual aura::Window* GetFocusableWindow(
187 aura::Window* window) const OVERRIDE {
188 return BaseFocusRules::GetFocusableWindow(
189 CanFocusOrActivate(window) ? window : focus_restriction_);
191 virtual aura::Window* GetNextActivatableWindow(
192 aura::Window* ignore) const OVERRIDE {
193 aura::Window* next_activatable =
194 BaseFocusRules::GetNextActivatableWindow(ignore);
195 return CanFocusOrActivate(next_activatable) ?
196 next_activatable : GetActivatableWindow(focus_restriction_);
199 private:
200 bool CanFocusOrActivate(aura::Window* window) const {
201 return !focus_restriction_ || focus_restriction_->Contains(window);
204 aura::Window* focus_restriction_;
206 DISALLOW_COPY_AND_ASSIGN(TestFocusRules);
209 // Common infrastructure shared by all FocusController test types.
210 class FocusControllerTestBase : public aura::test::AuraTestBase {
211 protected:
212 FocusControllerTestBase() {}
214 // Overridden from aura::test::AuraTestBase:
215 virtual void SetUp() OVERRIDE {
216 // FocusController registers itself as an Env observer so it can catch all
217 // window initializations, including the root_window()'s, so we create it
218 // before allowing the base setup.
219 test_focus_rules_ = new TestFocusRules;
220 focus_controller_.reset(new FocusController(test_focus_rules_));
221 aura::test::AuraTestBase::SetUp();
222 root_window()->AddPreTargetHandler(focus_controller_.get());
223 aura::client::SetFocusClient(root_window(), focus_controller_.get());
224 aura::client::SetActivationClient(root_window(), focus_controller_.get());
226 // Hierarchy used by all tests:
227 // root_window
228 // +-- w1
229 // | +-- w11
230 // | +-- w12
231 // +-- w2
232 // | +-- w21
233 // | +-- w211
234 // +-- w3
235 aura::Window* w1 = aura::test::CreateTestWindowWithDelegate(
236 aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 1,
237 gfx::Rect(0, 0, 50, 50), root_window());
238 aura::test::CreateTestWindowWithDelegate(
239 aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 11,
240 gfx::Rect(5, 5, 10, 10), w1);
241 aura::test::CreateTestWindowWithDelegate(
242 aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 12,
243 gfx::Rect(15, 15, 10, 10), w1);
244 aura::Window* w2 = aura::test::CreateTestWindowWithDelegate(
245 aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 2,
246 gfx::Rect(75, 75, 50, 50), root_window());
247 aura::Window* w21 = aura::test::CreateTestWindowWithDelegate(
248 aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 21,
249 gfx::Rect(5, 5, 10, 10), w2);
250 aura::test::CreateTestWindowWithDelegate(
251 aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 211,
252 gfx::Rect(1, 1, 5, 5), w21);
253 aura::test::CreateTestWindowWithDelegate(
254 aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 3,
255 gfx::Rect(125, 125, 50, 50), root_window());
257 virtual void TearDown() OVERRIDE {
258 root_window()->RemovePreTargetHandler(focus_controller_.get());
259 aura::test::AuraTestBase::TearDown();
260 test_focus_rules_ = NULL; // Owned by FocusController.
261 focus_controller_.reset();
264 void FocusWindow(aura::Window* window) {
265 aura::client::GetFocusClient(root_window())->FocusWindow(window);
267 aura::Window* GetFocusedWindow() {
268 return aura::client::GetFocusClient(root_window())->GetFocusedWindow();
270 int GetFocusedWindowId() {
271 return GetFocusedWindow()->id();
273 void ActivateWindow(aura::Window* window) {
274 aura::client::GetActivationClient(root_window())->ActivateWindow(window);
276 void DeactivateWindow(aura::Window* window) {
277 aura::client::GetActivationClient(root_window())->DeactivateWindow(window);
279 aura::Window* GetActiveWindow() {
280 return aura::client::GetActivationClient(root_window())->GetActiveWindow();
282 int GetActiveWindowId() {
283 aura::Window* active_window = GetActiveWindow();
284 return active_window ? active_window->id() : -1;
287 TestFocusRules* test_focus_rules() { return test_focus_rules_; }
289 // Test functions.
290 virtual void BasicFocus() = 0;
291 virtual void BasicActivation() = 0;
292 virtual void FocusEvents() = 0;
293 virtual void DuplicateFocusEvents() {}
294 virtual void ActivationEvents() = 0;
295 virtual void ReactivationEvents() {}
296 virtual void DuplicateActivationEvents() {}
297 virtual void ShiftFocusWithinActiveWindow() {}
298 virtual void ShiftFocusToChildOfInactiveWindow() {}
299 virtual void ShiftFocusToParentOfFocusedWindow() {}
300 virtual void FocusRulesOverride() = 0;
301 virtual void ActivationRulesOverride() = 0;
302 virtual void ShiftFocusOnActivation() {}
303 virtual void ShiftFocusOnActivationDueToHide() {}
304 virtual void NoShiftActiveOnActivation() {}
305 virtual void NoFocusChangeOnClickOnCaptureWindow() {}
307 private:
308 scoped_ptr<FocusController> focus_controller_;
309 TestFocusRules* test_focus_rules_;
311 DISALLOW_COPY_AND_ASSIGN(FocusControllerTestBase);
314 // Test base for tests where focus is directly set to a target window.
315 class FocusControllerDirectTestBase : public FocusControllerTestBase {
316 protected:
317 FocusControllerDirectTestBase() {}
319 // Different test types shift focus in different ways.
320 virtual void FocusWindowDirect(aura::Window* window) = 0;
321 virtual void ActivateWindowDirect(aura::Window* window) = 0;
322 virtual void DeactivateWindowDirect(aura::Window* window) = 0;
324 // Input events do not change focus if the window can not be focused.
325 virtual bool IsInputEvent() = 0;
327 void FocusWindowById(int id) {
328 aura::Window* window = root_window()->GetChildById(id);
329 DCHECK(window);
330 FocusWindowDirect(window);
332 void ActivateWindowById(int id) {
333 aura::Window* window = root_window()->GetChildById(id);
334 DCHECK(window);
335 ActivateWindowDirect(window);
338 // Overridden from FocusControllerTestBase:
339 virtual void BasicFocus() OVERRIDE {
340 EXPECT_EQ(NULL, GetFocusedWindow());
341 FocusWindowById(1);
342 EXPECT_EQ(1, GetFocusedWindowId());
343 FocusWindowById(2);
344 EXPECT_EQ(2, GetFocusedWindowId());
346 virtual void BasicActivation() OVERRIDE {
347 EXPECT_EQ(NULL, GetActiveWindow());
348 ActivateWindowById(1);
349 EXPECT_EQ(1, GetActiveWindowId());
350 ActivateWindowById(2);
351 EXPECT_EQ(2, GetActiveWindowId());
352 // Verify that attempting to deactivate NULL does not crash and does not
353 // change activation.
354 DeactivateWindow(NULL);
355 EXPECT_EQ(2, GetActiveWindowId());
356 DeactivateWindow(GetActiveWindow());
357 EXPECT_EQ(1, GetActiveWindowId());
359 virtual void FocusEvents() OVERRIDE {
360 ScopedFocusNotificationObserver root_observer(root_window());
361 ScopedTargetFocusNotificationObserver observer1(root_window(), 1);
362 ScopedTargetFocusNotificationObserver observer2(root_window(), 2);
364 root_observer.ExpectCounts(0, 0);
365 observer1.ExpectCounts(0, 0);
366 observer2.ExpectCounts(0, 0);
368 FocusWindowById(1);
369 root_observer.ExpectCounts(1, 1);
370 observer1.ExpectCounts(1, 1);
371 observer2.ExpectCounts(0, 0);
373 FocusWindowById(2);
374 root_observer.ExpectCounts(2, 2);
375 observer1.ExpectCounts(2, 2);
376 observer2.ExpectCounts(1, 1);
378 virtual void DuplicateFocusEvents() OVERRIDE {
379 // Focusing an existing focused window should not resend focus events.
380 ScopedFocusNotificationObserver root_observer(root_window());
381 ScopedTargetFocusNotificationObserver observer1(root_window(), 1);
383 root_observer.ExpectCounts(0, 0);
384 observer1.ExpectCounts(0, 0);
386 FocusWindowById(1);
387 root_observer.ExpectCounts(1, 1);
388 observer1.ExpectCounts(1, 1);
390 FocusWindowById(1);
391 root_observer.ExpectCounts(1, 1);
392 observer1.ExpectCounts(1, 1);
394 virtual void ActivationEvents() OVERRIDE {
395 ActivateWindowById(1);
397 ScopedFocusNotificationObserver root_observer(root_window());
398 ScopedTargetFocusNotificationObserver observer1(root_window(), 1);
399 ScopedTargetFocusNotificationObserver observer2(root_window(), 2);
401 root_observer.ExpectCounts(0, 0);
402 observer1.ExpectCounts(0, 0);
403 observer2.ExpectCounts(0, 0);
405 ActivateWindowById(2);
406 root_observer.ExpectCounts(1, 1);
407 observer1.ExpectCounts(1, 1);
408 observer2.ExpectCounts(1, 1);
410 virtual void ReactivationEvents() OVERRIDE {
411 ActivateWindowById(1);
412 ScopedFocusNotificationObserver root_observer(root_window());
413 EXPECT_EQ(0, root_observer.reactivation_count());
414 root_window()->GetChildById(2)->Hide();
415 // When we attempt to activate "2", which cannot be activated because it
416 // is not visible, "1" will be reactivated.
417 ActivateWindowById(2);
418 EXPECT_EQ(1, root_observer.reactivation_count());
419 EXPECT_EQ(root_window()->GetChildById(2),
420 root_observer.reactivation_requested_window());
421 EXPECT_EQ(root_window()->GetChildById(1),
422 root_observer.reactivation_actual_window());
424 virtual void DuplicateActivationEvents() OVERRIDE {
425 // Activating an existing active window should not resend activation events.
426 ActivateWindowById(1);
428 ScopedFocusNotificationObserver root_observer(root_window());
429 ScopedTargetFocusNotificationObserver observer1(root_window(), 1);
430 ScopedTargetFocusNotificationObserver observer2(root_window(), 2);
432 root_observer.ExpectCounts(0, 0);
433 observer1.ExpectCounts(0, 0);
434 observer2.ExpectCounts(0, 0);
436 ActivateWindowById(2);
437 root_observer.ExpectCounts(1, 1);
438 observer1.ExpectCounts(1, 1);
439 observer2.ExpectCounts(1, 1);
441 ActivateWindowById(2);
442 root_observer.ExpectCounts(1, 1);
443 observer1.ExpectCounts(1, 1);
444 observer2.ExpectCounts(1, 1);
446 virtual void ShiftFocusWithinActiveWindow() OVERRIDE {
447 ActivateWindowById(1);
448 EXPECT_EQ(1, GetActiveWindowId());
449 EXPECT_EQ(1, GetFocusedWindowId());
450 FocusWindowById(11);
451 EXPECT_EQ(11, GetFocusedWindowId());
452 FocusWindowById(12);
453 EXPECT_EQ(12, GetFocusedWindowId());
455 virtual void ShiftFocusToChildOfInactiveWindow() OVERRIDE {
456 ActivateWindowById(2);
457 EXPECT_EQ(2, GetActiveWindowId());
458 EXPECT_EQ(2, GetFocusedWindowId());
459 FocusWindowById(11);
460 EXPECT_EQ(1, GetActiveWindowId());
461 EXPECT_EQ(11, GetFocusedWindowId());
463 virtual void ShiftFocusToParentOfFocusedWindow() OVERRIDE {
464 ActivateWindowById(1);
465 EXPECT_EQ(1, GetFocusedWindowId());
466 FocusWindowById(11);
467 EXPECT_EQ(11, GetFocusedWindowId());
468 FocusWindowById(1);
469 // Focus should _not_ shift to the parent of the already-focused window.
470 EXPECT_EQ(11, GetFocusedWindowId());
472 virtual void FocusRulesOverride() OVERRIDE {
473 EXPECT_EQ(NULL, GetFocusedWindow());
474 FocusWindowById(11);
475 EXPECT_EQ(11, GetFocusedWindowId());
477 test_focus_rules()->set_focus_restriction(root_window()->GetChildById(211));
478 FocusWindowById(12);
479 // Input events leave focus unchanged; direct API calls will change focus
480 // to the restricted window.
481 int focused_window = IsInputEvent() ? 11 : 211;
482 EXPECT_EQ(focused_window, GetFocusedWindowId());
484 test_focus_rules()->set_focus_restriction(NULL);
485 FocusWindowById(12);
486 EXPECT_EQ(12, GetFocusedWindowId());
488 virtual void ActivationRulesOverride() OVERRIDE {
489 ActivateWindowById(1);
490 EXPECT_EQ(1, GetActiveWindowId());
491 EXPECT_EQ(1, GetFocusedWindowId());
493 aura::Window* w3 = root_window()->GetChildById(3);
494 test_focus_rules()->set_focus_restriction(w3);
496 ActivateWindowById(2);
497 // Input events leave activation unchanged; direct API calls will activate
498 // the restricted window.
499 int active_window = IsInputEvent() ? 1 : 3;
500 EXPECT_EQ(active_window, GetActiveWindowId());
501 EXPECT_EQ(active_window, GetFocusedWindowId());
503 test_focus_rules()->set_focus_restriction(NULL);
504 ActivateWindowById(2);
505 EXPECT_EQ(2, GetActiveWindowId());
506 EXPECT_EQ(2, GetFocusedWindowId());
508 virtual void ShiftFocusOnActivation() OVERRIDE {
509 // When a window is activated, by default that window is also focused.
510 // An ActivationChangeObserver may shift focus to another window within the
511 // same activatable window.
512 ActivateWindowById(2);
513 EXPECT_EQ(2, GetFocusedWindowId());
514 ActivateWindowById(1);
515 EXPECT_EQ(1, GetFocusedWindowId());
517 ActivateWindowById(2);
519 aura::Window* target = root_window()->GetChildById(1);
520 aura::client::ActivationClient* client =
521 aura::client::GetActivationClient(root_window());
523 scoped_ptr<FocusShiftingActivationObserver> observer(
524 new FocusShiftingActivationObserver(target));
525 observer->set_shift_focus_to(target->GetChildById(11));
526 client->AddObserver(observer.get());
528 ActivateWindowById(1);
530 // w1's ActivationChangeObserver shifted focus to this child, pre-empting
531 // FocusController's default setting.
532 EXPECT_EQ(11, GetFocusedWindowId());
534 ActivateWindowById(2);
535 EXPECT_EQ(2, GetFocusedWindowId());
537 // Simulate a focus reset by the ActivationChangeObserver. This should
538 // trigger the default setting in FocusController.
539 observer->set_shift_focus_to(NULL);
540 ActivateWindowById(1);
541 EXPECT_EQ(1, GetFocusedWindowId());
543 client->RemoveObserver(observer.get());
545 ActivateWindowById(2);
546 EXPECT_EQ(2, GetFocusedWindowId());
547 ActivateWindowById(1);
548 EXPECT_EQ(1, GetFocusedWindowId());
550 virtual void ShiftFocusOnActivationDueToHide() OVERRIDE {
551 // Similar to ShiftFocusOnActivation except the activation change is
552 // triggered by hiding the active window.
553 ActivateWindowById(1);
554 EXPECT_EQ(1, GetFocusedWindowId());
556 // Removes window 3 as candidate for next activatable window.
557 root_window()->GetChildById(3)->Hide();
558 EXPECT_EQ(1, GetFocusedWindowId());
560 aura::Window* target = root_window()->GetChildById(2);
561 aura::client::ActivationClient* client =
562 aura::client::GetActivationClient(root_window());
564 scoped_ptr<FocusShiftingActivationObserver> observer(
565 new FocusShiftingActivationObserver(target));
566 observer->set_shift_focus_to(target->GetChildById(21));
567 client->AddObserver(observer.get());
569 // Hide the active window.
570 root_window()->GetChildById(1)->Hide();
572 EXPECT_EQ(21, GetFocusedWindowId());
574 client->RemoveObserver(observer.get());
576 virtual void NoShiftActiveOnActivation() OVERRIDE {
577 // When a window is activated, we need to prevent any change to activation
578 // from being made in response to an activation change notification.
581 virtual void NoFocusChangeOnClickOnCaptureWindow() OVERRIDE {
582 scoped_ptr<aura::client::DefaultCaptureClient> capture_client(
583 new aura::client::DefaultCaptureClient(root_window()));
584 // Clicking on a window which has capture should not cause a focus change
585 // to the window. This test verifies whether that is indeed the case.
586 ActivateWindowById(1);
588 EXPECT_EQ(1, GetActiveWindowId());
589 EXPECT_EQ(1, GetFocusedWindowId());
591 aura::Window* w2 = root_window()->GetChildById(2);
592 aura::client::GetCaptureClient(root_window())->SetCapture(w2);
593 aura::test::EventGenerator generator(root_window(), w2);
594 generator.ClickLeftButton();
596 EXPECT_EQ(1, GetActiveWindowId());
597 EXPECT_EQ(1, GetFocusedWindowId());
598 aura::client::GetCaptureClient(root_window())->ReleaseCapture(w2);
601 private:
602 DISALLOW_COPY_AND_ASSIGN(FocusControllerDirectTestBase);
605 // Focus and Activation changes via aura::client::ActivationClient API.
606 class FocusControllerApiTest : public FocusControllerDirectTestBase {
607 public:
608 FocusControllerApiTest() {}
610 private:
611 // Overridden from FocusControllerTestBase:
612 virtual void FocusWindowDirect(aura::Window* window) OVERRIDE {
613 FocusWindow(window);
615 virtual void ActivateWindowDirect(aura::Window* window) OVERRIDE {
616 ActivateWindow(window);
618 virtual void DeactivateWindowDirect(aura::Window* window) OVERRIDE {
619 DeactivateWindow(window);
621 virtual bool IsInputEvent() OVERRIDE { return false; }
623 DISALLOW_COPY_AND_ASSIGN(FocusControllerApiTest);
626 // Focus and Activation changes via input events.
627 class FocusControllerMouseEventTest : public FocusControllerDirectTestBase {
628 public:
629 FocusControllerMouseEventTest() {}
631 private:
632 // Overridden from FocusControllerTestBase:
633 virtual void FocusWindowDirect(aura::Window* window) OVERRIDE {
634 aura::test::EventGenerator generator(root_window(), window);
635 generator.ClickLeftButton();
637 virtual void ActivateWindowDirect(aura::Window* window) OVERRIDE {
638 aura::test::EventGenerator generator(root_window(), window);
639 generator.ClickLeftButton();
641 virtual void DeactivateWindowDirect(aura::Window* window) OVERRIDE {
642 aura::Window* next_activatable =
643 test_focus_rules()->GetNextActivatableWindow(window);
644 aura::test::EventGenerator generator(root_window(), next_activatable);
645 generator.ClickLeftButton();
647 virtual bool IsInputEvent() OVERRIDE { return true; }
649 DISALLOW_COPY_AND_ASSIGN(FocusControllerMouseEventTest);
652 class FocusControllerGestureEventTest : public FocusControllerDirectTestBase {
653 public:
654 FocusControllerGestureEventTest() {}
656 private:
657 // Overridden from FocusControllerTestBase:
658 virtual void FocusWindowDirect(aura::Window* window) OVERRIDE {
659 aura::test::EventGenerator generator(root_window(), window);
660 generator.GestureTapAt(window->bounds().CenterPoint());
662 virtual void ActivateWindowDirect(aura::Window* window) OVERRIDE {
663 aura::test::EventGenerator generator(root_window(), window);
664 generator.GestureTapAt(window->bounds().CenterPoint());
666 virtual void DeactivateWindowDirect(aura::Window* window) OVERRIDE {
667 aura::Window* next_activatable =
668 test_focus_rules()->GetNextActivatableWindow(window);
669 aura::test::EventGenerator generator(root_window(), next_activatable);
670 generator.GestureTapAt(window->bounds().CenterPoint());
672 virtual bool IsInputEvent() OVERRIDE { return true; }
674 DISALLOW_COPY_AND_ASSIGN(FocusControllerGestureEventTest);
677 // Test base for tests where focus is implicitly set to a window as the result
678 // of a disposition change to the focused window or the hierarchy that contains
679 // it.
680 class FocusControllerImplicitTestBase : public FocusControllerTestBase {
681 protected:
682 explicit FocusControllerImplicitTestBase(bool parent) : parent_(parent) {}
684 aura::Window* GetDispositionWindow(aura::Window* window) {
685 return parent_ ? window->parent() : window;
688 // Change the disposition of |window| in such a way as it will lose focus.
689 virtual void ChangeWindowDisposition(aura::Window* window) = 0;
691 // Allow each disposition change test to add additional post-disposition
692 // change expectations.
693 virtual void PostDispostionChangeExpectations() {}
695 // Overridden from FocusControllerTestBase:
696 virtual void BasicFocus() OVERRIDE {
697 EXPECT_EQ(NULL, GetFocusedWindow());
699 aura::Window* w211 = root_window()->GetChildById(211);
700 FocusWindow(w211);
701 EXPECT_EQ(211, GetFocusedWindowId());
703 ChangeWindowDisposition(w211);
704 // BasicFocusRules passes focus to the parent.
705 EXPECT_EQ(parent_ ? 2 : 21, GetFocusedWindowId());
707 virtual void BasicActivation() OVERRIDE {
708 DCHECK(!parent_) << "Activation tests don't support parent changes.";
710 EXPECT_EQ(NULL, GetActiveWindow());
712 aura::Window* w2 = root_window()->GetChildById(2);
713 ActivateWindow(w2);
714 EXPECT_EQ(2, GetActiveWindowId());
716 ChangeWindowDisposition(w2);
717 EXPECT_EQ(3, GetActiveWindowId());
718 PostDispostionChangeExpectations();
720 virtual void FocusEvents() OVERRIDE {
721 aura::Window* w211 = root_window()->GetChildById(211);
722 FocusWindow(w211);
724 ScopedFocusNotificationObserver root_observer(root_window());
725 ScopedTargetFocusNotificationObserver observer211(root_window(), 211);
726 root_observer.ExpectCounts(0, 0);
727 observer211.ExpectCounts(0, 0);
729 ChangeWindowDisposition(w211);
730 root_observer.ExpectCounts(0, 1);
731 observer211.ExpectCounts(0, 1);
733 virtual void ActivationEvents() OVERRIDE {
734 DCHECK(!parent_) << "Activation tests don't support parent changes.";
736 aura::Window* w2 = root_window()->GetChildById(2);
737 ActivateWindow(w2);
739 ScopedFocusNotificationObserver root_observer(root_window());
740 ScopedTargetFocusNotificationObserver observer2(root_window(), 2);
741 ScopedTargetFocusNotificationObserver observer3(root_window(), 3);
742 root_observer.ExpectCounts(0, 0);
743 observer2.ExpectCounts(0, 0);
744 observer3.ExpectCounts(0, 0);
746 ChangeWindowDisposition(w2);
747 root_observer.ExpectCounts(1, 1);
748 observer2.ExpectCounts(1, 1);
749 observer3.ExpectCounts(1, 1);
751 virtual void FocusRulesOverride() OVERRIDE {
752 EXPECT_EQ(NULL, GetFocusedWindow());
753 aura::Window* w211 = root_window()->GetChildById(211);
754 FocusWindow(w211);
755 EXPECT_EQ(211, GetFocusedWindowId());
757 test_focus_rules()->set_focus_restriction(root_window()->GetChildById(11));
758 ChangeWindowDisposition(w211);
759 // Normally, focus would shift to the parent (w21) but the override shifts
760 // it to 11.
761 EXPECT_EQ(11, GetFocusedWindowId());
763 test_focus_rules()->set_focus_restriction(NULL);
765 virtual void ActivationRulesOverride() OVERRIDE {
766 DCHECK(!parent_) << "Activation tests don't support parent changes.";
768 aura::Window* w1 = root_window()->GetChildById(1);
769 ActivateWindow(w1);
771 EXPECT_EQ(1, GetActiveWindowId());
772 EXPECT_EQ(1, GetFocusedWindowId());
774 aura::Window* w3 = root_window()->GetChildById(3);
775 test_focus_rules()->set_focus_restriction(w3);
777 // Normally, activation/focus would move to w2, but since we have a focus
778 // restriction, it should move to w3 instead.
779 ChangeWindowDisposition(w1);
780 EXPECT_EQ(3, GetActiveWindowId());
781 EXPECT_EQ(3, GetFocusedWindowId());
783 test_focus_rules()->set_focus_restriction(NULL);
784 ActivateWindow(root_window()->GetChildById(2));
785 EXPECT_EQ(2, GetActiveWindowId());
786 EXPECT_EQ(2, GetFocusedWindowId());
789 private:
790 // When true, the disposition change occurs to the parent of the window
791 // instead of to the window. This verifies that changes occurring in the
792 // hierarchy that contains the window affect the window's focus.
793 bool parent_;
795 DISALLOW_COPY_AND_ASSIGN(FocusControllerImplicitTestBase);
798 // Focus and Activation changes in response to window visibility changes.
799 class FocusControllerHideTest : public FocusControllerImplicitTestBase {
800 public:
801 FocusControllerHideTest() : FocusControllerImplicitTestBase(false) {}
803 protected:
804 FocusControllerHideTest(bool parent)
805 : FocusControllerImplicitTestBase(parent) {}
807 // Overridden from FocusControllerImplicitTestBase:
808 virtual void ChangeWindowDisposition(aura::Window* window) OVERRIDE {
809 GetDispositionWindow(window)->Hide();
811 virtual void PostDispostionChangeExpectations() OVERRIDE {
812 // BasicActivation() starts with the stacking order: 1, 2, 3 (3 topmost)
813 // and then activates 2. After 2 is hidden in ChangeWindowDisposition
814 // above, 3 is activated, but code in
815 // FocusController::OnWindowVisibilityChanging keeps 2's layer above 3's
816 // until a hide animation completes (e.g. a fade-out transition).
817 aura::Window* w2 = root_window()->GetChildById(2);
818 aura::Window* w3 = root_window()->GetChildById(3);
820 // W2 was hidden, but its layer should still be stacked above W3's.
821 typedef std::vector<ui::Layer*> Layers;
822 const Layers& children = w3->parent()->layer()->children();
823 Layers::const_iterator w3_iter =
824 std::find(children.begin(), children.end(), w3->layer());
825 Layers::const_iterator w2_iter =
826 std::find(children.begin(), children.end(), w2->layer());
827 EXPECT_TRUE(w2_iter > w3_iter);
830 private:
831 DISALLOW_COPY_AND_ASSIGN(FocusControllerHideTest);
834 // Focus and Activation changes in response to window parent visibility
835 // changes.
836 class FocusControllerParentHideTest : public FocusControllerHideTest {
837 public:
838 FocusControllerParentHideTest() : FocusControllerHideTest(true) {}
840 private:
841 DISALLOW_COPY_AND_ASSIGN(FocusControllerParentHideTest);
844 // Focus and Activation changes in response to window destruction.
845 class FocusControllerDestructionTest : public FocusControllerImplicitTestBase {
846 public:
847 FocusControllerDestructionTest() : FocusControllerImplicitTestBase(false) {}
849 protected:
850 FocusControllerDestructionTest(bool parent)
851 : FocusControllerImplicitTestBase(parent) {}
853 // Overridden from FocusControllerImplicitTestBase:
854 virtual void ChangeWindowDisposition(aura::Window* window) OVERRIDE {
855 delete GetDispositionWindow(window);
858 private:
859 DISALLOW_COPY_AND_ASSIGN(FocusControllerDestructionTest);
862 // Focus and Activation changes in response to window parent destruction.
863 class FocusControllerParentDestructionTest
864 : public FocusControllerDestructionTest {
865 public:
866 FocusControllerParentDestructionTest()
867 : FocusControllerDestructionTest(true) {}
869 private:
870 DISALLOW_COPY_AND_ASSIGN(FocusControllerParentDestructionTest);
873 // Focus and Activation changes in response to window removal.
874 class FocusControllerRemovalTest : public FocusControllerImplicitTestBase {
875 public:
876 FocusControllerRemovalTest() : FocusControllerImplicitTestBase(false) {}
878 protected:
879 FocusControllerRemovalTest(bool parent)
880 : FocusControllerImplicitTestBase(parent) {}
882 // Overridden from FocusControllerImplicitTestBase:
883 virtual void ChangeWindowDisposition(aura::Window* window) OVERRIDE {
884 aura::Window* disposition_window = GetDispositionWindow(window);
885 disposition_window->parent()->RemoveChild(disposition_window);
886 window_owner_.reset(disposition_window);
888 virtual void TearDown() OVERRIDE {
889 window_owner_.reset();
890 FocusControllerImplicitTestBase::TearDown();
893 private:
894 scoped_ptr<aura::Window> window_owner_;
896 DISALLOW_COPY_AND_ASSIGN(FocusControllerRemovalTest);
899 // Focus and Activation changes in response to window parent removal.
900 class FocusControllerParentRemovalTest : public FocusControllerRemovalTest {
901 public:
902 FocusControllerParentRemovalTest() : FocusControllerRemovalTest(true) {}
904 private:
905 DISALLOW_COPY_AND_ASSIGN(FocusControllerParentRemovalTest);
909 #define FOCUS_CONTROLLER_TEST(TESTCLASS, TESTNAME) \
910 TEST_F(TESTCLASS, TESTNAME) { TESTNAME(); }
912 // Runs direct focus change tests (input events and API calls).
913 #define DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \
914 FOCUS_CONTROLLER_TEST(FocusControllerApiTest, TESTNAME) \
915 FOCUS_CONTROLLER_TEST(FocusControllerMouseEventTest, TESTNAME) \
916 FOCUS_CONTROLLER_TEST(FocusControllerGestureEventTest, TESTNAME)
918 // Runs implicit focus change tests for disposition changes to target.
919 #define IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME) \
920 FOCUS_CONTROLLER_TEST(FocusControllerHideTest, TESTNAME) \
921 FOCUS_CONTROLLER_TEST(FocusControllerDestructionTest, TESTNAME) \
922 FOCUS_CONTROLLER_TEST(FocusControllerRemovalTest, TESTNAME)
924 // Runs implicit focus change tests for disposition changes to target's parent
925 // hierarchy.
926 #define IMPLICIT_FOCUS_CHANGE_PARENT_TESTS(TESTNAME) \
927 /* TODO(beng): parent destruction tests are not supported at
928 present due to workspace manager issues. \
929 FOCUS_CONTROLLER_TEST(FocusControllerParentDestructionTest, TESTNAME) */ \
930 FOCUS_CONTROLLER_TEST(FocusControllerParentHideTest, TESTNAME) \
931 FOCUS_CONTROLLER_TEST(FocusControllerParentRemovalTest, TESTNAME)
933 // Runs all implicit focus change tests (changes to the target and target's
934 // parent hierarchy)
935 #define IMPLICIT_FOCUS_CHANGE_TESTS(TESTNAME) \
936 IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME) \
937 IMPLICIT_FOCUS_CHANGE_PARENT_TESTS(TESTNAME)
939 // Runs all possible focus change tests.
940 #define ALL_FOCUS_TESTS(TESTNAME) \
941 DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \
942 IMPLICIT_FOCUS_CHANGE_TESTS(TESTNAME)
944 // Runs focus change tests that apply only to the target. For example,
945 // implicit activation changes caused by window disposition changes do not
946 // occur when changes to the containing hierarchy happen.
947 #define TARGET_FOCUS_TESTS(TESTNAME) \
948 DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \
949 IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME)
951 // - Focuses a window, verifies that focus changed.
952 ALL_FOCUS_TESTS(BasicFocus);
954 // - Activates a window, verifies that activation changed.
955 TARGET_FOCUS_TESTS(BasicActivation);
957 // - Focuses a window, verifies that focus events were dispatched.
958 ALL_FOCUS_TESTS(FocusEvents);
960 // - Focuses or activates a window multiple times, verifies that events are only
961 // dispatched when focus/activation actually changes.
962 DIRECT_FOCUS_CHANGE_TESTS(DuplicateFocusEvents);
963 DIRECT_FOCUS_CHANGE_TESTS(DuplicateActivationEvents);
965 // - Activates a window, verifies that activation events were dispatched.
966 TARGET_FOCUS_TESTS(ActivationEvents);
968 // - Attempts to active a hidden window, verifies that current window is
969 // attempted to be reactivated and the appropriate event dispatched.
970 FOCUS_CONTROLLER_TEST(FocusControllerApiTest, ReactivationEvents);
972 // - Input events/API calls shift focus between focusable windows within the
973 // active window.
974 DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusWithinActiveWindow);
976 // - Input events/API calls to a child window of an inactive window shifts
977 // activation to the activatable parent and focuses the child.
978 DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusToChildOfInactiveWindow);
980 // - Input events/API calls to focus the parent of the focused window do not
981 // shift focus away from the child.
982 DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusToParentOfFocusedWindow);
984 // - Verifies that FocusRules determine what can be focused.
985 ALL_FOCUS_TESTS(FocusRulesOverride);
987 // - Verifies that FocusRules determine what can be activated.
988 TARGET_FOCUS_TESTS(ActivationRulesOverride);
990 // - Verifies that attempts to change focus or activation from a focus or
991 // activation change observer are ignored.
992 DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusOnActivation);
993 DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusOnActivationDueToHide);
994 DIRECT_FOCUS_CHANGE_TESTS(NoShiftActiveOnActivation);
996 // Clicking on a window which has capture should not result in a focus change.
997 DIRECT_FOCUS_CHANGE_TESTS(NoFocusChangeOnClickOnCaptureWindow);
999 } // namespace corewm
1000 } // namespace views