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