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 "ui/views/corewm/focus_controller.h" 6 7#include <map> 8 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/events/event_handler.h" 22#include "ui/views/corewm/base_focus_rules.h" 23 24namespace views { 25namespace corewm { 26 27class 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() {} 37 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_); 41 } 42 int reactivation_count() const { 43 return reactivation_count_; 44 } 45 aura::Window* reactivation_requested_window() const { 46 return reactivation_requested_window_; 47 } 48 aura::Window* reactivation_actual_window() const { 49 return reactivation_actual_window_; 50 } 51 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_; 57 } 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; 64 } 65 66 // Overridden from aura::client::FocusChangeObserver: 67 virtual void OnWindowFocused(aura::Window* gained_focus, 68 aura::Window* lost_focus) OVERRIDE { 69 ++focus_changed_count_; 70 } 71 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_; 77 78 DISALLOW_COPY_AND_ASSIGN(FocusNotificationObserver); 79}; 80 81// ActivationChangeObserver that keeps a vector of all the windows that lost 82// active. 83class RecordingActivationChangeObserver 84 : public aura::client::ActivationChangeObserver { 85 public: 86 explicit RecordingActivationChangeObserver(aura::Window* root) 87 : root_(root) { 88 aura::client::GetActivationClient(root_)->AddObserver(this); 89 } 90 virtual ~RecordingActivationChangeObserver() { 91 aura::client::GetActivationClient(root_)->RemoveObserver(this); 92 } 93 94 // Each time we get OnWindowActivated() the |lost_active| parameter is 95 // added here. 96 const std::vector<aura::Window*>& lost() const { return lost_; } 97 98 // Overridden from aura::client::ActivationChangeObserver: 99 virtual void OnWindowActivated(aura::Window* gained_active, 100 aura::Window* lost_active) OVERRIDE { 101 lost_.push_back(lost_active); 102 } 103 104 private: 105 aura::Window* root_; 106 std::vector<aura::Window*> lost_; 107 108 DISALLOW_COPY_AND_ASSIGN(RecordingActivationChangeObserver); 109}; 110 111// ActivationChangeObserver that deletes the window losing activation. 112class DeleteOnLoseActivationChangeObserver 113 : public aura::client::ActivationChangeObserver { 114 public: 115 explicit DeleteOnLoseActivationChangeObserver(aura::Window* window) 116 : root_(window->GetRootWindow()), 117 window_(window) { 118 aura::client::GetActivationClient(root_)->AddObserver(this); 119 } 120 virtual ~DeleteOnLoseActivationChangeObserver() { 121 aura::client::GetActivationClient(root_)->RemoveObserver(this); 122 } 123 124 bool did_delete() const { return window_ == NULL; } 125 126 // Overridden from aura::client::ActivationChangeObserver: 127 virtual void OnWindowActivated(aura::Window* gained_active, 128 aura::Window* lost_active) OVERRIDE { 129 if (window_ && lost_active == window_) { 130 window_ = NULL; 131 delete lost_active; 132 } 133 } 134 135 private: 136 aura::Window* root_; 137 aura::Window* window_; 138 139 DISALLOW_COPY_AND_ASSIGN(DeleteOnLoseActivationChangeObserver); 140}; 141 142class ScopedFocusNotificationObserver : public FocusNotificationObserver { 143 public: 144 ScopedFocusNotificationObserver(aura::Window* root_window) 145 : root_window_(root_window) { 146 aura::client::GetActivationClient(root_window_)->AddObserver(this); 147 aura::client::GetFocusClient(root_window_)->AddObserver(this); 148 } 149 virtual ~ScopedFocusNotificationObserver() { 150 aura::client::GetActivationClient(root_window_)->RemoveObserver(this); 151 aura::client::GetFocusClient(root_window_)->RemoveObserver(this); 152 } 153 154 private: 155 aura::Window* root_window_; 156 157 DISALLOW_COPY_AND_ASSIGN(ScopedFocusNotificationObserver); 158}; 159 160class ScopedTargetFocusNotificationObserver : public FocusNotificationObserver { 161 public: 162 ScopedTargetFocusNotificationObserver(aura::Window* root_window, int id) 163 : target_(root_window->GetChildById(id)) { 164 aura::client::SetActivationChangeObserver(target_, this); 165 aura::client::SetFocusChangeObserver(target_, this); 166 tracker_.Add(target_); 167 } 168 virtual ~ScopedTargetFocusNotificationObserver() { 169 if (tracker_.Contains(target_)) { 170 aura::client::SetActivationChangeObserver(target_, NULL); 171 aura::client::SetFocusChangeObserver(target_, NULL); 172 } 173 } 174 175 private: 176 aura::Window* target_; 177 aura::WindowTracker tracker_; 178 179 DISALLOW_COPY_AND_ASSIGN(ScopedTargetFocusNotificationObserver); 180}; 181 182class FocusShiftingActivationObserver 183 : public aura::client::ActivationChangeObserver { 184 public: 185 explicit FocusShiftingActivationObserver(aura::Window* activated_window) 186 : activated_window_(activated_window), 187 shift_focus_to_(NULL) {} 188 virtual ~FocusShiftingActivationObserver() {} 189 190 void set_shift_focus_to(aura::Window* shift_focus_to) { 191 shift_focus_to_ = shift_focus_to; 192 } 193 194 private: 195 // Overridden from aura::client::ActivationChangeObserver: 196 virtual void OnWindowActivated(aura::Window* gained_active, 197 aura::Window* lost_active) OVERRIDE { 198 // Shift focus to a child. This should prevent the default focusing from 199 // occurring in FocusController::FocusWindow(). 200 if (gained_active == activated_window_) { 201 aura::client::FocusClient* client = 202 aura::client::GetFocusClient(gained_active); 203 client->FocusWindow(shift_focus_to_); 204 } 205 } 206 207 aura::Window* activated_window_; 208 aura::Window* shift_focus_to_; 209 210 DISALLOW_COPY_AND_ASSIGN(FocusShiftingActivationObserver); 211}; 212 213// BaseFocusRules subclass that allows basic overrides of focus/activation to 214// be tested. This is intended more as a test that the override system works at 215// all, rather than as an exhaustive set of use cases, those should be covered 216// in tests for those FocusRules implementations. 217class TestFocusRules : public BaseFocusRules { 218 public: 219 TestFocusRules() : focus_restriction_(NULL) {} 220 221 // Restricts focus and activation to this window and its child hierarchy. 222 void set_focus_restriction(aura::Window* focus_restriction) { 223 focus_restriction_ = focus_restriction; 224 } 225 226 // Overridden from BaseFocusRules: 227 virtual bool SupportsChildActivation(aura::Window* window) const OVERRIDE { 228 // In FocusControllerTests, only the RootWindow has activatable children. 229 return window->GetRootWindow() == window; 230 } 231 virtual bool CanActivateWindow(aura::Window* window) const OVERRIDE { 232 // Restricting focus to a non-activatable child window means the activatable 233 // parent outside the focus restriction is activatable. 234 bool can_activate = 235 CanFocusOrActivate(window) || window->Contains(focus_restriction_); 236 return can_activate ? BaseFocusRules::CanActivateWindow(window) : false; 237 } 238 virtual bool CanFocusWindow(aura::Window* window) const OVERRIDE { 239 return CanFocusOrActivate(window) ? 240 BaseFocusRules::CanFocusWindow(window) : false; 241 } 242 virtual aura::Window* GetActivatableWindow( 243 aura::Window* window) const OVERRIDE { 244 return BaseFocusRules::GetActivatableWindow( 245 CanFocusOrActivate(window) ? window : focus_restriction_); 246 } 247 virtual aura::Window* GetFocusableWindow( 248 aura::Window* window) const OVERRIDE { 249 return BaseFocusRules::GetFocusableWindow( 250 CanFocusOrActivate(window) ? window : focus_restriction_); 251 } 252 virtual aura::Window* GetNextActivatableWindow( 253 aura::Window* ignore) const OVERRIDE { 254 aura::Window* next_activatable = 255 BaseFocusRules::GetNextActivatableWindow(ignore); 256 return CanFocusOrActivate(next_activatable) ? 257 next_activatable : GetActivatableWindow(focus_restriction_); 258 } 259 260 private: 261 bool CanFocusOrActivate(aura::Window* window) const { 262 return !focus_restriction_ || focus_restriction_->Contains(window); 263 } 264 265 aura::Window* focus_restriction_; 266 267 DISALLOW_COPY_AND_ASSIGN(TestFocusRules); 268}; 269 270// Common infrastructure shared by all FocusController test types. 271class FocusControllerTestBase : public aura::test::AuraTestBase { 272 protected: 273 FocusControllerTestBase() {} 274 275 // Overridden from aura::test::AuraTestBase: 276 virtual void SetUp() OVERRIDE { 277 // FocusController registers itself as an Env observer so it can catch all 278 // window initializations, including the root_window()'s, so we create it 279 // before allowing the base setup. 280 test_focus_rules_ = new TestFocusRules; 281 focus_controller_.reset(new FocusController(test_focus_rules_)); 282 aura::test::AuraTestBase::SetUp(); 283 root_window()->AddPreTargetHandler(focus_controller_.get()); 284 aura::client::SetFocusClient(root_window(), focus_controller_.get()); 285 aura::client::SetActivationClient(root_window(), focus_controller_.get()); 286 287 // Hierarchy used by all tests: 288 // root_window 289 // +-- w1 290 // | +-- w11 291 // | +-- w12 292 // +-- w2 293 // | +-- w21 294 // | +-- w211 295 // +-- w3 296 aura::Window* w1 = aura::test::CreateTestWindowWithDelegate( 297 aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 1, 298 gfx::Rect(0, 0, 50, 50), root_window()); 299 aura::test::CreateTestWindowWithDelegate( 300 aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 11, 301 gfx::Rect(5, 5, 10, 10), w1); 302 aura::test::CreateTestWindowWithDelegate( 303 aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 12, 304 gfx::Rect(15, 15, 10, 10), w1); 305 aura::Window* w2 = aura::test::CreateTestWindowWithDelegate( 306 aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 2, 307 gfx::Rect(75, 75, 50, 50), root_window()); 308 aura::Window* w21 = aura::test::CreateTestWindowWithDelegate( 309 aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 21, 310 gfx::Rect(5, 5, 10, 10), w2); 311 aura::test::CreateTestWindowWithDelegate( 312 aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 211, 313 gfx::Rect(1, 1, 5, 5), w21); 314 aura::test::CreateTestWindowWithDelegate( 315 aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), 3, 316 gfx::Rect(125, 125, 50, 50), root_window()); 317 } 318 virtual void TearDown() OVERRIDE { 319 root_window()->RemovePreTargetHandler(focus_controller_.get()); 320 aura::test::AuraTestBase::TearDown(); 321 test_focus_rules_ = NULL; // Owned by FocusController. 322 focus_controller_.reset(); 323 } 324 325 void FocusWindow(aura::Window* window) { 326 aura::client::GetFocusClient(root_window())->FocusWindow(window); 327 } 328 aura::Window* GetFocusedWindow() { 329 return aura::client::GetFocusClient(root_window())->GetFocusedWindow(); 330 } 331 int GetFocusedWindowId() { 332 aura::Window* focused_window = GetFocusedWindow(); 333 return focused_window ? focused_window->id() : -1; 334 } 335 void ActivateWindow(aura::Window* window) { 336 aura::client::GetActivationClient(root_window())->ActivateWindow(window); 337 } 338 void DeactivateWindow(aura::Window* window) { 339 aura::client::GetActivationClient(root_window())->DeactivateWindow(window); 340 } 341 aura::Window* GetActiveWindow() { 342 return aura::client::GetActivationClient(root_window())->GetActiveWindow(); 343 } 344 int GetActiveWindowId() { 345 aura::Window* active_window = GetActiveWindow(); 346 return active_window ? active_window->id() : -1; 347 } 348 349 TestFocusRules* test_focus_rules() { return test_focus_rules_; } 350 351 // Test functions. 352 virtual void BasicFocus() = 0; 353 virtual void BasicActivation() = 0; 354 virtual void FocusEvents() = 0; 355 virtual void DuplicateFocusEvents() {} 356 virtual void ActivationEvents() = 0; 357 virtual void ReactivationEvents() {} 358 virtual void DuplicateActivationEvents() {} 359 virtual void ShiftFocusWithinActiveWindow() {} 360 virtual void ShiftFocusToChildOfInactiveWindow() {} 361 virtual void ShiftFocusToParentOfFocusedWindow() {} 362 virtual void FocusRulesOverride() = 0; 363 virtual void ActivationRulesOverride() = 0; 364 virtual void ShiftFocusOnActivation() {} 365 virtual void ShiftFocusOnActivationDueToHide() {} 366 virtual void NoShiftActiveOnActivation() {} 367 virtual void NoFocusChangeOnClickOnCaptureWindow() {} 368 virtual void ChangeFocusWhenNothingFocusedAndCaptured() {} 369 virtual void DontPassDeletedWindow() {} 370 371 private: 372 scoped_ptr<FocusController> focus_controller_; 373 TestFocusRules* test_focus_rules_; 374 375 DISALLOW_COPY_AND_ASSIGN(FocusControllerTestBase); 376}; 377 378// Test base for tests where focus is directly set to a target window. 379class FocusControllerDirectTestBase : public FocusControllerTestBase { 380 protected: 381 FocusControllerDirectTestBase() {} 382 383 // Different test types shift focus in different ways. 384 virtual void FocusWindowDirect(aura::Window* window) = 0; 385 virtual void ActivateWindowDirect(aura::Window* window) = 0; 386 virtual void DeactivateWindowDirect(aura::Window* window) = 0; 387 388 // Input events do not change focus if the window can not be focused. 389 virtual bool IsInputEvent() = 0; 390 391 void FocusWindowById(int id) { 392 aura::Window* window = root_window()->GetChildById(id); 393 DCHECK(window); 394 FocusWindowDirect(window); 395 } 396 void ActivateWindowById(int id) { 397 aura::Window* window = root_window()->GetChildById(id); 398 DCHECK(window); 399 ActivateWindowDirect(window); 400 } 401 402 // Overridden from FocusControllerTestBase: 403 virtual void BasicFocus() OVERRIDE { 404 EXPECT_EQ(NULL, GetFocusedWindow()); 405 FocusWindowById(1); 406 EXPECT_EQ(1, GetFocusedWindowId()); 407 FocusWindowById(2); 408 EXPECT_EQ(2, GetFocusedWindowId()); 409 } 410 virtual void BasicActivation() OVERRIDE { 411 EXPECT_EQ(NULL, GetActiveWindow()); 412 ActivateWindowById(1); 413 EXPECT_EQ(1, GetActiveWindowId()); 414 ActivateWindowById(2); 415 EXPECT_EQ(2, GetActiveWindowId()); 416 // Verify that attempting to deactivate NULL does not crash and does not 417 // change activation. 418 DeactivateWindow(NULL); 419 EXPECT_EQ(2, GetActiveWindowId()); 420 DeactivateWindow(GetActiveWindow()); 421 EXPECT_EQ(1, GetActiveWindowId()); 422 } 423 virtual void FocusEvents() OVERRIDE { 424 ScopedFocusNotificationObserver root_observer(root_window()); 425 ScopedTargetFocusNotificationObserver observer1(root_window(), 1); 426 ScopedTargetFocusNotificationObserver observer2(root_window(), 2); 427 428 root_observer.ExpectCounts(0, 0); 429 observer1.ExpectCounts(0, 0); 430 observer2.ExpectCounts(0, 0); 431 432 FocusWindowById(1); 433 root_observer.ExpectCounts(1, 1); 434 observer1.ExpectCounts(1, 1); 435 observer2.ExpectCounts(0, 0); 436 437 FocusWindowById(2); 438 root_observer.ExpectCounts(2, 2); 439 observer1.ExpectCounts(2, 2); 440 observer2.ExpectCounts(1, 1); 441 } 442 virtual void DuplicateFocusEvents() OVERRIDE { 443 // Focusing an existing focused window should not resend focus events. 444 ScopedFocusNotificationObserver root_observer(root_window()); 445 ScopedTargetFocusNotificationObserver observer1(root_window(), 1); 446 447 root_observer.ExpectCounts(0, 0); 448 observer1.ExpectCounts(0, 0); 449 450 FocusWindowById(1); 451 root_observer.ExpectCounts(1, 1); 452 observer1.ExpectCounts(1, 1); 453 454 FocusWindowById(1); 455 root_observer.ExpectCounts(1, 1); 456 observer1.ExpectCounts(1, 1); 457 } 458 virtual void ActivationEvents() OVERRIDE { 459 ActivateWindowById(1); 460 461 ScopedFocusNotificationObserver root_observer(root_window()); 462 ScopedTargetFocusNotificationObserver observer1(root_window(), 1); 463 ScopedTargetFocusNotificationObserver observer2(root_window(), 2); 464 465 root_observer.ExpectCounts(0, 0); 466 observer1.ExpectCounts(0, 0); 467 observer2.ExpectCounts(0, 0); 468 469 ActivateWindowById(2); 470 root_observer.ExpectCounts(1, 1); 471 observer1.ExpectCounts(1, 1); 472 observer2.ExpectCounts(1, 1); 473 } 474 virtual void ReactivationEvents() OVERRIDE { 475 ActivateWindowById(1); 476 ScopedFocusNotificationObserver root_observer(root_window()); 477 EXPECT_EQ(0, root_observer.reactivation_count()); 478 root_window()->GetChildById(2)->Hide(); 479 // When we attempt to activate "2", which cannot be activated because it 480 // is not visible, "1" will be reactivated. 481 ActivateWindowById(2); 482 EXPECT_EQ(1, root_observer.reactivation_count()); 483 EXPECT_EQ(root_window()->GetChildById(2), 484 root_observer.reactivation_requested_window()); 485 EXPECT_EQ(root_window()->GetChildById(1), 486 root_observer.reactivation_actual_window()); 487 } 488 virtual void DuplicateActivationEvents() OVERRIDE { 489 // Activating an existing active window should not resend activation events. 490 ActivateWindowById(1); 491 492 ScopedFocusNotificationObserver root_observer(root_window()); 493 ScopedTargetFocusNotificationObserver observer1(root_window(), 1); 494 ScopedTargetFocusNotificationObserver observer2(root_window(), 2); 495 496 root_observer.ExpectCounts(0, 0); 497 observer1.ExpectCounts(0, 0); 498 observer2.ExpectCounts(0, 0); 499 500 ActivateWindowById(2); 501 root_observer.ExpectCounts(1, 1); 502 observer1.ExpectCounts(1, 1); 503 observer2.ExpectCounts(1, 1); 504 505 ActivateWindowById(2); 506 root_observer.ExpectCounts(1, 1); 507 observer1.ExpectCounts(1, 1); 508 observer2.ExpectCounts(1, 1); 509 } 510 virtual void ShiftFocusWithinActiveWindow() OVERRIDE { 511 ActivateWindowById(1); 512 EXPECT_EQ(1, GetActiveWindowId()); 513 EXPECT_EQ(1, GetFocusedWindowId()); 514 FocusWindowById(11); 515 EXPECT_EQ(11, GetFocusedWindowId()); 516 FocusWindowById(12); 517 EXPECT_EQ(12, GetFocusedWindowId()); 518 } 519 virtual void ShiftFocusToChildOfInactiveWindow() OVERRIDE { 520 ActivateWindowById(2); 521 EXPECT_EQ(2, GetActiveWindowId()); 522 EXPECT_EQ(2, GetFocusedWindowId()); 523 FocusWindowById(11); 524 EXPECT_EQ(1, GetActiveWindowId()); 525 EXPECT_EQ(11, GetFocusedWindowId()); 526 } 527 virtual void ShiftFocusToParentOfFocusedWindow() OVERRIDE { 528 ActivateWindowById(1); 529 EXPECT_EQ(1, GetFocusedWindowId()); 530 FocusWindowById(11); 531 EXPECT_EQ(11, GetFocusedWindowId()); 532 FocusWindowById(1); 533 // Focus should _not_ shift to the parent of the already-focused window. 534 EXPECT_EQ(11, GetFocusedWindowId()); 535 } 536 virtual void FocusRulesOverride() OVERRIDE { 537 EXPECT_EQ(NULL, GetFocusedWindow()); 538 FocusWindowById(11); 539 EXPECT_EQ(11, GetFocusedWindowId()); 540 541 test_focus_rules()->set_focus_restriction(root_window()->GetChildById(211)); 542 FocusWindowById(12); 543 // Input events leave focus unchanged; direct API calls will change focus 544 // to the restricted window. 545 int focused_window = IsInputEvent() ? 11 : 211; 546 EXPECT_EQ(focused_window, GetFocusedWindowId()); 547 548 test_focus_rules()->set_focus_restriction(NULL); 549 FocusWindowById(12); 550 EXPECT_EQ(12, GetFocusedWindowId()); 551 } 552 virtual void ActivationRulesOverride() OVERRIDE { 553 ActivateWindowById(1); 554 EXPECT_EQ(1, GetActiveWindowId()); 555 EXPECT_EQ(1, GetFocusedWindowId()); 556 557 aura::Window* w3 = root_window()->GetChildById(3); 558 test_focus_rules()->set_focus_restriction(w3); 559 560 ActivateWindowById(2); 561 // Input events leave activation unchanged; direct API calls will activate 562 // the restricted window. 563 int active_window = IsInputEvent() ? 1 : 3; 564 EXPECT_EQ(active_window, GetActiveWindowId()); 565 EXPECT_EQ(active_window, GetFocusedWindowId()); 566 567 test_focus_rules()->set_focus_restriction(NULL); 568 ActivateWindowById(2); 569 EXPECT_EQ(2, GetActiveWindowId()); 570 EXPECT_EQ(2, GetFocusedWindowId()); 571 } 572 virtual void ShiftFocusOnActivation() OVERRIDE { 573 // When a window is activated, by default that window is also focused. 574 // An ActivationChangeObserver may shift focus to another window within the 575 // same activatable window. 576 ActivateWindowById(2); 577 EXPECT_EQ(2, GetFocusedWindowId()); 578 ActivateWindowById(1); 579 EXPECT_EQ(1, GetFocusedWindowId()); 580 581 ActivateWindowById(2); 582 583 aura::Window* target = root_window()->GetChildById(1); 584 aura::client::ActivationClient* client = 585 aura::client::GetActivationClient(root_window()); 586 587 scoped_ptr<FocusShiftingActivationObserver> observer( 588 new FocusShiftingActivationObserver(target)); 589 observer->set_shift_focus_to(target->GetChildById(11)); 590 client->AddObserver(observer.get()); 591 592 ActivateWindowById(1); 593 594 // w1's ActivationChangeObserver shifted focus to this child, pre-empting 595 // FocusController's default setting. 596 EXPECT_EQ(11, GetFocusedWindowId()); 597 598 ActivateWindowById(2); 599 EXPECT_EQ(2, GetFocusedWindowId()); 600 601 // Simulate a focus reset by the ActivationChangeObserver. This should 602 // trigger the default setting in FocusController. 603 observer->set_shift_focus_to(NULL); 604 ActivateWindowById(1); 605 EXPECT_EQ(1, GetFocusedWindowId()); 606 607 client->RemoveObserver(observer.get()); 608 609 ActivateWindowById(2); 610 EXPECT_EQ(2, GetFocusedWindowId()); 611 ActivateWindowById(1); 612 EXPECT_EQ(1, GetFocusedWindowId()); 613 } 614 virtual void ShiftFocusOnActivationDueToHide() OVERRIDE { 615 // Similar to ShiftFocusOnActivation except the activation change is 616 // triggered by hiding the active window. 617 ActivateWindowById(1); 618 EXPECT_EQ(1, GetFocusedWindowId()); 619 620 // Removes window 3 as candidate for next activatable window. 621 root_window()->GetChildById(3)->Hide(); 622 EXPECT_EQ(1, GetFocusedWindowId()); 623 624 aura::Window* target = root_window()->GetChildById(2); 625 aura::client::ActivationClient* client = 626 aura::client::GetActivationClient(root_window()); 627 628 scoped_ptr<FocusShiftingActivationObserver> observer( 629 new FocusShiftingActivationObserver(target)); 630 observer->set_shift_focus_to(target->GetChildById(21)); 631 client->AddObserver(observer.get()); 632 633 // Hide the active window. 634 root_window()->GetChildById(1)->Hide(); 635 636 EXPECT_EQ(21, GetFocusedWindowId()); 637 638 client->RemoveObserver(observer.get()); 639 } 640 virtual void NoShiftActiveOnActivation() OVERRIDE { 641 // When a window is activated, we need to prevent any change to activation 642 // from being made in response to an activation change notification. 643 } 644 645 virtual void NoFocusChangeOnClickOnCaptureWindow() OVERRIDE { 646 scoped_ptr<aura::client::DefaultCaptureClient> capture_client( 647 new aura::client::DefaultCaptureClient(root_window())); 648 // Clicking on a window which has capture should not cause a focus change 649 // to the window. This test verifies whether that is indeed the case. 650 ActivateWindowById(1); 651 652 EXPECT_EQ(1, GetActiveWindowId()); 653 EXPECT_EQ(1, GetFocusedWindowId()); 654 655 aura::Window* w2 = root_window()->GetChildById(2); 656 aura::client::GetCaptureClient(root_window())->SetCapture(w2); 657 aura::test::EventGenerator generator(root_window(), w2); 658 generator.ClickLeftButton(); 659 660 EXPECT_EQ(1, GetActiveWindowId()); 661 EXPECT_EQ(1, GetFocusedWindowId()); 662 aura::client::GetCaptureClient(root_window())->ReleaseCapture(w2); 663 } 664 665 // Verifies focus change is honored while capture held. 666 virtual void ChangeFocusWhenNothingFocusedAndCaptured() OVERRIDE { 667 scoped_ptr<aura::client::DefaultCaptureClient> capture_client( 668 new aura::client::DefaultCaptureClient(root_window())); 669 aura::Window* w1 = root_window()->GetChildById(1); 670 aura::client::GetCaptureClient(root_window())->SetCapture(w1); 671 672 EXPECT_EQ(-1, GetActiveWindowId()); 673 EXPECT_EQ(-1, GetFocusedWindowId()); 674 675 FocusWindowById(1); 676 677 EXPECT_EQ(1, GetActiveWindowId()); 678 EXPECT_EQ(1, GetFocusedWindowId()); 679 680 aura::client::GetCaptureClient(root_window())->ReleaseCapture(w1); 681 } 682 683 // Verfies if a window that loses activation is deleted during observer 684 // notification we don't pass the deleted window to other observers. 685 virtual void DontPassDeletedWindow() OVERRIDE { 686 FocusWindowById(1); 687 688 EXPECT_EQ(1, GetActiveWindowId()); 689 EXPECT_EQ(1, GetFocusedWindowId()); 690 691 DeleteOnLoseActivationChangeObserver observer1( 692 root_window()->GetChildById(1)); 693 RecordingActivationChangeObserver observer2(root_window()); 694 695 FocusWindowById(2); 696 697 EXPECT_EQ(2, GetActiveWindowId()); 698 EXPECT_EQ(2, GetFocusedWindowId()); 699 700 EXPECT_TRUE(observer1.did_delete()); 701 ASSERT_EQ(1u, observer2.lost().size()); 702 EXPECT_TRUE(observer2.lost()[0] == NULL); 703 } 704 705 private: 706 DISALLOW_COPY_AND_ASSIGN(FocusControllerDirectTestBase); 707}; 708 709// Focus and Activation changes via aura::client::ActivationClient API. 710class FocusControllerApiTest : public FocusControllerDirectTestBase { 711 public: 712 FocusControllerApiTest() {} 713 714 private: 715 // Overridden from FocusControllerTestBase: 716 virtual void FocusWindowDirect(aura::Window* window) OVERRIDE { 717 FocusWindow(window); 718 } 719 virtual void ActivateWindowDirect(aura::Window* window) OVERRIDE { 720 ActivateWindow(window); 721 } 722 virtual void DeactivateWindowDirect(aura::Window* window) OVERRIDE { 723 DeactivateWindow(window); 724 } 725 virtual bool IsInputEvent() OVERRIDE { return false; } 726 727 DISALLOW_COPY_AND_ASSIGN(FocusControllerApiTest); 728}; 729 730// Focus and Activation changes via input events. 731class FocusControllerMouseEventTest : public FocusControllerDirectTestBase { 732 public: 733 FocusControllerMouseEventTest() {} 734 735 private: 736 // Overridden from FocusControllerTestBase: 737 virtual void FocusWindowDirect(aura::Window* window) OVERRIDE { 738 aura::test::EventGenerator generator(root_window(), window); 739 generator.ClickLeftButton(); 740 } 741 virtual void ActivateWindowDirect(aura::Window* window) OVERRIDE { 742 aura::test::EventGenerator generator(root_window(), window); 743 generator.ClickLeftButton(); 744 } 745 virtual void DeactivateWindowDirect(aura::Window* window) OVERRIDE { 746 aura::Window* next_activatable = 747 test_focus_rules()->GetNextActivatableWindow(window); 748 aura::test::EventGenerator generator(root_window(), next_activatable); 749 generator.ClickLeftButton(); 750 } 751 virtual bool IsInputEvent() OVERRIDE { return true; } 752 753 DISALLOW_COPY_AND_ASSIGN(FocusControllerMouseEventTest); 754}; 755 756class FocusControllerGestureEventTest : public FocusControllerDirectTestBase { 757 public: 758 FocusControllerGestureEventTest() {} 759 760 private: 761 // Overridden from FocusControllerTestBase: 762 virtual void FocusWindowDirect(aura::Window* window) OVERRIDE { 763 aura::test::EventGenerator generator(root_window(), window); 764 generator.GestureTapAt(window->bounds().CenterPoint()); 765 } 766 virtual void ActivateWindowDirect(aura::Window* window) OVERRIDE { 767 aura::test::EventGenerator generator(root_window(), window); 768 generator.GestureTapAt(window->bounds().CenterPoint()); 769 } 770 virtual void DeactivateWindowDirect(aura::Window* window) OVERRIDE { 771 aura::Window* next_activatable = 772 test_focus_rules()->GetNextActivatableWindow(window); 773 aura::test::EventGenerator generator(root_window(), next_activatable); 774 generator.GestureTapAt(window->bounds().CenterPoint()); 775 } 776 virtual bool IsInputEvent() OVERRIDE { return true; } 777 778 DISALLOW_COPY_AND_ASSIGN(FocusControllerGestureEventTest); 779}; 780 781// Test base for tests where focus is implicitly set to a window as the result 782// of a disposition change to the focused window or the hierarchy that contains 783// it. 784class FocusControllerImplicitTestBase : public FocusControllerTestBase { 785 protected: 786 explicit FocusControllerImplicitTestBase(bool parent) : parent_(parent) {} 787 788 aura::Window* GetDispositionWindow(aura::Window* window) { 789 return parent_ ? window->parent() : window; 790 } 791 792 // Change the disposition of |window| in such a way as it will lose focus. 793 virtual void ChangeWindowDisposition(aura::Window* window) = 0; 794 795 // Allow each disposition change test to add additional post-disposition 796 // change expectations. 797 virtual void PostDispostionChangeExpectations() {} 798 799 // Overridden from FocusControllerTestBase: 800 virtual void BasicFocus() OVERRIDE { 801 EXPECT_EQ(NULL, GetFocusedWindow()); 802 803 aura::Window* w211 = root_window()->GetChildById(211); 804 FocusWindow(w211); 805 EXPECT_EQ(211, GetFocusedWindowId()); 806 807 ChangeWindowDisposition(w211); 808 // BasicFocusRules passes focus to the parent. 809 EXPECT_EQ(parent_ ? 2 : 21, GetFocusedWindowId()); 810 } 811 virtual void BasicActivation() OVERRIDE { 812 DCHECK(!parent_) << "Activation tests don't support parent changes."; 813 814 EXPECT_EQ(NULL, GetActiveWindow()); 815 816 aura::Window* w2 = root_window()->GetChildById(2); 817 ActivateWindow(w2); 818 EXPECT_EQ(2, GetActiveWindowId()); 819 820 ChangeWindowDisposition(w2); 821 EXPECT_EQ(3, GetActiveWindowId()); 822 PostDispostionChangeExpectations(); 823 } 824 virtual void FocusEvents() OVERRIDE { 825 aura::Window* w211 = root_window()->GetChildById(211); 826 FocusWindow(w211); 827 828 ScopedFocusNotificationObserver root_observer(root_window()); 829 ScopedTargetFocusNotificationObserver observer211(root_window(), 211); 830 root_observer.ExpectCounts(0, 0); 831 observer211.ExpectCounts(0, 0); 832 833 ChangeWindowDisposition(w211); 834 root_observer.ExpectCounts(0, 1); 835 observer211.ExpectCounts(0, 1); 836 } 837 virtual void ActivationEvents() OVERRIDE { 838 DCHECK(!parent_) << "Activation tests don't support parent changes."; 839 840 aura::Window* w2 = root_window()->GetChildById(2); 841 ActivateWindow(w2); 842 843 ScopedFocusNotificationObserver root_observer(root_window()); 844 ScopedTargetFocusNotificationObserver observer2(root_window(), 2); 845 ScopedTargetFocusNotificationObserver observer3(root_window(), 3); 846 root_observer.ExpectCounts(0, 0); 847 observer2.ExpectCounts(0, 0); 848 observer3.ExpectCounts(0, 0); 849 850 ChangeWindowDisposition(w2); 851 root_observer.ExpectCounts(1, 1); 852 observer2.ExpectCounts(1, 1); 853 observer3.ExpectCounts(1, 1); 854 } 855 virtual void FocusRulesOverride() OVERRIDE { 856 EXPECT_EQ(NULL, GetFocusedWindow()); 857 aura::Window* w211 = root_window()->GetChildById(211); 858 FocusWindow(w211); 859 EXPECT_EQ(211, GetFocusedWindowId()); 860 861 test_focus_rules()->set_focus_restriction(root_window()->GetChildById(11)); 862 ChangeWindowDisposition(w211); 863 // Normally, focus would shift to the parent (w21) but the override shifts 864 // it to 11. 865 EXPECT_EQ(11, GetFocusedWindowId()); 866 867 test_focus_rules()->set_focus_restriction(NULL); 868 } 869 virtual void ActivationRulesOverride() OVERRIDE { 870 DCHECK(!parent_) << "Activation tests don't support parent changes."; 871 872 aura::Window* w1 = root_window()->GetChildById(1); 873 ActivateWindow(w1); 874 875 EXPECT_EQ(1, GetActiveWindowId()); 876 EXPECT_EQ(1, GetFocusedWindowId()); 877 878 aura::Window* w3 = root_window()->GetChildById(3); 879 test_focus_rules()->set_focus_restriction(w3); 880 881 // Normally, activation/focus would move to w2, but since we have a focus 882 // restriction, it should move to w3 instead. 883 ChangeWindowDisposition(w1); 884 EXPECT_EQ(3, GetActiveWindowId()); 885 EXPECT_EQ(3, GetFocusedWindowId()); 886 887 test_focus_rules()->set_focus_restriction(NULL); 888 ActivateWindow(root_window()->GetChildById(2)); 889 EXPECT_EQ(2, GetActiveWindowId()); 890 EXPECT_EQ(2, GetFocusedWindowId()); 891 } 892 893 private: 894 // When true, the disposition change occurs to the parent of the window 895 // instead of to the window. This verifies that changes occurring in the 896 // hierarchy that contains the window affect the window's focus. 897 bool parent_; 898 899 DISALLOW_COPY_AND_ASSIGN(FocusControllerImplicitTestBase); 900}; 901 902// Focus and Activation changes in response to window visibility changes. 903class FocusControllerHideTest : public FocusControllerImplicitTestBase { 904 public: 905 FocusControllerHideTest() : FocusControllerImplicitTestBase(false) {} 906 907 protected: 908 FocusControllerHideTest(bool parent) 909 : FocusControllerImplicitTestBase(parent) {} 910 911 // Overridden from FocusControllerImplicitTestBase: 912 virtual void ChangeWindowDisposition(aura::Window* window) OVERRIDE { 913 GetDispositionWindow(window)->Hide(); 914 } 915 virtual void PostDispostionChangeExpectations() OVERRIDE { 916 // BasicActivation() starts with the stacking order: 1, 2, 3 (3 topmost) 917 // and then activates 2. After 2 is hidden in ChangeWindowDisposition 918 // above, 3 is activated, but code in 919 // FocusController::OnWindowVisibilityChanging keeps 2's layer above 3's 920 // until a hide animation completes (e.g. a fade-out transition). 921 aura::Window* w2 = root_window()->GetChildById(2); 922 aura::Window* w3 = root_window()->GetChildById(3); 923 924 // W2 was hidden, but its layer should still be stacked above W3's. 925 typedef std::vector<ui::Layer*> Layers; 926 const Layers& children = w3->parent()->layer()->children(); 927 Layers::const_iterator w3_iter = 928 std::find(children.begin(), children.end(), w3->layer()); 929 Layers::const_iterator w2_iter = 930 std::find(children.begin(), children.end(), w2->layer()); 931 EXPECT_TRUE(w2_iter > w3_iter); 932 } 933 934 private: 935 DISALLOW_COPY_AND_ASSIGN(FocusControllerHideTest); 936}; 937 938// Focus and Activation changes in response to window parent visibility 939// changes. 940class FocusControllerParentHideTest : public FocusControllerHideTest { 941 public: 942 FocusControllerParentHideTest() : FocusControllerHideTest(true) {} 943 944 private: 945 DISALLOW_COPY_AND_ASSIGN(FocusControllerParentHideTest); 946}; 947 948// Focus and Activation changes in response to window destruction. 949class FocusControllerDestructionTest : public FocusControllerImplicitTestBase { 950 public: 951 FocusControllerDestructionTest() : FocusControllerImplicitTestBase(false) {} 952 953 protected: 954 FocusControllerDestructionTest(bool parent) 955 : FocusControllerImplicitTestBase(parent) {} 956 957 // Overridden from FocusControllerImplicitTestBase: 958 virtual void ChangeWindowDisposition(aura::Window* window) OVERRIDE { 959 delete GetDispositionWindow(window); 960 } 961 962 private: 963 DISALLOW_COPY_AND_ASSIGN(FocusControllerDestructionTest); 964}; 965 966// Focus and Activation changes in response to window parent destruction. 967class FocusControllerParentDestructionTest 968 : public FocusControllerDestructionTest { 969 public: 970 FocusControllerParentDestructionTest() 971 : FocusControllerDestructionTest(true) {} 972 973 private: 974 DISALLOW_COPY_AND_ASSIGN(FocusControllerParentDestructionTest); 975}; 976 977// Focus and Activation changes in response to window removal. 978class FocusControllerRemovalTest : public FocusControllerImplicitTestBase { 979 public: 980 FocusControllerRemovalTest() : FocusControllerImplicitTestBase(false) {} 981 982 protected: 983 FocusControllerRemovalTest(bool parent) 984 : FocusControllerImplicitTestBase(parent) {} 985 986 // Overridden from FocusControllerImplicitTestBase: 987 virtual void ChangeWindowDisposition(aura::Window* window) OVERRIDE { 988 aura::Window* disposition_window = GetDispositionWindow(window); 989 disposition_window->parent()->RemoveChild(disposition_window); 990 window_owner_.reset(disposition_window); 991 } 992 virtual void TearDown() OVERRIDE { 993 window_owner_.reset(); 994 FocusControllerImplicitTestBase::TearDown(); 995 } 996 997 private: 998 scoped_ptr<aura::Window> window_owner_; 999 1000 DISALLOW_COPY_AND_ASSIGN(FocusControllerRemovalTest); 1001}; 1002 1003// Focus and Activation changes in response to window parent removal. 1004class FocusControllerParentRemovalTest : public FocusControllerRemovalTest { 1005 public: 1006 FocusControllerParentRemovalTest() : FocusControllerRemovalTest(true) {} 1007 1008 private: 1009 DISALLOW_COPY_AND_ASSIGN(FocusControllerParentRemovalTest); 1010}; 1011 1012 1013#define FOCUS_CONTROLLER_TEST(TESTCLASS, TESTNAME) \ 1014 TEST_F(TESTCLASS, TESTNAME) { TESTNAME(); } 1015 1016// Runs direct focus change tests (input events and API calls). 1017#define DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \ 1018 FOCUS_CONTROLLER_TEST(FocusControllerApiTest, TESTNAME) \ 1019 FOCUS_CONTROLLER_TEST(FocusControllerMouseEventTest, TESTNAME) \ 1020 FOCUS_CONTROLLER_TEST(FocusControllerGestureEventTest, TESTNAME) 1021 1022// Runs implicit focus change tests for disposition changes to target. 1023#define IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME) \ 1024 FOCUS_CONTROLLER_TEST(FocusControllerHideTest, TESTNAME) \ 1025 FOCUS_CONTROLLER_TEST(FocusControllerDestructionTest, TESTNAME) \ 1026 FOCUS_CONTROLLER_TEST(FocusControllerRemovalTest, TESTNAME) 1027 1028// Runs implicit focus change tests for disposition changes to target's parent 1029// hierarchy. 1030#define IMPLICIT_FOCUS_CHANGE_PARENT_TESTS(TESTNAME) \ 1031 /* TODO(beng): parent destruction tests are not supported at 1032 present due to workspace manager issues. \ 1033 FOCUS_CONTROLLER_TEST(FocusControllerParentDestructionTest, TESTNAME) */ \ 1034 FOCUS_CONTROLLER_TEST(FocusControllerParentHideTest, TESTNAME) \ 1035 FOCUS_CONTROLLER_TEST(FocusControllerParentRemovalTest, TESTNAME) 1036 1037// Runs all implicit focus change tests (changes to the target and target's 1038// parent hierarchy) 1039#define IMPLICIT_FOCUS_CHANGE_TESTS(TESTNAME) \ 1040 IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME) \ 1041 IMPLICIT_FOCUS_CHANGE_PARENT_TESTS(TESTNAME) 1042 1043// Runs all possible focus change tests. 1044#define ALL_FOCUS_TESTS(TESTNAME) \ 1045 DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \ 1046 IMPLICIT_FOCUS_CHANGE_TESTS(TESTNAME) 1047 1048// Runs focus change tests that apply only to the target. For example, 1049// implicit activation changes caused by window disposition changes do not 1050// occur when changes to the containing hierarchy happen. 1051#define TARGET_FOCUS_TESTS(TESTNAME) \ 1052 DIRECT_FOCUS_CHANGE_TESTS(TESTNAME) \ 1053 IMPLICIT_FOCUS_CHANGE_TARGET_TESTS(TESTNAME) 1054 1055// - Focuses a window, verifies that focus changed. 1056ALL_FOCUS_TESTS(BasicFocus); 1057 1058// - Activates a window, verifies that activation changed. 1059TARGET_FOCUS_TESTS(BasicActivation); 1060 1061// - Focuses a window, verifies that focus events were dispatched. 1062ALL_FOCUS_TESTS(FocusEvents); 1063 1064// - Focuses or activates a window multiple times, verifies that events are only 1065// dispatched when focus/activation actually changes. 1066DIRECT_FOCUS_CHANGE_TESTS(DuplicateFocusEvents); 1067DIRECT_FOCUS_CHANGE_TESTS(DuplicateActivationEvents); 1068 1069// - Activates a window, verifies that activation events were dispatched. 1070TARGET_FOCUS_TESTS(ActivationEvents); 1071 1072// - Attempts to active a hidden window, verifies that current window is 1073// attempted to be reactivated and the appropriate event dispatched. 1074FOCUS_CONTROLLER_TEST(FocusControllerApiTest, ReactivationEvents); 1075 1076// - Input events/API calls shift focus between focusable windows within the 1077// active window. 1078DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusWithinActiveWindow); 1079 1080// - Input events/API calls to a child window of an inactive window shifts 1081// activation to the activatable parent and focuses the child. 1082DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusToChildOfInactiveWindow); 1083 1084// - Input events/API calls to focus the parent of the focused window do not 1085// shift focus away from the child. 1086DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusToParentOfFocusedWindow); 1087 1088// - Verifies that FocusRules determine what can be focused. 1089ALL_FOCUS_TESTS(FocusRulesOverride); 1090 1091// - Verifies that FocusRules determine what can be activated. 1092TARGET_FOCUS_TESTS(ActivationRulesOverride); 1093 1094// - Verifies that attempts to change focus or activation from a focus or 1095// activation change observer are ignored. 1096DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusOnActivation); 1097DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusOnActivationDueToHide); 1098DIRECT_FOCUS_CHANGE_TESTS(NoShiftActiveOnActivation); 1099 1100// Clicking on a window which has capture should not result in a focus change. 1101DIRECT_FOCUS_CHANGE_TESTS(NoFocusChangeOnClickOnCaptureWindow); 1102 1103FOCUS_CONTROLLER_TEST(FocusControllerApiTest, 1104 ChangeFocusWhenNothingFocusedAndCaptured); 1105 1106// See description above DontPassDeletedWindow() for details. 1107FOCUS_CONTROLLER_TEST(FocusControllerApiTest, DontPassDeletedWindow); 1108 1109} // namespace corewm 1110} // namespace views 1111