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"
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"
27 class FocusNotificationObserver
: public aura::client::ActivationChangeObserver
,
28 public aura::client::FocusChangeObserver
{
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_
;
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
{
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);
94 aura::RootWindow
* root_window_
;
96 DISALLOW_COPY_AND_ASSIGN(ScopedFocusNotificationObserver
);
99 class ScopedTargetFocusNotificationObserver
: public FocusNotificationObserver
{
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
);
115 aura::Window
* target_
;
116 aura::WindowTracker tracker_
;
118 DISALLOW_COPY_AND_ASSIGN(ScopedTargetFocusNotificationObserver
);
121 class FocusShiftingActivationObserver
122 : public aura::client::ActivationChangeObserver
{
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
;
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
{
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.
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_
);
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
{
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:
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_
; }
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() {}
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
{
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
);
330 FocusWindowDirect(window
);
332 void ActivateWindowById(int id
) {
333 aura::Window
* window
= root_window()->GetChildById(id
);
335 ActivateWindowDirect(window
);
338 // Overridden from FocusControllerTestBase:
339 virtual void BasicFocus() OVERRIDE
{
340 EXPECT_EQ(NULL
, GetFocusedWindow());
342 EXPECT_EQ(1, GetFocusedWindowId());
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);
369 root_observer
.ExpectCounts(1, 1);
370 observer1
.ExpectCounts(1, 1);
371 observer2
.ExpectCounts(0, 0);
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);
387 root_observer
.ExpectCounts(1, 1);
388 observer1
.ExpectCounts(1, 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());
451 EXPECT_EQ(11, GetFocusedWindowId());
453 EXPECT_EQ(12, GetFocusedWindowId());
455 virtual void ShiftFocusToChildOfInactiveWindow() OVERRIDE
{
456 ActivateWindowById(2);
457 EXPECT_EQ(2, GetActiveWindowId());
458 EXPECT_EQ(2, GetFocusedWindowId());
460 EXPECT_EQ(1, GetActiveWindowId());
461 EXPECT_EQ(11, GetFocusedWindowId());
463 virtual void ShiftFocusToParentOfFocusedWindow() OVERRIDE
{
464 ActivateWindowById(1);
465 EXPECT_EQ(1, GetFocusedWindowId());
467 EXPECT_EQ(11, GetFocusedWindowId());
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());
475 EXPECT_EQ(11, GetFocusedWindowId());
477 test_focus_rules()->set_focus_restriction(root_window()->GetChildById(211));
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
);
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
);
602 DISALLOW_COPY_AND_ASSIGN(FocusControllerDirectTestBase
);
605 // Focus and Activation changes via aura::client::ActivationClient API.
606 class FocusControllerApiTest
: public FocusControllerDirectTestBase
{
608 FocusControllerApiTest() {}
611 // Overridden from FocusControllerTestBase:
612 virtual void FocusWindowDirect(aura::Window
* window
) OVERRIDE
{
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
{
629 FocusControllerMouseEventTest() {}
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
{
654 FocusControllerGestureEventTest() {}
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
680 class FocusControllerImplicitTestBase
: public FocusControllerTestBase
{
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);
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);
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);
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);
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);
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
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);
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());
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.
795 DISALLOW_COPY_AND_ASSIGN(FocusControllerImplicitTestBase
);
798 // Focus and Activation changes in response to window visibility changes.
799 class FocusControllerHideTest
: public FocusControllerImplicitTestBase
{
801 FocusControllerHideTest() : FocusControllerImplicitTestBase(false) {}
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
);
831 DISALLOW_COPY_AND_ASSIGN(FocusControllerHideTest
);
834 // Focus and Activation changes in response to window parent visibility
836 class FocusControllerParentHideTest
: public FocusControllerHideTest
{
838 FocusControllerParentHideTest() : FocusControllerHideTest(true) {}
841 DISALLOW_COPY_AND_ASSIGN(FocusControllerParentHideTest
);
844 // Focus and Activation changes in response to window destruction.
845 class FocusControllerDestructionTest
: public FocusControllerImplicitTestBase
{
847 FocusControllerDestructionTest() : FocusControllerImplicitTestBase(false) {}
850 FocusControllerDestructionTest(bool parent
)
851 : FocusControllerImplicitTestBase(parent
) {}
853 // Overridden from FocusControllerImplicitTestBase:
854 virtual void ChangeWindowDisposition(aura::Window
* window
) OVERRIDE
{
855 delete GetDispositionWindow(window
);
859 DISALLOW_COPY_AND_ASSIGN(FocusControllerDestructionTest
);
862 // Focus and Activation changes in response to window parent destruction.
863 class FocusControllerParentDestructionTest
864 : public FocusControllerDestructionTest
{
866 FocusControllerParentDestructionTest()
867 : FocusControllerDestructionTest(true) {}
870 DISALLOW_COPY_AND_ASSIGN(FocusControllerParentDestructionTest
);
873 // Focus and Activation changes in response to window removal.
874 class FocusControllerRemovalTest
: public FocusControllerImplicitTestBase
{
876 FocusControllerRemovalTest() : FocusControllerImplicitTestBase(false) {}
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();
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
{
902 FocusControllerParentRemovalTest() : FocusControllerRemovalTest(true) {}
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
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
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
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