Disable discard_framebuffer on ARM Mali-400 on Linux
[chromium-blink-merge.git] / ui / aura / window_unittest.cc
blob46ebc8bf4b1437354bcd156341a38b39f306de6d
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/aura/window.h"
7 #include <string>
8 #include <utility>
9 #include <vector>
11 #include "base/basictypes.h"
12 #include "base/compiler_specific.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "ui/aura/client/capture_client.h"
18 #include "ui/aura/client/focus_change_observer.h"
19 #include "ui/aura/client/visibility_client.h"
20 #include "ui/aura/client/window_tree_client.h"
21 #include "ui/aura/test/aura_test_base.h"
22 #include "ui/aura/test/aura_test_utils.h"
23 #include "ui/aura/test/test_window_delegate.h"
24 #include "ui/aura/test/test_windows.h"
25 #include "ui/aura/test/window_test_api.h"
26 #include "ui/aura/window_delegate.h"
27 #include "ui/aura/window_event_dispatcher.h"
28 #include "ui/aura/window_observer.h"
29 #include "ui/aura/window_property.h"
30 #include "ui/aura/window_tree_host.h"
31 #include "ui/base/hit_test.h"
32 #include "ui/compositor/layer.h"
33 #include "ui/compositor/layer_animation_observer.h"
34 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
35 #include "ui/compositor/scoped_layer_animation_settings.h"
36 #include "ui/compositor/test/test_layers.h"
37 #include "ui/events/event.h"
38 #include "ui/events/event_utils.h"
39 #include "ui/events/gesture_detection/gesture_configuration.h"
40 #include "ui/events/keycodes/keyboard_codes.h"
41 #include "ui/events/test/event_generator.h"
42 #include "ui/gfx/canvas.h"
43 #include "ui/gfx/geometry/vector2d.h"
44 #include "ui/gfx/screen.h"
45 #include "ui/gfx/skia_util.h"
47 DECLARE_WINDOW_PROPERTY_TYPE(const char*)
49 namespace {
51 class TestProperty {
52 public:
53 TestProperty() {}
54 ~TestProperty() {
55 last_deleted_ = this;
57 static TestProperty* last_deleted() { return last_deleted_; }
59 private:
60 static TestProperty* last_deleted_;
61 DISALLOW_COPY_AND_ASSIGN(TestProperty);
64 TestProperty* TestProperty::last_deleted_ = nullptr;
66 DEFINE_OWNED_WINDOW_PROPERTY_KEY(TestProperty, kOwnedKey, NULL);
68 } // namespace
70 DECLARE_WINDOW_PROPERTY_TYPE(TestProperty*);
72 namespace aura {
73 namespace test {
75 class WindowTest : public AuraTestBase {
76 public:
77 WindowTest() : max_separation_(0) {
80 void SetUp() override {
81 AuraTestBase::SetUp();
82 // TODO: there needs to be an easier way to do this.
83 max_separation_ = ui::GestureConfiguration::GetInstance()
84 ->max_separation_for_gesture_touches_in_pixels();
85 ui::GestureConfiguration::GetInstance()
86 ->set_max_separation_for_gesture_touches_in_pixels(0);
89 void TearDown() override {
90 AuraTestBase::TearDown();
91 ui::GestureConfiguration::GetInstance()
92 ->set_max_separation_for_gesture_touches_in_pixels(max_separation_);
95 private:
96 float max_separation_;
98 DISALLOW_COPY_AND_ASSIGN(WindowTest);
101 namespace {
103 // Used for verifying destruction methods are invoked.
104 class DestroyTrackingDelegateImpl : public TestWindowDelegate {
105 public:
106 DestroyTrackingDelegateImpl()
107 : destroying_count_(0),
108 destroyed_count_(0),
109 in_destroying_(false) {}
111 void clear_destroying_count() { destroying_count_ = 0; }
112 int destroying_count() const { return destroying_count_; }
114 void clear_destroyed_count() { destroyed_count_ = 0; }
115 int destroyed_count() const { return destroyed_count_; }
117 bool in_destroying() const { return in_destroying_; }
119 void OnWindowDestroying(Window* window) override {
120 EXPECT_FALSE(in_destroying_);
121 in_destroying_ = true;
122 destroying_count_++;
125 void OnWindowDestroyed(Window* window) override {
126 EXPECT_TRUE(in_destroying_);
127 in_destroying_ = false;
128 destroyed_count_++;
131 private:
132 int destroying_count_;
133 int destroyed_count_;
134 bool in_destroying_;
136 DISALLOW_COPY_AND_ASSIGN(DestroyTrackingDelegateImpl);
139 // Used to verify that when OnWindowDestroying is invoked the parent is also
140 // is in the process of being destroyed.
141 class ChildWindowDelegateImpl : public DestroyTrackingDelegateImpl {
142 public:
143 explicit ChildWindowDelegateImpl(
144 DestroyTrackingDelegateImpl* parent_delegate)
145 : parent_delegate_(parent_delegate) {
148 void OnWindowDestroying(Window* window) override {
149 EXPECT_TRUE(parent_delegate_->in_destroying());
150 DestroyTrackingDelegateImpl::OnWindowDestroying(window);
153 private:
154 DestroyTrackingDelegateImpl* parent_delegate_;
156 DISALLOW_COPY_AND_ASSIGN(ChildWindowDelegateImpl);
159 // Used to verify that a Window is removed from its parent when
160 // OnWindowDestroyed is called.
161 class DestroyOrphanDelegate : public TestWindowDelegate {
162 public:
163 DestroyOrphanDelegate() : window_(NULL) {
166 void set_window(Window* window) { window_ = window; }
168 void OnWindowDestroyed(Window* window) override {
169 EXPECT_FALSE(window_->parent());
172 private:
173 Window* window_;
174 DISALLOW_COPY_AND_ASSIGN(DestroyOrphanDelegate);
177 // Used in verifying mouse capture.
178 class CaptureWindowDelegateImpl : public TestWindowDelegate {
179 public:
180 CaptureWindowDelegateImpl() {
181 ResetCounts();
184 void ResetCounts() {
185 capture_changed_event_count_ = 0;
186 capture_lost_count_ = 0;
187 mouse_event_count_ = 0;
188 touch_event_count_ = 0;
189 gesture_event_count_ = 0;
192 int capture_changed_event_count() const {
193 return capture_changed_event_count_;
195 int capture_lost_count() const { return capture_lost_count_; }
196 int mouse_event_count() const { return mouse_event_count_; }
197 int touch_event_count() const { return touch_event_count_; }
198 int gesture_event_count() const { return gesture_event_count_; }
200 void OnMouseEvent(ui::MouseEvent* event) override {
201 if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
202 capture_changed_event_count_++;
203 mouse_event_count_++;
205 void OnTouchEvent(ui::TouchEvent* event) override { touch_event_count_++; }
206 void OnGestureEvent(ui::GestureEvent* event) override {
207 gesture_event_count_++;
209 void OnCaptureLost() override { capture_lost_count_++; }
211 private:
212 int capture_changed_event_count_;
213 int capture_lost_count_;
214 int mouse_event_count_;
215 int touch_event_count_;
216 int gesture_event_count_;
218 DISALLOW_COPY_AND_ASSIGN(CaptureWindowDelegateImpl);
221 // Keeps track of the location of the gesture.
222 class GestureTrackPositionDelegate : public TestWindowDelegate {
223 public:
224 GestureTrackPositionDelegate() {}
226 void OnGestureEvent(ui::GestureEvent* event) override {
227 position_ = event->location();
228 event->StopPropagation();
231 const gfx::Point& position() const { return position_; }
233 private:
234 gfx::Point position_;
236 DISALLOW_COPY_AND_ASSIGN(GestureTrackPositionDelegate);
239 base::TimeDelta getTime() {
240 return ui::EventTimeForNow();
243 class SelfEventHandlingWindowDelegate : public TestWindowDelegate {
244 public:
245 SelfEventHandlingWindowDelegate() {}
247 bool ShouldDescendIntoChildForEventHandling(
248 Window* child,
249 const gfx::Point& location) override {
250 return false;
253 private:
254 DISALLOW_COPY_AND_ASSIGN(SelfEventHandlingWindowDelegate);
257 // The delegate deletes itself when the window is being destroyed.
258 class DestroyWindowDelegate : public TestWindowDelegate {
259 public:
260 DestroyWindowDelegate() {}
262 private:
263 ~DestroyWindowDelegate() override {}
265 // Overridden from WindowDelegate.
266 void OnWindowDestroyed(Window* window) override { delete this; }
268 DISALLOW_COPY_AND_ASSIGN(DestroyWindowDelegate);
271 void OffsetBounds(Window* window, int horizontal, int vertical) {
272 gfx::Rect bounds = window->bounds();
273 bounds.Offset(horizontal, vertical);
274 window->SetBounds(bounds);
277 } // namespace
279 TEST_F(WindowTest, GetChildById) {
280 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
281 scoped_ptr<Window> w11(CreateTestWindowWithId(11, w1.get()));
282 scoped_ptr<Window> w111(CreateTestWindowWithId(111, w11.get()));
283 scoped_ptr<Window> w12(CreateTestWindowWithId(12, w1.get()));
285 EXPECT_EQ(NULL, w1->GetChildById(57));
286 EXPECT_EQ(w12.get(), w1->GetChildById(12));
287 EXPECT_EQ(w111.get(), w1->GetChildById(111));
290 // Make sure that Window::Contains correctly handles children, grandchildren,
291 // and not containing NULL or parents.
292 TEST_F(WindowTest, Contains) {
293 Window parent(NULL);
294 parent.Init(ui::LAYER_NOT_DRAWN);
295 Window child1(NULL);
296 child1.Init(ui::LAYER_NOT_DRAWN);
297 Window child2(NULL);
298 child2.Init(ui::LAYER_NOT_DRAWN);
300 parent.AddChild(&child1);
301 child1.AddChild(&child2);
303 EXPECT_TRUE(parent.Contains(&parent));
304 EXPECT_TRUE(parent.Contains(&child1));
305 EXPECT_TRUE(parent.Contains(&child2));
307 EXPECT_FALSE(parent.Contains(NULL));
308 EXPECT_FALSE(child1.Contains(&parent));
309 EXPECT_FALSE(child2.Contains(&child1));
312 TEST_F(WindowTest, ContainsPointInRoot) {
313 scoped_ptr<Window> w(
314 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 5, 5),
315 root_window()));
316 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(9, 9)));
317 EXPECT_TRUE(w->ContainsPointInRoot(gfx::Point(10, 10)));
318 EXPECT_TRUE(w->ContainsPointInRoot(gfx::Point(14, 14)));
319 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(15, 15)));
320 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(20, 20)));
323 TEST_F(WindowTest, ContainsPoint) {
324 scoped_ptr<Window> w(
325 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 5, 5),
326 root_window()));
327 EXPECT_TRUE(w->ContainsPoint(gfx::Point(0, 0)));
328 EXPECT_TRUE(w->ContainsPoint(gfx::Point(4, 4)));
329 EXPECT_FALSE(w->ContainsPoint(gfx::Point(5, 5)));
330 EXPECT_FALSE(w->ContainsPoint(gfx::Point(10, 10)));
333 TEST_F(WindowTest, ConvertPointToWindow) {
334 // Window::ConvertPointToWindow is mostly identical to
335 // Layer::ConvertPointToLayer, except NULL values for |source| are permitted,
336 // in which case the function just returns.
337 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
338 gfx::Point reference_point(100, 100);
339 gfx::Point test_point = reference_point;
340 Window::ConvertPointToTarget(NULL, w1.get(), &test_point);
341 EXPECT_EQ(reference_point, test_point);
344 TEST_F(WindowTest, MoveCursorTo) {
345 scoped_ptr<Window> w1(
346 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
347 root_window()));
348 scoped_ptr<Window> w11(
349 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
350 scoped_ptr<Window> w111(
351 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
352 scoped_ptr<Window> w1111(
353 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
355 Window* root = root_window();
356 root->MoveCursorTo(gfx::Point(10, 10));
357 EXPECT_EQ("10,10",
358 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
359 w1->MoveCursorTo(gfx::Point(10, 10));
360 EXPECT_EQ("20,20",
361 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
362 w11->MoveCursorTo(gfx::Point(10, 10));
363 EXPECT_EQ("25,25",
364 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
365 w111->MoveCursorTo(gfx::Point(10, 10));
366 EXPECT_EQ("30,30",
367 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
368 w1111->MoveCursorTo(gfx::Point(10, 10));
369 EXPECT_EQ("35,35",
370 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
373 TEST_F(WindowTest, ContainsMouse) {
374 scoped_ptr<Window> w(
375 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
376 root_window()));
377 w->Show();
378 WindowTestApi w_test_api(w.get());
379 Window* root = root_window();
380 root->MoveCursorTo(gfx::Point(10, 10));
381 EXPECT_TRUE(w_test_api.ContainsMouse());
382 root->MoveCursorTo(gfx::Point(9, 10));
383 EXPECT_FALSE(w_test_api.ContainsMouse());
386 // Test Window::ConvertPointToWindow() with transform to root_window.
387 TEST_F(WindowTest, MoveCursorToWithTransformRootWindow) {
388 gfx::Transform transform;
389 transform.Translate(100.0, 100.0);
390 transform.Rotate(90.0);
391 transform.Scale(2.0, 5.0);
392 host()->SetRootTransform(transform);
393 host()->MoveCursorTo(gfx::Point(10, 10));
394 #if !defined(OS_WIN)
395 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.OD
396 EXPECT_EQ("50,120", QueryLatestMousePositionRequestInHost(host()).ToString());
397 #endif
398 EXPECT_EQ("10,10", gfx::Screen::GetScreenFor(
399 root_window())->GetCursorScreenPoint().ToString());
402 // Tests Window::ConvertPointToWindow() with transform to non-root windows.
403 TEST_F(WindowTest, MoveCursorToWithTransformWindow) {
404 scoped_ptr<Window> w1(
405 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
406 root_window()));
408 gfx::Transform transform1;
409 transform1.Scale(2, 2);
410 w1->SetTransform(transform1);
411 w1->MoveCursorTo(gfx::Point(10, 10));
412 EXPECT_EQ("30,30",
413 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
415 gfx::Transform transform2;
416 transform2.Translate(-10, 20);
417 w1->SetTransform(transform2);
418 w1->MoveCursorTo(gfx::Point(10, 10));
419 EXPECT_EQ("10,40",
420 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
422 gfx::Transform transform3;
423 transform3.Rotate(90.0);
424 w1->SetTransform(transform3);
425 w1->MoveCursorTo(gfx::Point(5, 5));
426 EXPECT_EQ("5,15",
427 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
429 gfx::Transform transform4;
430 transform4.Translate(100.0, 100.0);
431 transform4.Rotate(90.0);
432 transform4.Scale(2.0, 5.0);
433 w1->SetTransform(transform4);
434 w1->MoveCursorTo(gfx::Point(10, 10));
435 EXPECT_EQ("60,130",
436 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
439 // Test Window::ConvertPointToWindow() with complex transforms to both root and
440 // non-root windows.
441 // Test Window::ConvertPointToWindow() with transform to root_window.
442 TEST_F(WindowTest, MoveCursorToWithComplexTransform) {
443 scoped_ptr<Window> w1(
444 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
445 root_window()));
446 scoped_ptr<Window> w11(
447 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
448 scoped_ptr<Window> w111(
449 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
450 scoped_ptr<Window> w1111(
451 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
453 Window* root = root_window();
455 // The root window expects transforms that produce integer rects.
456 gfx::Transform root_transform;
457 root_transform.Translate(60.0, 70.0);
458 root_transform.Rotate(-90.0);
459 root_transform.Translate(-50.0, -50.0);
460 root_transform.Scale(2.0, 3.0);
462 gfx::Transform transform;
463 transform.Translate(10.0, 20.0);
464 transform.Rotate(10.0);
465 transform.Scale(0.3f, 0.5f);
466 host()->SetRootTransform(root_transform);
467 w1->SetTransform(transform);
468 w11->SetTransform(transform);
469 w111->SetTransform(transform);
470 w1111->SetTransform(transform);
472 w1111->MoveCursorTo(gfx::Point(10, 10));
474 #if !defined(OS_WIN)
475 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.
476 EXPECT_EQ("169,80", QueryLatestMousePositionRequestInHost(host()).ToString());
477 #endif
478 EXPECT_EQ("20,53",
479 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
482 // Tests that we do not crash when a Window is destroyed by going out of
483 // scope (as opposed to being explicitly deleted by its WindowDelegate).
484 TEST_F(WindowTest, NoCrashOnWindowDelete) {
485 CaptureWindowDelegateImpl delegate;
486 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
487 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
490 TEST_F(WindowTest, GetEventHandlerForPoint) {
491 scoped_ptr<Window> w1(
492 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
493 root_window()));
494 scoped_ptr<Window> w11(
495 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
496 scoped_ptr<Window> w111(
497 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
498 scoped_ptr<Window> w1111(
499 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
500 scoped_ptr<Window> w12(
501 CreateTestWindow(SK_ColorMAGENTA, 12, gfx::Rect(10, 420, 25, 25),
502 w1.get()));
503 scoped_ptr<Window> w121(
504 CreateTestWindow(SK_ColorYELLOW, 121, gfx::Rect(5, 5, 5, 5), w12.get()));
505 scoped_ptr<Window> w13(
506 CreateTestWindow(SK_ColorGRAY, 13, gfx::Rect(5, 470, 50, 50), w1.get()));
508 Window* root = root_window();
509 w1->parent()->SetBounds(gfx::Rect(500, 500));
510 EXPECT_EQ(NULL, root->GetEventHandlerForPoint(gfx::Point(5, 5)));
511 EXPECT_EQ(w1.get(), root->GetEventHandlerForPoint(gfx::Point(11, 11)));
512 EXPECT_EQ(w11.get(), root->GetEventHandlerForPoint(gfx::Point(16, 16)));
513 EXPECT_EQ(w111.get(), root->GetEventHandlerForPoint(gfx::Point(21, 21)));
514 EXPECT_EQ(w1111.get(), root->GetEventHandlerForPoint(gfx::Point(26, 26)));
515 EXPECT_EQ(w12.get(), root->GetEventHandlerForPoint(gfx::Point(21, 431)));
516 EXPECT_EQ(w121.get(), root->GetEventHandlerForPoint(gfx::Point(26, 436)));
517 EXPECT_EQ(w13.get(), root->GetEventHandlerForPoint(gfx::Point(26, 481)));
520 TEST_F(WindowTest, GetEventHandlerForPointWithOverride) {
521 // If our child is flush to our top-left corner he gets events just inside the
522 // window edges.
523 scoped_ptr<Window> parent(
524 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 20, 400, 500),
525 root_window()));
526 scoped_ptr<Window> child(
527 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(0, 0, 60, 70), parent.get()));
528 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
529 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(1, 1)));
531 // We can override the hit test bounds of the parent to make the parent grab
532 // events along that edge.
533 parent->set_hit_test_bounds_override_inner(gfx::Insets(1, 1, 1, 1));
534 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
535 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(1, 1)));
538 TEST_F(WindowTest, GetEventHandlerForPointWithOverrideDescendingOrder) {
539 scoped_ptr<SelfEventHandlingWindowDelegate> parent_delegate(
540 new SelfEventHandlingWindowDelegate);
541 scoped_ptr<Window> parent(CreateTestWindowWithDelegate(
542 parent_delegate.get(), 1, gfx::Rect(10, 20, 400, 500), root_window()));
543 scoped_ptr<Window> child(
544 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(0, 0, 390, 480),
545 parent.get()));
547 // We can override ShouldDescendIntoChildForEventHandling to make the parent
548 // grab all events.
549 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
550 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(50, 50)));
553 TEST_F(WindowTest, GetTopWindowContainingPoint) {
554 Window* root = root_window();
555 root->SetBounds(gfx::Rect(0, 0, 300, 300));
557 scoped_ptr<Window> w1(
558 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 100, 100),
559 root_window()));
560 scoped_ptr<Window> w11(
561 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(0, 0, 120, 120), w1.get()));
563 scoped_ptr<Window> w2(
564 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(5, 5, 55, 55),
565 root_window()));
567 scoped_ptr<Window> w3(
568 CreateTestWindowWithDelegate(
569 NULL, 3, gfx::Rect(200, 200, 100, 100), root_window()));
570 scoped_ptr<Window> w31(
571 CreateTestWindow(SK_ColorCYAN, 31, gfx::Rect(0, 0, 50, 50), w3.get()));
572 scoped_ptr<Window> w311(
573 CreateTestWindow(SK_ColorBLUE, 311, gfx::Rect(0, 0, 10, 10), w31.get()));
575 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(0, 0)));
576 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(5, 5)));
577 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(10, 10)));
578 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(59, 59)));
579 EXPECT_EQ(w1.get(), root->GetTopWindowContainingPoint(gfx::Point(60, 60)));
580 EXPECT_EQ(w1.get(), root->GetTopWindowContainingPoint(gfx::Point(109, 109)));
581 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(110, 110)));
582 EXPECT_EQ(w31.get(), root->GetTopWindowContainingPoint(gfx::Point(200, 200)));
583 EXPECT_EQ(w31.get(), root->GetTopWindowContainingPoint(gfx::Point(220, 220)));
584 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(260, 260)));
587 TEST_F(WindowTest, GetToplevelWindow) {
588 const gfx::Rect kBounds(0, 0, 10, 10);
589 TestWindowDelegate delegate;
591 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
592 scoped_ptr<Window> w11(
593 CreateTestWindowWithDelegate(&delegate, 11, kBounds, w1.get()));
594 scoped_ptr<Window> w111(CreateTestWindowWithId(111, w11.get()));
595 scoped_ptr<Window> w1111(
596 CreateTestWindowWithDelegate(&delegate, 1111, kBounds, w111.get()));
598 EXPECT_TRUE(root_window()->GetToplevelWindow() == NULL);
599 EXPECT_TRUE(w1->GetToplevelWindow() == NULL);
600 EXPECT_EQ(w11.get(), w11->GetToplevelWindow());
601 EXPECT_EQ(w11.get(), w111->GetToplevelWindow());
602 EXPECT_EQ(w11.get(), w1111->GetToplevelWindow());
605 class AddedToRootWindowObserver : public WindowObserver {
606 public:
607 AddedToRootWindowObserver() : called_(false) {}
609 void OnWindowAddedToRootWindow(Window* window) override { called_ = true; }
611 bool called() const { return called_; }
613 private:
614 bool called_;
616 DISALLOW_COPY_AND_ASSIGN(AddedToRootWindowObserver);
619 TEST_F(WindowTest, WindowAddedToRootWindowShouldNotifyChildAndNotParent) {
620 AddedToRootWindowObserver parent_observer;
621 AddedToRootWindowObserver child_observer;
622 scoped_ptr<Window> parent_window(CreateTestWindowWithId(1, root_window()));
623 scoped_ptr<Window> child_window(new Window(NULL));
624 child_window->Init(ui::LAYER_TEXTURED);
625 child_window->Show();
627 parent_window->AddObserver(&parent_observer);
628 child_window->AddObserver(&child_observer);
630 parent_window->AddChild(child_window.get());
632 EXPECT_FALSE(parent_observer.called());
633 EXPECT_TRUE(child_observer.called());
635 parent_window->RemoveObserver(&parent_observer);
636 child_window->RemoveObserver(&child_observer);
639 // Various destruction assertions.
640 TEST_F(WindowTest, DestroyTest) {
641 DestroyTrackingDelegateImpl parent_delegate;
642 ChildWindowDelegateImpl child_delegate(&parent_delegate);
644 scoped_ptr<Window> parent(
645 CreateTestWindowWithDelegate(&parent_delegate, 0, gfx::Rect(),
646 root_window()));
647 CreateTestWindowWithDelegate(&child_delegate, 0, gfx::Rect(), parent.get());
649 // Both the parent and child should have been destroyed.
650 EXPECT_EQ(1, parent_delegate.destroying_count());
651 EXPECT_EQ(1, parent_delegate.destroyed_count());
652 EXPECT_EQ(1, child_delegate.destroying_count());
653 EXPECT_EQ(1, child_delegate.destroyed_count());
656 // Tests that a window is orphaned before OnWindowDestroyed is called.
657 TEST_F(WindowTest, OrphanedBeforeOnDestroyed) {
658 TestWindowDelegate parent_delegate;
659 DestroyOrphanDelegate child_delegate;
661 scoped_ptr<Window> parent(
662 CreateTestWindowWithDelegate(&parent_delegate, 0, gfx::Rect(),
663 root_window()));
664 scoped_ptr<Window> child(CreateTestWindowWithDelegate(&child_delegate, 0,
665 gfx::Rect(), parent.get()));
666 child_delegate.set_window(child.get());
670 // Make sure StackChildAtTop moves both the window and layer to the front.
671 TEST_F(WindowTest, StackChildAtTop) {
672 Window parent(NULL);
673 parent.Init(ui::LAYER_NOT_DRAWN);
674 Window child1(NULL);
675 child1.Init(ui::LAYER_NOT_DRAWN);
676 Window child2(NULL);
677 child2.Init(ui::LAYER_NOT_DRAWN);
679 parent.AddChild(&child1);
680 parent.AddChild(&child2);
681 ASSERT_EQ(2u, parent.children().size());
682 EXPECT_EQ(&child1, parent.children()[0]);
683 EXPECT_EQ(&child2, parent.children()[1]);
684 ASSERT_EQ(2u, parent.layer()->children().size());
685 EXPECT_EQ(child1.layer(), parent.layer()->children()[0]);
686 EXPECT_EQ(child2.layer(), parent.layer()->children()[1]);
688 parent.StackChildAtTop(&child1);
689 ASSERT_EQ(2u, parent.children().size());
690 EXPECT_EQ(&child1, parent.children()[1]);
691 EXPECT_EQ(&child2, parent.children()[0]);
692 ASSERT_EQ(2u, parent.layer()->children().size());
693 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
694 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
697 // Make sure StackChildBelow works.
698 TEST_F(WindowTest, StackChildBelow) {
699 Window parent(NULL);
700 parent.Init(ui::LAYER_NOT_DRAWN);
701 Window child1(NULL);
702 child1.Init(ui::LAYER_NOT_DRAWN);
703 child1.set_id(1);
704 Window child2(NULL);
705 child2.Init(ui::LAYER_NOT_DRAWN);
706 child2.set_id(2);
707 Window child3(NULL);
708 child3.Init(ui::LAYER_NOT_DRAWN);
709 child3.set_id(3);
711 parent.AddChild(&child1);
712 parent.AddChild(&child2);
713 parent.AddChild(&child3);
714 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent));
716 parent.StackChildBelow(&child1, &child2);
717 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent));
719 parent.StackChildBelow(&child2, &child1);
720 EXPECT_EQ("2 1 3", ChildWindowIDsAsString(&parent));
722 parent.StackChildBelow(&child3, &child2);
723 EXPECT_EQ("3 2 1", ChildWindowIDsAsString(&parent));
725 parent.StackChildBelow(&child3, &child1);
726 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(&parent));
729 // Various assertions for StackChildAbove.
730 TEST_F(WindowTest, StackChildAbove) {
731 Window parent(NULL);
732 parent.Init(ui::LAYER_NOT_DRAWN);
733 Window child1(NULL);
734 child1.Init(ui::LAYER_NOT_DRAWN);
735 Window child2(NULL);
736 child2.Init(ui::LAYER_NOT_DRAWN);
737 Window child3(NULL);
738 child3.Init(ui::LAYER_NOT_DRAWN);
740 parent.AddChild(&child1);
741 parent.AddChild(&child2);
743 // Move 1 in front of 2.
744 parent.StackChildAbove(&child1, &child2);
745 ASSERT_EQ(2u, parent.children().size());
746 EXPECT_EQ(&child2, parent.children()[0]);
747 EXPECT_EQ(&child1, parent.children()[1]);
748 ASSERT_EQ(2u, parent.layer()->children().size());
749 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
750 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
752 // Add 3, resulting in order [2, 1, 3], then move 2 in front of 1, resulting
753 // in [1, 2, 3].
754 parent.AddChild(&child3);
755 parent.StackChildAbove(&child2, &child1);
756 ASSERT_EQ(3u, parent.children().size());
757 EXPECT_EQ(&child1, parent.children()[0]);
758 EXPECT_EQ(&child2, parent.children()[1]);
759 EXPECT_EQ(&child3, parent.children()[2]);
760 ASSERT_EQ(3u, parent.layer()->children().size());
761 EXPECT_EQ(child1.layer(), parent.layer()->children()[0]);
762 EXPECT_EQ(child2.layer(), parent.layer()->children()[1]);
763 EXPECT_EQ(child3.layer(), parent.layer()->children()[2]);
765 // Move 1 in front of 3, resulting in [2, 3, 1].
766 parent.StackChildAbove(&child1, &child3);
767 ASSERT_EQ(3u, parent.children().size());
768 EXPECT_EQ(&child2, parent.children()[0]);
769 EXPECT_EQ(&child3, parent.children()[1]);
770 EXPECT_EQ(&child1, parent.children()[2]);
771 ASSERT_EQ(3u, parent.layer()->children().size());
772 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
773 EXPECT_EQ(child3.layer(), parent.layer()->children()[1]);
774 EXPECT_EQ(child1.layer(), parent.layer()->children()[2]);
776 // Moving 1 in front of 2 should lower it, resulting in [2, 1, 3].
777 parent.StackChildAbove(&child1, &child2);
778 ASSERT_EQ(3u, parent.children().size());
779 EXPECT_EQ(&child2, parent.children()[0]);
780 EXPECT_EQ(&child1, parent.children()[1]);
781 EXPECT_EQ(&child3, parent.children()[2]);
782 ASSERT_EQ(3u, parent.layer()->children().size());
783 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
784 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
785 EXPECT_EQ(child3.layer(), parent.layer()->children()[2]);
788 // Various capture assertions.
789 TEST_F(WindowTest, CaptureTests) {
790 CaptureWindowDelegateImpl delegate;
791 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
792 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
793 EXPECT_FALSE(window->HasCapture());
795 delegate.ResetCounts();
797 // Do a capture.
798 window->SetCapture();
799 EXPECT_TRUE(window->HasCapture());
800 EXPECT_EQ(0, delegate.capture_lost_count());
801 EXPECT_EQ(0, delegate.capture_changed_event_count());
802 ui::test::EventGenerator generator(root_window(), gfx::Point(50, 50));
803 generator.PressLeftButton();
804 EXPECT_EQ(1, delegate.mouse_event_count());
805 generator.ReleaseLeftButton();
807 EXPECT_EQ(2, delegate.mouse_event_count());
808 delegate.ResetCounts();
810 ui::TouchEvent touchev(
811 ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), 0, getTime());
812 DispatchEventUsingWindowDispatcher(&touchev);
813 EXPECT_EQ(1, delegate.touch_event_count());
814 delegate.ResetCounts();
816 window->ReleaseCapture();
817 EXPECT_FALSE(window->HasCapture());
818 EXPECT_EQ(1, delegate.capture_lost_count());
819 EXPECT_EQ(1, delegate.capture_changed_event_count());
820 EXPECT_EQ(1, delegate.mouse_event_count());
821 EXPECT_EQ(0, delegate.touch_event_count());
823 generator.PressLeftButton();
824 EXPECT_EQ(1, delegate.mouse_event_count());
826 ui::TouchEvent touchev2(
827 ui::ET_TOUCH_PRESSED, gfx::Point(250, 250), 1, getTime());
828 DispatchEventUsingWindowDispatcher(&touchev2);
829 EXPECT_EQ(0, delegate.touch_event_count());
831 // Removing the capture window from parent should reset the capture window
832 // in the root window.
833 window->SetCapture();
834 EXPECT_EQ(window.get(), aura::client::GetCaptureWindow(root_window()));
835 window->parent()->RemoveChild(window.get());
836 EXPECT_FALSE(window->HasCapture());
837 EXPECT_EQ(NULL, aura::client::GetCaptureWindow(root_window()));
840 TEST_F(WindowTest, TouchCaptureCancelsOtherTouches) {
841 CaptureWindowDelegateImpl delegate1;
842 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
843 &delegate1, 0, gfx::Rect(0, 0, 50, 50), root_window()));
844 CaptureWindowDelegateImpl delegate2;
845 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
846 &delegate2, 0, gfx::Rect(50, 50, 50, 50), root_window()));
848 // Press on w1.
849 ui::TouchEvent press1(
850 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
851 DispatchEventUsingWindowDispatcher(&press1);
852 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
853 EXPECT_EQ(2, delegate1.gesture_event_count());
854 delegate1.ResetCounts();
856 // Capturing to w2 should cause the touch to be canceled.
857 w2->SetCapture();
858 EXPECT_EQ(1, delegate1.touch_event_count());
859 EXPECT_EQ(0, delegate2.touch_event_count());
860 delegate1.ResetCounts();
861 delegate2.ResetCounts();
863 // Events are now untargetted.
864 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, getTime());
865 DispatchEventUsingWindowDispatcher(&move);
866 EXPECT_EQ(0, delegate1.gesture_event_count());
867 EXPECT_EQ(0, delegate1.touch_event_count());
868 EXPECT_EQ(0, delegate2.gesture_event_count());
869 EXPECT_EQ(0, delegate2.touch_event_count());
871 ui::TouchEvent release(
872 ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, getTime());
873 DispatchEventUsingWindowDispatcher(&release);
874 EXPECT_EQ(0, delegate1.gesture_event_count());
875 EXPECT_EQ(0, delegate2.gesture_event_count());
877 // A new press is captured by w2.
878 ui::TouchEvent press2(
879 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
880 DispatchEventUsingWindowDispatcher(&press2);
881 EXPECT_EQ(0, delegate1.gesture_event_count());
882 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
883 EXPECT_EQ(2, delegate2.gesture_event_count());
884 delegate1.ResetCounts();
885 delegate2.ResetCounts();
887 // And releasing capture changes nothing.
888 w2->ReleaseCapture();
889 EXPECT_EQ(0, delegate1.gesture_event_count());
890 EXPECT_EQ(0, delegate1.touch_event_count());
891 EXPECT_EQ(0, delegate2.gesture_event_count());
892 EXPECT_EQ(0, delegate2.touch_event_count());
895 TEST_F(WindowTest, TouchCaptureDoesntCancelCapturedTouches) {
896 CaptureWindowDelegateImpl delegate;
897 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
898 &delegate, 0, gfx::Rect(0, 0, 50, 50), root_window()));
899 base::TimeDelta time = getTime();
900 const int kTimeDelta = 100;
902 ui::TouchEvent press(
903 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, time);
904 DispatchEventUsingWindowDispatcher(&press);
906 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
907 EXPECT_EQ(2, delegate.gesture_event_count());
908 EXPECT_EQ(1, delegate.touch_event_count());
909 delegate.ResetCounts();
911 window->SetCapture();
912 EXPECT_EQ(0, delegate.gesture_event_count());
913 EXPECT_EQ(0, delegate.touch_event_count());
914 delegate.ResetCounts();
916 // On move We will get TOUCH_MOVED, GESTURE_TAP_CANCEL,
917 // GESTURE_SCROLL_START and GESTURE_SCROLL_UPDATE.
918 time += base::TimeDelta::FromMilliseconds(kTimeDelta);
919 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, time);
920 DispatchEventUsingWindowDispatcher(&move);
921 EXPECT_EQ(1, delegate.touch_event_count());
922 EXPECT_EQ(3, delegate.gesture_event_count());
923 delegate.ResetCounts();
925 // Release capture shouldn't change anything.
926 window->ReleaseCapture();
927 EXPECT_EQ(0, delegate.touch_event_count());
928 EXPECT_EQ(0, delegate.gesture_event_count());
929 delegate.ResetCounts();
931 // On move we still get TOUCH_MOVED and GESTURE_SCROLL_UPDATE.
932 time += base::TimeDelta::FromMilliseconds(kTimeDelta);
933 ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(10, 30), 0, time);
934 DispatchEventUsingWindowDispatcher(&move2);
935 EXPECT_EQ(1, delegate.touch_event_count());
936 EXPECT_EQ(1, delegate.gesture_event_count());
937 delegate.ResetCounts();
939 // And on release we get TOUCH_RELEASED, GESTURE_SCROLL_END, GESTURE_END
940 time += base::TimeDelta::FromMilliseconds(kTimeDelta);
941 ui::TouchEvent release(
942 ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, time);
943 DispatchEventUsingWindowDispatcher(&release);
944 EXPECT_EQ(1, delegate.touch_event_count());
945 EXPECT_EQ(2, delegate.gesture_event_count());
949 // Assertions around SetCapture() and touch/gestures.
950 TEST_F(WindowTest, TransferCaptureTouchEvents) {
951 // Touch on |w1|.
952 CaptureWindowDelegateImpl d1;
953 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
954 &d1, 0, gfx::Rect(0, 0, 20, 20), root_window()));
955 ui::TouchEvent p1(ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
956 DispatchEventUsingWindowDispatcher(&p1);
957 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
958 EXPECT_EQ(1, d1.touch_event_count());
959 EXPECT_EQ(2, d1.gesture_event_count());
960 d1.ResetCounts();
962 // Touch on |w2| with a different id.
963 CaptureWindowDelegateImpl d2;
964 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
965 &d2, 0, gfx::Rect(40, 0, 40, 20), root_window()));
966 ui::TouchEvent p2(ui::ET_TOUCH_PRESSED, gfx::Point(41, 10), 1, getTime());
967 DispatchEventUsingWindowDispatcher(&p2);
968 EXPECT_EQ(0, d1.touch_event_count());
969 EXPECT_EQ(0, d1.gesture_event_count());
970 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN for new target window.
971 EXPECT_EQ(1, d2.touch_event_count());
972 EXPECT_EQ(2, d2.gesture_event_count());
973 d1.ResetCounts();
974 d2.ResetCounts();
976 // Set capture on |w2|, this should send a cancel (TAP_CANCEL, END) to |w1|
977 // but not |w2|.
978 w2->SetCapture();
979 EXPECT_EQ(1, d1.touch_event_count());
980 EXPECT_EQ(2, d1.gesture_event_count());
981 EXPECT_EQ(0, d2.touch_event_count());
982 EXPECT_EQ(0, d2.gesture_event_count());
983 d1.ResetCounts();
984 d2.ResetCounts();
986 CaptureWindowDelegateImpl d3;
987 scoped_ptr<Window> w3(CreateTestWindowWithDelegate(
988 &d3, 0, gfx::Rect(0, 0, 100, 101), root_window()));
989 // Set capture on |w3|. All touches have already been cancelled.
990 w3->SetCapture();
991 EXPECT_EQ(0, d1.touch_event_count());
992 EXPECT_EQ(0, d1.gesture_event_count());
993 EXPECT_EQ(1, d2.touch_event_count());
994 EXPECT_EQ(2, d2.gesture_event_count());
995 EXPECT_EQ(0, d3.touch_event_count());
996 EXPECT_EQ(0, d3.gesture_event_count());
997 d2.ResetCounts();
999 // Move touch id originally associated with |w2|. The touch has been
1000 // cancelled, so no events should be dispatched.
1001 ui::TouchEvent m3(ui::ET_TOUCH_MOVED, gfx::Point(110, 105), 1, getTime());
1002 DispatchEventUsingWindowDispatcher(&m3);
1003 EXPECT_EQ(0, d1.touch_event_count());
1004 EXPECT_EQ(0, d1.gesture_event_count());
1005 EXPECT_EQ(0, d2.touch_event_count());
1006 EXPECT_EQ(0, d2.gesture_event_count());
1007 EXPECT_EQ(0, d3.touch_event_count());
1008 EXPECT_EQ(0, d3.gesture_event_count());
1010 // When we release capture, no touches are canceled.
1011 w3->ReleaseCapture();
1012 EXPECT_EQ(0, d1.touch_event_count());
1013 EXPECT_EQ(0, d1.gesture_event_count());
1014 EXPECT_EQ(0, d2.touch_event_count());
1015 EXPECT_EQ(0, d2.gesture_event_count());
1016 EXPECT_EQ(0, d3.touch_event_count());
1017 EXPECT_EQ(0, d3.gesture_event_count());
1019 // The touch has been cancelled, so no events are dispatched.
1020 ui::TouchEvent m4(ui::ET_TOUCH_MOVED, gfx::Point(120, 105), 1, getTime());
1021 DispatchEventUsingWindowDispatcher(&m4);
1022 EXPECT_EQ(0, d1.touch_event_count());
1023 EXPECT_EQ(0, d1.gesture_event_count());
1024 EXPECT_EQ(0, d2.touch_event_count());
1025 EXPECT_EQ(0, d2.gesture_event_count());
1026 EXPECT_EQ(0, d3.touch_event_count());
1027 EXPECT_EQ(0, d3.gesture_event_count());
1030 // Changes capture while capture is already ongoing.
1031 TEST_F(WindowTest, ChangeCaptureWhileMouseDown) {
1032 CaptureWindowDelegateImpl delegate;
1033 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
1034 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1035 CaptureWindowDelegateImpl delegate2;
1036 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
1037 &delegate2, 0, gfx::Rect(20, 20, 20, 20), root_window()));
1039 // Execute the scheduled draws so that mouse events are not
1040 // aggregated.
1041 RunAllPendingInMessageLoop();
1043 EXPECT_FALSE(window->HasCapture());
1045 // Do a capture.
1046 delegate.ResetCounts();
1047 window->SetCapture();
1048 EXPECT_TRUE(window->HasCapture());
1049 EXPECT_EQ(0, delegate.capture_lost_count());
1050 EXPECT_EQ(0, delegate.capture_changed_event_count());
1051 ui::test::EventGenerator generator(root_window(), gfx::Point(50, 50));
1052 generator.PressLeftButton();
1053 EXPECT_EQ(0, delegate.capture_lost_count());
1054 EXPECT_EQ(0, delegate.capture_changed_event_count());
1055 EXPECT_EQ(1, delegate.mouse_event_count());
1057 // Set capture to |w2|, should implicitly unset capture for |window|.
1058 delegate.ResetCounts();
1059 delegate2.ResetCounts();
1060 w2->SetCapture();
1062 generator.MoveMouseTo(gfx::Point(40, 40), 2);
1063 EXPECT_EQ(1, delegate.capture_lost_count());
1064 EXPECT_EQ(1, delegate.capture_changed_event_count());
1065 EXPECT_EQ(1, delegate.mouse_event_count());
1066 EXPECT_EQ(2, delegate2.mouse_event_count());
1069 // Verifies capture is reset when a window is destroyed.
1070 TEST_F(WindowTest, ReleaseCaptureOnDestroy) {
1071 CaptureWindowDelegateImpl delegate;
1072 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
1073 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1074 EXPECT_FALSE(window->HasCapture());
1076 // Do a capture.
1077 window->SetCapture();
1078 EXPECT_TRUE(window->HasCapture());
1080 // Destroy the window.
1081 window.reset();
1083 // Make sure the root window doesn't reference the window anymore.
1084 EXPECT_EQ(NULL, host()->dispatcher()->mouse_pressed_handler());
1085 EXPECT_EQ(NULL, aura::client::GetCaptureWindow(root_window()));
1088 TEST_F(WindowTest, GetBoundsInRootWindow) {
1089 scoped_ptr<Window> viewport(CreateTestWindowWithBounds(
1090 gfx::Rect(0, 0, 300, 300), root_window()));
1091 scoped_ptr<Window> child(CreateTestWindowWithBounds(
1092 gfx::Rect(0, 0, 100, 100), viewport.get()));
1093 // Sanity check.
1094 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1096 // The |child| window's screen bounds should move along with the |viewport|.
1097 viewport->SetBounds(gfx::Rect(-100, -100, 300, 300));
1098 EXPECT_EQ("-100,-100 100x100", child->GetBoundsInRootWindow().ToString());
1100 // The |child| window is moved to the 0,0 in screen coordinates.
1101 // |GetBoundsInRootWindow()| should return 0,0.
1102 child->SetBounds(gfx::Rect(100, 100, 100, 100));
1103 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1106 TEST_F(WindowTest, GetBoundsInRootWindowWithLayers) {
1107 scoped_ptr<Window> viewport(
1108 CreateTestWindowWithBounds(gfx::Rect(0, 0, 300, 300), root_window()));
1110 scoped_ptr<Window> widget(
1111 CreateTestWindowWithBounds(gfx::Rect(0, 0, 200, 200), viewport.get()));
1113 scoped_ptr<Window> child(
1114 CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), widget.get()));
1116 // Sanity check.
1117 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1119 // The |child| window's screen bounds should move along with the |viewport|.
1120 OffsetBounds(viewport.get(), -100, -100);
1121 EXPECT_EQ("-100,-100 100x100", child->GetBoundsInRootWindow().ToString());
1123 OffsetBounds(widget.get(), 50, 50);
1124 EXPECT_EQ("-50,-50 100x100", child->GetBoundsInRootWindow().ToString());
1126 // The |child| window is moved to the 0,0 in screen coordinates.
1127 // |GetBoundsInRootWindow()| should return 0,0.
1128 OffsetBounds(child.get(), 50, 50);
1129 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1132 TEST_F(WindowTest, GetBoundsInRootWindowWithLayersAndTranslations) {
1133 scoped_ptr<Window> viewport(
1134 CreateTestWindowWithBounds(gfx::Rect(0, 0, 300, 300), root_window()));
1136 scoped_ptr<Window> widget(
1137 CreateTestWindowWithBounds(gfx::Rect(0, 0, 200, 200), viewport.get()));
1139 scoped_ptr<Window> child(
1140 CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), widget.get()));
1142 // Sanity check.
1143 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1145 // The |child| window's screen bounds should move along with the |viewport|.
1146 viewport->SetBounds(gfx::Rect(-100, -100, 300, 300));
1147 EXPECT_EQ("-100,-100 100x100", child->GetBoundsInRootWindow().ToString());
1149 widget->SetBounds(gfx::Rect(50, 50, 200, 200));
1150 EXPECT_EQ("-50,-50 100x100", child->GetBoundsInRootWindow().ToString());
1152 // The |child| window is moved to the 0,0 in screen coordinates.
1153 // |GetBoundsInRootWindow()| should return 0,0.
1154 child->SetBounds(gfx::Rect(50, 50, 100, 100));
1155 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1157 gfx::Transform transform1;
1158 transform1.Translate(-10, 20);
1159 viewport->SetTransform(transform1);
1160 EXPECT_EQ("-10,20 100x100", child->GetBoundsInRootWindow().ToString());
1162 gfx::Transform transform2;
1163 transform2.Translate(40, 100);
1164 widget->SetTransform(transform2);
1165 EXPECT_EQ("30,120 100x100", child->GetBoundsInRootWindow().ToString());
1167 // Testing potentially buggy place
1168 gfx::Transform transform3;
1169 transform3.Translate(-30, -120);
1170 child->SetTransform(transform3);
1171 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1174 // TODO(tdanderson): Remove this class and use
1175 // test::EventCountDelegate in its place.
1176 class MouseEnterExitWindowDelegate : public TestWindowDelegate {
1177 public:
1178 MouseEnterExitWindowDelegate() : entered_(false), exited_(false) {}
1180 void OnMouseEvent(ui::MouseEvent* event) override {
1181 switch (event->type()) {
1182 case ui::ET_MOUSE_ENTERED:
1183 EXPECT_TRUE(event->flags() & ui::EF_IS_SYNTHESIZED);
1184 entered_ = true;
1185 break;
1186 case ui::ET_MOUSE_EXITED:
1187 EXPECT_TRUE(event->flags() & ui::EF_IS_SYNTHESIZED);
1188 exited_ = true;
1189 break;
1190 default:
1191 break;
1195 bool entered() const { return entered_; }
1196 bool exited() const { return exited_; }
1198 // Clear the entered / exited states.
1199 void ResetExpectations() {
1200 entered_ = false;
1201 exited_ = false;
1204 private:
1205 bool entered_;
1206 bool exited_;
1208 DISALLOW_COPY_AND_ASSIGN(MouseEnterExitWindowDelegate);
1211 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1212 // mouse transitions from window to window.
1213 TEST_F(WindowTest, MouseEnterExit) {
1214 MouseEnterExitWindowDelegate d1;
1215 scoped_ptr<Window> w1(
1216 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1217 root_window()));
1218 MouseEnterExitWindowDelegate d2;
1219 scoped_ptr<Window> w2(
1220 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50),
1221 root_window()));
1223 ui::test::EventGenerator generator(root_window());
1224 generator.MoveMouseToCenterOf(w1.get());
1225 EXPECT_TRUE(d1.entered());
1226 EXPECT_FALSE(d1.exited());
1227 EXPECT_FALSE(d2.entered());
1228 EXPECT_FALSE(d2.exited());
1230 generator.MoveMouseToCenterOf(w2.get());
1231 EXPECT_TRUE(d1.entered());
1232 EXPECT_TRUE(d1.exited());
1233 EXPECT_TRUE(d2.entered());
1234 EXPECT_FALSE(d2.exited());
1237 // Verifies that the WindowDelegate receives MouseExit from ET_MOUSE_EXITED.
1238 TEST_F(WindowTest, WindowTreeHostExit) {
1239 MouseEnterExitWindowDelegate d1;
1240 scoped_ptr<Window> w1(
1241 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1242 root_window()));
1244 ui::test::EventGenerator generator(root_window());
1245 generator.MoveMouseToCenterOf(w1.get());
1246 EXPECT_TRUE(d1.entered());
1247 EXPECT_FALSE(d1.exited());
1248 d1.ResetExpectations();
1250 ui::MouseEvent exit_event(ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(),
1251 ui::EventTimeForNow(), 0, 0);
1252 DispatchEventUsingWindowDispatcher(&exit_event);
1253 EXPECT_FALSE(d1.entered());
1254 EXPECT_TRUE(d1.exited());
1257 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1258 // mouse transitions from window to window, even if the entered window sets
1259 // and releases capture.
1260 TEST_F(WindowTest, MouseEnterExitWithClick) {
1261 MouseEnterExitWindowDelegate d1;
1262 scoped_ptr<Window> w1(
1263 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1264 root_window()));
1265 MouseEnterExitWindowDelegate d2;
1266 scoped_ptr<Window> w2(
1267 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50),
1268 root_window()));
1270 ui::test::EventGenerator generator(root_window());
1271 generator.MoveMouseToCenterOf(w1.get());
1272 EXPECT_TRUE(d1.entered());
1273 EXPECT_FALSE(d1.exited());
1274 EXPECT_FALSE(d2.entered());
1275 EXPECT_FALSE(d2.exited());
1277 // Emmulate what Views does on a click by grabbing and releasing capture.
1278 generator.PressLeftButton();
1279 w1->SetCapture();
1280 w1->ReleaseCapture();
1281 generator.ReleaseLeftButton();
1283 generator.MoveMouseToCenterOf(w2.get());
1284 EXPECT_TRUE(d1.entered());
1285 EXPECT_TRUE(d1.exited());
1286 EXPECT_TRUE(d2.entered());
1287 EXPECT_FALSE(d2.exited());
1290 TEST_F(WindowTest, MouseEnterExitWhenDeleteWithCapture) {
1291 MouseEnterExitWindowDelegate delegate;
1292 scoped_ptr<Window> window(
1293 CreateTestWindowWithDelegate(&delegate, 1, gfx::Rect(10, 10, 50, 50),
1294 root_window()));
1296 ui::test::EventGenerator generator(root_window());
1297 generator.MoveMouseToCenterOf(window.get());
1298 EXPECT_TRUE(delegate.entered());
1299 EXPECT_FALSE(delegate.exited());
1301 // Emmulate what Views does on a click by grabbing and releasing capture.
1302 generator.PressLeftButton();
1303 window->SetCapture();
1305 delegate.ResetExpectations();
1306 generator.MoveMouseTo(0, 0);
1307 EXPECT_FALSE(delegate.entered());
1308 EXPECT_FALSE(delegate.exited());
1310 delegate.ResetExpectations();
1311 window.reset();
1312 EXPECT_FALSE(delegate.entered());
1313 EXPECT_FALSE(delegate.exited());
1316 // Verifies that the correct enter / exits are sent if windows appear and are
1317 // deleted under the current mouse position.
1318 TEST_F(WindowTest, MouseEnterExitWithWindowAppearAndDelete) {
1319 MouseEnterExitWindowDelegate d1;
1320 scoped_ptr<Window> w1(
1321 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1322 root_window()));
1324 // The cursor is moved into the bounds of |w1|. We expect the delegate
1325 // of |w1| to see an ET_MOUSE_ENTERED event.
1326 ui::test::EventGenerator generator(root_window());
1327 generator.MoveMouseToCenterOf(w1.get());
1328 EXPECT_TRUE(d1.entered());
1329 EXPECT_FALSE(d1.exited());
1330 d1.ResetExpectations();
1332 MouseEnterExitWindowDelegate d2;
1334 scoped_ptr<Window> w2(
1335 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1336 root_window()));
1337 // Enters / exits can be sent asynchronously.
1338 RunAllPendingInMessageLoop();
1340 // |w2| appears over top of |w1|. We expect the delegate of |w1| to see
1341 // an ET_MOUSE_EXITED and the delegate of |w2| to see an ET_MOUSE_ENTERED.
1342 EXPECT_FALSE(d1.entered());
1343 EXPECT_TRUE(d1.exited());
1344 EXPECT_TRUE(d2.entered());
1345 EXPECT_FALSE(d2.exited());
1346 d1.ResetExpectations();
1347 d2.ResetExpectations();
1350 // Enters / exits can be sent asynchronously.
1351 RunAllPendingInMessageLoop();
1353 // |w2| has been destroyed, so its delegate should see no further events.
1354 // The delegate of |w1| should see an ET_MOUSE_ENTERED event.
1355 EXPECT_TRUE(d1.entered());
1356 EXPECT_FALSE(d1.exited());
1357 EXPECT_FALSE(d2.entered());
1358 EXPECT_FALSE(d2.exited());
1361 // Verifies that enter / exits are sent if windows appear and are hidden
1362 // under the current mouse position..
1363 TEST_F(WindowTest, MouseEnterExitWithHide) {
1364 MouseEnterExitWindowDelegate d1;
1365 scoped_ptr<Window> w1(
1366 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1367 root_window()));
1369 ui::test::EventGenerator generator(root_window());
1370 generator.MoveMouseToCenterOf(w1.get());
1371 EXPECT_TRUE(d1.entered());
1372 EXPECT_FALSE(d1.exited());
1374 MouseEnterExitWindowDelegate d2;
1375 scoped_ptr<Window> w2(
1376 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1377 root_window()));
1378 // Enters / exits can be send asynchronously.
1379 RunAllPendingInMessageLoop();
1380 EXPECT_TRUE(d1.entered());
1381 EXPECT_TRUE(d1.exited());
1382 EXPECT_TRUE(d2.entered());
1383 EXPECT_FALSE(d2.exited());
1385 d1.ResetExpectations();
1386 w2->Hide();
1387 // Enters / exits can be send asynchronously.
1388 RunAllPendingInMessageLoop();
1389 EXPECT_TRUE(d2.exited());
1390 EXPECT_TRUE(d1.entered());
1393 TEST_F(WindowTest, MouseEnterExitWithParentHide) {
1394 MouseEnterExitWindowDelegate d1;
1395 scoped_ptr<Window> w1(
1396 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1397 root_window()));
1398 MouseEnterExitWindowDelegate d2;
1399 Window* w2 = CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1400 w1.get());
1401 ui::test::EventGenerator generator(root_window());
1402 generator.MoveMouseToCenterOf(w2);
1403 // Enters / exits can be send asynchronously.
1404 RunAllPendingInMessageLoop();
1405 EXPECT_TRUE(d2.entered());
1406 EXPECT_FALSE(d2.exited());
1408 d2.ResetExpectations();
1409 w1->Hide();
1410 RunAllPendingInMessageLoop();
1411 EXPECT_FALSE(d2.entered());
1412 EXPECT_TRUE(d2.exited());
1414 w1.reset();
1417 TEST_F(WindowTest, MouseEnterExitWithParentDelete) {
1418 MouseEnterExitWindowDelegate d1;
1419 scoped_ptr<Window> w1(
1420 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1421 root_window()));
1422 MouseEnterExitWindowDelegate d2;
1423 Window* w2 = CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1424 w1.get());
1425 ui::test::EventGenerator generator(root_window());
1426 generator.MoveMouseToCenterOf(w2);
1428 // Enters / exits can be send asynchronously.
1429 RunAllPendingInMessageLoop();
1430 EXPECT_TRUE(d2.entered());
1431 EXPECT_FALSE(d2.exited());
1433 d2.ResetExpectations();
1434 w1.reset();
1435 RunAllPendingInMessageLoop();
1437 // Both windows are in the process of destroying, so their delegates should
1438 // not see any mouse events.
1439 EXPECT_FALSE(d1.entered());
1440 EXPECT_FALSE(d1.exited());
1441 EXPECT_FALSE(d2.entered());
1442 EXPECT_FALSE(d2.exited());
1445 // Creates a window with a delegate (w111) that can handle events at a lower
1446 // z-index than a window without a delegate (w12). w12 is sized to fill the
1447 // entire bounds of the container. This test verifies that
1448 // GetEventHandlerForPoint() skips w12 even though its bounds contain the event,
1449 // because it has no children that can handle the event and it has no delegate
1450 // allowing it to handle the event itself.
1451 TEST_F(WindowTest, GetEventHandlerForPoint_NoDelegate) {
1452 TestWindowDelegate d111;
1453 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(NULL, 1,
1454 gfx::Rect(0, 0, 500, 500), root_window()));
1455 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(NULL, 11,
1456 gfx::Rect(0, 0, 500, 500), w1.get()));
1457 scoped_ptr<Window> w111(CreateTestWindowWithDelegate(&d111, 111,
1458 gfx::Rect(50, 50, 450, 450), w11.get()));
1459 scoped_ptr<Window> w12(CreateTestWindowWithDelegate(NULL, 12,
1460 gfx::Rect(0, 0, 500, 500), w1.get()));
1462 gfx::Point target_point = w111->bounds().CenterPoint();
1463 EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(target_point));
1466 class VisibilityWindowDelegate : public TestWindowDelegate {
1467 public:
1468 VisibilityWindowDelegate()
1469 : shown_(0),
1470 hidden_(0) {
1473 int shown() const { return shown_; }
1474 int hidden() const { return hidden_; }
1475 void Clear() {
1476 shown_ = 0;
1477 hidden_ = 0;
1480 void OnWindowTargetVisibilityChanged(bool visible) override {
1481 if (visible)
1482 shown_++;
1483 else
1484 hidden_++;
1487 private:
1488 int shown_;
1489 int hidden_;
1491 DISALLOW_COPY_AND_ASSIGN(VisibilityWindowDelegate);
1494 // Verifies show/hide propagate correctly to children and the layer.
1495 TEST_F(WindowTest, Visibility) {
1496 VisibilityWindowDelegate d;
1497 VisibilityWindowDelegate d2;
1498 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(&d, 1, gfx::Rect(),
1499 root_window()));
1500 scoped_ptr<Window> w2(
1501 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(), w1.get()));
1502 scoped_ptr<Window> w3(CreateTestWindowWithId(3, w2.get()));
1504 // Create shows all the windows.
1505 EXPECT_TRUE(w1->IsVisible());
1506 EXPECT_TRUE(w2->IsVisible());
1507 EXPECT_TRUE(w3->IsVisible());
1508 EXPECT_EQ(1, d.shown());
1510 d.Clear();
1511 w1->Hide();
1512 EXPECT_FALSE(w1->IsVisible());
1513 EXPECT_FALSE(w2->IsVisible());
1514 EXPECT_FALSE(w3->IsVisible());
1515 EXPECT_EQ(1, d.hidden());
1516 EXPECT_EQ(0, d.shown());
1518 w2->Show();
1519 EXPECT_FALSE(w1->IsVisible());
1520 EXPECT_FALSE(w2->IsVisible());
1521 EXPECT_FALSE(w3->IsVisible());
1523 w3->Hide();
1524 EXPECT_FALSE(w1->IsVisible());
1525 EXPECT_FALSE(w2->IsVisible());
1526 EXPECT_FALSE(w3->IsVisible());
1528 d.Clear();
1529 w1->Show();
1530 EXPECT_TRUE(w1->IsVisible());
1531 EXPECT_TRUE(w2->IsVisible());
1532 EXPECT_FALSE(w3->IsVisible());
1533 EXPECT_EQ(0, d.hidden());
1534 EXPECT_EQ(1, d.shown());
1536 w3->Show();
1537 EXPECT_TRUE(w1->IsVisible());
1538 EXPECT_TRUE(w2->IsVisible());
1539 EXPECT_TRUE(w3->IsVisible());
1541 // Verify that if an ancestor isn't visible and we change the visibility of a
1542 // child window that OnChildWindowVisibilityChanged() is still invoked.
1543 w1->Hide();
1544 d2.Clear();
1545 w2->Hide();
1546 EXPECT_EQ(1, d2.hidden());
1547 EXPECT_EQ(0, d2.shown());
1548 d2.Clear();
1549 w2->Show();
1550 EXPECT_EQ(0, d2.hidden());
1551 EXPECT_EQ(1, d2.shown());
1554 TEST_F(WindowTest, IgnoreEventsTest) {
1555 TestWindowDelegate d11;
1556 TestWindowDelegate d12;
1557 TestWindowDelegate d111;
1558 TestWindowDelegate d121;
1559 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(NULL, 1,
1560 gfx::Rect(0, 0, 500, 500), root_window()));
1561 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(&d11, 11,
1562 gfx::Rect(0, 0, 500, 500), w1.get()));
1563 scoped_ptr<Window> w111(CreateTestWindowWithDelegate(&d111, 111,
1564 gfx::Rect(50, 50, 450, 450), w11.get()));
1565 scoped_ptr<Window> w12(CreateTestWindowWithDelegate(&d12, 12,
1566 gfx::Rect(0, 0, 500, 500), w1.get()));
1567 scoped_ptr<Window> w121(CreateTestWindowWithDelegate(&d121, 121,
1568 gfx::Rect(150, 150, 50, 50), w12.get()));
1570 EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10)));
1571 w12->set_ignore_events(true);
1572 EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10)));
1573 w12->set_ignore_events(false);
1575 EXPECT_EQ(w121.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1576 w121->set_ignore_events(true);
1577 EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1578 w12->set_ignore_events(true);
1579 EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1580 w111->set_ignore_events(true);
1581 EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1584 // Tests transformation on the root window.
1585 TEST_F(WindowTest, Transform) {
1586 gfx::Size size = host()->GetBounds().size();
1587 EXPECT_EQ(gfx::Rect(size),
1588 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1589 gfx::Point()).bounds());
1591 // Rotate it clock-wise 90 degrees.
1592 gfx::Transform transform;
1593 transform.Translate(size.height(), 0);
1594 transform.Rotate(90.0);
1595 host()->SetRootTransform(transform);
1597 // The size should be the transformed size.
1598 gfx::Size transformed_size(size.height(), size.width());
1599 EXPECT_EQ(transformed_size.ToString(),
1600 root_window()->bounds().size().ToString());
1601 EXPECT_EQ(
1602 gfx::Rect(transformed_size).ToString(),
1603 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1604 gfx::Point()).bounds().ToString());
1606 // Host size shouldn't change.
1607 EXPECT_EQ(size.ToString(), host()->GetBounds().size().ToString());
1610 TEST_F(WindowTest, TransformGesture) {
1611 gfx::Size size = host()->GetBounds().size();
1613 scoped_ptr<GestureTrackPositionDelegate> delegate(
1614 new GestureTrackPositionDelegate);
1615 scoped_ptr<Window> window(CreateTestWindowWithDelegate(delegate.get(), -1234,
1616 gfx::Rect(0, 0, 20, 20), root_window()));
1618 // Rotate the root-window clock-wise 90 degrees.
1619 gfx::Transform transform;
1620 transform.Translate(size.height(), 0.0);
1621 transform.Rotate(90.0);
1622 host()->SetRootTransform(transform);
1624 ui::TouchEvent press(
1625 ui::ET_TOUCH_PRESSED, gfx::Point(size.height() - 10, 10), 0, getTime());
1626 DispatchEventUsingWindowDispatcher(&press);
1627 EXPECT_EQ(gfx::Point(10, 10).ToString(), delegate->position().ToString());
1630 namespace {
1631 DEFINE_WINDOW_PROPERTY_KEY(int, kIntKey, -2);
1632 DEFINE_WINDOW_PROPERTY_KEY(const char*, kStringKey, "squeamish");
1635 TEST_F(WindowTest, Property) {
1636 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window()));
1638 static const char native_prop_key[] = "fnord";
1640 // Non-existent properties should return the default values.
1641 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1642 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1643 EXPECT_EQ(NULL, w->GetNativeWindowProperty(native_prop_key));
1645 // A set property value should be returned again (even if it's the default
1646 // value).
1647 w->SetProperty(kIntKey, INT_MAX);
1648 EXPECT_EQ(INT_MAX, w->GetProperty(kIntKey));
1649 w->SetProperty(kIntKey, -2);
1650 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1651 w->SetProperty(kIntKey, INT_MIN);
1652 EXPECT_EQ(INT_MIN, w->GetProperty(kIntKey));
1654 w->SetProperty(kStringKey, static_cast<const char*>(NULL));
1655 EXPECT_EQ(NULL, w->GetProperty(kStringKey));
1656 w->SetProperty(kStringKey, "squeamish");
1657 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1658 w->SetProperty(kStringKey, "ossifrage");
1659 EXPECT_EQ(std::string("ossifrage"), w->GetProperty(kStringKey));
1661 w->SetNativeWindowProperty(native_prop_key, &*w);
1662 EXPECT_EQ(&*w, w->GetNativeWindowProperty(native_prop_key));
1663 w->SetNativeWindowProperty(native_prop_key, NULL);
1664 EXPECT_EQ(NULL, w->GetNativeWindowProperty(native_prop_key));
1666 // ClearProperty should restore the default value.
1667 w->ClearProperty(kIntKey);
1668 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1669 w->ClearProperty(kStringKey);
1670 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1673 TEST_F(WindowTest, OwnedProperty) {
1674 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window()));
1675 EXPECT_EQ(NULL, w->GetProperty(kOwnedKey));
1676 TestProperty* p1 = new TestProperty();
1677 w->SetProperty(kOwnedKey, p1);
1678 EXPECT_EQ(p1, w->GetProperty(kOwnedKey));
1679 EXPECT_EQ(NULL, TestProperty::last_deleted());
1681 TestProperty* p2 = new TestProperty();
1682 w->SetProperty(kOwnedKey, p2);
1683 EXPECT_EQ(p2, w->GetProperty(kOwnedKey));
1684 EXPECT_EQ(p1, TestProperty::last_deleted());
1686 w->ClearProperty(kOwnedKey);
1687 EXPECT_EQ(NULL, w->GetProperty(kOwnedKey));
1688 EXPECT_EQ(p2, TestProperty::last_deleted());
1690 TestProperty* p3 = new TestProperty();
1691 w->SetProperty(kOwnedKey, p3);
1692 EXPECT_EQ(p3, w->GetProperty(kOwnedKey));
1693 EXPECT_EQ(p2, TestProperty::last_deleted());
1694 w.reset();
1695 EXPECT_EQ(p3, TestProperty::last_deleted());
1698 TEST_F(WindowTest, SetBoundsInternalShouldCheckTargetBounds) {
1699 // We cannot short-circuit animations in this test.
1700 ui::ScopedAnimationDurationScaleMode test_duration_mode(
1701 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
1703 scoped_ptr<Window> w1(
1704 CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), root_window()));
1706 EXPECT_TRUE(w1->layer());
1707 w1->layer()->GetAnimator()->set_disable_timer_for_test(true);
1708 ui::LayerAnimator* animator = w1->layer()->GetAnimator();
1710 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1711 EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString());
1713 // Animate to a different position.
1715 ui::ScopedLayerAnimationSettings settings(w1->layer()->GetAnimator());
1716 w1->SetBounds(gfx::Rect(100, 100, 100, 100));
1719 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1720 EXPECT_EQ("100,100 100x100", w1->layer()->GetTargetBounds().ToString());
1722 // Animate back to the first position. The animation hasn't started yet, so
1723 // the current bounds are still (0, 0, 100, 100), but the target bounds are
1724 // (100, 100, 100, 100). If we step the animator ahead, we should find that
1725 // we're at (0, 0, 100, 100). That is, the second animation should be applied.
1727 ui::ScopedLayerAnimationSettings settings(w1->layer()->GetAnimator());
1728 w1->SetBounds(gfx::Rect(0, 0, 100, 100));
1731 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1732 EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString());
1734 // Confirm that the target bounds are reached.
1735 base::TimeTicks start_time =
1736 w1->layer()->GetAnimator()->last_step_time();
1738 animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
1740 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1744 typedef std::pair<const void*, intptr_t> PropertyChangeInfo;
1746 class WindowObserverTest : public WindowTest,
1747 public WindowObserver {
1748 public:
1749 struct VisibilityInfo {
1750 bool window_visible;
1751 bool visible_param;
1752 int changed_count;
1755 WindowObserverTest()
1756 : added_count_(0),
1757 removed_count_(0),
1758 destroyed_count_(0),
1759 old_property_value_(-3) {
1762 ~WindowObserverTest() override {}
1764 const VisibilityInfo* GetVisibilityInfo() const {
1765 return visibility_info_.get();
1768 void ResetVisibilityInfo() {
1769 visibility_info_.reset();
1772 // Returns a description of the WindowObserver methods that have been invoked.
1773 std::string WindowObserverCountStateAndClear() {
1774 std::string result(
1775 base::StringPrintf("added=%d removed=%d",
1776 added_count_, removed_count_));
1777 added_count_ = removed_count_ = 0;
1778 return result;
1781 int DestroyedCountAndClear() {
1782 int result = destroyed_count_;
1783 destroyed_count_ = 0;
1784 return result;
1787 // Return a tuple of the arguments passed in OnPropertyChanged callback.
1788 PropertyChangeInfo PropertyChangeInfoAndClear() {
1789 PropertyChangeInfo result(property_key_, old_property_value_);
1790 property_key_ = NULL;
1791 old_property_value_ = -3;
1792 return result;
1795 std::string TransformNotificationsAndClear() {
1796 std::string result;
1797 for (std::vector<std::pair<int, int> >::iterator it =
1798 transform_notifications_.begin();
1799 it != transform_notifications_.end();
1800 ++it) {
1801 base::StringAppendF(&result, "(%d,%d)", it->first, it->second);
1803 transform_notifications_.clear();
1804 return result;
1807 private:
1808 void OnWindowAdded(Window* new_window) override { added_count_++; }
1810 void OnWillRemoveWindow(Window* window) override { removed_count_++; }
1812 void OnWindowVisibilityChanged(Window* window, bool visible) override {
1813 if (!visibility_info_) {
1814 visibility_info_.reset(new VisibilityInfo);
1815 visibility_info_->changed_count = 0;
1817 visibility_info_->window_visible = window->IsVisible();
1818 visibility_info_->visible_param = visible;
1819 visibility_info_->changed_count++;
1822 void OnWindowDestroyed(Window* window) override {
1823 EXPECT_FALSE(window->parent());
1824 destroyed_count_++;
1827 void OnWindowPropertyChanged(Window* window,
1828 const void* key,
1829 intptr_t old) override {
1830 property_key_ = key;
1831 old_property_value_ = old;
1834 void OnAncestorWindowTransformed(Window* source, Window* window) override {
1835 transform_notifications_.push_back(
1836 std::make_pair(source->id(), window->id()));
1839 int added_count_;
1840 int removed_count_;
1841 int destroyed_count_;
1842 scoped_ptr<VisibilityInfo> visibility_info_;
1843 const void* property_key_;
1844 intptr_t old_property_value_;
1845 std::vector<std::pair<int, int> > transform_notifications_;
1847 DISALLOW_COPY_AND_ASSIGN(WindowObserverTest);
1850 // Various assertions for WindowObserver.
1851 TEST_F(WindowObserverTest, WindowObserver) {
1852 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1853 w1->AddObserver(this);
1855 // Create a new window as a child of w1, our observer should be notified.
1856 scoped_ptr<Window> w2(CreateTestWindowWithId(2, w1.get()));
1857 EXPECT_EQ("added=1 removed=0", WindowObserverCountStateAndClear());
1859 // Delete w2, which should result in the remove notification.
1860 w2.reset();
1861 EXPECT_EQ("added=0 removed=1", WindowObserverCountStateAndClear());
1863 // Create a window that isn't parented to w1, we shouldn't get any
1864 // notification.
1865 scoped_ptr<Window> w3(CreateTestWindowWithId(3, root_window()));
1866 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1868 // Similarly destroying w3 shouldn't notify us either.
1869 w3.reset();
1870 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1871 w1->RemoveObserver(this);
1874 // Test if OnWindowVisibilityChanged is invoked with expected
1875 // parameters.
1876 TEST_F(WindowObserverTest, WindowVisibility) {
1877 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1878 scoped_ptr<Window> w2(CreateTestWindowWithId(1, w1.get()));
1879 w2->AddObserver(this);
1881 // Hide should make the window invisible and the passed visible
1882 // parameter is false.
1883 w2->Hide();
1884 EXPECT_TRUE(GetVisibilityInfo());
1885 EXPECT_TRUE(GetVisibilityInfo());
1886 if (!GetVisibilityInfo())
1887 return;
1888 EXPECT_FALSE(GetVisibilityInfo()->window_visible);
1889 EXPECT_FALSE(GetVisibilityInfo()->visible_param);
1890 EXPECT_EQ(1, GetVisibilityInfo()->changed_count);
1892 // If parent isn't visible, showing window won't make the window visible, but
1893 // passed visible value must be true.
1894 w1->Hide();
1895 ResetVisibilityInfo();
1896 EXPECT_TRUE(!GetVisibilityInfo());
1897 w2->Show();
1898 EXPECT_TRUE(GetVisibilityInfo());
1899 if (!GetVisibilityInfo())
1900 return;
1901 EXPECT_FALSE(GetVisibilityInfo()->window_visible);
1902 EXPECT_TRUE(GetVisibilityInfo()->visible_param);
1903 EXPECT_EQ(1, GetVisibilityInfo()->changed_count);
1905 // If parent is visible, showing window will make the window
1906 // visible and the passed visible value is true.
1907 w1->Show();
1908 w2->Hide();
1909 ResetVisibilityInfo();
1910 w2->Show();
1911 EXPECT_TRUE(GetVisibilityInfo());
1912 if (!GetVisibilityInfo())
1913 return;
1914 EXPECT_TRUE(GetVisibilityInfo()->window_visible);
1915 EXPECT_TRUE(GetVisibilityInfo()->visible_param);
1916 EXPECT_EQ(1, GetVisibilityInfo()->changed_count);
1918 // Verify that the OnWindowVisibilityChanged only once
1919 // per visibility change.
1920 w2->Hide();
1921 EXPECT_EQ(2, GetVisibilityInfo()->changed_count);
1923 w2->Hide();
1924 EXPECT_EQ(2, GetVisibilityInfo()->changed_count);
1927 // Test if OnWindowDestroyed is invoked as expected.
1928 TEST_F(WindowObserverTest, WindowDestroyed) {
1929 // Delete a window should fire a destroyed notification.
1930 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1931 w1->AddObserver(this);
1932 w1.reset();
1933 EXPECT_EQ(1, DestroyedCountAndClear());
1935 // Observe on child and delete parent window should fire a notification.
1936 scoped_ptr<Window> parent(CreateTestWindowWithId(1, root_window()));
1937 Window* child = CreateTestWindowWithId(1, parent.get()); // owned by parent
1938 child->AddObserver(this);
1939 parent.reset();
1940 EXPECT_EQ(1, DestroyedCountAndClear());
1943 TEST_F(WindowObserverTest, PropertyChanged) {
1944 // Setting property should fire a property change notification.
1945 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1946 w1->AddObserver(this);
1948 static const WindowProperty<int> prop = {-2};
1949 static const char native_prop_key[] = "fnord";
1951 w1->SetProperty(&prop, 1);
1952 EXPECT_EQ(PropertyChangeInfo(&prop, -2), PropertyChangeInfoAndClear());
1953 w1->SetProperty(&prop, -2);
1954 EXPECT_EQ(PropertyChangeInfo(&prop, 1), PropertyChangeInfoAndClear());
1955 w1->SetProperty(&prop, 3);
1956 EXPECT_EQ(PropertyChangeInfo(&prop, -2), PropertyChangeInfoAndClear());
1957 w1->ClearProperty(&prop);
1958 EXPECT_EQ(PropertyChangeInfo(&prop, 3), PropertyChangeInfoAndClear());
1960 w1->SetNativeWindowProperty(native_prop_key, &*w1);
1961 EXPECT_EQ(PropertyChangeInfo(native_prop_key, 0),
1962 PropertyChangeInfoAndClear());
1963 w1->SetNativeWindowProperty(native_prop_key, NULL);
1964 EXPECT_EQ(PropertyChangeInfo(native_prop_key,
1965 reinterpret_cast<intptr_t>(&*w1)),
1966 PropertyChangeInfoAndClear());
1968 // Sanity check to see if |PropertyChangeInfoAndClear| really clears.
1969 EXPECT_EQ(PropertyChangeInfo(
1970 reinterpret_cast<const void*>(NULL), -3), PropertyChangeInfoAndClear());
1973 TEST_F(WindowObserverTest, AncestorTransformed) {
1974 // Create following window hierarchy:
1975 // root_window
1976 // +-- w1
1977 // +-- w2
1978 // +-- w3
1979 // +-- w4
1980 // Then, apply a transform to |w1| and ensure all its descendants are
1981 // notified.
1982 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1983 w1->AddObserver(this);
1984 scoped_ptr<Window> w2(CreateTestWindowWithId(2, w1.get()));
1985 w2->AddObserver(this);
1986 scoped_ptr<Window> w3(CreateTestWindowWithId(3, w1.get()));
1987 w3->AddObserver(this);
1988 scoped_ptr<Window> w4(CreateTestWindowWithId(4, w3.get()));
1989 w4->AddObserver(this);
1991 EXPECT_EQ(std::string(), TransformNotificationsAndClear());
1993 gfx::Transform transform;
1994 transform.Translate(10, 10);
1995 w1->SetTransform(transform);
1997 EXPECT_EQ("(1,1)(1,2)(1,3)(1,4)", TransformNotificationsAndClear());
2000 TEST_F(WindowTest, AcquireLayer) {
2001 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
2002 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
2003 ui::Layer* parent = window1->parent()->layer();
2004 EXPECT_EQ(2U, parent->children().size());
2006 WindowTestApi window1_test_api(window1.get());
2007 WindowTestApi window2_test_api(window2.get());
2009 EXPECT_TRUE(window1_test_api.OwnsLayer());
2010 EXPECT_TRUE(window2_test_api.OwnsLayer());
2012 // After acquisition, window1 should not own its layer, but it should still
2013 // be available to the window.
2014 scoped_ptr<ui::Layer> window1_layer(window1->AcquireLayer());
2015 EXPECT_FALSE(window1_test_api.OwnsLayer());
2016 EXPECT_TRUE(window1_layer.get() == window1->layer());
2018 // The acquired layer's owner should be set NULL and re-acquring
2019 // should return NULL.
2020 EXPECT_FALSE(window1_layer->owner());
2021 scoped_ptr<ui::Layer> window1_layer_reacquired(window1->AcquireLayer());
2022 EXPECT_FALSE(window1_layer_reacquired.get());
2024 // Upon destruction, window1's layer should still be valid, and in the layer
2025 // hierarchy, but window2's should be gone, and no longer in the hierarchy.
2026 window1.reset();
2027 window2.reset();
2029 // This should be set by the window's destructor.
2030 EXPECT_TRUE(window1_layer->delegate() == NULL);
2031 EXPECT_EQ(1U, parent->children().size());
2034 // Make sure that properties which should persist from the old layer to the new
2035 // layer actually do.
2036 TEST_F(WindowTest, RecreateLayer) {
2037 // Set properties to non default values.
2038 Window w(new ColorTestWindowDelegate(SK_ColorWHITE));
2039 w.set_id(1);
2040 w.Init(ui::LAYER_SOLID_COLOR);
2041 w.SetBounds(gfx::Rect(0, 0, 100, 100));
2043 ui::Layer* layer = w.layer();
2044 layer->SetVisible(false);
2045 layer->SetMasksToBounds(true);
2047 ui::Layer child_layer;
2048 layer->Add(&child_layer);
2050 scoped_ptr<ui::Layer> old_layer(w.RecreateLayer());
2051 layer = w.layer();
2052 EXPECT_EQ(ui::LAYER_SOLID_COLOR, layer->type());
2053 EXPECT_FALSE(layer->visible());
2054 EXPECT_EQ(1u, layer->children().size());
2055 EXPECT_TRUE(layer->GetMasksToBounds());
2056 EXPECT_EQ("0,0 100x100", w.bounds().ToString());
2057 EXPECT_EQ("0,0 100x100", layer->bounds().ToString());
2060 // Verify that RecreateLayer() stacks the old layer above the newly creatd
2061 // layer.
2062 TEST_F(WindowTest, RecreateLayerZOrder) {
2063 scoped_ptr<Window> w(
2064 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(0, 0, 100, 100),
2065 root_window()));
2066 scoped_ptr<ui::Layer> old_layer(w->RecreateLayer());
2068 const std::vector<ui::Layer*>& child_layers =
2069 root_window()->layer()->children();
2070 ASSERT_EQ(2u, child_layers.size());
2071 EXPECT_EQ(w->layer(), child_layers[0]);
2072 EXPECT_EQ(old_layer.get(), child_layers[1]);
2075 // Ensure that acquiring a layer then recreating a layer does not crash
2076 // and that RecreateLayer returns null.
2077 TEST_F(WindowTest, AcquireThenRecreateLayer) {
2078 scoped_ptr<Window> w(
2079 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(0, 0, 100, 100),
2080 root_window()));
2081 scoped_ptr<ui::Layer> acquired_layer(w->AcquireLayer());
2082 scoped_ptr<ui::Layer> doubly_acquired_layer(w->RecreateLayer());
2083 EXPECT_EQ(NULL, doubly_acquired_layer.get());
2085 // Destroy window before layer gets destroyed.
2086 w.reset();
2089 class TestVisibilityClient : public client::VisibilityClient {
2090 public:
2091 explicit TestVisibilityClient(Window* root_window)
2092 : ignore_visibility_changes_(false) {
2093 client::SetVisibilityClient(root_window, this);
2095 ~TestVisibilityClient() override {}
2097 void set_ignore_visibility_changes(bool ignore_visibility_changes) {
2098 ignore_visibility_changes_ = ignore_visibility_changes;
2101 // Overridden from client::VisibilityClient:
2102 void UpdateLayerVisibility(aura::Window* window, bool visible) override {
2103 if (!ignore_visibility_changes_)
2104 window->layer()->SetVisible(visible);
2107 private:
2108 bool ignore_visibility_changes_;
2109 DISALLOW_COPY_AND_ASSIGN(TestVisibilityClient);
2112 TEST_F(WindowTest, VisibilityClientIsVisible) {
2113 TestVisibilityClient client(root_window());
2115 scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window()));
2116 EXPECT_TRUE(window->IsVisible());
2117 EXPECT_TRUE(window->layer()->visible());
2119 window->Hide();
2120 EXPECT_FALSE(window->IsVisible());
2121 EXPECT_FALSE(window->layer()->visible());
2122 window->Show();
2124 client.set_ignore_visibility_changes(true);
2125 window->Hide();
2126 EXPECT_FALSE(window->IsVisible());
2127 EXPECT_TRUE(window->layer()->visible());
2130 // Tests the mouse events seen by WindowDelegates in a Window hierarchy when
2131 // changing the properties of a leaf Window.
2132 TEST_F(WindowTest, MouseEventsOnLeafWindowChange) {
2133 gfx::Size size = host()->GetBounds().size();
2135 ui::test::EventGenerator generator(root_window());
2136 generator.MoveMouseTo(50, 50);
2138 EventCountDelegate d1;
2139 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(&d1, 1,
2140 gfx::Rect(0, 0, 100, 100), root_window()));
2141 RunAllPendingInMessageLoop();
2142 // The format of result is "Enter/Move/Leave".
2143 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2145 // Add new window |w11| on top of |w1| which contains the cursor.
2146 EventCountDelegate d11;
2147 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(
2148 &d11, 1, gfx::Rect(0, 0, 100, 100), w1.get()));
2149 RunAllPendingInMessageLoop();
2150 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2151 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2153 // Resize |w11| so that it does not contain the cursor.
2154 w11->SetBounds(gfx::Rect(0, 0, 10, 10));
2155 RunAllPendingInMessageLoop();
2156 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2157 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2159 // Resize |w11| so that it does contain the cursor.
2160 w11->SetBounds(gfx::Rect(0, 0, 60, 60));
2161 RunAllPendingInMessageLoop();
2162 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2163 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2165 // Detach |w11| from |w1|.
2166 w1->RemoveChild(w11.get());
2167 RunAllPendingInMessageLoop();
2168 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2169 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2171 // Re-attach |w11| to |w1|.
2172 w1->AddChild(w11.get());
2173 RunAllPendingInMessageLoop();
2174 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2175 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2177 // Hide |w11|.
2178 w11->Hide();
2179 RunAllPendingInMessageLoop();
2180 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2181 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2183 // Show |w11|.
2184 w11->Show();
2185 RunAllPendingInMessageLoop();
2186 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2187 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2189 // Translate |w11| so that it does not contain the mouse cursor.
2190 gfx::Transform transform;
2191 transform.Translate(100, 100);
2192 w11->SetTransform(transform);
2193 RunAllPendingInMessageLoop();
2194 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2195 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2197 // Clear the transform on |w11| so that it does contain the cursor.
2198 w11->SetTransform(gfx::Transform());
2199 RunAllPendingInMessageLoop();
2200 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2201 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2203 // Close |w11|. Note that since |w11| is being destroyed, its delegate should
2204 // not see any further events.
2205 w11.reset();
2206 RunAllPendingInMessageLoop();
2207 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2208 EXPECT_EQ("0 0 0", d11.GetMouseMotionCountsAndReset());
2210 // Move the mouse outside the bounds of the root window. Since the mouse
2211 // cursor is no longer within their bounds, the delegates of the child
2212 // windows should not see any mouse events.
2213 generator.MoveMouseTo(-10, -10);
2214 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2215 EXPECT_EQ("0 0 0", d11.GetMouseMotionCountsAndReset());
2217 // Add |w11|.
2218 w11.reset(CreateTestWindowWithDelegate(
2219 &d11, 1, gfx::Rect(0, 0, 100, 100), w1.get()));
2220 RunAllPendingInMessageLoop();
2221 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset());
2222 EXPECT_EQ("0 0 0", d11.GetMouseMotionCountsAndReset());
2224 // Close |w11|.
2225 w11.reset();
2226 RunAllPendingInMessageLoop();
2227 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset());
2228 EXPECT_EQ("0 0 0", d11.GetMouseMotionCountsAndReset());
2231 // Tests the mouse events seen by WindowDelegates in a Window hierarchy when
2232 // deleting a non-leaf Window.
2233 TEST_F(WindowTest, MouseEventsOnNonLeafWindowDelete) {
2234 gfx::Size size = host()->GetBounds().size();
2236 ui::test::EventGenerator generator(root_window());
2237 generator.MoveMouseTo(50, 50);
2239 EventCountDelegate d1;
2240 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(&d1, 1,
2241 gfx::Rect(0, 0, 100, 100), root_window()));
2242 RunAllPendingInMessageLoop();
2243 // The format of result is "Enter/Move/Leave".
2244 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2246 // Add new window |w2| on top of |w1| which contains the cursor.
2247 EventCountDelegate d2;
2248 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
2249 &d2, 1, gfx::Rect(0, 0, 100, 100), w1.get()));
2250 RunAllPendingInMessageLoop();
2251 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2252 EXPECT_EQ("1 1 0", d2.GetMouseMotionCountsAndReset());
2254 // Add new window on top of |w2| which contains the cursor.
2255 EventCountDelegate d3;
2256 CreateTestWindowWithDelegate(
2257 &d3, 1, gfx::Rect(0, 0, 100, 100), w2.get());
2258 RunAllPendingInMessageLoop();
2259 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset());
2260 EXPECT_EQ("0 0 1", d2.GetMouseMotionCountsAndReset());
2261 EXPECT_EQ("1 1 0", d3.GetMouseMotionCountsAndReset());
2263 // Delete |w2|, which will also delete its owned child window. Since |w2| and
2264 // its child are in the process of being destroyed, their delegates should
2265 // not see any further events.
2266 w2.reset();
2267 RunAllPendingInMessageLoop();
2268 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2269 EXPECT_EQ("0 0 0", d2.GetMouseMotionCountsAndReset());
2270 EXPECT_EQ("0 0 0", d3.GetMouseMotionCountsAndReset());
2273 class RootWindowAttachmentObserver : public WindowObserver {
2274 public:
2275 RootWindowAttachmentObserver() : added_count_(0), removed_count_(0) {}
2276 ~RootWindowAttachmentObserver() override {}
2278 int added_count() const { return added_count_; }
2279 int removed_count() const { return removed_count_; }
2281 void Clear() {
2282 added_count_ = 0;
2283 removed_count_ = 0;
2286 // Overridden from WindowObserver:
2287 void OnWindowAddedToRootWindow(Window* window) override { ++added_count_; }
2288 void OnWindowRemovingFromRootWindow(Window* window,
2289 Window* new_root) override {
2290 ++removed_count_;
2293 private:
2294 int added_count_;
2295 int removed_count_;
2297 DISALLOW_COPY_AND_ASSIGN(RootWindowAttachmentObserver);
2300 TEST_F(WindowTest, RootWindowAttachment) {
2301 RootWindowAttachmentObserver observer;
2303 // Test a direct add/remove from the RootWindow.
2304 scoped_ptr<Window> w1(new Window(NULL));
2305 w1->Init(ui::LAYER_NOT_DRAWN);
2306 w1->AddObserver(&observer);
2308 ParentWindow(w1.get());
2309 EXPECT_EQ(1, observer.added_count());
2310 EXPECT_EQ(0, observer.removed_count());
2312 w1.reset();
2313 EXPECT_EQ(1, observer.added_count());
2314 EXPECT_EQ(1, observer.removed_count());
2316 observer.Clear();
2318 // Test an indirect add/remove from the RootWindow.
2319 w1.reset(new Window(NULL));
2320 w1->Init(ui::LAYER_NOT_DRAWN);
2321 Window* w11 = new Window(NULL);
2322 w11->Init(ui::LAYER_NOT_DRAWN);
2323 w11->AddObserver(&observer);
2324 w1->AddChild(w11);
2325 EXPECT_EQ(0, observer.added_count());
2326 EXPECT_EQ(0, observer.removed_count());
2328 ParentWindow(w1.get());
2329 EXPECT_EQ(1, observer.added_count());
2330 EXPECT_EQ(0, observer.removed_count());
2332 w1.reset(); // Deletes w11.
2333 w11 = NULL;
2334 EXPECT_EQ(1, observer.added_count());
2335 EXPECT_EQ(1, observer.removed_count());
2337 observer.Clear();
2339 // Test an indirect add/remove with nested observers.
2340 w1.reset(new Window(NULL));
2341 w1->Init(ui::LAYER_NOT_DRAWN);
2342 w11 = new Window(NULL);
2343 w11->Init(ui::LAYER_NOT_DRAWN);
2344 w11->AddObserver(&observer);
2345 w1->AddChild(w11);
2346 Window* w111 = new Window(NULL);
2347 w111->Init(ui::LAYER_NOT_DRAWN);
2348 w111->AddObserver(&observer);
2349 w11->AddChild(w111);
2351 EXPECT_EQ(0, observer.added_count());
2352 EXPECT_EQ(0, observer.removed_count());
2354 ParentWindow(w1.get());
2355 EXPECT_EQ(2, observer.added_count());
2356 EXPECT_EQ(0, observer.removed_count());
2358 w1.reset(); // Deletes w11 and w111.
2359 w11 = NULL;
2360 w111 = NULL;
2361 EXPECT_EQ(2, observer.added_count());
2362 EXPECT_EQ(2, observer.removed_count());
2365 class BoundsChangedWindowObserver : public WindowObserver {
2366 public:
2367 BoundsChangedWindowObserver() : root_set_(false) {}
2369 void OnWindowBoundsChanged(Window* window,
2370 const gfx::Rect& old_bounds,
2371 const gfx::Rect& new_bounds) override {
2372 root_set_ = window->GetRootWindow() != NULL;
2375 bool root_set() const { return root_set_; }
2377 private:
2378 bool root_set_;
2380 DISALLOW_COPY_AND_ASSIGN(BoundsChangedWindowObserver);
2383 TEST_F(WindowTest, RootWindowSetWhenReparenting) {
2384 Window parent1(NULL);
2385 parent1.Init(ui::LAYER_NOT_DRAWN);
2386 Window parent2(NULL);
2387 parent2.Init(ui::LAYER_NOT_DRAWN);
2388 ParentWindow(&parent1);
2389 ParentWindow(&parent2);
2390 parent1.SetBounds(gfx::Rect(10, 10, 300, 300));
2391 parent2.SetBounds(gfx::Rect(20, 20, 300, 300));
2393 BoundsChangedWindowObserver observer;
2394 Window child(NULL);
2395 child.Init(ui::LAYER_NOT_DRAWN);
2396 child.SetBounds(gfx::Rect(5, 5, 100, 100));
2397 parent1.AddChild(&child);
2399 // We need animations to start in order to observe the bounds changes.
2400 ui::ScopedAnimationDurationScaleMode test_duration_mode(
2401 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2402 ui::ScopedLayerAnimationSettings settings1(child.layer()->GetAnimator());
2403 settings1.SetTransitionDuration(base::TimeDelta::FromMilliseconds(100));
2404 gfx::Rect new_bounds(gfx::Rect(35, 35, 50, 50));
2405 child.SetBounds(new_bounds);
2407 child.AddObserver(&observer);
2409 // Reparenting the |child| will cause it to get moved. During this move
2410 // the window should still have root window set.
2411 parent2.AddChild(&child);
2412 EXPECT_TRUE(observer.root_set());
2414 // Animations should stop and the bounds should be as set before the |child|
2415 // got reparented.
2416 EXPECT_EQ(new_bounds.ToString(), child.GetTargetBounds().ToString());
2417 EXPECT_EQ(new_bounds.ToString(), child.bounds().ToString());
2418 EXPECT_EQ("55,55 50x50", child.GetBoundsInRootWindow().ToString());
2421 TEST_F(WindowTest, OwnedByParentFalse) {
2422 // By default, a window is owned by its parent. If this is set to false, the
2423 // window will not be destroyed when its parent is.
2425 scoped_ptr<Window> w1(new Window(NULL));
2426 w1->Init(ui::LAYER_NOT_DRAWN);
2427 scoped_ptr<Window> w2(new Window(NULL));
2428 w2->set_owned_by_parent(false);
2429 w2->Init(ui::LAYER_NOT_DRAWN);
2430 w1->AddChild(w2.get());
2432 w1.reset();
2434 // We should be able to deref w2 still, but its parent should now be NULL.
2435 EXPECT_EQ(NULL, w2->parent());
2438 namespace {
2440 // Used By DeleteWindowFromOnWindowDestroyed. Destroys a Window from
2441 // OnWindowDestroyed().
2442 class OwningWindowDelegate : public TestWindowDelegate {
2443 public:
2444 OwningWindowDelegate() {}
2446 void SetOwnedWindow(Window* window) {
2447 owned_window_.reset(window);
2450 void OnWindowDestroyed(Window* window) override { owned_window_.reset(NULL); }
2452 private:
2453 scoped_ptr<Window> owned_window_;
2455 DISALLOW_COPY_AND_ASSIGN(OwningWindowDelegate);
2458 } // namespace
2460 // Creates a window with two child windows. When the first child window is
2461 // destroyed (WindowDelegate::OnWindowDestroyed) it deletes the second child.
2462 // This synthesizes BrowserView and the status bubble. Both are children of the
2463 // same parent and destroying BrowserView triggers it destroying the status
2464 // bubble.
2465 TEST_F(WindowTest, DeleteWindowFromOnWindowDestroyed) {
2466 scoped_ptr<Window> parent(new Window(NULL));
2467 parent->Init(ui::LAYER_NOT_DRAWN);
2468 OwningWindowDelegate delegate;
2469 Window* c1 = new Window(&delegate);
2470 c1->Init(ui::LAYER_NOT_DRAWN);
2471 parent->AddChild(c1);
2472 Window* c2 = new Window(NULL);
2473 c2->Init(ui::LAYER_NOT_DRAWN);
2474 parent->AddChild(c2);
2475 delegate.SetOwnedWindow(c2);
2476 parent.reset();
2479 namespace {
2481 // Used by DelegateNotifiedAsBoundsChange to verify OnBoundsChanged() is
2482 // invoked.
2483 class BoundsChangeDelegate : public TestWindowDelegate {
2484 public:
2485 BoundsChangeDelegate() : bounds_changed_(false) {}
2487 void clear_bounds_changed() { bounds_changed_ = false; }
2488 bool bounds_changed() const {
2489 return bounds_changed_;
2492 // Window
2493 void OnBoundsChanged(const gfx::Rect& old_bounds,
2494 const gfx::Rect& new_bounds) override {
2495 bounds_changed_ = true;
2498 private:
2499 // Was OnBoundsChanged() invoked?
2500 bool bounds_changed_;
2502 DISALLOW_COPY_AND_ASSIGN(BoundsChangeDelegate);
2505 } // namespace
2507 // Verifies the delegate is notified when the actual bounds of the layer
2508 // change.
2509 TEST_F(WindowTest, DelegateNotifiedAsBoundsChange) {
2510 BoundsChangeDelegate delegate;
2512 // We cannot short-circuit animations in this test.
2513 ui::ScopedAnimationDurationScaleMode test_duration_mode(
2514 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2516 scoped_ptr<Window> window(
2517 CreateTestWindowWithDelegate(&delegate, 1,
2518 gfx::Rect(0, 0, 100, 100), root_window()));
2519 window->layer()->GetAnimator()->set_disable_timer_for_test(true);
2521 delegate.clear_bounds_changed();
2523 // Animate to a different position.
2525 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
2526 window->SetBounds(gfx::Rect(100, 100, 100, 100));
2529 // Bounds shouldn't immediately have changed.
2530 EXPECT_EQ("0,0 100x100", window->bounds().ToString());
2531 EXPECT_FALSE(delegate.bounds_changed());
2533 // Animate to the end, which should notify of the change.
2534 base::TimeTicks start_time =
2535 window->layer()->GetAnimator()->last_step_time();
2536 ui::LayerAnimator* animator = window->layer()->GetAnimator();
2537 animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
2538 EXPECT_TRUE(delegate.bounds_changed());
2539 EXPECT_NE("0,0 100x100", window->bounds().ToString());
2542 // Verifies the delegate is notified when the actual bounds of the layer
2543 // change even when the window is not the layer's delegate
2544 TEST_F(WindowTest, DelegateNotifiedAsBoundsChangeInHiddenLayer) {
2545 BoundsChangeDelegate delegate;
2547 // We cannot short-circuit animations in this test.
2548 ui::ScopedAnimationDurationScaleMode test_duration_mode(
2549 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2551 scoped_ptr<Window> window(
2552 CreateTestWindowWithDelegate(&delegate, 1,
2553 gfx::Rect(0, 0, 100, 100), root_window()));
2554 window->layer()->GetAnimator()->set_disable_timer_for_test(true);
2556 delegate.clear_bounds_changed();
2558 // Suppress paint on the window since it is hidden (should reset the layer's
2559 // delegate to NULL)
2560 window->SuppressPaint();
2561 EXPECT_EQ(NULL, window->layer()->delegate());
2563 // Animate to a different position.
2565 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
2566 window->SetBounds(gfx::Rect(100, 100, 110, 100));
2569 // Layer delegate is NULL but we should still get bounds changed notification.
2570 EXPECT_EQ("100,100 110x100", window->GetTargetBounds().ToString());
2571 EXPECT_TRUE(delegate.bounds_changed());
2573 delegate.clear_bounds_changed();
2575 // Animate to the end: will *not* notify of the change since we are hidden.
2576 base::TimeTicks start_time =
2577 window->layer()->GetAnimator()->last_step_time();
2578 ui::LayerAnimator* animator = window->layer()->GetAnimator();
2579 animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
2581 // No bounds changed notification at the end of animation since layer
2582 // delegate is NULL.
2583 EXPECT_FALSE(delegate.bounds_changed());
2584 EXPECT_NE("0,0 100x100", window->layer()->bounds().ToString());
2587 namespace {
2589 // Used by AddChildNotifications to track notification counts.
2590 class AddChildNotificationsObserver : public WindowObserver {
2591 public:
2592 AddChildNotificationsObserver() : added_count_(0), removed_count_(0) {}
2594 std::string CountStringAndReset() {
2595 std::string result = base::IntToString(added_count_) + " " +
2596 base::IntToString(removed_count_);
2597 added_count_ = removed_count_ = 0;
2598 return result;
2601 // WindowObserver overrides:
2602 void OnWindowAddedToRootWindow(Window* window) override { added_count_++; }
2603 void OnWindowRemovingFromRootWindow(Window* window,
2604 Window* new_root) override {
2605 removed_count_++;
2608 private:
2609 int added_count_;
2610 int removed_count_;
2612 DISALLOW_COPY_AND_ASSIGN(AddChildNotificationsObserver);
2615 } // namespace
2617 // Assertions around when root window notifications are sent.
2618 TEST_F(WindowTest, AddChildNotifications) {
2619 AddChildNotificationsObserver observer;
2620 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
2621 scoped_ptr<Window> w2(CreateTestWindowWithId(1, root_window()));
2622 w2->AddObserver(&observer);
2623 w2->Focus();
2624 EXPECT_TRUE(w2->HasFocus());
2626 // Move |w2| to be a child of |w1|.
2627 w1->AddChild(w2.get());
2628 // Sine we moved in the same root, observer shouldn't be notified.
2629 EXPECT_EQ("0 0", observer.CountStringAndReset());
2630 // |w2| should still have focus after moving.
2631 EXPECT_TRUE(w2->HasFocus());
2634 // Tests that a delegate that destroys itself when the window is destroyed does
2635 // not break.
2636 TEST_F(WindowTest, DelegateDestroysSelfOnWindowDestroy) {
2637 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
2638 new DestroyWindowDelegate(),
2640 gfx::Rect(10, 20, 30, 40),
2641 root_window()));
2644 class HierarchyObserver : public WindowObserver {
2645 public:
2646 explicit HierarchyObserver(Window* target) : target_(target) {
2647 target_->AddObserver(this);
2649 ~HierarchyObserver() override { target_->RemoveObserver(this); }
2651 void ValidateState(
2652 int index,
2653 const WindowObserver::HierarchyChangeParams& params) const {
2654 ParamsMatch(params_[index], params);
2657 void Reset() {
2658 params_.clear();
2661 private:
2662 // Overridden from WindowObserver:
2663 void OnWindowHierarchyChanging(const HierarchyChangeParams& params) override {
2664 params_.push_back(params);
2666 void OnWindowHierarchyChanged(const HierarchyChangeParams& params) override {
2667 params_.push_back(params);
2670 void ParamsMatch(const WindowObserver::HierarchyChangeParams& p1,
2671 const WindowObserver::HierarchyChangeParams& p2) const {
2672 EXPECT_EQ(p1.phase, p2.phase);
2673 EXPECT_EQ(p1.target, p2.target);
2674 EXPECT_EQ(p1.new_parent, p2.new_parent);
2675 EXPECT_EQ(p1.old_parent, p2.old_parent);
2676 EXPECT_EQ(p1.receiver, p2.receiver);
2679 Window* target_;
2680 std::vector<WindowObserver::HierarchyChangeParams> params_;
2682 DISALLOW_COPY_AND_ASSIGN(HierarchyObserver);
2685 // Tests hierarchy change notifications.
2686 TEST_F(WindowTest, OnWindowHierarchyChange) {
2688 // Simple add & remove.
2689 HierarchyObserver oroot(root_window());
2691 scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL));
2692 HierarchyObserver o1(w1.get());
2694 // Add.
2695 root_window()->AddChild(w1.get());
2697 WindowObserver::HierarchyChangeParams params;
2698 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2699 params.target = w1.get();
2700 params.old_parent = NULL;
2701 params.new_parent = root_window();
2702 params.receiver = w1.get();
2703 o1.ValidateState(0, params);
2705 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2706 params.receiver = w1.get();
2707 o1.ValidateState(1, params);
2709 params.receiver = root_window();
2710 oroot.ValidateState(0, params);
2712 // Remove.
2713 o1.Reset();
2714 oroot.Reset();
2716 root_window()->RemoveChild(w1.get());
2718 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2719 params.old_parent = root_window();
2720 params.new_parent = NULL;
2721 params.receiver = w1.get();
2723 o1.ValidateState(0, params);
2725 params.receiver = root_window();
2726 oroot.ValidateState(0, params);
2728 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2729 params.receiver = w1.get();
2730 o1.ValidateState(1, params);
2734 // Add & remove of hierarchy. Tests notification order per documentation in
2735 // WindowObserver.
2736 HierarchyObserver o(root_window());
2737 scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL));
2738 Window* w11 = CreateTestWindowWithId(11, w1.get());
2739 w1->AddObserver(&o);
2740 w11->AddObserver(&o);
2742 // Add.
2743 root_window()->AddChild(w1.get());
2745 // Dispatched to target first.
2746 int index = 0;
2747 WindowObserver::HierarchyChangeParams params;
2748 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2749 params.target = w1.get();
2750 params.old_parent = NULL;
2751 params.new_parent = root_window();
2752 params.receiver = w1.get();
2753 o.ValidateState(index++, params);
2755 // Dispatched to target's children.
2756 params.receiver = w11;
2757 o.ValidateState(index++, params);
2759 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2761 // Now process the "changed" phase.
2762 params.receiver = w1.get();
2763 o.ValidateState(index++, params);
2764 params.receiver = w11;
2765 o.ValidateState(index++, params);
2766 params.receiver = root_window();
2767 o.ValidateState(index++, params);
2769 // Remove.
2770 root_window()->RemoveChild(w1.get());
2771 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2772 params.old_parent = root_window();
2773 params.new_parent = NULL;
2774 params.receiver = w1.get();
2775 o.ValidateState(index++, params);
2776 params.receiver = w11;
2777 o.ValidateState(index++, params);
2778 params.receiver = root_window();
2779 o.ValidateState(index++, params);
2780 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2781 params.receiver = w1.get();
2782 o.ValidateState(index++, params);
2783 params.receiver = w11;
2784 o.ValidateState(index++, params);
2786 w1.reset();
2790 // Reparent. Tests notification order per documentation in WindowObserver.
2791 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
2792 Window* w11 = CreateTestWindowWithId(11, w1.get());
2793 Window* w111 = CreateTestWindowWithId(111, w11);
2794 scoped_ptr<Window> w2(CreateTestWindowWithId(2, root_window()));
2796 HierarchyObserver o(root_window());
2797 w1->AddObserver(&o);
2798 w11->AddObserver(&o);
2799 w111->AddObserver(&o);
2800 w2->AddObserver(&o);
2802 w2->AddChild(w11);
2804 // Dispatched to target first.
2805 int index = 0;
2806 WindowObserver::HierarchyChangeParams params;
2807 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2808 params.target = w11;
2809 params.old_parent = w1.get();
2810 params.new_parent = w2.get();
2811 params.receiver = w11;
2812 o.ValidateState(index++, params);
2814 // Then to target's children.
2815 params.receiver = w111;
2816 o.ValidateState(index++, params);
2818 // Then to target's old parent chain.
2819 params.receiver = w1.get();
2820 o.ValidateState(index++, params);
2821 params.receiver = root_window();
2822 o.ValidateState(index++, params);
2824 // "Changed" phase.
2825 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2826 params.receiver = w11;
2827 o.ValidateState(index++, params);
2828 params.receiver = w111;
2829 o.ValidateState(index++, params);
2830 params.receiver = w2.get();
2831 o.ValidateState(index++, params);
2832 params.receiver = root_window();
2833 o.ValidateState(index++, params);
2835 w1.reset();
2836 w2.reset();
2840 namespace {
2842 class TestLayerAnimationObserver : public ui::LayerAnimationObserver {
2843 public:
2844 TestLayerAnimationObserver()
2845 : animation_completed_(false),
2846 animation_aborted_(false) {}
2847 ~TestLayerAnimationObserver() override {}
2849 bool animation_completed() const { return animation_completed_; }
2850 bool animation_aborted() const { return animation_aborted_; }
2852 void Reset() {
2853 animation_completed_ = false;
2854 animation_aborted_ = false;
2857 private:
2858 // ui::LayerAnimationObserver:
2859 void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override {
2860 animation_completed_ = true;
2863 void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override {
2864 animation_aborted_ = true;
2867 void OnLayerAnimationScheduled(
2868 ui::LayerAnimationSequence* sequence) override {}
2870 bool animation_completed_;
2871 bool animation_aborted_;
2873 DISALLOW_COPY_AND_ASSIGN(TestLayerAnimationObserver);
2876 } // namespace
2878 TEST_F(WindowTest, WindowDestroyCompletesAnimations) {
2879 ui::ScopedAnimationDurationScaleMode test_duration_mode(
2880 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2881 scoped_refptr<ui::LayerAnimator> animator =
2882 ui::LayerAnimator::CreateImplicitAnimator();
2883 TestLayerAnimationObserver observer;
2884 animator->AddObserver(&observer);
2885 // Make sure destroying a Window completes the animation.
2887 scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window()));
2888 window->layer()->SetAnimator(animator.get());
2890 gfx::Transform transform;
2891 transform.Scale(0.5f, 0.5f);
2892 window->SetTransform(transform);
2894 EXPECT_TRUE(animator->is_animating());
2895 EXPECT_FALSE(observer.animation_completed());
2897 EXPECT_TRUE(animator.get());
2898 EXPECT_FALSE(animator->is_animating());
2899 EXPECT_TRUE(observer.animation_completed());
2900 EXPECT_FALSE(observer.animation_aborted());
2901 animator->RemoveObserver(&observer);
2902 observer.Reset();
2904 animator = ui::LayerAnimator::CreateImplicitAnimator();
2905 animator->AddObserver(&observer);
2906 ui::Layer layer;
2907 layer.SetAnimator(animator.get());
2909 scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window()));
2910 window->layer()->Add(&layer);
2912 gfx::Transform transform;
2913 transform.Scale(0.5f, 0.5f);
2914 layer.SetTransform(transform);
2916 EXPECT_TRUE(animator->is_animating());
2917 EXPECT_FALSE(observer.animation_completed());
2920 EXPECT_TRUE(animator.get());
2921 EXPECT_FALSE(animator->is_animating());
2922 EXPECT_TRUE(observer.animation_completed());
2923 EXPECT_FALSE(observer.animation_aborted());
2924 animator->RemoveObserver(&observer);
2927 } // namespace test
2928 } // namespace aura