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"
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*)
57 static TestProperty
* last_deleted() { return last_deleted_
; }
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
);
70 DECLARE_WINDOW_PROPERTY_TYPE(TestProperty
*);
75 class WindowTest
: public AuraTestBase
{
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_
);
96 float max_separation_
;
98 DISALLOW_COPY_AND_ASSIGN(WindowTest
);
103 // Used for verifying destruction methods are invoked.
104 class DestroyTrackingDelegateImpl
: public TestWindowDelegate
{
106 DestroyTrackingDelegateImpl()
107 : destroying_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;
125 void OnWindowDestroyed(Window
* window
) override
{
126 EXPECT_TRUE(in_destroying_
);
127 in_destroying_
= false;
132 int destroying_count_
;
133 int destroyed_count_
;
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
{
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
);
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
{
163 DestroyOrphanDelegate() : window_(NULL
) {
166 void set_window(Window
* window
) { window_
= window
; }
168 void OnWindowDestroyed(Window
* window
) override
{
169 EXPECT_FALSE(window_
->parent());
174 DISALLOW_COPY_AND_ASSIGN(DestroyOrphanDelegate
);
177 // Used in verifying mouse capture.
178 class CaptureWindowDelegateImpl
: public TestWindowDelegate
{
180 CaptureWindowDelegateImpl() {
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_
++; }
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
{
224 GestureTrackPositionDelegate() {}
226 void OnGestureEvent(ui::GestureEvent
* event
) override
{
227 position_
= event
->location();
228 event
->StopPropagation();
231 const gfx::Point
& position() const { return position_
; }
234 gfx::Point position_
;
236 DISALLOW_COPY_AND_ASSIGN(GestureTrackPositionDelegate
);
239 base::TimeDelta
getTime() {
240 return ui::EventTimeForNow();
243 class SelfEventHandlingWindowDelegate
: public TestWindowDelegate
{
245 SelfEventHandlingWindowDelegate() {}
247 bool ShouldDescendIntoChildForEventHandling(
249 const gfx::Point
& location
) override
{
254 DISALLOW_COPY_AND_ASSIGN(SelfEventHandlingWindowDelegate
);
257 // The delegate deletes itself when the window is being destroyed.
258 class DestroyWindowDelegate
: public TestWindowDelegate
{
260 DestroyWindowDelegate() {}
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
);
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
) {
294 parent
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
296 child1
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
298 child2
.Init(aura::WINDOW_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),
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),
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),
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));
358 gfx::Screen::GetScreenFor(root
)->GetCursorScreenPoint().ToString());
359 w1
->MoveCursorTo(gfx::Point(10, 10));
361 gfx::Screen::GetScreenFor(root
)->GetCursorScreenPoint().ToString());
362 w11
->MoveCursorTo(gfx::Point(10, 10));
364 gfx::Screen::GetScreenFor(root
)->GetCursorScreenPoint().ToString());
365 w111
->MoveCursorTo(gfx::Point(10, 10));
367 gfx::Screen::GetScreenFor(root
)->GetCursorScreenPoint().ToString());
368 w1111
->MoveCursorTo(gfx::Point(10, 10));
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),
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));
395 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.OD
396 EXPECT_EQ("50,120", QueryLatestMousePositionRequestInHost(host()).ToString());
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),
408 gfx::Transform transform1
;
409 transform1
.Scale(2, 2);
410 w1
->SetTransform(transform1
);
411 w1
->MoveCursorTo(gfx::Point(10, 10));
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));
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));
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));
436 gfx::Screen::GetScreenFor(w1
.get())->GetCursorScreenPoint().ToString());
439 // Test Window::ConvertPointToWindow() with complex transforms to both root and
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),
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));
475 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.
476 EXPECT_EQ("169,80", QueryLatestMousePositionRequestInHost(host()).ToString());
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),
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),
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
523 scoped_ptr
<Window
> parent(
524 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(10, 20, 400, 500),
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),
547 // We can override ShouldDescendIntoChildForEventHandling to make the parent
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),
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),
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
{
607 AddedToRootWindowObserver() : called_(false) {}
609 void OnWindowAddedToRootWindow(Window
* window
) override
{ called_
= true; }
611 bool called() const { return 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(aura::WINDOW_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(),
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(),
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
) {
673 parent
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
675 child1
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
677 child2
.Init(aura::WINDOW_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
) {
700 parent
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
702 child1
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
705 child2
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
708 child3
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
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
) {
732 parent
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
734 child1
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
736 child2
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
738 child3
.Init(aura::WINDOW_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
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();
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()));
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.
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
) {
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());
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());
976 // Set capture on |w2|, this should send a cancel (TAP_CANCEL, END) to |w1|
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());
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. No new events should be received.
990 // Note this difference in behavior between the first and second capture
991 // is confusing and error prone. http://crbug.com/236930
993 EXPECT_EQ(0, d1
.touch_event_count());
994 EXPECT_EQ(0, d1
.gesture_event_count());
995 EXPECT_EQ(0, d2
.touch_event_count());
996 EXPECT_EQ(0, d2
.gesture_event_count());
997 EXPECT_EQ(0, d3
.touch_event_count());
998 EXPECT_EQ(0, d3
.gesture_event_count());
1000 // Move touch id originally associated with |w2|. Since capture was transfered
1001 // from 2 to 3 only |w3| should get the event.
1002 ui::TouchEvent
m3(ui::ET_TOUCH_MOVED
, gfx::Point(110, 105), 1, getTime());
1003 DispatchEventUsingWindowDispatcher(&m3
);
1004 EXPECT_EQ(0, d1
.touch_event_count());
1005 EXPECT_EQ(0, d1
.gesture_event_count());
1006 EXPECT_EQ(0, d2
.touch_event_count());
1007 EXPECT_EQ(0, d2
.gesture_event_count());
1008 // |w3| gets a TOUCH_MOVE, TAP_CANCEL and two scroll related events.
1009 EXPECT_EQ(1, d3
.touch_event_count());
1010 EXPECT_EQ(3, d3
.gesture_event_count());
1015 // When we release capture, no touches are canceled.
1016 w3
->ReleaseCapture();
1017 EXPECT_EQ(0, d1
.touch_event_count());
1018 EXPECT_EQ(0, d1
.gesture_event_count());
1019 EXPECT_EQ(0, d2
.touch_event_count());
1020 EXPECT_EQ(0, d2
.gesture_event_count());
1021 EXPECT_EQ(0, d3
.touch_event_count());
1022 EXPECT_EQ(0, d3
.gesture_event_count());
1024 // And when we move the touch again, |w3| still gets the events.
1025 ui::TouchEvent
m4(ui::ET_TOUCH_MOVED
, gfx::Point(120, 105), 1, getTime());
1026 DispatchEventUsingWindowDispatcher(&m4
);
1027 EXPECT_EQ(0, d1
.touch_event_count());
1028 EXPECT_EQ(0, d1
.gesture_event_count());
1029 EXPECT_EQ(0, d2
.touch_event_count());
1030 EXPECT_EQ(0, d2
.gesture_event_count());
1031 EXPECT_EQ(1, d3
.touch_event_count());
1032 EXPECT_EQ(1, d3
.gesture_event_count());
1038 // Changes capture while capture is already ongoing.
1039 TEST_F(WindowTest
, ChangeCaptureWhileMouseDown
) {
1040 CaptureWindowDelegateImpl delegate
;
1041 scoped_ptr
<Window
> window(CreateTestWindowWithDelegate(
1042 &delegate
, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1043 CaptureWindowDelegateImpl delegate2
;
1044 scoped_ptr
<Window
> w2(CreateTestWindowWithDelegate(
1045 &delegate2
, 0, gfx::Rect(20, 20, 20, 20), root_window()));
1047 // Execute the scheduled draws so that mouse events are not
1049 RunAllPendingInMessageLoop();
1051 EXPECT_FALSE(window
->HasCapture());
1054 delegate
.ResetCounts();
1055 window
->SetCapture();
1056 EXPECT_TRUE(window
->HasCapture());
1057 EXPECT_EQ(0, delegate
.capture_lost_count());
1058 EXPECT_EQ(0, delegate
.capture_changed_event_count());
1059 ui::test::EventGenerator
generator(root_window(), gfx::Point(50, 50));
1060 generator
.PressLeftButton();
1061 EXPECT_EQ(0, delegate
.capture_lost_count());
1062 EXPECT_EQ(0, delegate
.capture_changed_event_count());
1063 EXPECT_EQ(1, delegate
.mouse_event_count());
1065 // Set capture to |w2|, should implicitly unset capture for |window|.
1066 delegate
.ResetCounts();
1067 delegate2
.ResetCounts();
1070 generator
.MoveMouseTo(gfx::Point(40, 40), 2);
1071 EXPECT_EQ(1, delegate
.capture_lost_count());
1072 EXPECT_EQ(1, delegate
.capture_changed_event_count());
1073 EXPECT_EQ(1, delegate
.mouse_event_count());
1074 EXPECT_EQ(2, delegate2
.mouse_event_count());
1077 // Verifies capture is reset when a window is destroyed.
1078 TEST_F(WindowTest
, ReleaseCaptureOnDestroy
) {
1079 CaptureWindowDelegateImpl delegate
;
1080 scoped_ptr
<Window
> window(CreateTestWindowWithDelegate(
1081 &delegate
, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1082 EXPECT_FALSE(window
->HasCapture());
1085 window
->SetCapture();
1086 EXPECT_TRUE(window
->HasCapture());
1088 // Destroy the window.
1091 // Make sure the root window doesn't reference the window anymore.
1092 EXPECT_EQ(NULL
, host()->dispatcher()->mouse_pressed_handler());
1093 EXPECT_EQ(NULL
, aura::client::GetCaptureWindow(root_window()));
1096 TEST_F(WindowTest
, GetBoundsInRootWindow
) {
1097 scoped_ptr
<Window
> viewport(CreateTestWindowWithBounds(
1098 gfx::Rect(0, 0, 300, 300), root_window()));
1099 scoped_ptr
<Window
> child(CreateTestWindowWithBounds(
1100 gfx::Rect(0, 0, 100, 100), viewport
.get()));
1102 EXPECT_EQ("0,0 100x100", child
->GetBoundsInRootWindow().ToString());
1104 // The |child| window's screen bounds should move along with the |viewport|.
1105 viewport
->SetBounds(gfx::Rect(-100, -100, 300, 300));
1106 EXPECT_EQ("-100,-100 100x100", child
->GetBoundsInRootWindow().ToString());
1108 // The |child| window is moved to the 0,0 in screen coordinates.
1109 // |GetBoundsInRootWindow()| should return 0,0.
1110 child
->SetBounds(gfx::Rect(100, 100, 100, 100));
1111 EXPECT_EQ("0,0 100x100", child
->GetBoundsInRootWindow().ToString());
1114 TEST_F(WindowTest
, GetBoundsInRootWindowWithLayers
) {
1115 scoped_ptr
<Window
> viewport(
1116 CreateTestWindowWithBounds(gfx::Rect(0, 0, 300, 300), root_window()));
1118 scoped_ptr
<Window
> widget(
1119 CreateTestWindowWithBounds(gfx::Rect(0, 0, 200, 200), viewport
.get()));
1121 scoped_ptr
<Window
> child(
1122 CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), widget
.get()));
1125 EXPECT_EQ("0,0 100x100", child
->GetBoundsInRootWindow().ToString());
1127 // The |child| window's screen bounds should move along with the |viewport|.
1128 OffsetBounds(viewport
.get(), -100, -100);
1129 EXPECT_EQ("-100,-100 100x100", child
->GetBoundsInRootWindow().ToString());
1131 OffsetBounds(widget
.get(), 50, 50);
1132 EXPECT_EQ("-50,-50 100x100", child
->GetBoundsInRootWindow().ToString());
1134 // The |child| window is moved to the 0,0 in screen coordinates.
1135 // |GetBoundsInRootWindow()| should return 0,0.
1136 OffsetBounds(child
.get(), 50, 50);
1137 EXPECT_EQ("0,0 100x100", child
->GetBoundsInRootWindow().ToString());
1140 TEST_F(WindowTest
, GetBoundsInRootWindowWithLayersAndTranslations
) {
1141 scoped_ptr
<Window
> viewport(
1142 CreateTestWindowWithBounds(gfx::Rect(0, 0, 300, 300), root_window()));
1144 scoped_ptr
<Window
> widget(
1145 CreateTestWindowWithBounds(gfx::Rect(0, 0, 200, 200), viewport
.get()));
1147 scoped_ptr
<Window
> child(
1148 CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), widget
.get()));
1151 EXPECT_EQ("0,0 100x100", child
->GetBoundsInRootWindow().ToString());
1153 // The |child| window's screen bounds should move along with the |viewport|.
1154 viewport
->SetBounds(gfx::Rect(-100, -100, 300, 300));
1155 EXPECT_EQ("-100,-100 100x100", child
->GetBoundsInRootWindow().ToString());
1157 widget
->SetBounds(gfx::Rect(50, 50, 200, 200));
1158 EXPECT_EQ("-50,-50 100x100", child
->GetBoundsInRootWindow().ToString());
1160 // The |child| window is moved to the 0,0 in screen coordinates.
1161 // |GetBoundsInRootWindow()| should return 0,0.
1162 child
->SetBounds(gfx::Rect(50, 50, 100, 100));
1163 EXPECT_EQ("0,0 100x100", child
->GetBoundsInRootWindow().ToString());
1165 gfx::Transform transform1
;
1166 transform1
.Translate(-10, 20);
1167 viewport
->SetTransform(transform1
);
1168 EXPECT_EQ("-10,20 100x100", child
->GetBoundsInRootWindow().ToString());
1170 gfx::Transform transform2
;
1171 transform2
.Translate(40, 100);
1172 widget
->SetTransform(transform2
);
1173 EXPECT_EQ("30,120 100x100", child
->GetBoundsInRootWindow().ToString());
1175 // Testing potentially buggy place
1176 gfx::Transform transform3
;
1177 transform3
.Translate(-30, -120);
1178 child
->SetTransform(transform3
);
1179 EXPECT_EQ("0,0 100x100", child
->GetBoundsInRootWindow().ToString());
1182 // TODO(tdanderson): Remove this class and use
1183 // test::EventCountDelegate in its place.
1184 class MouseEnterExitWindowDelegate
: public TestWindowDelegate
{
1186 MouseEnterExitWindowDelegate() : entered_(false), exited_(false) {}
1188 void OnMouseEvent(ui::MouseEvent
* event
) override
{
1189 switch (event
->type()) {
1190 case ui::ET_MOUSE_ENTERED
:
1191 EXPECT_TRUE(event
->flags() & ui::EF_IS_SYNTHESIZED
);
1194 case ui::ET_MOUSE_EXITED
:
1195 EXPECT_TRUE(event
->flags() & ui::EF_IS_SYNTHESIZED
);
1203 bool entered() const { return entered_
; }
1204 bool exited() const { return exited_
; }
1206 // Clear the entered / exited states.
1207 void ResetExpectations() {
1216 DISALLOW_COPY_AND_ASSIGN(MouseEnterExitWindowDelegate
);
1219 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1220 // mouse transitions from window to window.
1221 TEST_F(WindowTest
, MouseEnterExit
) {
1222 MouseEnterExitWindowDelegate d1
;
1223 scoped_ptr
<Window
> w1(
1224 CreateTestWindowWithDelegate(&d1
, 1, gfx::Rect(10, 10, 50, 50),
1226 MouseEnterExitWindowDelegate d2
;
1227 scoped_ptr
<Window
> w2(
1228 CreateTestWindowWithDelegate(&d2
, 2, gfx::Rect(70, 70, 50, 50),
1231 ui::test::EventGenerator
generator(root_window());
1232 generator
.MoveMouseToCenterOf(w1
.get());
1233 EXPECT_TRUE(d1
.entered());
1234 EXPECT_FALSE(d1
.exited());
1235 EXPECT_FALSE(d2
.entered());
1236 EXPECT_FALSE(d2
.exited());
1238 generator
.MoveMouseToCenterOf(w2
.get());
1239 EXPECT_TRUE(d1
.entered());
1240 EXPECT_TRUE(d1
.exited());
1241 EXPECT_TRUE(d2
.entered());
1242 EXPECT_FALSE(d2
.exited());
1245 // Verifies that the WindowDelegate receives MouseExit from ET_MOUSE_EXITED.
1246 TEST_F(WindowTest
, WindowTreeHostExit
) {
1247 MouseEnterExitWindowDelegate d1
;
1248 scoped_ptr
<Window
> w1(
1249 CreateTestWindowWithDelegate(&d1
, 1, gfx::Rect(10, 10, 50, 50),
1252 ui::test::EventGenerator
generator(root_window());
1253 generator
.MoveMouseToCenterOf(w1
.get());
1254 EXPECT_TRUE(d1
.entered());
1255 EXPECT_FALSE(d1
.exited());
1256 d1
.ResetExpectations();
1258 ui::MouseEvent
exit_event(ui::ET_MOUSE_EXITED
, gfx::Point(), gfx::Point(),
1259 ui::EventTimeForNow(), 0, 0);
1260 DispatchEventUsingWindowDispatcher(&exit_event
);
1261 EXPECT_FALSE(d1
.entered());
1262 EXPECT_TRUE(d1
.exited());
1265 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1266 // mouse transitions from window to window, even if the entered window sets
1267 // and releases capture.
1268 TEST_F(WindowTest
, MouseEnterExitWithClick
) {
1269 MouseEnterExitWindowDelegate d1
;
1270 scoped_ptr
<Window
> w1(
1271 CreateTestWindowWithDelegate(&d1
, 1, gfx::Rect(10, 10, 50, 50),
1273 MouseEnterExitWindowDelegate d2
;
1274 scoped_ptr
<Window
> w2(
1275 CreateTestWindowWithDelegate(&d2
, 2, gfx::Rect(70, 70, 50, 50),
1278 ui::test::EventGenerator
generator(root_window());
1279 generator
.MoveMouseToCenterOf(w1
.get());
1280 EXPECT_TRUE(d1
.entered());
1281 EXPECT_FALSE(d1
.exited());
1282 EXPECT_FALSE(d2
.entered());
1283 EXPECT_FALSE(d2
.exited());
1285 // Emmulate what Views does on a click by grabbing and releasing capture.
1286 generator
.PressLeftButton();
1288 w1
->ReleaseCapture();
1289 generator
.ReleaseLeftButton();
1291 generator
.MoveMouseToCenterOf(w2
.get());
1292 EXPECT_TRUE(d1
.entered());
1293 EXPECT_TRUE(d1
.exited());
1294 EXPECT_TRUE(d2
.entered());
1295 EXPECT_FALSE(d2
.exited());
1298 TEST_F(WindowTest
, MouseEnterExitWhenDeleteWithCapture
) {
1299 MouseEnterExitWindowDelegate delegate
;
1300 scoped_ptr
<Window
> window(
1301 CreateTestWindowWithDelegate(&delegate
, 1, gfx::Rect(10, 10, 50, 50),
1304 ui::test::EventGenerator
generator(root_window());
1305 generator
.MoveMouseToCenterOf(window
.get());
1306 EXPECT_TRUE(delegate
.entered());
1307 EXPECT_FALSE(delegate
.exited());
1309 // Emmulate what Views does on a click by grabbing and releasing capture.
1310 generator
.PressLeftButton();
1311 window
->SetCapture();
1313 delegate
.ResetExpectations();
1314 generator
.MoveMouseTo(0, 0);
1315 EXPECT_FALSE(delegate
.entered());
1316 EXPECT_FALSE(delegate
.exited());
1318 delegate
.ResetExpectations();
1320 EXPECT_FALSE(delegate
.entered());
1321 EXPECT_FALSE(delegate
.exited());
1324 // Verifies that the correct enter / exits are sent if windows appear and are
1325 // deleted under the current mouse position.
1326 TEST_F(WindowTest
, MouseEnterExitWithWindowAppearAndDelete
) {
1327 MouseEnterExitWindowDelegate d1
;
1328 scoped_ptr
<Window
> w1(
1329 CreateTestWindowWithDelegate(&d1
, 1, gfx::Rect(10, 10, 50, 50),
1332 // The cursor is moved into the bounds of |w1|. We expect the delegate
1333 // of |w1| to see an ET_MOUSE_ENTERED event.
1334 ui::test::EventGenerator
generator(root_window());
1335 generator
.MoveMouseToCenterOf(w1
.get());
1336 EXPECT_TRUE(d1
.entered());
1337 EXPECT_FALSE(d1
.exited());
1338 d1
.ResetExpectations();
1340 MouseEnterExitWindowDelegate d2
;
1342 scoped_ptr
<Window
> w2(
1343 CreateTestWindowWithDelegate(&d2
, 2, gfx::Rect(10, 10, 50, 50),
1345 // Enters / exits can be sent asynchronously.
1346 RunAllPendingInMessageLoop();
1348 // |w2| appears over top of |w1|. We expect the delegate of |w1| to see
1349 // an ET_MOUSE_EXITED and the delegate of |w2| to see an ET_MOUSE_ENTERED.
1350 EXPECT_FALSE(d1
.entered());
1351 EXPECT_TRUE(d1
.exited());
1352 EXPECT_TRUE(d2
.entered());
1353 EXPECT_FALSE(d2
.exited());
1354 d1
.ResetExpectations();
1355 d2
.ResetExpectations();
1358 // Enters / exits can be sent asynchronously.
1359 RunAllPendingInMessageLoop();
1361 // |w2| has been destroyed, so its delegate should see no further events.
1362 // The delegate of |w1| should see an ET_MOUSE_ENTERED event.
1363 EXPECT_TRUE(d1
.entered());
1364 EXPECT_FALSE(d1
.exited());
1365 EXPECT_FALSE(d2
.entered());
1366 EXPECT_FALSE(d2
.exited());
1369 // Verifies that enter / exits are sent if windows appear and are hidden
1370 // under the current mouse position..
1371 TEST_F(WindowTest
, MouseEnterExitWithHide
) {
1372 MouseEnterExitWindowDelegate d1
;
1373 scoped_ptr
<Window
> w1(
1374 CreateTestWindowWithDelegate(&d1
, 1, gfx::Rect(10, 10, 50, 50),
1377 ui::test::EventGenerator
generator(root_window());
1378 generator
.MoveMouseToCenterOf(w1
.get());
1379 EXPECT_TRUE(d1
.entered());
1380 EXPECT_FALSE(d1
.exited());
1382 MouseEnterExitWindowDelegate d2
;
1383 scoped_ptr
<Window
> w2(
1384 CreateTestWindowWithDelegate(&d2
, 2, gfx::Rect(10, 10, 50, 50),
1386 // Enters / exits can be send asynchronously.
1387 RunAllPendingInMessageLoop();
1388 EXPECT_TRUE(d1
.entered());
1389 EXPECT_TRUE(d1
.exited());
1390 EXPECT_TRUE(d2
.entered());
1391 EXPECT_FALSE(d2
.exited());
1393 d1
.ResetExpectations();
1395 // Enters / exits can be send asynchronously.
1396 RunAllPendingInMessageLoop();
1397 EXPECT_TRUE(d2
.exited());
1398 EXPECT_TRUE(d1
.entered());
1401 TEST_F(WindowTest
, MouseEnterExitWithParentHide
) {
1402 MouseEnterExitWindowDelegate d1
;
1403 scoped_ptr
<Window
> w1(
1404 CreateTestWindowWithDelegate(&d1
, 1, gfx::Rect(10, 10, 50, 50),
1406 MouseEnterExitWindowDelegate d2
;
1407 Window
* w2
= CreateTestWindowWithDelegate(&d2
, 2, gfx::Rect(10, 10, 50, 50),
1409 ui::test::EventGenerator
generator(root_window());
1410 generator
.MoveMouseToCenterOf(w2
);
1411 // Enters / exits can be send asynchronously.
1412 RunAllPendingInMessageLoop();
1413 EXPECT_TRUE(d2
.entered());
1414 EXPECT_FALSE(d2
.exited());
1416 d2
.ResetExpectations();
1418 RunAllPendingInMessageLoop();
1419 EXPECT_FALSE(d2
.entered());
1420 EXPECT_TRUE(d2
.exited());
1425 TEST_F(WindowTest
, MouseEnterExitWithParentDelete
) {
1426 MouseEnterExitWindowDelegate d1
;
1427 scoped_ptr
<Window
> w1(
1428 CreateTestWindowWithDelegate(&d1
, 1, gfx::Rect(10, 10, 50, 50),
1430 MouseEnterExitWindowDelegate d2
;
1431 Window
* w2
= CreateTestWindowWithDelegate(&d2
, 2, gfx::Rect(10, 10, 50, 50),
1433 ui::test::EventGenerator
generator(root_window());
1434 generator
.MoveMouseToCenterOf(w2
);
1436 // Enters / exits can be send asynchronously.
1437 RunAllPendingInMessageLoop();
1438 EXPECT_TRUE(d2
.entered());
1439 EXPECT_FALSE(d2
.exited());
1441 d2
.ResetExpectations();
1443 RunAllPendingInMessageLoop();
1445 // Both windows are in the process of destroying, so their delegates should
1446 // not see any mouse events.
1447 EXPECT_FALSE(d1
.entered());
1448 EXPECT_FALSE(d1
.exited());
1449 EXPECT_FALSE(d2
.entered());
1450 EXPECT_FALSE(d2
.exited());
1453 // Creates a window with a delegate (w111) that can handle events at a lower
1454 // z-index than a window without a delegate (w12). w12 is sized to fill the
1455 // entire bounds of the container. This test verifies that
1456 // GetEventHandlerForPoint() skips w12 even though its bounds contain the event,
1457 // because it has no children that can handle the event and it has no delegate
1458 // allowing it to handle the event itself.
1459 TEST_F(WindowTest
, GetEventHandlerForPoint_NoDelegate
) {
1460 TestWindowDelegate d111
;
1461 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(NULL
, 1,
1462 gfx::Rect(0, 0, 500, 500), root_window()));
1463 scoped_ptr
<Window
> w11(CreateTestWindowWithDelegate(NULL
, 11,
1464 gfx::Rect(0, 0, 500, 500), w1
.get()));
1465 scoped_ptr
<Window
> w111(CreateTestWindowWithDelegate(&d111
, 111,
1466 gfx::Rect(50, 50, 450, 450), w11
.get()));
1467 scoped_ptr
<Window
> w12(CreateTestWindowWithDelegate(NULL
, 12,
1468 gfx::Rect(0, 0, 500, 500), w1
.get()));
1470 gfx::Point target_point
= w111
->bounds().CenterPoint();
1471 EXPECT_EQ(w111
.get(), w1
->GetEventHandlerForPoint(target_point
));
1474 class VisibilityWindowDelegate
: public TestWindowDelegate
{
1476 VisibilityWindowDelegate()
1481 int shown() const { return shown_
; }
1482 int hidden() const { return hidden_
; }
1488 void OnWindowTargetVisibilityChanged(bool visible
) override
{
1499 DISALLOW_COPY_AND_ASSIGN(VisibilityWindowDelegate
);
1502 // Verifies show/hide propagate correctly to children and the layer.
1503 TEST_F(WindowTest
, Visibility
) {
1504 VisibilityWindowDelegate d
;
1505 VisibilityWindowDelegate d2
;
1506 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(&d
, 1, gfx::Rect(),
1508 scoped_ptr
<Window
> w2(
1509 CreateTestWindowWithDelegate(&d2
, 2, gfx::Rect(), w1
.get()));
1510 scoped_ptr
<Window
> w3(CreateTestWindowWithId(3, w2
.get()));
1512 // Create shows all the windows.
1513 EXPECT_TRUE(w1
->IsVisible());
1514 EXPECT_TRUE(w2
->IsVisible());
1515 EXPECT_TRUE(w3
->IsVisible());
1516 EXPECT_EQ(1, d
.shown());
1520 EXPECT_FALSE(w1
->IsVisible());
1521 EXPECT_FALSE(w2
->IsVisible());
1522 EXPECT_FALSE(w3
->IsVisible());
1523 EXPECT_EQ(1, d
.hidden());
1524 EXPECT_EQ(0, d
.shown());
1527 EXPECT_FALSE(w1
->IsVisible());
1528 EXPECT_FALSE(w2
->IsVisible());
1529 EXPECT_FALSE(w3
->IsVisible());
1532 EXPECT_FALSE(w1
->IsVisible());
1533 EXPECT_FALSE(w2
->IsVisible());
1534 EXPECT_FALSE(w3
->IsVisible());
1538 EXPECT_TRUE(w1
->IsVisible());
1539 EXPECT_TRUE(w2
->IsVisible());
1540 EXPECT_FALSE(w3
->IsVisible());
1541 EXPECT_EQ(0, d
.hidden());
1542 EXPECT_EQ(1, d
.shown());
1545 EXPECT_TRUE(w1
->IsVisible());
1546 EXPECT_TRUE(w2
->IsVisible());
1547 EXPECT_TRUE(w3
->IsVisible());
1549 // Verify that if an ancestor isn't visible and we change the visibility of a
1550 // child window that OnChildWindowVisibilityChanged() is still invoked.
1554 EXPECT_EQ(1, d2
.hidden());
1555 EXPECT_EQ(0, d2
.shown());
1558 EXPECT_EQ(0, d2
.hidden());
1559 EXPECT_EQ(1, d2
.shown());
1562 TEST_F(WindowTest
, IgnoreEventsTest
) {
1563 TestWindowDelegate d11
;
1564 TestWindowDelegate d12
;
1565 TestWindowDelegate d111
;
1566 TestWindowDelegate d121
;
1567 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(NULL
, 1,
1568 gfx::Rect(0, 0, 500, 500), root_window()));
1569 scoped_ptr
<Window
> w11(CreateTestWindowWithDelegate(&d11
, 11,
1570 gfx::Rect(0, 0, 500, 500), w1
.get()));
1571 scoped_ptr
<Window
> w111(CreateTestWindowWithDelegate(&d111
, 111,
1572 gfx::Rect(50, 50, 450, 450), w11
.get()));
1573 scoped_ptr
<Window
> w12(CreateTestWindowWithDelegate(&d12
, 12,
1574 gfx::Rect(0, 0, 500, 500), w1
.get()));
1575 scoped_ptr
<Window
> w121(CreateTestWindowWithDelegate(&d121
, 121,
1576 gfx::Rect(150, 150, 50, 50), w12
.get()));
1578 EXPECT_EQ(w12
.get(), w1
->GetEventHandlerForPoint(gfx::Point(10, 10)));
1579 w12
->set_ignore_events(true);
1580 EXPECT_EQ(w11
.get(), w1
->GetEventHandlerForPoint(gfx::Point(10, 10)));
1581 w12
->set_ignore_events(false);
1583 EXPECT_EQ(w121
.get(), w1
->GetEventHandlerForPoint(gfx::Point(160, 160)));
1584 w121
->set_ignore_events(true);
1585 EXPECT_EQ(w12
.get(), w1
->GetEventHandlerForPoint(gfx::Point(160, 160)));
1586 w12
->set_ignore_events(true);
1587 EXPECT_EQ(w111
.get(), w1
->GetEventHandlerForPoint(gfx::Point(160, 160)));
1588 w111
->set_ignore_events(true);
1589 EXPECT_EQ(w11
.get(), w1
->GetEventHandlerForPoint(gfx::Point(160, 160)));
1592 // Tests transformation on the root window.
1593 TEST_F(WindowTest
, Transform
) {
1594 gfx::Size size
= host()->GetBounds().size();
1595 EXPECT_EQ(gfx::Rect(size
),
1596 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1597 gfx::Point()).bounds());
1599 // Rotate it clock-wise 90 degrees.
1600 gfx::Transform transform
;
1601 transform
.Translate(size
.height(), 0);
1602 transform
.Rotate(90.0);
1603 host()->SetRootTransform(transform
);
1605 // The size should be the transformed size.
1606 gfx::Size
transformed_size(size
.height(), size
.width());
1607 EXPECT_EQ(transformed_size
.ToString(),
1608 root_window()->bounds().size().ToString());
1610 gfx::Rect(transformed_size
).ToString(),
1611 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1612 gfx::Point()).bounds().ToString());
1614 // Host size shouldn't change.
1615 EXPECT_EQ(size
.ToString(), host()->GetBounds().size().ToString());
1618 TEST_F(WindowTest
, TransformGesture
) {
1619 gfx::Size size
= host()->GetBounds().size();
1621 scoped_ptr
<GestureTrackPositionDelegate
> delegate(
1622 new GestureTrackPositionDelegate
);
1623 scoped_ptr
<Window
> window(CreateTestWindowWithDelegate(delegate
.get(), -1234,
1624 gfx::Rect(0, 0, 20, 20), root_window()));
1626 // Rotate the root-window clock-wise 90 degrees.
1627 gfx::Transform transform
;
1628 transform
.Translate(size
.height(), 0.0);
1629 transform
.Rotate(90.0);
1630 host()->SetRootTransform(transform
);
1632 ui::TouchEvent
press(
1633 ui::ET_TOUCH_PRESSED
, gfx::Point(size
.height() - 10, 10), 0, getTime());
1634 DispatchEventUsingWindowDispatcher(&press
);
1635 EXPECT_EQ(gfx::Point(10, 10).ToString(), delegate
->position().ToString());
1639 DEFINE_WINDOW_PROPERTY_KEY(int, kIntKey
, -2);
1640 DEFINE_WINDOW_PROPERTY_KEY(const char*, kStringKey
, "squeamish");
1643 TEST_F(WindowTest
, Property
) {
1644 scoped_ptr
<Window
> w(CreateTestWindowWithId(0, root_window()));
1646 static const char native_prop_key
[] = "fnord";
1648 // Non-existent properties should return the default values.
1649 EXPECT_EQ(-2, w
->GetProperty(kIntKey
));
1650 EXPECT_EQ(std::string("squeamish"), w
->GetProperty(kStringKey
));
1651 EXPECT_EQ(NULL
, w
->GetNativeWindowProperty(native_prop_key
));
1653 // A set property value should be returned again (even if it's the default
1655 w
->SetProperty(kIntKey
, INT_MAX
);
1656 EXPECT_EQ(INT_MAX
, w
->GetProperty(kIntKey
));
1657 w
->SetProperty(kIntKey
, -2);
1658 EXPECT_EQ(-2, w
->GetProperty(kIntKey
));
1659 w
->SetProperty(kIntKey
, INT_MIN
);
1660 EXPECT_EQ(INT_MIN
, w
->GetProperty(kIntKey
));
1662 w
->SetProperty(kStringKey
, static_cast<const char*>(NULL
));
1663 EXPECT_EQ(NULL
, w
->GetProperty(kStringKey
));
1664 w
->SetProperty(kStringKey
, "squeamish");
1665 EXPECT_EQ(std::string("squeamish"), w
->GetProperty(kStringKey
));
1666 w
->SetProperty(kStringKey
, "ossifrage");
1667 EXPECT_EQ(std::string("ossifrage"), w
->GetProperty(kStringKey
));
1669 w
->SetNativeWindowProperty(native_prop_key
, &*w
);
1670 EXPECT_EQ(&*w
, w
->GetNativeWindowProperty(native_prop_key
));
1671 w
->SetNativeWindowProperty(native_prop_key
, NULL
);
1672 EXPECT_EQ(NULL
, w
->GetNativeWindowProperty(native_prop_key
));
1674 // ClearProperty should restore the default value.
1675 w
->ClearProperty(kIntKey
);
1676 EXPECT_EQ(-2, w
->GetProperty(kIntKey
));
1677 w
->ClearProperty(kStringKey
);
1678 EXPECT_EQ(std::string("squeamish"), w
->GetProperty(kStringKey
));
1681 TEST_F(WindowTest
, OwnedProperty
) {
1682 scoped_ptr
<Window
> w(CreateTestWindowWithId(0, root_window()));
1683 EXPECT_EQ(NULL
, w
->GetProperty(kOwnedKey
));
1684 TestProperty
* p1
= new TestProperty();
1685 w
->SetProperty(kOwnedKey
, p1
);
1686 EXPECT_EQ(p1
, w
->GetProperty(kOwnedKey
));
1687 EXPECT_EQ(NULL
, TestProperty::last_deleted());
1689 TestProperty
* p2
= new TestProperty();
1690 w
->SetProperty(kOwnedKey
, p2
);
1691 EXPECT_EQ(p2
, w
->GetProperty(kOwnedKey
));
1692 EXPECT_EQ(p1
, TestProperty::last_deleted());
1694 w
->ClearProperty(kOwnedKey
);
1695 EXPECT_EQ(NULL
, w
->GetProperty(kOwnedKey
));
1696 EXPECT_EQ(p2
, TestProperty::last_deleted());
1698 TestProperty
* p3
= new TestProperty();
1699 w
->SetProperty(kOwnedKey
, p3
);
1700 EXPECT_EQ(p3
, w
->GetProperty(kOwnedKey
));
1701 EXPECT_EQ(p2
, TestProperty::last_deleted());
1703 EXPECT_EQ(p3
, TestProperty::last_deleted());
1706 TEST_F(WindowTest
, SetBoundsInternalShouldCheckTargetBounds
) {
1707 // We cannot short-circuit animations in this test.
1708 ui::ScopedAnimationDurationScaleMode
test_duration_mode(
1709 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION
);
1711 scoped_ptr
<Window
> w1(
1712 CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), root_window()));
1714 EXPECT_FALSE(!w1
->layer());
1715 w1
->layer()->GetAnimator()->set_disable_timer_for_test(true);
1716 ui::LayerAnimator
* animator
= w1
->layer()->GetAnimator();
1718 EXPECT_EQ("0,0 100x100", w1
->bounds().ToString());
1719 EXPECT_EQ("0,0 100x100", w1
->layer()->GetTargetBounds().ToString());
1721 // Animate to a different position.
1723 ui::ScopedLayerAnimationSettings
settings(w1
->layer()->GetAnimator());
1724 w1
->SetBounds(gfx::Rect(100, 100, 100, 100));
1727 EXPECT_EQ("0,0 100x100", w1
->bounds().ToString());
1728 EXPECT_EQ("100,100 100x100", w1
->layer()->GetTargetBounds().ToString());
1730 // Animate back to the first position. The animation hasn't started yet, so
1731 // the current bounds are still (0, 0, 100, 100), but the target bounds are
1732 // (100, 100, 100, 100). If we step the animator ahead, we should find that
1733 // we're at (0, 0, 100, 100). That is, the second animation should be applied.
1735 ui::ScopedLayerAnimationSettings
settings(w1
->layer()->GetAnimator());
1736 w1
->SetBounds(gfx::Rect(0, 0, 100, 100));
1739 EXPECT_EQ("0,0 100x100", w1
->bounds().ToString());
1740 EXPECT_EQ("0,0 100x100", w1
->layer()->GetTargetBounds().ToString());
1742 // Confirm that the target bounds are reached.
1743 base::TimeTicks start_time
=
1744 w1
->layer()->GetAnimator()->last_step_time();
1746 animator
->Step(start_time
+ base::TimeDelta::FromMilliseconds(1000));
1748 EXPECT_EQ("0,0 100x100", w1
->bounds().ToString());
1752 typedef std::pair
<const void*, intptr_t> PropertyChangeInfo
;
1754 class WindowObserverTest
: public WindowTest
,
1755 public WindowObserver
{
1757 struct VisibilityInfo
{
1758 bool window_visible
;
1763 WindowObserverTest()
1766 destroyed_count_(0),
1767 old_property_value_(-3) {
1770 ~WindowObserverTest() override
{}
1772 const VisibilityInfo
* GetVisibilityInfo() const {
1773 return visibility_info_
.get();
1776 void ResetVisibilityInfo() {
1777 visibility_info_
.reset();
1780 // Returns a description of the WindowObserver methods that have been invoked.
1781 std::string
WindowObserverCountStateAndClear() {
1783 base::StringPrintf("added=%d removed=%d",
1784 added_count_
, removed_count_
));
1785 added_count_
= removed_count_
= 0;
1789 int DestroyedCountAndClear() {
1790 int result
= destroyed_count_
;
1791 destroyed_count_
= 0;
1795 // Return a tuple of the arguments passed in OnPropertyChanged callback.
1796 PropertyChangeInfo
PropertyChangeInfoAndClear() {
1797 PropertyChangeInfo
result(property_key_
, old_property_value_
);
1798 property_key_
= NULL
;
1799 old_property_value_
= -3;
1803 std::string
TransformNotificationsAndClear() {
1805 for (std::vector
<std::pair
<int, int> >::iterator it
=
1806 transform_notifications_
.begin();
1807 it
!= transform_notifications_
.end();
1809 base::StringAppendF(&result
, "(%d,%d)", it
->first
, it
->second
);
1811 transform_notifications_
.clear();
1816 void OnWindowAdded(Window
* new_window
) override
{ added_count_
++; }
1818 void OnWillRemoveWindow(Window
* window
) override
{ removed_count_
++; }
1820 void OnWindowVisibilityChanged(Window
* window
, bool visible
) override
{
1821 if (!visibility_info_
) {
1822 visibility_info_
.reset(new VisibilityInfo
);
1823 visibility_info_
->changed_count
= 0;
1825 visibility_info_
->window_visible
= window
->IsVisible();
1826 visibility_info_
->visible_param
= visible
;
1827 visibility_info_
->changed_count
++;
1830 void OnWindowDestroyed(Window
* window
) override
{
1831 EXPECT_FALSE(window
->parent());
1835 void OnWindowPropertyChanged(Window
* window
,
1837 intptr_t old
) override
{
1838 property_key_
= key
;
1839 old_property_value_
= old
;
1842 void OnAncestorWindowTransformed(Window
* source
, Window
* window
) override
{
1843 transform_notifications_
.push_back(
1844 std::make_pair(source
->id(), window
->id()));
1849 int destroyed_count_
;
1850 scoped_ptr
<VisibilityInfo
> visibility_info_
;
1851 const void* property_key_
;
1852 intptr_t old_property_value_
;
1853 std::vector
<std::pair
<int, int> > transform_notifications_
;
1855 DISALLOW_COPY_AND_ASSIGN(WindowObserverTest
);
1858 // Various assertions for WindowObserver.
1859 TEST_F(WindowObserverTest
, WindowObserver
) {
1860 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
1861 w1
->AddObserver(this);
1863 // Create a new window as a child of w1, our observer should be notified.
1864 scoped_ptr
<Window
> w2(CreateTestWindowWithId(2, w1
.get()));
1865 EXPECT_EQ("added=1 removed=0", WindowObserverCountStateAndClear());
1867 // Delete w2, which should result in the remove notification.
1869 EXPECT_EQ("added=0 removed=1", WindowObserverCountStateAndClear());
1871 // Create a window that isn't parented to w1, we shouldn't get any
1873 scoped_ptr
<Window
> w3(CreateTestWindowWithId(3, root_window()));
1874 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1876 // Similarly destroying w3 shouldn't notify us either.
1878 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1879 w1
->RemoveObserver(this);
1882 // Test if OnWindowVisibilityChagned is invoked with expected
1884 TEST_F(WindowObserverTest
, WindowVisibility
) {
1885 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
1886 scoped_ptr
<Window
> w2(CreateTestWindowWithId(1, w1
.get()));
1887 w2
->AddObserver(this);
1889 // Hide should make the window invisible and the passed visible
1890 // parameter is false.
1892 EXPECT_FALSE(!GetVisibilityInfo());
1893 EXPECT_FALSE(!GetVisibilityInfo());
1894 if (!GetVisibilityInfo())
1896 EXPECT_FALSE(GetVisibilityInfo()->window_visible
);
1897 EXPECT_FALSE(GetVisibilityInfo()->visible_param
);
1898 EXPECT_EQ(1, GetVisibilityInfo()->changed_count
);
1900 // If parent isn't visible, showing window won't make the window visible, but
1901 // passed visible value must be true.
1903 ResetVisibilityInfo();
1904 EXPECT_TRUE(!GetVisibilityInfo());
1906 EXPECT_FALSE(!GetVisibilityInfo());
1907 if (!GetVisibilityInfo())
1909 EXPECT_FALSE(GetVisibilityInfo()->window_visible
);
1910 EXPECT_TRUE(GetVisibilityInfo()->visible_param
);
1911 EXPECT_EQ(1, GetVisibilityInfo()->changed_count
);
1913 // If parent is visible, showing window will make the window
1914 // visible and the passed visible value is true.
1917 ResetVisibilityInfo();
1919 EXPECT_FALSE(!GetVisibilityInfo());
1920 if (!GetVisibilityInfo())
1922 EXPECT_TRUE(GetVisibilityInfo()->window_visible
);
1923 EXPECT_TRUE(GetVisibilityInfo()->visible_param
);
1924 EXPECT_EQ(1, GetVisibilityInfo()->changed_count
);
1926 // Verify that the OnWindowVisibilityChanged only once
1927 // per visibility change.
1929 EXPECT_EQ(2, GetVisibilityInfo()->changed_count
);
1932 EXPECT_EQ(2, GetVisibilityInfo()->changed_count
);
1935 // Test if OnWindowDestroyed is invoked as expected.
1936 TEST_F(WindowObserverTest
, WindowDestroyed
) {
1937 // Delete a window should fire a destroyed notification.
1938 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
1939 w1
->AddObserver(this);
1941 EXPECT_EQ(1, DestroyedCountAndClear());
1943 // Observe on child and delete parent window should fire a notification.
1944 scoped_ptr
<Window
> parent(CreateTestWindowWithId(1, root_window()));
1945 Window
* child
= CreateTestWindowWithId(1, parent
.get()); // owned by parent
1946 child
->AddObserver(this);
1948 EXPECT_EQ(1, DestroyedCountAndClear());
1951 TEST_F(WindowObserverTest
, PropertyChanged
) {
1952 // Setting property should fire a property change notification.
1953 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
1954 w1
->AddObserver(this);
1956 static const WindowProperty
<int> prop
= {-2};
1957 static const char native_prop_key
[] = "fnord";
1959 w1
->SetProperty(&prop
, 1);
1960 EXPECT_EQ(PropertyChangeInfo(&prop
, -2), PropertyChangeInfoAndClear());
1961 w1
->SetProperty(&prop
, -2);
1962 EXPECT_EQ(PropertyChangeInfo(&prop
, 1), PropertyChangeInfoAndClear());
1963 w1
->SetProperty(&prop
, 3);
1964 EXPECT_EQ(PropertyChangeInfo(&prop
, -2), PropertyChangeInfoAndClear());
1965 w1
->ClearProperty(&prop
);
1966 EXPECT_EQ(PropertyChangeInfo(&prop
, 3), PropertyChangeInfoAndClear());
1968 w1
->SetNativeWindowProperty(native_prop_key
, &*w1
);
1969 EXPECT_EQ(PropertyChangeInfo(native_prop_key
, 0),
1970 PropertyChangeInfoAndClear());
1971 w1
->SetNativeWindowProperty(native_prop_key
, NULL
);
1972 EXPECT_EQ(PropertyChangeInfo(native_prop_key
,
1973 reinterpret_cast<intptr_t>(&*w1
)),
1974 PropertyChangeInfoAndClear());
1976 // Sanity check to see if |PropertyChangeInfoAndClear| really clears.
1977 EXPECT_EQ(PropertyChangeInfo(
1978 reinterpret_cast<const void*>(NULL
), -3), PropertyChangeInfoAndClear());
1981 TEST_F(WindowObserverTest
, AncestorTransformed
) {
1982 // Create following window hierarchy:
1988 // Then, apply a transform to |w1| and ensure all its descendants are
1990 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
1991 w1
->AddObserver(this);
1992 scoped_ptr
<Window
> w2(CreateTestWindowWithId(2, w1
.get()));
1993 w2
->AddObserver(this);
1994 scoped_ptr
<Window
> w3(CreateTestWindowWithId(3, w1
.get()));
1995 w3
->AddObserver(this);
1996 scoped_ptr
<Window
> w4(CreateTestWindowWithId(4, w3
.get()));
1997 w4
->AddObserver(this);
1999 EXPECT_EQ(std::string(), TransformNotificationsAndClear());
2001 gfx::Transform transform
;
2002 transform
.Translate(10, 10);
2003 w1
->SetTransform(transform
);
2005 EXPECT_EQ("(1,1)(1,2)(1,3)(1,4)", TransformNotificationsAndClear());
2008 TEST_F(WindowTest
, AcquireLayer
) {
2009 scoped_ptr
<Window
> window1(CreateTestWindowWithId(1, root_window()));
2010 scoped_ptr
<Window
> window2(CreateTestWindowWithId(2, root_window()));
2011 ui::Layer
* parent
= window1
->parent()->layer();
2012 EXPECT_EQ(2U, parent
->children().size());
2014 WindowTestApi
window1_test_api(window1
.get());
2015 WindowTestApi
window2_test_api(window2
.get());
2017 EXPECT_TRUE(window1_test_api
.OwnsLayer());
2018 EXPECT_TRUE(window2_test_api
.OwnsLayer());
2020 // After acquisition, window1 should not own its layer, but it should still
2021 // be available to the window.
2022 scoped_ptr
<ui::Layer
> window1_layer(window1
->AcquireLayer());
2023 EXPECT_FALSE(window1_test_api
.OwnsLayer());
2024 EXPECT_TRUE(window1_layer
.get() == window1
->layer());
2026 // The acquired layer's owner should be set NULL and re-acquring
2027 // should return NULL.
2028 EXPECT_FALSE(window1_layer
->owner());
2029 scoped_ptr
<ui::Layer
> window1_layer_reacquired(window1
->AcquireLayer());
2030 EXPECT_FALSE(window1_layer_reacquired
.get());
2032 // Upon destruction, window1's layer should still be valid, and in the layer
2033 // hierarchy, but window2's should be gone, and no longer in the hierarchy.
2037 // This should be set by the window's destructor.
2038 EXPECT_TRUE(window1_layer
->delegate() == NULL
);
2039 EXPECT_EQ(1U, parent
->children().size());
2042 // Make sure that properties which should persist from the old layer to the new
2043 // layer actually do.
2044 TEST_F(WindowTest
, RecreateLayer
) {
2045 // Set properties to non default values.
2046 Window
w(new ColorTestWindowDelegate(SK_ColorWHITE
));
2048 w
.Init(aura::WINDOW_LAYER_SOLID_COLOR
);
2049 w
.SetBounds(gfx::Rect(0, 0, 100, 100));
2051 ui::Layer
* layer
= w
.layer();
2052 layer
->SetVisible(false);
2053 layer
->SetMasksToBounds(true);
2055 ui::Layer child_layer
;
2056 layer
->Add(&child_layer
);
2058 scoped_ptr
<ui::Layer
> old_layer(w
.RecreateLayer());
2060 EXPECT_EQ(ui::LAYER_SOLID_COLOR
, layer
->type());
2061 EXPECT_FALSE(layer
->visible());
2062 EXPECT_EQ(1u, layer
->children().size());
2063 EXPECT_TRUE(layer
->GetMasksToBounds());
2064 EXPECT_EQ("0,0 100x100", w
.bounds().ToString());
2065 EXPECT_EQ("0,0 100x100", layer
->bounds().ToString());
2068 // Verify that RecreateLayer() stacks the old layer above the newly creatd
2070 TEST_F(WindowTest
, RecreateLayerZOrder
) {
2071 scoped_ptr
<Window
> w(
2072 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(0, 0, 100, 100),
2074 scoped_ptr
<ui::Layer
> old_layer(w
->RecreateLayer());
2076 const std::vector
<ui::Layer
*>& child_layers
=
2077 root_window()->layer()->children();
2078 ASSERT_EQ(2u, child_layers
.size());
2079 EXPECT_EQ(w
->layer(), child_layers
[0]);
2080 EXPECT_EQ(old_layer
.get(), child_layers
[1]);
2083 // Ensure that acquiring a layer then recreating a layer does not crash
2084 // and that RecreateLayer returns null.
2085 TEST_F(WindowTest
, AcquireThenRecreateLayer
) {
2086 scoped_ptr
<Window
> w(
2087 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(0, 0, 100, 100),
2089 scoped_ptr
<ui::Layer
> acquired_layer(w
->AcquireLayer());
2090 scoped_ptr
<ui::Layer
> doubly_acquired_layer(w
->RecreateLayer());
2091 EXPECT_EQ(NULL
, doubly_acquired_layer
.get());
2093 // Destroy window before layer gets destroyed.
2097 class TestVisibilityClient
: public client::VisibilityClient
{
2099 explicit TestVisibilityClient(Window
* root_window
)
2100 : ignore_visibility_changes_(false) {
2101 client::SetVisibilityClient(root_window
, this);
2103 ~TestVisibilityClient() override
{}
2105 void set_ignore_visibility_changes(bool ignore_visibility_changes
) {
2106 ignore_visibility_changes_
= ignore_visibility_changes
;
2109 // Overridden from client::VisibilityClient:
2110 void UpdateLayerVisibility(aura::Window
* window
, bool visible
) override
{
2111 if (!ignore_visibility_changes_
)
2112 window
->layer()->SetVisible(visible
);
2116 bool ignore_visibility_changes_
;
2117 DISALLOW_COPY_AND_ASSIGN(TestVisibilityClient
);
2120 TEST_F(WindowTest
, VisibilityClientIsVisible
) {
2121 TestVisibilityClient
client(root_window());
2123 scoped_ptr
<Window
> window(CreateTestWindowWithId(1, root_window()));
2124 EXPECT_TRUE(window
->IsVisible());
2125 EXPECT_TRUE(window
->layer()->visible());
2128 EXPECT_FALSE(window
->IsVisible());
2129 EXPECT_FALSE(window
->layer()->visible());
2132 client
.set_ignore_visibility_changes(true);
2134 EXPECT_FALSE(window
->IsVisible());
2135 EXPECT_TRUE(window
->layer()->visible());
2138 // Tests the mouse events seen by WindowDelegates in a Window hierarchy when
2139 // changing the properties of a leaf Window.
2140 TEST_F(WindowTest
, MouseEventsOnLeafWindowChange
) {
2141 gfx::Size size
= host()->GetBounds().size();
2143 ui::test::EventGenerator
generator(root_window());
2144 generator
.MoveMouseTo(50, 50);
2146 EventCountDelegate d1
;
2147 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(&d1
, 1,
2148 gfx::Rect(0, 0, 100, 100), root_window()));
2149 RunAllPendingInMessageLoop();
2150 // The format of result is "Enter/Move/Leave".
2151 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2153 // Add new window |w11| on top of |w1| which contains the cursor.
2154 EventCountDelegate d11
;
2155 scoped_ptr
<Window
> w11(CreateTestWindowWithDelegate(
2156 &d11
, 1, gfx::Rect(0, 0, 100, 100), w1
.get()));
2157 RunAllPendingInMessageLoop();
2158 EXPECT_EQ("0 0 1", d1
.GetMouseMotionCountsAndReset());
2159 EXPECT_EQ("1 1 0", d11
.GetMouseMotionCountsAndReset());
2161 // Resize |w11| so that it does not contain the cursor.
2162 w11
->SetBounds(gfx::Rect(0, 0, 10, 10));
2163 RunAllPendingInMessageLoop();
2164 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2165 EXPECT_EQ("0 0 1", d11
.GetMouseMotionCountsAndReset());
2167 // Resize |w11| so that it does contain the cursor.
2168 w11
->SetBounds(gfx::Rect(0, 0, 60, 60));
2169 RunAllPendingInMessageLoop();
2170 EXPECT_EQ("0 0 1", d1
.GetMouseMotionCountsAndReset());
2171 EXPECT_EQ("1 1 0", d11
.GetMouseMotionCountsAndReset());
2173 // Detach |w11| from |w1|.
2174 w1
->RemoveChild(w11
.get());
2175 RunAllPendingInMessageLoop();
2176 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2177 EXPECT_EQ("0 0 1", d11
.GetMouseMotionCountsAndReset());
2179 // Re-attach |w11| to |w1|.
2180 w1
->AddChild(w11
.get());
2181 RunAllPendingInMessageLoop();
2182 EXPECT_EQ("0 0 1", d1
.GetMouseMotionCountsAndReset());
2183 EXPECT_EQ("1 1 0", d11
.GetMouseMotionCountsAndReset());
2187 RunAllPendingInMessageLoop();
2188 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2189 EXPECT_EQ("0 0 1", d11
.GetMouseMotionCountsAndReset());
2193 RunAllPendingInMessageLoop();
2194 EXPECT_EQ("0 0 1", d1
.GetMouseMotionCountsAndReset());
2195 EXPECT_EQ("1 1 0", d11
.GetMouseMotionCountsAndReset());
2197 // Translate |w11| so that it does not contain the mouse cursor.
2198 gfx::Transform transform
;
2199 transform
.Translate(100, 100);
2200 w11
->SetTransform(transform
);
2201 RunAllPendingInMessageLoop();
2202 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2203 EXPECT_EQ("0 0 1", d11
.GetMouseMotionCountsAndReset());
2205 // Clear the transform on |w11| so that it does contain the cursor.
2206 w11
->SetTransform(gfx::Transform());
2207 RunAllPendingInMessageLoop();
2208 EXPECT_EQ("0 0 1", d1
.GetMouseMotionCountsAndReset());
2209 EXPECT_EQ("1 1 0", d11
.GetMouseMotionCountsAndReset());
2211 // Close |w11|. Note that since |w11| is being destroyed, its delegate should
2212 // not see any further events.
2214 RunAllPendingInMessageLoop();
2215 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2216 EXPECT_EQ("0 0 0", d11
.GetMouseMotionCountsAndReset());
2218 // Move the mouse outside the bounds of the root window. Since the mouse
2219 // cursor is no longer within their bounds, the delegates of the child
2220 // windows should not see any mouse events.
2221 generator
.MoveMouseTo(-10, -10);
2222 EXPECT_EQ("0 0 1", d1
.GetMouseMotionCountsAndReset());
2223 EXPECT_EQ("0 0 0", d11
.GetMouseMotionCountsAndReset());
2226 w11
.reset(CreateTestWindowWithDelegate(
2227 &d11
, 1, gfx::Rect(0, 0, 100, 100), w1
.get()));
2228 RunAllPendingInMessageLoop();
2229 EXPECT_EQ("0 0 0", d1
.GetMouseMotionCountsAndReset());
2230 EXPECT_EQ("0 0 0", d11
.GetMouseMotionCountsAndReset());
2234 RunAllPendingInMessageLoop();
2235 EXPECT_EQ("0 0 0", d1
.GetMouseMotionCountsAndReset());
2236 EXPECT_EQ("0 0 0", d11
.GetMouseMotionCountsAndReset());
2239 // Tests the mouse events seen by WindowDelegates in a Window hierarchy when
2240 // deleting a non-leaf Window.
2241 TEST_F(WindowTest
, MouseEventsOnNonLeafWindowDelete
) {
2242 gfx::Size size
= host()->GetBounds().size();
2244 ui::test::EventGenerator
generator(root_window());
2245 generator
.MoveMouseTo(50, 50);
2247 EventCountDelegate d1
;
2248 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(&d1
, 1,
2249 gfx::Rect(0, 0, 100, 100), root_window()));
2250 RunAllPendingInMessageLoop();
2251 // The format of result is "Enter/Move/Leave".
2252 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2254 // Add new window |w2| on top of |w1| which contains the cursor.
2255 EventCountDelegate d2
;
2256 scoped_ptr
<Window
> w2(CreateTestWindowWithDelegate(
2257 &d2
, 1, gfx::Rect(0, 0, 100, 100), w1
.get()));
2258 RunAllPendingInMessageLoop();
2259 EXPECT_EQ("0 0 1", d1
.GetMouseMotionCountsAndReset());
2260 EXPECT_EQ("1 1 0", d2
.GetMouseMotionCountsAndReset());
2262 // Add new window on top of |w2| which contains the cursor.
2263 EventCountDelegate d3
;
2264 CreateTestWindowWithDelegate(
2265 &d3
, 1, gfx::Rect(0, 0, 100, 100), w2
.get());
2266 RunAllPendingInMessageLoop();
2267 EXPECT_EQ("0 0 0", d1
.GetMouseMotionCountsAndReset());
2268 EXPECT_EQ("0 0 1", d2
.GetMouseMotionCountsAndReset());
2269 EXPECT_EQ("1 1 0", d3
.GetMouseMotionCountsAndReset());
2271 // Delete |w2|, which will also delete its owned child window. Since |w2| and
2272 // its child are in the process of being destroyed, their delegates should
2273 // not see any further events.
2275 RunAllPendingInMessageLoop();
2276 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2277 EXPECT_EQ("0 0 0", d2
.GetMouseMotionCountsAndReset());
2278 EXPECT_EQ("0 0 0", d3
.GetMouseMotionCountsAndReset());
2281 class RootWindowAttachmentObserver
: public WindowObserver
{
2283 RootWindowAttachmentObserver() : added_count_(0), removed_count_(0) {}
2284 ~RootWindowAttachmentObserver() override
{}
2286 int added_count() const { return added_count_
; }
2287 int removed_count() const { return removed_count_
; }
2294 // Overridden from WindowObserver:
2295 void OnWindowAddedToRootWindow(Window
* window
) override
{ ++added_count_
; }
2296 void OnWindowRemovingFromRootWindow(Window
* window
,
2297 Window
* new_root
) override
{
2305 DISALLOW_COPY_AND_ASSIGN(RootWindowAttachmentObserver
);
2308 TEST_F(WindowTest
, RootWindowAttachment
) {
2309 RootWindowAttachmentObserver observer
;
2311 // Test a direct add/remove from the RootWindow.
2312 scoped_ptr
<Window
> w1(new Window(NULL
));
2313 w1
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2314 w1
->AddObserver(&observer
);
2316 ParentWindow(w1
.get());
2317 EXPECT_EQ(1, observer
.added_count());
2318 EXPECT_EQ(0, observer
.removed_count());
2321 EXPECT_EQ(1, observer
.added_count());
2322 EXPECT_EQ(1, observer
.removed_count());
2326 // Test an indirect add/remove from the RootWindow.
2327 w1
.reset(new Window(NULL
));
2328 w1
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2329 Window
* w11
= new Window(NULL
);
2330 w11
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2331 w11
->AddObserver(&observer
);
2333 EXPECT_EQ(0, observer
.added_count());
2334 EXPECT_EQ(0, observer
.removed_count());
2336 ParentWindow(w1
.get());
2337 EXPECT_EQ(1, observer
.added_count());
2338 EXPECT_EQ(0, observer
.removed_count());
2340 w1
.reset(); // Deletes w11.
2342 EXPECT_EQ(1, observer
.added_count());
2343 EXPECT_EQ(1, observer
.removed_count());
2347 // Test an indirect add/remove with nested observers.
2348 w1
.reset(new Window(NULL
));
2349 w1
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2350 w11
= new Window(NULL
);
2351 w11
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2352 w11
->AddObserver(&observer
);
2354 Window
* w111
= new Window(NULL
);
2355 w111
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2356 w111
->AddObserver(&observer
);
2357 w11
->AddChild(w111
);
2359 EXPECT_EQ(0, observer
.added_count());
2360 EXPECT_EQ(0, observer
.removed_count());
2362 ParentWindow(w1
.get());
2363 EXPECT_EQ(2, observer
.added_count());
2364 EXPECT_EQ(0, observer
.removed_count());
2366 w1
.reset(); // Deletes w11 and w111.
2369 EXPECT_EQ(2, observer
.added_count());
2370 EXPECT_EQ(2, observer
.removed_count());
2373 class BoundsChangedWindowObserver
: public WindowObserver
{
2375 BoundsChangedWindowObserver() : root_set_(false) {}
2377 void OnWindowBoundsChanged(Window
* window
,
2378 const gfx::Rect
& old_bounds
,
2379 const gfx::Rect
& new_bounds
) override
{
2380 root_set_
= window
->GetRootWindow() != NULL
;
2383 bool root_set() const { return root_set_
; }
2388 DISALLOW_COPY_AND_ASSIGN(BoundsChangedWindowObserver
);
2391 TEST_F(WindowTest
, RootWindowSetWhenReparenting
) {
2392 Window
parent1(NULL
);
2393 parent1
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2394 Window
parent2(NULL
);
2395 parent2
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2396 ParentWindow(&parent1
);
2397 ParentWindow(&parent2
);
2398 parent1
.SetBounds(gfx::Rect(10, 10, 300, 300));
2399 parent2
.SetBounds(gfx::Rect(20, 20, 300, 300));
2401 BoundsChangedWindowObserver observer
;
2403 child
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2404 child
.SetBounds(gfx::Rect(5, 5, 100, 100));
2405 parent1
.AddChild(&child
);
2407 // We need animations to start in order to observe the bounds changes.
2408 ui::ScopedAnimationDurationScaleMode
test_duration_mode(
2409 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION
);
2410 ui::ScopedLayerAnimationSettings
settings1(child
.layer()->GetAnimator());
2411 settings1
.SetTransitionDuration(base::TimeDelta::FromMilliseconds(100));
2412 gfx::Rect
new_bounds(gfx::Rect(35, 35, 50, 50));
2413 child
.SetBounds(new_bounds
);
2415 child
.AddObserver(&observer
);
2417 // Reparenting the |child| will cause it to get moved. During this move
2418 // the window should still have root window set.
2419 parent2
.AddChild(&child
);
2420 EXPECT_TRUE(observer
.root_set());
2422 // Animations should stop and the bounds should be as set before the |child|
2424 EXPECT_EQ(new_bounds
.ToString(), child
.GetTargetBounds().ToString());
2425 EXPECT_EQ(new_bounds
.ToString(), child
.bounds().ToString());
2426 EXPECT_EQ("55,55 50x50", child
.GetBoundsInRootWindow().ToString());
2429 TEST_F(WindowTest
, OwnedByParentFalse
) {
2430 // By default, a window is owned by its parent. If this is set to false, the
2431 // window will not be destroyed when its parent is.
2433 scoped_ptr
<Window
> w1(new Window(NULL
));
2434 w1
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2435 scoped_ptr
<Window
> w2(new Window(NULL
));
2436 w2
->set_owned_by_parent(false);
2437 w2
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2438 w1
->AddChild(w2
.get());
2442 // We should be able to deref w2 still, but its parent should now be NULL.
2443 EXPECT_EQ(NULL
, w2
->parent());
2448 // Used By DeleteWindowFromOnWindowDestroyed. Destroys a Window from
2449 // OnWindowDestroyed().
2450 class OwningWindowDelegate
: public TestWindowDelegate
{
2452 OwningWindowDelegate() {}
2454 void SetOwnedWindow(Window
* window
) {
2455 owned_window_
.reset(window
);
2458 void OnWindowDestroyed(Window
* window
) override
{ owned_window_
.reset(NULL
); }
2461 scoped_ptr
<Window
> owned_window_
;
2463 DISALLOW_COPY_AND_ASSIGN(OwningWindowDelegate
);
2468 // Creates a window with two child windows. When the first child window is
2469 // destroyed (WindowDelegate::OnWindowDestroyed) it deletes the second child.
2470 // This synthesizes BrowserView and the status bubble. Both are children of the
2471 // same parent and destroying BrowserView triggers it destroying the status
2473 TEST_F(WindowTest
, DeleteWindowFromOnWindowDestroyed
) {
2474 scoped_ptr
<Window
> parent(new Window(NULL
));
2475 parent
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2476 OwningWindowDelegate delegate
;
2477 Window
* c1
= new Window(&delegate
);
2478 c1
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2479 parent
->AddChild(c1
);
2480 Window
* c2
= new Window(NULL
);
2481 c2
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2482 parent
->AddChild(c2
);
2483 delegate
.SetOwnedWindow(c2
);
2489 // Used by DelegateNotifiedAsBoundsChange to verify OnBoundsChanged() is
2491 class BoundsChangeDelegate
: public TestWindowDelegate
{
2493 BoundsChangeDelegate() : bounds_changed_(false) {}
2495 void clear_bounds_changed() { bounds_changed_
= false; }
2496 bool bounds_changed() const {
2497 return bounds_changed_
;
2501 void OnBoundsChanged(const gfx::Rect
& old_bounds
,
2502 const gfx::Rect
& new_bounds
) override
{
2503 bounds_changed_
= true;
2507 // Was OnBoundsChanged() invoked?
2508 bool bounds_changed_
;
2510 DISALLOW_COPY_AND_ASSIGN(BoundsChangeDelegate
);
2515 // Verifies the delegate is notified when the actual bounds of the layer
2517 TEST_F(WindowTest
, DelegateNotifiedAsBoundsChange
) {
2518 BoundsChangeDelegate delegate
;
2520 // We cannot short-circuit animations in this test.
2521 ui::ScopedAnimationDurationScaleMode
test_duration_mode(
2522 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION
);
2524 scoped_ptr
<Window
> window(
2525 CreateTestWindowWithDelegate(&delegate
, 1,
2526 gfx::Rect(0, 0, 100, 100), root_window()));
2527 window
->layer()->GetAnimator()->set_disable_timer_for_test(true);
2529 delegate
.clear_bounds_changed();
2531 // Animate to a different position.
2533 ui::ScopedLayerAnimationSettings
settings(window
->layer()->GetAnimator());
2534 window
->SetBounds(gfx::Rect(100, 100, 100, 100));
2537 // Bounds shouldn't immediately have changed.
2538 EXPECT_EQ("0,0 100x100", window
->bounds().ToString());
2539 EXPECT_FALSE(delegate
.bounds_changed());
2541 // Animate to the end, which should notify of the change.
2542 base::TimeTicks start_time
=
2543 window
->layer()->GetAnimator()->last_step_time();
2544 ui::LayerAnimator
* animator
= window
->layer()->GetAnimator();
2545 animator
->Step(start_time
+ base::TimeDelta::FromMilliseconds(1000));
2546 EXPECT_TRUE(delegate
.bounds_changed());
2547 EXPECT_NE("0,0 100x100", window
->bounds().ToString());
2550 // Verifies the delegate is notified when the actual bounds of the layer
2551 // change even when the window is not the layer's delegate
2552 TEST_F(WindowTest
, DelegateNotifiedAsBoundsChangeInHiddenLayer
) {
2553 BoundsChangeDelegate delegate
;
2555 // We cannot short-circuit animations in this test.
2556 ui::ScopedAnimationDurationScaleMode
test_duration_mode(
2557 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION
);
2559 scoped_ptr
<Window
> window(
2560 CreateTestWindowWithDelegate(&delegate
, 1,
2561 gfx::Rect(0, 0, 100, 100), root_window()));
2562 window
->layer()->GetAnimator()->set_disable_timer_for_test(true);
2564 delegate
.clear_bounds_changed();
2566 // Suppress paint on the window since it is hidden (should reset the layer's
2567 // delegate to NULL)
2568 window
->SuppressPaint();
2569 EXPECT_EQ(NULL
, window
->layer()->delegate());
2571 // Animate to a different position.
2573 ui::ScopedLayerAnimationSettings
settings(window
->layer()->GetAnimator());
2574 window
->SetBounds(gfx::Rect(100, 100, 110, 100));
2577 // Layer delegate is NULL but we should still get bounds changed notification.
2578 EXPECT_EQ("100,100 110x100", window
->GetTargetBounds().ToString());
2579 EXPECT_TRUE(delegate
.bounds_changed());
2581 delegate
.clear_bounds_changed();
2583 // Animate to the end: will *not* notify of the change since we are hidden.
2584 base::TimeTicks start_time
=
2585 window
->layer()->GetAnimator()->last_step_time();
2586 ui::LayerAnimator
* animator
= window
->layer()->GetAnimator();
2587 animator
->Step(start_time
+ base::TimeDelta::FromMilliseconds(1000));
2589 // No bounds changed notification at the end of animation since layer
2590 // delegate is NULL.
2591 EXPECT_FALSE(delegate
.bounds_changed());
2592 EXPECT_NE("0,0 100x100", window
->layer()->bounds().ToString());
2597 // Used by AddChildNotifications to track notification counts.
2598 class AddChildNotificationsObserver
: public WindowObserver
{
2600 AddChildNotificationsObserver() : added_count_(0), removed_count_(0) {}
2602 std::string
CountStringAndReset() {
2603 std::string result
= base::IntToString(added_count_
) + " " +
2604 base::IntToString(removed_count_
);
2605 added_count_
= removed_count_
= 0;
2609 // WindowObserver overrides:
2610 void OnWindowAddedToRootWindow(Window
* window
) override
{ added_count_
++; }
2611 void OnWindowRemovingFromRootWindow(Window
* window
,
2612 Window
* new_root
) override
{
2620 DISALLOW_COPY_AND_ASSIGN(AddChildNotificationsObserver
);
2625 // Assertions around when root window notifications are sent.
2626 TEST_F(WindowTest
, AddChildNotifications
) {
2627 AddChildNotificationsObserver observer
;
2628 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
2629 scoped_ptr
<Window
> w2(CreateTestWindowWithId(1, root_window()));
2630 w2
->AddObserver(&observer
);
2632 EXPECT_TRUE(w2
->HasFocus());
2634 // Move |w2| to be a child of |w1|.
2635 w1
->AddChild(w2
.get());
2636 // Sine we moved in the same root, observer shouldn't be notified.
2637 EXPECT_EQ("0 0", observer
.CountStringAndReset());
2638 // |w2| should still have focus after moving.
2639 EXPECT_TRUE(w2
->HasFocus());
2642 // Tests that a delegate that destroys itself when the window is destroyed does
2644 TEST_F(WindowTest
, DelegateDestroysSelfOnWindowDestroy
) {
2645 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(
2646 new DestroyWindowDelegate(),
2648 gfx::Rect(10, 20, 30, 40),
2652 class HierarchyObserver
: public WindowObserver
{
2654 HierarchyObserver(Window
* target
) : target_(target
) {
2655 target_
->AddObserver(this);
2657 ~HierarchyObserver() override
{ target_
->RemoveObserver(this); }
2661 const WindowObserver::HierarchyChangeParams
& params
) const {
2662 ParamsMatch(params_
[index
], params
);
2670 // Overridden from WindowObserver:
2671 void OnWindowHierarchyChanging(const HierarchyChangeParams
& params
) override
{
2672 params_
.push_back(params
);
2674 void OnWindowHierarchyChanged(const HierarchyChangeParams
& params
) override
{
2675 params_
.push_back(params
);
2678 void ParamsMatch(const WindowObserver::HierarchyChangeParams
& p1
,
2679 const WindowObserver::HierarchyChangeParams
& p2
) const {
2680 EXPECT_EQ(p1
.phase
, p2
.phase
);
2681 EXPECT_EQ(p1
.target
, p2
.target
);
2682 EXPECT_EQ(p1
.new_parent
, p2
.new_parent
);
2683 EXPECT_EQ(p1
.old_parent
, p2
.old_parent
);
2684 EXPECT_EQ(p1
.receiver
, p2
.receiver
);
2688 std::vector
<WindowObserver::HierarchyChangeParams
> params_
;
2690 DISALLOW_COPY_AND_ASSIGN(HierarchyObserver
);
2693 // Tests hierarchy change notifications.
2694 TEST_F(WindowTest
, OnWindowHierarchyChange
) {
2696 // Simple add & remove.
2697 HierarchyObserver
oroot(root_window());
2699 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, NULL
));
2700 HierarchyObserver
o1(w1
.get());
2703 root_window()->AddChild(w1
.get());
2705 WindowObserver::HierarchyChangeParams params
;
2706 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING
;
2707 params
.target
= w1
.get();
2708 params
.old_parent
= NULL
;
2709 params
.new_parent
= root_window();
2710 params
.receiver
= w1
.get();
2711 o1
.ValidateState(0, params
);
2713 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED
;
2714 params
.receiver
= w1
.get();
2715 o1
.ValidateState(1, params
);
2717 params
.receiver
= root_window();
2718 oroot
.ValidateState(0, params
);
2724 root_window()->RemoveChild(w1
.get());
2726 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING
;
2727 params
.old_parent
= root_window();
2728 params
.new_parent
= NULL
;
2729 params
.receiver
= w1
.get();
2731 o1
.ValidateState(0, params
);
2733 params
.receiver
= root_window();
2734 oroot
.ValidateState(0, params
);
2736 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED
;
2737 params
.receiver
= w1
.get();
2738 o1
.ValidateState(1, params
);
2742 // Add & remove of hierarchy. Tests notification order per documentation in
2744 HierarchyObserver
o(root_window());
2745 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, NULL
));
2746 Window
* w11
= CreateTestWindowWithId(11, w1
.get());
2747 w1
->AddObserver(&o
);
2748 w11
->AddObserver(&o
);
2751 root_window()->AddChild(w1
.get());
2753 // Dispatched to target first.
2755 WindowObserver::HierarchyChangeParams params
;
2756 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING
;
2757 params
.target
= w1
.get();
2758 params
.old_parent
= NULL
;
2759 params
.new_parent
= root_window();
2760 params
.receiver
= w1
.get();
2761 o
.ValidateState(index
++, params
);
2763 // Dispatched to target's children.
2764 params
.receiver
= w11
;
2765 o
.ValidateState(index
++, params
);
2767 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED
;
2769 // Now process the "changed" phase.
2770 params
.receiver
= w1
.get();
2771 o
.ValidateState(index
++, params
);
2772 params
.receiver
= w11
;
2773 o
.ValidateState(index
++, params
);
2774 params
.receiver
= root_window();
2775 o
.ValidateState(index
++, params
);
2778 root_window()->RemoveChild(w1
.get());
2779 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING
;
2780 params
.old_parent
= root_window();
2781 params
.new_parent
= NULL
;
2782 params
.receiver
= w1
.get();
2783 o
.ValidateState(index
++, params
);
2784 params
.receiver
= w11
;
2785 o
.ValidateState(index
++, params
);
2786 params
.receiver
= root_window();
2787 o
.ValidateState(index
++, params
);
2788 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED
;
2789 params
.receiver
= w1
.get();
2790 o
.ValidateState(index
++, params
);
2791 params
.receiver
= w11
;
2792 o
.ValidateState(index
++, params
);
2798 // Reparent. Tests notification order per documentation in WindowObserver.
2799 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
2800 Window
* w11
= CreateTestWindowWithId(11, w1
.get());
2801 Window
* w111
= CreateTestWindowWithId(111, w11
);
2802 scoped_ptr
<Window
> w2(CreateTestWindowWithId(2, root_window()));
2804 HierarchyObserver
o(root_window());
2805 w1
->AddObserver(&o
);
2806 w11
->AddObserver(&o
);
2807 w111
->AddObserver(&o
);
2808 w2
->AddObserver(&o
);
2812 // Dispatched to target first.
2814 WindowObserver::HierarchyChangeParams params
;
2815 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING
;
2816 params
.target
= w11
;
2817 params
.old_parent
= w1
.get();
2818 params
.new_parent
= w2
.get();
2819 params
.receiver
= w11
;
2820 o
.ValidateState(index
++, params
);
2822 // Then to target's children.
2823 params
.receiver
= w111
;
2824 o
.ValidateState(index
++, params
);
2826 // Then to target's old parent chain.
2827 params
.receiver
= w1
.get();
2828 o
.ValidateState(index
++, params
);
2829 params
.receiver
= root_window();
2830 o
.ValidateState(index
++, params
);
2833 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED
;
2834 params
.receiver
= w11
;
2835 o
.ValidateState(index
++, params
);
2836 params
.receiver
= w111
;
2837 o
.ValidateState(index
++, params
);
2838 params
.receiver
= w2
.get();
2839 o
.ValidateState(index
++, params
);
2840 params
.receiver
= root_window();
2841 o
.ValidateState(index
++, params
);
2849 // Verifies SchedulePaint() on a layerless window results in damaging the right
2851 TEST_F(WindowTest
, LayerlessWindowSchedulePaint
) {
2853 root
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2854 root
.SetBounds(gfx::Rect(0, 0, 100, 100));
2856 Window
* layerless_window
= new Window(NULL
); // Owned by |root|.
2857 layerless_window
->Init(WINDOW_LAYER_NONE
);
2858 layerless_window
->SetBounds(gfx::Rect(10, 11, 12, 13));
2859 root
.AddChild(layerless_window
);
2861 root
.layer()->SendDamagedRects();
2862 layerless_window
->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4));
2863 // Note the the region is clipped by the parent hence 100 going to 11.
2864 EXPECT_EQ("11,13 11x4",
2865 gfx::SkIRectToRect(root
.layer()->damaged_region().getBounds()).
2868 Window
* layerless_window2
= new Window(NULL
); // Owned by |layerless_window|.
2869 layerless_window2
->Init(WINDOW_LAYER_NONE
);
2870 layerless_window2
->SetBounds(gfx::Rect(1, 2, 3, 4));
2871 layerless_window
->AddChild(layerless_window2
);
2873 root
.layer()->SendDamagedRects();
2874 layerless_window2
->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4));
2875 // Note the the region is clipped by the |layerless_window| hence 100 going to
2877 EXPECT_EQ("12,15 2x2",
2878 gfx::SkIRectToRect(root
.layer()->damaged_region().getBounds()).
2882 // Verifies bounds of layerless windows are correctly updated when adding
2884 TEST_F(WindowTest
, NestedLayerlessWindowsBoundsOnAddRemove
) {
2885 // Creates the following structure (all children owned by root):
2893 // ll: layer less, eg no layer
2895 root
.Init(WINDOW_LAYER_NOT_DRAWN
);
2896 root
.SetBounds(gfx::Rect(0, 0, 100, 100));
2898 Window
* w1ll
= new Window(NULL
);
2899 w1ll
->Init(WINDOW_LAYER_NONE
);
2900 w1ll
->SetBounds(gfx::Rect(1, 2, 100, 100));
2902 Window
* w11ll
= new Window(NULL
);
2903 w11ll
->Init(WINDOW_LAYER_NONE
);
2904 w11ll
->SetBounds(gfx::Rect(3, 4, 100, 100));
2905 w1ll
->AddChild(w11ll
);
2907 Window
* w111
= new Window(NULL
);
2908 w111
->Init(WINDOW_LAYER_NOT_DRAWN
);
2909 w111
->SetBounds(gfx::Rect(5, 6, 100, 100));
2910 w11ll
->AddChild(w111
);
2912 Window
* w12
= new Window(NULL
);
2913 w12
->Init(WINDOW_LAYER_NOT_DRAWN
);
2914 w12
->SetBounds(gfx::Rect(7, 8, 100, 100));
2915 w1ll
->AddChild(w12
);
2917 Window
* w121
= new Window(NULL
);
2918 w121
->Init(WINDOW_LAYER_NOT_DRAWN
);
2919 w121
->SetBounds(gfx::Rect(9, 10, 100, 100));
2920 w12
->AddChild(w121
);
2922 root
.AddChild(w1ll
);
2924 // All layers should be parented to the root.
2925 EXPECT_EQ(root
.layer(), w111
->layer()->parent());
2926 EXPECT_EQ(root
.layer(), w12
->layer()->parent());
2927 EXPECT_EQ(w12
->layer(), w121
->layer()->parent());
2929 // Ensure bounds are what we expect.
2930 EXPECT_EQ("1,2 100x100", w1ll
->bounds().ToString());
2931 EXPECT_EQ("3,4 100x100", w11ll
->bounds().ToString());
2932 EXPECT_EQ("5,6 100x100", w111
->bounds().ToString());
2933 EXPECT_EQ("7,8 100x100", w12
->bounds().ToString());
2934 EXPECT_EQ("9,10 100x100", w121
->bounds().ToString());
2936 // Bounds of layers are relative to the nearest ancestor with a layer.
2937 EXPECT_EQ("8,10 100x100", w12
->layer()->bounds().ToString());
2938 EXPECT_EQ("9,12 100x100", w111
->layer()->bounds().ToString());
2939 EXPECT_EQ("9,10 100x100", w121
->layer()->bounds().ToString());
2941 // Remove and repeat.
2942 root
.RemoveChild(w1ll
);
2944 EXPECT_TRUE(w111
->layer()->parent() == NULL
);
2945 EXPECT_TRUE(w12
->layer()->parent() == NULL
);
2947 // Verify bounds haven't changed again.
2948 EXPECT_EQ("1,2 100x100", w1ll
->bounds().ToString());
2949 EXPECT_EQ("3,4 100x100", w11ll
->bounds().ToString());
2950 EXPECT_EQ("5,6 100x100", w111
->bounds().ToString());
2951 EXPECT_EQ("7,8 100x100", w12
->bounds().ToString());
2952 EXPECT_EQ("9,10 100x100", w121
->bounds().ToString());
2954 // Bounds of layers should now match that of windows.
2955 EXPECT_EQ("7,8 100x100", w12
->layer()->bounds().ToString());
2956 EXPECT_EQ("5,6 100x100", w111
->layer()->bounds().ToString());
2957 EXPECT_EQ("9,10 100x100", w121
->layer()->bounds().ToString());
2962 // Verifies bounds of layerless windows are correctly updated when bounds
2963 // of ancestor changes.
2964 TEST_F(WindowTest
, NestedLayerlessWindowsBoundsOnSetBounds
) {
2965 // Creates the following structure (all children owned by root):
2973 // ll: layer less, eg no layer
2975 root
.Init(WINDOW_LAYER_NOT_DRAWN
);
2976 root
.SetBounds(gfx::Rect(0, 0, 100, 100));
2978 Window
* w1ll
= new Window(NULL
);
2979 w1ll
->Init(WINDOW_LAYER_NONE
);
2980 w1ll
->SetBounds(gfx::Rect(1, 2, 100, 100));
2982 Window
* w11ll
= new Window(NULL
);
2983 w11ll
->Init(WINDOW_LAYER_NONE
);
2984 w11ll
->SetBounds(gfx::Rect(3, 4, 100, 100));
2985 w1ll
->AddChild(w11ll
);
2987 Window
* w111
= new Window(NULL
);
2988 w111
->Init(WINDOW_LAYER_NOT_DRAWN
);
2989 w111
->SetBounds(gfx::Rect(5, 6, 100, 100));
2990 w11ll
->AddChild(w111
);
2992 Window
* w12
= new Window(NULL
);
2993 w12
->Init(WINDOW_LAYER_NOT_DRAWN
);
2994 w12
->SetBounds(gfx::Rect(7, 8, 100, 100));
2995 w1ll
->AddChild(w12
);
2997 Window
* w121
= new Window(NULL
);
2998 w121
->Init(WINDOW_LAYER_NOT_DRAWN
);
2999 w121
->SetBounds(gfx::Rect(9, 10, 100, 100));
3000 w12
->AddChild(w121
);
3002 root
.AddChild(w1ll
);
3004 w111
->SetBounds(gfx::Rect(7, 8, 11, 12));
3005 EXPECT_EQ("7,8 11x12", w111
->bounds().ToString());
3006 EXPECT_EQ("7,8 11x12", w111
->GetTargetBounds().ToString());
3007 EXPECT_EQ("11,14 11x12", w111
->layer()->bounds().ToString());
3010 w111
->SetBounds(gfx::Rect(5, 6, 100, 100));
3011 EXPECT_EQ("5,6 100x100", w111
->bounds().ToString());
3012 EXPECT_EQ("5,6 100x100", w111
->GetTargetBounds().ToString());
3013 EXPECT_EQ("9,12 100x100", w111
->layer()->bounds().ToString());
3015 // Setting the bounds of a layerless window needs to adjust the bounds of
3016 // layered children.
3017 w11ll
->SetBounds(gfx::Rect(5, 6, 100, 100));
3018 EXPECT_EQ("5,6 100x100", w11ll
->bounds().ToString());
3019 EXPECT_EQ("5,6 100x100", w11ll
->GetTargetBounds().ToString());
3020 EXPECT_EQ("5,6 100x100", w111
->bounds().ToString());
3021 EXPECT_EQ("5,6 100x100", w111
->GetTargetBounds().ToString());
3022 EXPECT_EQ("11,14 100x100", w111
->layer()->bounds().ToString());
3024 root
.RemoveChild(w1ll
);
3026 w111
->SetBounds(gfx::Rect(7, 8, 11, 12));
3027 EXPECT_EQ("7,8 11x12", w111
->bounds().ToString());
3028 EXPECT_EQ("7,8 11x12", w111
->GetTargetBounds().ToString());
3029 EXPECT_EQ("7,8 11x12", w111
->layer()->bounds().ToString());
3036 // Tracks the number of times paint is invoked along with what the clip and
3038 class PaintWindowDelegate
: public TestWindowDelegate
{
3040 PaintWindowDelegate() : paint_count_(0) {}
3041 ~PaintWindowDelegate() override
{}
3043 const gfx::Rect
& most_recent_paint_clip_bounds() const {
3044 return most_recent_paint_clip_bounds_
;
3047 const gfx::Vector2d
& most_recent_paint_matrix_offset() const {
3048 return most_recent_paint_matrix_offset_
;
3051 void clear_paint_count() { paint_count_
= 0; }
3052 int paint_count() const { return paint_count_
; }
3054 // TestWindowDelegate::
3055 void OnPaint(gfx::Canvas
* canvas
) override
{
3057 canvas
->GetClipBounds(&most_recent_paint_clip_bounds_
);
3058 const SkMatrix
& matrix
= canvas
->sk_canvas()->getTotalMatrix();
3059 most_recent_paint_matrix_offset_
= gfx::Vector2d(
3060 SkScalarFloorToInt(matrix
.getTranslateX()),
3061 SkScalarFloorToInt(matrix
.getTranslateY()));
3066 gfx::Rect most_recent_paint_clip_bounds_
;
3067 gfx::Vector2d most_recent_paint_matrix_offset_
;
3069 DISALLOW_COPY_AND_ASSIGN(PaintWindowDelegate
);
3074 // Assertions around layerless children being painted when non-layerless window
3076 TEST_F(WindowTest
, PaintLayerless
) {
3077 // Creates the following structure (all children owned by root):
3083 // ll: layer less, eg no layer
3084 PaintWindowDelegate w1ll_delegate
;
3085 PaintWindowDelegate w11ll_delegate
;
3086 PaintWindowDelegate w111_delegate
;
3089 root
.Init(WINDOW_LAYER_NOT_DRAWN
);
3090 root
.SetBounds(gfx::Rect(0, 0, 100, 100));
3092 Window
* w1ll
= new Window(&w1ll_delegate
);
3093 w1ll
->Init(WINDOW_LAYER_NONE
);
3094 w1ll
->SetBounds(gfx::Rect(1, 2, 40, 50));
3096 root
.AddChild(w1ll
);
3098 Window
* w11ll
= new Window(&w11ll_delegate
);
3099 w11ll
->Init(WINDOW_LAYER_NONE
);
3100 w11ll
->SetBounds(gfx::Rect(3, 4, 11, 12));
3102 w1ll
->AddChild(w11ll
);
3104 Window
* w111
= new Window(&w111_delegate
);
3105 w111
->Init(WINDOW_LAYER_NOT_DRAWN
);
3106 w111
->SetBounds(gfx::Rect(5, 6, 100, 100));
3108 w11ll
->AddChild(w111
);
3110 EXPECT_EQ(0, w1ll_delegate
.paint_count());
3111 EXPECT_EQ(0, w11ll_delegate
.paint_count());
3112 EXPECT_EQ(0, w111_delegate
.paint_count());
3114 // Paint the root, this should trigger painting of the two layerless
3115 // descendants but not the layered descendant.
3116 gfx::Canvas
canvas(gfx::Size(200, 200), 1.0f
, true);
3117 static_cast<ui::LayerDelegate
&>(root
).OnPaintLayer(&canvas
);
3119 // NOTE: SkCanvas::getClipBounds() extends the clip 1 pixel to the left and up
3120 // and 2 pixels down and to the right.
3121 EXPECT_EQ(1, w1ll_delegate
.paint_count());
3122 EXPECT_EQ("-1,-1 42x52",
3123 w1ll_delegate
.most_recent_paint_clip_bounds().ToString());
3125 w1ll_delegate
.most_recent_paint_matrix_offset().ToString());
3126 EXPECT_EQ(1, w11ll_delegate
.paint_count());
3127 EXPECT_EQ("-1,-1 13x14",
3128 w11ll_delegate
.most_recent_paint_clip_bounds().ToString());
3130 w11ll_delegate
.most_recent_paint_matrix_offset().ToString());
3131 EXPECT_EQ(0, w111_delegate
.paint_count());
3136 std::string
ConvertPointToTargetString(const Window
* source
,
3137 const Window
* target
) {
3138 gfx::Point location
;
3139 Window::ConvertPointToTarget(source
, target
, &location
);
3140 return location
.ToString();
3145 // Assertions around Window::ConvertPointToTarget() with layerless windows.
3146 TEST_F(WindowTest
, ConvertPointToTargetLayerless
) {
3147 // Creates the following structure (all children owned by root):
3155 // ll: layer less, eg no layer
3157 root
.Init(WINDOW_LAYER_NOT_DRAWN
);
3158 root
.SetBounds(gfx::Rect(0, 0, 100, 100));
3160 Window
* w1ll
= new Window(NULL
);
3161 w1ll
->Init(WINDOW_LAYER_NONE
);
3162 w1ll
->SetBounds(gfx::Rect(1, 2, 100, 100));
3164 Window
* w11ll
= new Window(NULL
);
3165 w11ll
->Init(WINDOW_LAYER_NONE
);
3166 w11ll
->SetBounds(gfx::Rect(3, 4, 100, 100));
3167 w1ll
->AddChild(w11ll
);
3169 Window
* w111
= new Window(NULL
);
3170 w111
->Init(WINDOW_LAYER_NOT_DRAWN
);
3171 w111
->SetBounds(gfx::Rect(5, 6, 100, 100));
3172 w11ll
->AddChild(w111
);
3174 Window
* w12
= new Window(NULL
);
3175 w12
->Init(WINDOW_LAYER_NOT_DRAWN
);
3176 w12
->SetBounds(gfx::Rect(7, 8, 100, 100));
3177 w1ll
->AddChild(w12
);
3179 Window
* w121
= new Window(NULL
);
3180 w121
->Init(WINDOW_LAYER_NOT_DRAWN
);
3181 w121
->SetBounds(gfx::Rect(9, 10, 100, 100));
3182 w12
->AddChild(w121
);
3184 root
.AddChild(w1ll
);
3187 EXPECT_EQ("5,6", ConvertPointToTargetString(w111
, w11ll
));
3190 EXPECT_EQ("8,10", ConvertPointToTargetString(w111
, w1ll
));
3193 EXPECT_EQ("9,12", ConvertPointToTargetString(w111
, &root
));
3196 EXPECT_EQ("1,2", ConvertPointToTargetString(w111
, w12
));
3199 EXPECT_EQ("-8,-8", ConvertPointToTargetString(w111
, w121
));
3202 EXPECT_EQ("-5,-6", ConvertPointToTargetString(w11ll
, w111
));
3205 EXPECT_EQ("3,4", ConvertPointToTargetString(w11ll
, w1ll
));
3208 EXPECT_EQ("4,6", ConvertPointToTargetString(w11ll
, &root
));
3211 EXPECT_EQ("-4,-4", ConvertPointToTargetString(w11ll
, w12
));
3214 #if !defined(NDEBUG)
3215 // Verifies PrintWindowHierarchy() doesn't crash with a layerless window.
3216 TEST_F(WindowTest
, PrintWindowHierarchyNotCrashLayerless
) {
3218 root
.Init(WINDOW_LAYER_NONE
);
3219 root
.SetBounds(gfx::Rect(0, 0, 100, 100));
3220 root
.PrintWindowHierarchy(0);
3226 // See AddWindowsFromString() for details.
3227 aura::Window
* CreateWindowFromDescription(const std::string
& description
,
3228 WindowDelegate
* delegate
) {
3229 WindowLayerType window_type
= WINDOW_LAYER_NOT_DRAWN
;
3230 std::vector
<std::string
> tokens
;
3231 Tokenize(description
, ":", &tokens
);
3232 DCHECK(!tokens
.empty());
3233 std::string
name(tokens
[0]);
3234 tokens
.erase(tokens
.begin());
3235 if (!tokens
.empty()) {
3236 if (tokens
[0] == "ll") {
3237 window_type
= WINDOW_LAYER_NONE
;
3238 tokens
.erase(tokens
.begin());
3240 DCHECK(tokens
.empty()) << "unknown tokens for creating window "
3243 Window
* window
= new Window(delegate
);
3244 window
->Init(window_type
);
3245 window
->SetName(name
);
3246 // Window name is only propagated to layer in debug builds.
3247 if (window
->layer())
3248 window
->layer()->set_name(name
);
3252 // Creates and adds a tree of windows to |parent|. |description| consists
3253 // of the following pieces:
3254 // X: Identifies a new window. Consists of a name and optionally ":ll" to
3255 // specify WINDOW_LAYER_NONE, eg "w1:ll".
3256 // []: optionally used to specify the children of the window. Contains any
3257 // number of window identifiers and their corresponding children.
3258 // For example: "[ a [ a1 a2:ll ] b c [ c1 ] ]" creates the tree:
3261 // a2 -> WINDOW_LAYER_NONE.
3265 // NOTE: you must have a space after every token.
3266 std::string::size_type
AddWindowsFromString(aura::Window
* parent
,
3267 const std::string
& description
,
3268 std::string::size_type start_pos
,
3269 WindowDelegate
* delegate
) {
3271 std::string::size_type end_pos
= description
.find(' ', start_pos
);
3272 while (end_pos
!= std::string::npos
) {
3273 const std::string::size_type part_length
= end_pos
- start_pos
;
3274 const std::string window_description
=
3275 description
.substr(start_pos
, part_length
);
3276 if (window_description
== "[") {
3277 start_pos
= AddWindowsFromString(parent
->children().back(),
3281 end_pos
= description
.find(' ', start_pos
);
3282 if (end_pos
== std::string::npos
&& start_pos
!= end_pos
)
3283 end_pos
= description
.length();
3284 } else if (window_description
== "]") {
3289 CreateWindowFromDescription(window_description
, delegate
);
3290 parent
->AddChild(window
);
3291 start_pos
= ++end_pos
;
3292 end_pos
= description
.find(' ', start_pos
);
3298 // Used by BuildRootWindowTreeDescription().
3299 std::string
BuildWindowTreeDescription(const aura::Window
& window
) {
3301 result
+= window
.name();
3302 if (window
.children().empty())
3306 for (size_t i
= 0; i
< window
.children().size(); ++i
) {
3309 result
+= BuildWindowTreeDescription(*(window
.children()[i
]));
3315 // Creates a string from |window|. See AddWindowsFromString() for details of the
3316 // returned string. This does *not* include the layer type in the description,
3318 std::string
BuildRootWindowTreeDescription(const aura::Window
& window
) {
3320 for (size_t i
= 0; i
< window
.children().size(); ++i
) {
3323 result
+= BuildWindowTreeDescription(*(window
.children()[i
]));
3328 // Used by BuildRootWindowTreeDescription().
3329 std::string
BuildLayerTreeDescription(const ui::Layer
& layer
) {
3331 result
+= layer
.name();
3332 if (layer
.children().empty())
3336 for (size_t i
= 0; i
< layer
.children().size(); ++i
) {
3339 result
+= BuildLayerTreeDescription(*(layer
.children()[i
]));
3345 // Builds a string for all the children of |layer|. The returned string is in
3346 // the same format as AddWindowsFromString() but only includes the name of the
3348 std::string
BuildRootLayerTreeDescription(const ui::Layer
& layer
) {
3350 for (size_t i
= 0; i
< layer
.children().size(); ++i
) {
3353 result
+= BuildLayerTreeDescription(*(layer
.children()[i
]));
3358 // Returns the first window whose name matches |name| in |parent|.
3359 aura::Window
* FindWindowByName(aura::Window
* parent
,
3360 const std::string
& name
) {
3361 if (parent
->name() == name
)
3363 for (size_t i
= 0; i
< parent
->children().size(); ++i
) {
3364 aura::Window
* child
= FindWindowByName(parent
->children()[i
], name
);
3373 // Direction to stack.
3381 // Permutations of StackChildAt with various data.
3382 TEST_F(WindowTest
, StackChildAtLayerless
) {
3384 // Describes the window tree to create. See AddWindowsFromString() for
3386 const std::string initial_description
;
3388 // Identifies the window to move.
3389 const std::string source_window
;
3391 // Window to move |source_window| relative to. Not used for STACK_AT_BOTTOM
3393 const std::string target_window
;
3395 StackType stack_type
;
3397 // Expected window and layer results.
3398 const std::string expected_description
;
3399 const std::string expected_layer_description
;
3403 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3407 "2 [ 21 ] 1 [ 11 12 ]",
3413 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3417 "1 [ 11 12 ] 2 [ 21 ]",
3423 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3427 "2 [ 21 ] 1 [ 11 12 ]",
3433 "1:ll [ 11 12 ] 2:ll [ 21 ] 3:ll",
3437 "1 [ 11 12 ] 3 2 [ 21 ]",
3443 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3447 "2 [ 21 ] 1 [ 11 12 ]",
3453 "1:ll [ 11 12 ] 2:ll [ 21 ] 3:ll",
3457 "2 [ 21 ] 3 1 [ 11 12 ]",
3463 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3467 "2 [ 21 ] 1 [ 11 12 ]",
3471 for (size_t i
= 0; i
< arraysize(data
); ++i
) {
3472 test::TestWindowDelegate delegate
;
3474 root
.Init(WINDOW_LAYER_NOT_DRAWN
);
3475 root
.SetBounds(gfx::Rect(0, 0, 100, 100));
3476 AddWindowsFromString(
3478 data
[i
].initial_description
,
3479 static_cast<std::string::size_type
>(0), &delegate
);
3480 aura::Window
* source
= FindWindowByName(&root
, data
[i
].source_window
);
3481 ASSERT_TRUE(source
!= NULL
) << "unable to find source window "
3482 << data
[i
].source_window
<< " at " << i
;
3483 aura::Window
* target
= FindWindowByName(&root
, data
[i
].target_window
);
3484 switch (data
[i
].stack_type
) {
3486 ASSERT_TRUE(target
!= NULL
) << "unable to find target window "
3487 << data
[i
].target_window
<< " at " << i
;
3488 source
->parent()->StackChildAbove(source
, target
);
3491 ASSERT_TRUE(target
!= NULL
) << "unable to find target window "
3492 << data
[i
].target_window
<< " at " << i
;
3493 source
->parent()->StackChildBelow(source
, target
);
3495 case STACK_AT_BOTTOM
:
3496 source
->parent()->StackChildAtBottom(source
);
3499 source
->parent()->StackChildAtTop(source
);
3502 EXPECT_EQ(data
[i
].expected_layer_description
,
3503 BuildRootLayerTreeDescription(*root
.layer()))
3504 << "layer tree doesn't match at " << i
;
3505 EXPECT_EQ(data
[i
].expected_description
,
3506 BuildRootWindowTreeDescription(root
))
3507 << "window tree doesn't match at " << i
;
3513 class TestLayerAnimationObserver
: public ui::LayerAnimationObserver
{
3515 TestLayerAnimationObserver()
3516 : animation_completed_(false),
3517 animation_aborted_(false) {}
3518 ~TestLayerAnimationObserver() override
{}
3520 bool animation_completed() const { return animation_completed_
; }
3521 bool animation_aborted() const { return animation_aborted_
; }
3524 animation_completed_
= false;
3525 animation_aborted_
= false;
3529 // ui::LayerAnimationObserver:
3530 void OnLayerAnimationEnded(ui::LayerAnimationSequence
* sequence
) override
{
3531 animation_completed_
= true;
3534 void OnLayerAnimationAborted(ui::LayerAnimationSequence
* sequence
) override
{
3535 animation_aborted_
= true;
3538 void OnLayerAnimationScheduled(
3539 ui::LayerAnimationSequence
* sequence
) override
{}
3541 bool animation_completed_
;
3542 bool animation_aborted_
;
3544 DISALLOW_COPY_AND_ASSIGN(TestLayerAnimationObserver
);
3549 TEST_F(WindowTest
, WindowDestroyCompletesAnimations
) {
3550 ui::ScopedAnimationDurationScaleMode
test_duration_mode(
3551 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION
);
3552 scoped_refptr
<ui::LayerAnimator
> animator
=
3553 ui::LayerAnimator::CreateImplicitAnimator();
3554 TestLayerAnimationObserver observer
;
3555 animator
->AddObserver(&observer
);
3556 // Make sure destroying a Window completes the animation.
3558 scoped_ptr
<Window
> window(CreateTestWindowWithId(1, root_window()));
3559 window
->layer()->SetAnimator(animator
.get());
3561 gfx::Transform transform
;
3562 transform
.Scale(0.5f
, 0.5f
);
3563 window
->SetTransform(transform
);
3565 EXPECT_TRUE(animator
->is_animating());
3566 EXPECT_FALSE(observer
.animation_completed());
3568 EXPECT_TRUE(animator
.get());
3569 EXPECT_FALSE(animator
->is_animating());
3570 EXPECT_TRUE(observer
.animation_completed());
3571 EXPECT_FALSE(observer
.animation_aborted());
3572 animator
->RemoveObserver(&observer
);
3575 animator
= ui::LayerAnimator::CreateImplicitAnimator();
3576 animator
->AddObserver(&observer
);
3578 layer
.SetAnimator(animator
.get());
3580 scoped_ptr
<Window
> window(CreateTestWindowWithId(1, root_window()));
3581 window
->layer()->Add(&layer
);
3583 gfx::Transform transform
;
3584 transform
.Scale(0.5f
, 0.5f
);
3585 layer
.SetTransform(transform
);
3587 EXPECT_TRUE(animator
->is_animating());
3588 EXPECT_FALSE(observer
.animation_completed());
3591 EXPECT_TRUE(animator
.get());
3592 EXPECT_FALSE(animator
->is_animating());
3593 EXPECT_TRUE(observer
.animation_completed());
3594 EXPECT_FALSE(observer
.animation_aborted());
3595 animator
->RemoveObserver(&observer
);