| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/views/corewm/focus_controller.h" | 5 #include "ui/views/corewm/focus_controller.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 | 8 |
| 9 #include "ui/aura/client/activation_change_observer.h" | 9 #include "ui/aura/client/activation_change_observer.h" |
| 10 #include "ui/aura/client/activation_client.h" | 10 #include "ui/aura/client/activation_client.h" |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 aura::client::GetActivationClient(root_window_)->RemoveObserver(this); | 66 aura::client::GetActivationClient(root_window_)->RemoveObserver(this); |
| 67 aura::client::GetFocusClient(root_window_)->RemoveObserver(this); | 67 aura::client::GetFocusClient(root_window_)->RemoveObserver(this); |
| 68 } | 68 } |
| 69 | 69 |
| 70 private: | 70 private: |
| 71 aura::RootWindow* root_window_; | 71 aura::RootWindow* root_window_; |
| 72 | 72 |
| 73 DISALLOW_COPY_AND_ASSIGN(ScopedFocusNotificationObserver); | 73 DISALLOW_COPY_AND_ASSIGN(ScopedFocusNotificationObserver); |
| 74 }; | 74 }; |
| 75 | 75 |
| 76 // Focus/Activation change observer that attempts to shift focus/activation |
| 77 // while processing an update to focus/activation. |
| 78 class RecurseFocusObserver : public aura::client::ActivationChangeObserver, |
| 79 public aura::client::FocusChangeObserver { |
| 80 public: |
| 81 explicit RecurseFocusObserver(aura::Window* other) : other_(other) {} |
| 82 virtual ~RecurseFocusObserver() {} |
| 83 |
| 84 private: |
| 85 // Overridden from aura::client::ActivationChangeObserver: |
| 86 virtual void OnWindowActivated(aura::Window* gained_active, |
| 87 aura::Window* lost_active) OVERRIDE { |
| 88 DCHECK_NE(gained_active, other_); |
| 89 aura::client::GetActivationClient(other_->GetRootWindow())->ActivateWindow( |
| 90 other_); |
| 91 } |
| 92 |
| 93 // Overridden from aura::client::FocusChangeObserver: |
| 94 virtual void OnWindowFocused(aura::Window* gained_focus, |
| 95 aura::Window* lost_focus) OVERRIDE { |
| 96 DCHECK_NE(gained_focus, other_); |
| 97 aura::client::GetFocusClient(other_)->FocusWindow(other_, NULL); |
| 98 } |
| 99 |
| 100 aura::Window* other_; |
| 101 |
| 102 DISALLOW_COPY_AND_ASSIGN(RecurseFocusObserver); |
| 103 }; |
| 104 |
| 105 class ScopedRecurseFocusObserver : public RecurseFocusObserver { |
| 106 public: |
| 107 ScopedRecurseFocusObserver(aura::RootWindow* root_window, |
| 108 aura::Window* other) |
| 109 : RecurseFocusObserver(other), |
| 110 root_window_(root_window) { |
| 111 aura::client::GetActivationClient(root_window_)->AddObserver(this); |
| 112 aura::client::GetFocusClient(root_window_)->AddObserver(this); |
| 113 } |
| 114 virtual ~ScopedRecurseFocusObserver() { |
| 115 aura::client::GetActivationClient(root_window_)->RemoveObserver(this); |
| 116 aura::client::GetFocusClient(root_window_)->RemoveObserver(this); |
| 117 } |
| 118 |
| 119 private: |
| 120 aura::RootWindow* root_window_; |
| 121 |
| 122 DISALLOW_COPY_AND_ASSIGN(ScopedRecurseFocusObserver); |
| 123 }; |
| 124 |
| 76 class ScopedTargetFocusNotificationObserver : public FocusNotificationObserver { | 125 class ScopedTargetFocusNotificationObserver : public FocusNotificationObserver { |
| 77 public: | 126 public: |
| 78 ScopedTargetFocusNotificationObserver(aura::RootWindow* root_window, int id) | 127 ScopedTargetFocusNotificationObserver(aura::RootWindow* root_window, int id) |
| 79 : target_(root_window->GetChildById(id)) { | 128 : target_(root_window->GetChildById(id)) { |
| 80 aura::client::SetActivationChangeObserver(target_, this); | 129 aura::client::SetActivationChangeObserver(target_, this); |
| 81 aura::client::SetFocusChangeObserver(target_, this); | 130 aura::client::SetFocusChangeObserver(target_, this); |
| 82 tracker_.Add(target_); | 131 tracker_.Add(target_); |
| 83 } | 132 } |
| 84 virtual ~ScopedTargetFocusNotificationObserver() { | 133 virtual ~ScopedTargetFocusNotificationObserver() { |
| 85 if (tracker_.Contains(target_)) { | 134 if (tracker_.Contains(target_)) { |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 | 290 |
| 242 // Test functions. | 291 // Test functions. |
| 243 virtual void BasicFocus() = 0; | 292 virtual void BasicFocus() = 0; |
| 244 virtual void BasicActivation() = 0; | 293 virtual void BasicActivation() = 0; |
| 245 virtual void FocusEvents() = 0; | 294 virtual void FocusEvents() = 0; |
| 246 virtual void DuplicateFocusEvents() {} | 295 virtual void DuplicateFocusEvents() {} |
| 247 virtual void ActivationEvents() = 0; | 296 virtual void ActivationEvents() = 0; |
| 248 virtual void DuplicateActivationEvents() {} | 297 virtual void DuplicateActivationEvents() {} |
| 249 virtual void ShiftFocusWithinActiveWindow() {} | 298 virtual void ShiftFocusWithinActiveWindow() {} |
| 250 virtual void ShiftFocusToChildOfInactiveWindow() {} | 299 virtual void ShiftFocusToChildOfInactiveWindow() {} |
| 300 virtual void ShiftFocusToParentOfFocusedWindow() {} |
| 251 virtual void FocusRulesOverride() = 0; | 301 virtual void FocusRulesOverride() = 0; |
| 252 virtual void ActivationRulesOverride() = 0; | 302 virtual void ActivationRulesOverride() = 0; |
| 303 virtual void NoRecurseFocus() {} |
| 304 virtual void NoRecurseActivation() {} |
| 253 | 305 |
| 254 private: | 306 private: |
| 255 scoped_ptr<FocusController> focus_controller_; | 307 scoped_ptr<FocusController> focus_controller_; |
| 256 TestFocusRules* test_focus_rules_; | 308 TestFocusRules* test_focus_rules_; |
| 257 | 309 |
| 258 DISALLOW_COPY_AND_ASSIGN(FocusControllerTestBase); | 310 DISALLOW_COPY_AND_ASSIGN(FocusControllerTestBase); |
| 259 }; | 311 }; |
| 260 | 312 |
| 261 // Test base for tests where focus is directly set to a target window. | 313 // Test base for tests where focus is directly set to a target window. |
| 262 class FocusControllerDirectTestBase : public FocusControllerTestBase { | 314 class FocusControllerDirectTestBase : public FocusControllerTestBase { |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 383 EXPECT_EQ(12, GetFocusedWindowId()); | 435 EXPECT_EQ(12, GetFocusedWindowId()); |
| 384 } | 436 } |
| 385 virtual void ShiftFocusToChildOfInactiveWindow() OVERRIDE { | 437 virtual void ShiftFocusToChildOfInactiveWindow() OVERRIDE { |
| 386 ActivateWindowById(2); | 438 ActivateWindowById(2); |
| 387 EXPECT_EQ(2, GetActiveWindowId()); | 439 EXPECT_EQ(2, GetActiveWindowId()); |
| 388 EXPECT_EQ(2, GetFocusedWindowId()); | 440 EXPECT_EQ(2, GetFocusedWindowId()); |
| 389 FocusWindowById(11); | 441 FocusWindowById(11); |
| 390 EXPECT_EQ(1, GetActiveWindowId()); | 442 EXPECT_EQ(1, GetActiveWindowId()); |
| 391 EXPECT_EQ(11, GetFocusedWindowId()); | 443 EXPECT_EQ(11, GetFocusedWindowId()); |
| 392 } | 444 } |
| 445 virtual void ShiftFocusToParentOfFocusedWindow() OVERRIDE { |
| 446 ActivateWindowById(1); |
| 447 EXPECT_EQ(1, GetFocusedWindowId()); |
| 448 FocusWindowById(11); |
| 449 EXPECT_EQ(11, GetFocusedWindowId()); |
| 450 FocusWindowById(1); |
| 451 // Focus should _not_ shift to the parent of the already-focused window. |
| 452 EXPECT_EQ(11, GetFocusedWindowId()); |
| 453 } |
| 393 virtual void FocusRulesOverride() OVERRIDE { | 454 virtual void FocusRulesOverride() OVERRIDE { |
| 394 EXPECT_EQ(NULL, GetFocusedWindow()); | 455 EXPECT_EQ(NULL, GetFocusedWindow()); |
| 395 FocusWindowById(11); | 456 FocusWindowById(11); |
| 396 EXPECT_EQ(11, GetFocusedWindowId()); | 457 EXPECT_EQ(11, GetFocusedWindowId()); |
| 397 | 458 |
| 398 test_focus_rules()->set_focus_restriction(root_window()->GetChildById(211)); | 459 test_focus_rules()->set_focus_restriction(root_window()->GetChildById(211)); |
| 399 FocusWindowById(12); | 460 FocusWindowById(12); |
| 400 EXPECT_EQ(211, GetFocusedWindowId()); | 461 EXPECT_EQ(211, GetFocusedWindowId()); |
| 401 | 462 |
| 402 test_focus_rules()->set_focus_restriction(NULL); | 463 test_focus_rules()->set_focus_restriction(NULL); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 414 ActivateWindowById(2); | 475 ActivateWindowById(2); |
| 415 // FocusRules restricts focus and activation to 3. | 476 // FocusRules restricts focus and activation to 3. |
| 416 EXPECT_EQ(3, GetActiveWindowId()); | 477 EXPECT_EQ(3, GetActiveWindowId()); |
| 417 EXPECT_EQ(3, GetFocusedWindowId()); | 478 EXPECT_EQ(3, GetFocusedWindowId()); |
| 418 | 479 |
| 419 test_focus_rules()->set_focus_restriction(NULL); | 480 test_focus_rules()->set_focus_restriction(NULL); |
| 420 ActivateWindowById(2); | 481 ActivateWindowById(2); |
| 421 EXPECT_EQ(2, GetActiveWindowId()); | 482 EXPECT_EQ(2, GetActiveWindowId()); |
| 422 EXPECT_EQ(2, GetFocusedWindowId()); | 483 EXPECT_EQ(2, GetFocusedWindowId()); |
| 423 } | 484 } |
| 485 virtual void NoRecurseFocus() OVERRIDE { |
| 486 aura::Window* w2 = root_window()->GetChildById(2); |
| 487 ScopedRecurseFocusObserver observer(root_window(), w2); |
| 488 FocusWindowById(1); |
| 489 // |observer| will try to set active to w2, but the focus system should |
| 490 // prevent recursive updating. |
| 491 EXPECT_EQ(1, GetFocusedWindowId()); |
| 492 } |
| 493 virtual void NoRecurseActivation() OVERRIDE { |
| 494 aura::Window* w2 = root_window()->GetChildById(2); |
| 495 ScopedRecurseFocusObserver observer(root_window(), w2); |
| 496 ActivateWindowById(1); |
| 497 // |observer| will try to set active to w2, but the focus system should |
| 498 // prevent recursive updating. |
| 499 EXPECT_EQ(1, GetActiveWindowId()); |
| 500 } |
| 424 | 501 |
| 425 private: | 502 private: |
| 426 DISALLOW_COPY_AND_ASSIGN(FocusControllerDirectTestBase); | 503 DISALLOW_COPY_AND_ASSIGN(FocusControllerDirectTestBase); |
| 427 }; | 504 }; |
| 428 | 505 |
| 429 // Focus and Activation changes via aura::client::ActivationClient API. | 506 // Focus and Activation changes via aura::client::ActivationClient API. |
| 430 class FocusControllerApiTest : public FocusControllerDirectTestBase { | 507 class FocusControllerApiTest : public FocusControllerDirectTestBase { |
| 431 public: | 508 public: |
| 432 FocusControllerApiTest() {} | 509 FocusControllerApiTest() {} |
| 433 | 510 |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 785 TARGET_FOCUS_TESTS(ActivationEvents); | 862 TARGET_FOCUS_TESTS(ActivationEvents); |
| 786 | 863 |
| 787 // - Input events/API calls shift focus between focusable windows within the | 864 // - Input events/API calls shift focus between focusable windows within the |
| 788 // active window. | 865 // active window. |
| 789 DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusWithinActiveWindow); | 866 DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusWithinActiveWindow); |
| 790 | 867 |
| 791 // - Input events/API calls to a child window of an inactive window shifts | 868 // - Input events/API calls to a child window of an inactive window shifts |
| 792 // activation to the activatable parent and focuses the child. | 869 // activation to the activatable parent and focuses the child. |
| 793 DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusToChildOfInactiveWindow); | 870 DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusToChildOfInactiveWindow); |
| 794 | 871 |
| 872 // - Input events/API calls to focus the parent of the focused window do not |
| 873 // shift focus away from the child. |
| 874 DIRECT_FOCUS_CHANGE_TESTS(ShiftFocusToParentOfFocusedWindow); |
| 875 |
| 795 // - Verifies that FocusRules determine what can be focused. | 876 // - Verifies that FocusRules determine what can be focused. |
| 796 ALL_FOCUS_TESTS(FocusRulesOverride); | 877 ALL_FOCUS_TESTS(FocusRulesOverride); |
| 797 | 878 |
| 798 // - Verifies that FocusRules determine what can be activated. | 879 // - Verifies that FocusRules determine what can be activated. |
| 799 TARGET_FOCUS_TESTS(ActivationRulesOverride); | 880 TARGET_FOCUS_TESTS(ActivationRulesOverride); |
| 800 | 881 |
| 882 // - Verifies that attempts to change focus or activation from a focus or |
| 883 // activation change observer are ignored. |
| 884 DIRECT_FOCUS_CHANGE_TESTS(NoRecurseFocus); |
| 885 DIRECT_FOCUS_CHANGE_TESTS(NoRecurseActivation); |
| 886 |
| 801 } // namespace corewm | 887 } // namespace corewm |
| 802 } // namespace views | 888 } // namespace views |
| OLD | NEW |