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 |