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"
9 #include "base/basictypes.h"
10 #include "base/compiler_specific.h"
11 #include "base/string_number_conversions.h"
12 #include "base/stringprintf.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "ui/aura/client/capture_client.h"
15 #include "ui/aura/client/focus_change_observer.h"
16 #include "ui/aura/client/stacking_client.h"
17 #include "ui/aura/client/visibility_client.h"
18 #include "ui/aura/layout_manager.h"
19 #include "ui/aura/root_window.h"
20 #include "ui/aura/root_window_host.h"
21 #include "ui/aura/root_window_observer.h"
22 #include "ui/aura/test/aura_test_base.h"
23 #include "ui/aura/test/event_generator.h"
24 #include "ui/aura/test/test_window_delegate.h"
25 #include "ui/aura/test/test_windows.h"
26 #include "ui/aura/test/window_test_api.h"
27 #include "ui/aura/window_delegate.h"
28 #include "ui/aura/window_observer.h"
29 #include "ui/aura/window_property.h"
30 #include "ui/base/events/event.h"
31 #include "ui/base/events/event_utils.h"
32 #include "ui/base/gestures/gesture_configuration.h"
33 #include "ui/base/hit_test.h"
34 #include "ui/base/keycodes/keyboard_codes.h"
35 #include "ui/compositor/layer.h"
36 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
37 #include "ui/compositor/scoped_layer_animation_settings.h"
38 #include "ui/gfx/canvas.h"
39 #include "ui/gfx/screen.h"
41 DECLARE_WINDOW_PROPERTY_TYPE(const char*)
42 DECLARE_WINDOW_PROPERTY_TYPE(int)
47 class WindowTest
: public AuraTestBase
{
49 WindowTest() : max_separation_(0) {
52 virtual void SetUp() OVERRIDE
{
53 AuraTestBase::SetUp();
54 // TODO: there needs to be an easier way to do this.
55 max_separation_
= ui::GestureConfiguration::
56 max_separation_for_gesture_touches_in_pixels();
57 ui::GestureConfiguration::
58 set_max_separation_for_gesture_touches_in_pixels(0);
61 virtual void TearDown() OVERRIDE
{
62 AuraTestBase::TearDown();
63 ui::GestureConfiguration::
64 set_max_separation_for_gesture_touches_in_pixels(max_separation_
);
67 // Adds |window| to |root_window_|, through the StackingClient.
68 void SetDefaultParentByPrimaryRootWindow(aura::Window
* window
) {
69 window
->SetDefaultParentByRootWindow(root_window(), gfx::Rect());
75 DISALLOW_COPY_AND_ASSIGN(WindowTest
);
80 // Used for verifying destruction methods are invoked.
81 class DestroyTrackingDelegateImpl
: public TestWindowDelegate
{
83 DestroyTrackingDelegateImpl()
84 : destroying_count_(0),
86 in_destroying_(false) {}
88 void clear_destroying_count() { destroying_count_
= 0; }
89 int destroying_count() const { return destroying_count_
; }
91 void clear_destroyed_count() { destroyed_count_
= 0; }
92 int destroyed_count() const { return destroyed_count_
; }
94 bool in_destroying() const { return in_destroying_
; }
96 virtual void OnWindowDestroying() OVERRIDE
{
97 EXPECT_FALSE(in_destroying_
);
98 in_destroying_
= true;
102 virtual void OnWindowDestroyed() OVERRIDE
{
103 EXPECT_TRUE(in_destroying_
);
104 in_destroying_
= false;
109 int destroying_count_
;
110 int destroyed_count_
;
113 DISALLOW_COPY_AND_ASSIGN(DestroyTrackingDelegateImpl
);
116 // Used to verify that when OnWindowDestroying is invoked the parent is also
117 // is in the process of being destroyed.
118 class ChildWindowDelegateImpl
: public DestroyTrackingDelegateImpl
{
120 explicit ChildWindowDelegateImpl(
121 DestroyTrackingDelegateImpl
* parent_delegate
)
122 : parent_delegate_(parent_delegate
) {
125 virtual void OnWindowDestroying() OVERRIDE
{
126 EXPECT_TRUE(parent_delegate_
->in_destroying());
127 DestroyTrackingDelegateImpl::OnWindowDestroying();
131 DestroyTrackingDelegateImpl
* parent_delegate_
;
133 DISALLOW_COPY_AND_ASSIGN(ChildWindowDelegateImpl
);
136 // Used to verify that a Window is removed from its parent when
137 // OnWindowDestroyed is called.
138 class DestroyOrphanDelegate
: public TestWindowDelegate
{
140 DestroyOrphanDelegate() : window_(NULL
) {
143 void set_window(Window
* window
) { window_
= window
; }
145 virtual void OnWindowDestroyed() OVERRIDE
{
146 EXPECT_FALSE(window_
->parent());
151 DISALLOW_COPY_AND_ASSIGN(DestroyOrphanDelegate
);
154 // Used in verifying mouse capture.
155 class CaptureWindowDelegateImpl
: public TestWindowDelegate
{
157 CaptureWindowDelegateImpl() {
162 capture_changed_event_count_
= 0;
163 capture_lost_count_
= 0;
164 mouse_event_count_
= 0;
165 touch_event_count_
= 0;
166 gesture_event_count_
= 0;
169 int capture_changed_event_count() const {
170 return capture_changed_event_count_
;
172 int capture_lost_count() const { return capture_lost_count_
; }
173 int mouse_event_count() const { return mouse_event_count_
; }
174 int touch_event_count() const { return touch_event_count_
; }
175 int gesture_event_count() const { return gesture_event_count_
; }
177 virtual void OnMouseEvent(ui::MouseEvent
* event
) OVERRIDE
{
178 if (event
->type() == ui::ET_MOUSE_CAPTURE_CHANGED
)
179 capture_changed_event_count_
++;
180 mouse_event_count_
++;
182 virtual void OnTouchEvent(ui::TouchEvent
* event
) OVERRIDE
{
183 touch_event_count_
++;
185 virtual void OnGestureEvent(ui::GestureEvent
* event
) OVERRIDE
{
186 gesture_event_count_
++;
188 virtual void OnCaptureLost() OVERRIDE
{
189 capture_lost_count_
++;
193 int capture_changed_event_count_
;
194 int capture_lost_count_
;
195 int mouse_event_count_
;
196 int touch_event_count_
;
197 int gesture_event_count_
;
199 DISALLOW_COPY_AND_ASSIGN(CaptureWindowDelegateImpl
);
202 // aura::WindowDelegate that tracks the window that was reported as having the
204 class FocusDelegate
: public TestWindowDelegate
,
205 public aura::client::FocusChangeObserver
{
207 FocusDelegate() : previous_focused_window_(NULL
) {
210 aura::Window
* previous_focused_window() const {
211 return previous_focused_window_
;
214 // Overridden from client::FocusChangeObserver:
215 virtual void OnWindowFocused(Window
* gained_focus
,
216 Window
* lost_focus
) OVERRIDE
{
217 previous_focused_window_
= lost_focus
;
221 aura::Window
* previous_focused_window_
;
223 DISALLOW_COPY_AND_ASSIGN(FocusDelegate
);
226 // Keeps track of the location of the gesture.
227 class GestureTrackPositionDelegate
: public TestWindowDelegate
{
229 GestureTrackPositionDelegate() {}
231 virtual void OnGestureEvent(ui::GestureEvent
* event
) OVERRIDE
{
232 position_
= event
->location();
233 event
->StopPropagation();
236 const gfx::Point
& position() const { return position_
; }
239 gfx::Point position_
;
241 DISALLOW_COPY_AND_ASSIGN(GestureTrackPositionDelegate
);
244 base::TimeDelta
getTime() {
245 return ui::EventTimeForNow();
248 class SelfEventHandlingWindowDelegate
: public TestWindowDelegate
{
250 SelfEventHandlingWindowDelegate() {}
252 virtual bool ShouldDescendIntoChildForEventHandling(
254 const gfx::Point
& location
) OVERRIDE
{
259 DISALLOW_COPY_AND_ASSIGN(SelfEventHandlingWindowDelegate
);
262 // The delegate deletes itself when the window is being destroyed.
263 class DestroyWindowDelegate
: public TestWindowDelegate
{
265 DestroyWindowDelegate() {}
268 virtual ~DestroyWindowDelegate() {}
270 // Overridden from WindowDelegate.
271 virtual void OnWindowDestroyed() OVERRIDE
{
275 DISALLOW_COPY_AND_ASSIGN(DestroyWindowDelegate
);
280 TEST_F(WindowTest
, GetChildById
) {
281 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
282 scoped_ptr
<Window
> w11(CreateTestWindowWithId(11, w1
.get()));
283 scoped_ptr
<Window
> w111(CreateTestWindowWithId(111, w11
.get()));
284 scoped_ptr
<Window
> w12(CreateTestWindowWithId(12, w1
.get()));
286 EXPECT_EQ(NULL
, w1
->GetChildById(57));
287 EXPECT_EQ(w12
.get(), w1
->GetChildById(12));
288 EXPECT_EQ(w111
.get(), w1
->GetChildById(111));
291 // Make sure that Window::Contains correctly handles children, grandchildren,
292 // and not containing NULL or parents.
293 TEST_F(WindowTest
, Contains
) {
295 parent
.Init(ui::LAYER_NOT_DRAWN
);
297 child1
.Init(ui::LAYER_NOT_DRAWN
);
299 child2
.Init(ui::LAYER_NOT_DRAWN
);
301 parent
.AddChild(&child1
);
302 child1
.AddChild(&child2
);
304 EXPECT_TRUE(parent
.Contains(&parent
));
305 EXPECT_TRUE(parent
.Contains(&child1
));
306 EXPECT_TRUE(parent
.Contains(&child2
));
308 EXPECT_FALSE(parent
.Contains(NULL
));
309 EXPECT_FALSE(child1
.Contains(&parent
));
310 EXPECT_FALSE(child2
.Contains(&child1
));
313 TEST_F(WindowTest
, ContainsPointInRoot
) {
314 scoped_ptr
<Window
> w(
315 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(10, 10, 5, 5),
317 EXPECT_FALSE(w
->ContainsPointInRoot(gfx::Point(9, 9)));
318 EXPECT_TRUE(w
->ContainsPointInRoot(gfx::Point(10, 10)));
319 EXPECT_TRUE(w
->ContainsPointInRoot(gfx::Point(14, 14)));
320 EXPECT_FALSE(w
->ContainsPointInRoot(gfx::Point(15, 15)));
321 EXPECT_FALSE(w
->ContainsPointInRoot(gfx::Point(20, 20)));
324 TEST_F(WindowTest
, ContainsPoint
) {
325 scoped_ptr
<Window
> w(
326 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(10, 10, 5, 5),
328 EXPECT_TRUE(w
->ContainsPoint(gfx::Point(0, 0)));
329 EXPECT_TRUE(w
->ContainsPoint(gfx::Point(4, 4)));
330 EXPECT_FALSE(w
->ContainsPoint(gfx::Point(5, 5)));
331 EXPECT_FALSE(w
->ContainsPoint(gfx::Point(10, 10)));
334 TEST_F(WindowTest
, ConvertPointToWindow
) {
335 // Window::ConvertPointToWindow is mostly identical to
336 // Layer::ConvertPointToLayer, except NULL values for |source| are permitted,
337 // in which case the function just returns.
338 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
339 gfx::Point
reference_point(100, 100);
340 gfx::Point test_point
= reference_point
;
341 Window::ConvertPointToTarget(NULL
, w1
.get(), &test_point
);
342 EXPECT_EQ(reference_point
, test_point
);
345 TEST_F(WindowTest
, MoveCursorTo
) {
346 scoped_ptr
<Window
> w1(
347 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(10, 10, 500, 500),
349 scoped_ptr
<Window
> w11(
350 CreateTestWindow(SK_ColorGREEN
, 11, gfx::Rect(5, 5, 100, 100), w1
.get()));
351 scoped_ptr
<Window
> w111(
352 CreateTestWindow(SK_ColorCYAN
, 111, gfx::Rect(5, 5, 75, 75), w11
.get()));
353 scoped_ptr
<Window
> w1111(
354 CreateTestWindow(SK_ColorRED
, 1111, gfx::Rect(5, 5, 50, 50), w111
.get()));
356 RootWindow
* root
= root_window();
357 root
->MoveCursorTo(gfx::Point(10, 10));
359 gfx::Screen::GetScreenFor(root
)->GetCursorScreenPoint().ToString());
360 w1
->MoveCursorTo(gfx::Point(10, 10));
362 gfx::Screen::GetScreenFor(root
)->GetCursorScreenPoint().ToString());
363 w11
->MoveCursorTo(gfx::Point(10, 10));
365 gfx::Screen::GetScreenFor(root
)->GetCursorScreenPoint().ToString());
366 w111
->MoveCursorTo(gfx::Point(10, 10));
368 gfx::Screen::GetScreenFor(root
)->GetCursorScreenPoint().ToString());
369 w1111
->MoveCursorTo(gfx::Point(10, 10));
371 gfx::Screen::GetScreenFor(root
)->GetCursorScreenPoint().ToString());
374 TEST_F(WindowTest
, ContainsMouse
) {
375 scoped_ptr
<Window
> w(
376 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(10, 10, 500, 500),
379 WindowTestApi
w_test_api(w
.get());
380 RootWindow
* root
= root_window();
381 root
->MoveCursorTo(gfx::Point(10, 10));
382 EXPECT_TRUE(w_test_api
.ContainsMouse());
383 root
->MoveCursorTo(gfx::Point(9, 10));
384 EXPECT_FALSE(w_test_api
.ContainsMouse());
387 // Test Window::ConvertPointToWindow() with transform to root_window.
388 TEST_F(WindowTest
, MoveCursorToWithTransformRootWindow
) {
389 RootWindow
* root
= root_window();
390 gfx::Transform transform
;
391 transform
.Translate(100.0, 100.0);
392 transform
.Rotate(90.0);
393 transform
.Scale(2.0, 5.0);
394 root
->SetTransform(transform
);
395 root
->MoveCursorTo(gfx::Point(10, 10));
397 gfx::Point mouse_location
;
398 EXPECT_TRUE(root
->QueryMouseLocationForTest(&mouse_location
));
399 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.OD
400 EXPECT_EQ("50,120", mouse_location
.ToString());
403 gfx::Screen::GetScreenFor(root
)->GetCursorScreenPoint().ToString());
406 // Tests Window::ConvertPointToWindow() with transform to non-root windows.
407 TEST_F(WindowTest
, MoveCursorToWithTransformWindow
) {
408 scoped_ptr
<Window
> w1(
409 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(10, 10, 500, 500),
412 gfx::Transform transform1
;
413 transform1
.Scale(2, 2);
414 w1
->SetTransform(transform1
);
415 w1
->MoveCursorTo(gfx::Point(10, 10));
417 gfx::Screen::GetScreenFor(w1
.get())->GetCursorScreenPoint().ToString());
419 gfx::Transform transform2
;
420 transform2
.Translate(-10, 20);
421 w1
->SetTransform(transform2
);
422 w1
->MoveCursorTo(gfx::Point(10, 10));
424 gfx::Screen::GetScreenFor(w1
.get())->GetCursorScreenPoint().ToString());
426 gfx::Transform transform3
;
427 transform3
.Rotate(90.0);
428 w1
->SetTransform(transform3
);
429 w1
->MoveCursorTo(gfx::Point(5, 5));
431 gfx::Screen::GetScreenFor(w1
.get())->GetCursorScreenPoint().ToString());
433 gfx::Transform transform4
;
434 transform4
.Translate(100.0, 100.0);
435 transform4
.Rotate(90.0);
436 transform4
.Scale(2.0, 5.0);
437 w1
->SetTransform(transform4
);
438 w1
->MoveCursorTo(gfx::Point(10, 10));
440 gfx::Screen::GetScreenFor(w1
.get())->GetCursorScreenPoint().ToString());
443 // Test Window::ConvertPointToWindow() with complex transforms to both root and
445 TEST_F(WindowTest
, MoveCursorToWithComplexTransform
) {
446 scoped_ptr
<Window
> w1(
447 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(10, 10, 500, 500),
449 scoped_ptr
<Window
> w11(
450 CreateTestWindow(SK_ColorGREEN
, 11, gfx::Rect(5, 5, 100, 100), w1
.get()));
451 scoped_ptr
<Window
> w111(
452 CreateTestWindow(SK_ColorCYAN
, 111, gfx::Rect(5, 5, 75, 75), w11
.get()));
453 scoped_ptr
<Window
> w1111(
454 CreateTestWindow(SK_ColorRED
, 1111, gfx::Rect(5, 5, 50, 50), w111
.get()));
456 RootWindow
* root
= root_window();
458 // The root window expects transforms that produce integer rects.
459 gfx::Transform root_transform
;
460 root_transform
.Translate(60.0, 70.0);
461 root_transform
.Rotate(-90.0);
462 root_transform
.Translate(-50.0, -50.0);
463 root_transform
.Scale(2.0, 3.0);
465 gfx::Transform transform
;
466 transform
.Translate(10.0, 20.0);
467 transform
.Rotate(10.0);
468 transform
.Scale(0.3, 0.5);
469 root
->SetTransform(root_transform
);
470 w1
->SetTransform(transform
);
471 w11
->SetTransform(transform
);
472 w111
->SetTransform(transform
);
473 w1111
->SetTransform(transform
);
475 w1111
->MoveCursorTo(gfx::Point(10, 10));
478 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.
479 gfx::Point mouse_location
;
480 EXPECT_TRUE(root
->QueryMouseLocationForTest(&mouse_location
));
481 EXPECT_EQ("169,80", mouse_location
.ToString());
484 gfx::Screen::GetScreenFor(root
)->GetCursorScreenPoint().ToString());
487 TEST_F(WindowTest
, HitTest
) {
488 Window
w1(new ColorTestWindowDelegate(SK_ColorWHITE
));
490 w1
.Init(ui::LAYER_TEXTURED
);
491 w1
.SetBounds(gfx::Rect(10, 20, 50, 60));
493 SetDefaultParentByPrimaryRootWindow(&w1
);
495 // Points are in the Window's coordinates.
496 EXPECT_TRUE(w1
.HitTest(gfx::Point(1, 1)));
497 EXPECT_FALSE(w1
.HitTest(gfx::Point(-1, -1)));
499 // We can expand the bounds slightly to track events outside our border.
500 w1
.SetHitTestBoundsOverrideOuter(gfx::Insets(-1, -1, -1, -1), 5);
501 EXPECT_TRUE(w1
.HitTest(gfx::Point(-1, -1)));
502 EXPECT_FALSE(w1
.HitTest(gfx::Point(-2, -2)));
504 ui::TouchEvent
pressed(
505 ui::ET_TOUCH_PRESSED
, gfx::Point(50, 50), 0, getTime());
506 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&pressed
);
507 EXPECT_TRUE(w1
.HitTest(gfx::Point(-2, -2)));
508 EXPECT_TRUE(w1
.HitTest(gfx::Point(-5, -5)));
509 EXPECT_FALSE(w1
.HitTest(gfx::Point(-5, -6)));
510 ui::TouchEvent
released(
511 ui::ET_TOUCH_RELEASED
, gfx::Point(50, 50), 0, getTime());
512 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&released
);
513 EXPECT_FALSE(w1
.HitTest(gfx::Point(-2, -2)));
515 // TODO(beng): clip Window to parent.
518 TEST_F(WindowTest
, HitTestMask
) {
519 MaskedWindowDelegate
d1(gfx::Rect(5, 6, 20, 30));
521 w1
.Init(ui::LAYER_NOT_DRAWN
);
522 w1
.SetBounds(gfx::Rect(10, 20, 50, 60));
524 SetDefaultParentByPrimaryRootWindow(&w1
);
526 // Points inside the mask.
527 EXPECT_TRUE(w1
.HitTest(gfx::Point(5, 6))); // top-left
528 EXPECT_TRUE(w1
.HitTest(gfx::Point(15, 21))); // center
529 EXPECT_TRUE(w1
.HitTest(gfx::Point(24, 35))); // bottom-right
531 // Points outside the mask.
532 EXPECT_FALSE(w1
.HitTest(gfx::Point(0, 0)));
533 EXPECT_FALSE(w1
.HitTest(gfx::Point(60, 80)));
534 EXPECT_FALSE(w1
.HitTest(gfx::Point(4, 6)));
535 EXPECT_FALSE(w1
.HitTest(gfx::Point(5, 5)));
536 EXPECT_FALSE(w1
.HitTest(gfx::Point(25, 36)));
539 TEST_F(WindowTest
, GetEventHandlerForPoint
) {
540 scoped_ptr
<Window
> w1(
541 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(10, 10, 500, 500),
543 scoped_ptr
<Window
> w11(
544 CreateTestWindow(SK_ColorGREEN
, 11, gfx::Rect(5, 5, 100, 100), w1
.get()));
545 scoped_ptr
<Window
> w111(
546 CreateTestWindow(SK_ColorCYAN
, 111, gfx::Rect(5, 5, 75, 75), w11
.get()));
547 scoped_ptr
<Window
> w1111(
548 CreateTestWindow(SK_ColorRED
, 1111, gfx::Rect(5, 5, 50, 50), w111
.get()));
549 scoped_ptr
<Window
> w12(
550 CreateTestWindow(SK_ColorMAGENTA
, 12, gfx::Rect(10, 420, 25, 25),
552 scoped_ptr
<Window
> w121(
553 CreateTestWindow(SK_ColorYELLOW
, 121, gfx::Rect(5, 5, 5, 5), w12
.get()));
554 scoped_ptr
<Window
> w13(
555 CreateTestWindow(SK_ColorGRAY
, 13, gfx::Rect(5, 470, 50, 50), w1
.get()));
557 Window
* root
= root_window();
558 w1
->parent()->SetBounds(gfx::Rect(500, 500));
559 EXPECT_EQ(NULL
, root
->GetEventHandlerForPoint(gfx::Point(5, 5)));
560 EXPECT_EQ(w1
.get(), root
->GetEventHandlerForPoint(gfx::Point(11, 11)));
561 EXPECT_EQ(w11
.get(), root
->GetEventHandlerForPoint(gfx::Point(16, 16)));
562 EXPECT_EQ(w111
.get(), root
->GetEventHandlerForPoint(gfx::Point(21, 21)));
563 EXPECT_EQ(w1111
.get(), root
->GetEventHandlerForPoint(gfx::Point(26, 26)));
564 EXPECT_EQ(w12
.get(), root
->GetEventHandlerForPoint(gfx::Point(21, 431)));
565 EXPECT_EQ(w121
.get(), root
->GetEventHandlerForPoint(gfx::Point(26, 436)));
566 EXPECT_EQ(w13
.get(), root
->GetEventHandlerForPoint(gfx::Point(26, 481)));
569 TEST_F(WindowTest
, GetEventHandlerForPointWithOverride
) {
570 // If our child is flush to our top-left corner he gets events just inside the
572 scoped_ptr
<Window
> parent(
573 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(10, 20, 400, 500),
575 scoped_ptr
<Window
> child(
576 CreateTestWindow(SK_ColorRED
, 2, gfx::Rect(0, 0, 60, 70), parent
.get()));
577 EXPECT_EQ(child
.get(), parent
->GetEventHandlerForPoint(gfx::Point(0, 0)));
578 EXPECT_EQ(child
.get(), parent
->GetEventHandlerForPoint(gfx::Point(1, 1)));
580 // We can override the hit test bounds of the parent to make the parent grab
581 // events along that edge.
582 parent
->set_hit_test_bounds_override_inner(gfx::Insets(1, 1, 1, 1));
583 EXPECT_EQ(parent
.get(), parent
->GetEventHandlerForPoint(gfx::Point(0, 0)));
584 EXPECT_EQ(child
.get(), parent
->GetEventHandlerForPoint(gfx::Point(1, 1)));
587 TEST_F(WindowTest
, GetEventHandlerForPointWithOverrideDescendingOrder
) {
588 scoped_ptr
<SelfEventHandlingWindowDelegate
> parent_delegate(
589 new SelfEventHandlingWindowDelegate
);
590 scoped_ptr
<Window
> parent(CreateTestWindowWithDelegate(
591 parent_delegate
.get(), 1, gfx::Rect(10, 20, 400, 500), root_window()));
592 scoped_ptr
<Window
> child(
593 CreateTestWindow(SK_ColorRED
, 2, gfx::Rect(0, 0, 390, 480),
596 // We can override ShouldDescendIntoChildForEventHandling to make the parent
598 EXPECT_EQ(parent
.get(), parent
->GetEventHandlerForPoint(gfx::Point(0, 0)));
599 EXPECT_EQ(parent
.get(), parent
->GetEventHandlerForPoint(gfx::Point(50, 50)));
602 TEST_F(WindowTest
, GetTopWindowContainingPoint
) {
603 Window
* root
= root_window();
604 root
->SetBounds(gfx::Rect(0, 0, 300, 300));
606 scoped_ptr
<Window
> w1(
607 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(10, 10, 100, 100),
609 scoped_ptr
<Window
> w11(
610 CreateTestWindow(SK_ColorGREEN
, 11, gfx::Rect(0, 0, 120, 120), w1
.get()));
612 scoped_ptr
<Window
> w2(
613 CreateTestWindow(SK_ColorRED
, 2, gfx::Rect(5, 5, 55, 55),
616 scoped_ptr
<Window
> w3(
617 CreateTestWindowWithDelegate(
618 NULL
, 3, gfx::Rect(200, 200, 100, 100), root_window()));
619 scoped_ptr
<Window
> w31(
620 CreateTestWindow(SK_ColorCYAN
, 31, gfx::Rect(0, 0, 50, 50), w3
.get()));
621 scoped_ptr
<Window
> w311(
622 CreateTestWindow(SK_ColorBLUE
, 311, gfx::Rect(0, 0, 10, 10), w31
.get()));
624 EXPECT_EQ(NULL
, root
->GetTopWindowContainingPoint(gfx::Point(0, 0)));
625 EXPECT_EQ(w2
.get(), root
->GetTopWindowContainingPoint(gfx::Point(5, 5)));
626 EXPECT_EQ(w2
.get(), root
->GetTopWindowContainingPoint(gfx::Point(10, 10)));
627 EXPECT_EQ(w2
.get(), root
->GetTopWindowContainingPoint(gfx::Point(59, 59)));
628 EXPECT_EQ(w1
.get(), root
->GetTopWindowContainingPoint(gfx::Point(60, 60)));
629 EXPECT_EQ(w1
.get(), root
->GetTopWindowContainingPoint(gfx::Point(109, 109)));
630 EXPECT_EQ(NULL
, root
->GetTopWindowContainingPoint(gfx::Point(110, 110)));
631 EXPECT_EQ(w31
.get(), root
->GetTopWindowContainingPoint(gfx::Point(200, 200)));
632 EXPECT_EQ(w31
.get(), root
->GetTopWindowContainingPoint(gfx::Point(220, 220)));
633 EXPECT_EQ(NULL
, root
->GetTopWindowContainingPoint(gfx::Point(260, 260)));
636 TEST_F(WindowTest
, GetToplevelWindow
) {
637 const gfx::Rect
kBounds(0, 0, 10, 10);
638 TestWindowDelegate delegate
;
640 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
641 scoped_ptr
<Window
> w11(
642 CreateTestWindowWithDelegate(&delegate
, 11, kBounds
, w1
.get()));
643 scoped_ptr
<Window
> w111(CreateTestWindowWithId(111, w11
.get()));
644 scoped_ptr
<Window
> w1111(
645 CreateTestWindowWithDelegate(&delegate
, 1111, kBounds
, w111
.get()));
647 EXPECT_TRUE(root_window()->GetToplevelWindow() == NULL
);
648 EXPECT_TRUE(w1
->GetToplevelWindow() == NULL
);
649 EXPECT_EQ(w11
.get(), w11
->GetToplevelWindow());
650 EXPECT_EQ(w11
.get(), w111
->GetToplevelWindow());
651 EXPECT_EQ(w11
.get(), w1111
->GetToplevelWindow());
654 class AddedToRootWindowObserver
: public WindowObserver
{
656 AddedToRootWindowObserver() : called_(false) {}
658 virtual void OnWindowAddedToRootWindow(Window
* window
) OVERRIDE
{
662 bool called() const { return called_
; }
667 DISALLOW_COPY_AND_ASSIGN(AddedToRootWindowObserver
);
670 TEST_F(WindowTest
, WindowAddedToRootWindowShouldNotifyChildAndNotParent
) {
671 AddedToRootWindowObserver parent_observer
;
672 AddedToRootWindowObserver child_observer
;
673 scoped_ptr
<Window
> parent_window(CreateTestWindowWithId(1, root_window()));
674 scoped_ptr
<Window
> child_window(new Window(NULL
));
675 child_window
->Init(ui::LAYER_TEXTURED
);
676 child_window
->Show();
678 parent_window
->AddObserver(&parent_observer
);
679 child_window
->AddObserver(&child_observer
);
681 parent_window
->AddChild(child_window
.get());
683 EXPECT_FALSE(parent_observer
.called());
684 EXPECT_TRUE(child_observer
.called());
686 parent_window
->RemoveObserver(&parent_observer
);
687 child_window
->RemoveObserver(&child_observer
);
690 // Various destruction assertions.
691 TEST_F(WindowTest
, DestroyTest
) {
692 DestroyTrackingDelegateImpl parent_delegate
;
693 ChildWindowDelegateImpl
child_delegate(&parent_delegate
);
695 scoped_ptr
<Window
> parent(
696 CreateTestWindowWithDelegate(&parent_delegate
, 0, gfx::Rect(),
698 CreateTestWindowWithDelegate(&child_delegate
, 0, gfx::Rect(), parent
.get());
700 // Both the parent and child should have been destroyed.
701 EXPECT_EQ(1, parent_delegate
.destroying_count());
702 EXPECT_EQ(1, parent_delegate
.destroyed_count());
703 EXPECT_EQ(1, child_delegate
.destroying_count());
704 EXPECT_EQ(1, child_delegate
.destroyed_count());
707 // Tests that a window is orphaned before OnWindowDestroyed is called.
708 TEST_F(WindowTest
, OrphanedBeforeOnDestroyed
) {
709 TestWindowDelegate parent_delegate
;
710 DestroyOrphanDelegate child_delegate
;
712 scoped_ptr
<Window
> parent(
713 CreateTestWindowWithDelegate(&parent_delegate
, 0, gfx::Rect(),
715 scoped_ptr
<Window
> child(CreateTestWindowWithDelegate(&child_delegate
, 0,
716 gfx::Rect(), parent
.get()));
717 child_delegate
.set_window(child
.get());
721 // Make sure StackChildAtTop moves both the window and layer to the front.
722 TEST_F(WindowTest
, StackChildAtTop
) {
724 parent
.Init(ui::LAYER_NOT_DRAWN
);
726 child1
.Init(ui::LAYER_NOT_DRAWN
);
728 child2
.Init(ui::LAYER_NOT_DRAWN
);
730 parent
.AddChild(&child1
);
731 parent
.AddChild(&child2
);
732 ASSERT_EQ(2u, parent
.children().size());
733 EXPECT_EQ(&child1
, parent
.children()[0]);
734 EXPECT_EQ(&child2
, parent
.children()[1]);
735 ASSERT_EQ(2u, parent
.layer()->children().size());
736 EXPECT_EQ(child1
.layer(), parent
.layer()->children()[0]);
737 EXPECT_EQ(child2
.layer(), parent
.layer()->children()[1]);
739 parent
.StackChildAtTop(&child1
);
740 ASSERT_EQ(2u, parent
.children().size());
741 EXPECT_EQ(&child1
, parent
.children()[1]);
742 EXPECT_EQ(&child2
, parent
.children()[0]);
743 ASSERT_EQ(2u, parent
.layer()->children().size());
744 EXPECT_EQ(child1
.layer(), parent
.layer()->children()[1]);
745 EXPECT_EQ(child2
.layer(), parent
.layer()->children()[0]);
748 // Make sure StackChildBelow works.
749 TEST_F(WindowTest
, StackChildBelow
) {
751 parent
.Init(ui::LAYER_NOT_DRAWN
);
753 child1
.Init(ui::LAYER_NOT_DRAWN
);
756 child2
.Init(ui::LAYER_NOT_DRAWN
);
759 child3
.Init(ui::LAYER_NOT_DRAWN
);
762 parent
.AddChild(&child1
);
763 parent
.AddChild(&child2
);
764 parent
.AddChild(&child3
);
765 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent
));
767 parent
.StackChildBelow(&child1
, &child2
);
768 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent
));
770 parent
.StackChildBelow(&child2
, &child1
);
771 EXPECT_EQ("2 1 3", ChildWindowIDsAsString(&parent
));
773 parent
.StackChildBelow(&child3
, &child2
);
774 EXPECT_EQ("3 2 1", ChildWindowIDsAsString(&parent
));
776 parent
.StackChildBelow(&child3
, &child1
);
777 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(&parent
));
780 // Various assertions for StackChildAbove.
781 TEST_F(WindowTest
, StackChildAbove
) {
783 parent
.Init(ui::LAYER_NOT_DRAWN
);
785 child1
.Init(ui::LAYER_NOT_DRAWN
);
787 child2
.Init(ui::LAYER_NOT_DRAWN
);
789 child3
.Init(ui::LAYER_NOT_DRAWN
);
791 parent
.AddChild(&child1
);
792 parent
.AddChild(&child2
);
794 // Move 1 in front of 2.
795 parent
.StackChildAbove(&child1
, &child2
);
796 ASSERT_EQ(2u, parent
.children().size());
797 EXPECT_EQ(&child2
, parent
.children()[0]);
798 EXPECT_EQ(&child1
, parent
.children()[1]);
799 ASSERT_EQ(2u, parent
.layer()->children().size());
800 EXPECT_EQ(child2
.layer(), parent
.layer()->children()[0]);
801 EXPECT_EQ(child1
.layer(), parent
.layer()->children()[1]);
803 // Add 3, resulting in order [2, 1, 3], then move 2 in front of 1, resulting
805 parent
.AddChild(&child3
);
806 parent
.StackChildAbove(&child2
, &child1
);
807 ASSERT_EQ(3u, parent
.children().size());
808 EXPECT_EQ(&child1
, parent
.children()[0]);
809 EXPECT_EQ(&child2
, parent
.children()[1]);
810 EXPECT_EQ(&child3
, parent
.children()[2]);
811 ASSERT_EQ(3u, parent
.layer()->children().size());
812 EXPECT_EQ(child1
.layer(), parent
.layer()->children()[0]);
813 EXPECT_EQ(child2
.layer(), parent
.layer()->children()[1]);
814 EXPECT_EQ(child3
.layer(), parent
.layer()->children()[2]);
816 // Move 1 in front of 3, resulting in [2, 3, 1].
817 parent
.StackChildAbove(&child1
, &child3
);
818 ASSERT_EQ(3u, parent
.children().size());
819 EXPECT_EQ(&child2
, parent
.children()[0]);
820 EXPECT_EQ(&child3
, parent
.children()[1]);
821 EXPECT_EQ(&child1
, parent
.children()[2]);
822 ASSERT_EQ(3u, parent
.layer()->children().size());
823 EXPECT_EQ(child2
.layer(), parent
.layer()->children()[0]);
824 EXPECT_EQ(child3
.layer(), parent
.layer()->children()[1]);
825 EXPECT_EQ(child1
.layer(), parent
.layer()->children()[2]);
827 // Moving 1 in front of 2 should lower it, resulting in [2, 1, 3].
828 parent
.StackChildAbove(&child1
, &child2
);
829 ASSERT_EQ(3u, parent
.children().size());
830 EXPECT_EQ(&child2
, parent
.children()[0]);
831 EXPECT_EQ(&child1
, parent
.children()[1]);
832 EXPECT_EQ(&child3
, parent
.children()[2]);
833 ASSERT_EQ(3u, parent
.layer()->children().size());
834 EXPECT_EQ(child2
.layer(), parent
.layer()->children()[0]);
835 EXPECT_EQ(child1
.layer(), parent
.layer()->children()[1]);
836 EXPECT_EQ(child3
.layer(), parent
.layer()->children()[2]);
839 // Various capture assertions.
840 TEST_F(WindowTest
, CaptureTests
) {
841 CaptureWindowDelegateImpl delegate
;
842 scoped_ptr
<Window
> window(CreateTestWindowWithDelegate(
843 &delegate
, 0, gfx::Rect(0, 0, 20, 20), root_window()));
844 EXPECT_FALSE(window
->HasCapture());
846 delegate
.ResetCounts();
849 window
->SetCapture();
850 EXPECT_TRUE(window
->HasCapture());
851 EXPECT_EQ(0, delegate
.capture_lost_count());
852 EXPECT_EQ(0, delegate
.capture_changed_event_count());
853 EventGenerator
generator(root_window(), gfx::Point(50, 50));
854 generator
.PressLeftButton();
855 EXPECT_EQ(1, delegate
.mouse_event_count());
856 generator
.ReleaseLeftButton();
858 EXPECT_EQ(2, delegate
.mouse_event_count());
859 delegate
.ResetCounts();
861 ui::TouchEvent
touchev(
862 ui::ET_TOUCH_PRESSED
, gfx::Point(50, 50), 0, getTime());
863 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&touchev
);
864 EXPECT_EQ(1, delegate
.touch_event_count());
865 delegate
.ResetCounts();
867 window
->ReleaseCapture();
868 EXPECT_FALSE(window
->HasCapture());
869 EXPECT_EQ(1, delegate
.capture_lost_count());
870 EXPECT_EQ(1, delegate
.capture_changed_event_count());
871 EXPECT_EQ(1, delegate
.mouse_event_count());
872 EXPECT_EQ(1, delegate
.touch_event_count());
874 generator
.PressLeftButton();
875 EXPECT_EQ(1, delegate
.mouse_event_count());
877 ui::TouchEvent
touchev2(
878 ui::ET_TOUCH_PRESSED
, gfx::Point(250, 250), 1, getTime());
879 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&touchev2
);
880 EXPECT_EQ(1, delegate
.touch_event_count());
882 // Removing the capture window from parent should reset the capture window
883 // in the root window.
884 window
->SetCapture();
885 EXPECT_EQ(window
.get(), aura::client::GetCaptureWindow(root_window()));
886 window
->parent()->RemoveChild(window
.get());
887 EXPECT_FALSE(window
->HasCapture());
888 EXPECT_EQ(NULL
, aura::client::GetCaptureWindow(root_window()));
891 TEST_F(WindowTest
, TouchCaptureCancelsOtherTouches
) {
892 CaptureWindowDelegateImpl delegate1
;
893 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(
894 &delegate1
, 0, gfx::Rect(0, 0, 20, 20), root_window()));
895 CaptureWindowDelegateImpl delegate2
;
896 scoped_ptr
<Window
> w2(CreateTestWindowWithDelegate(
897 &delegate2
, 0, gfx::Rect(20, 20, 20, 20), root_window()));
900 ui::TouchEvent
press(
901 ui::ET_TOUCH_PRESSED
, gfx::Point(10, 10), 0, getTime());
902 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press
);
903 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
904 EXPECT_EQ(2, delegate1
.gesture_event_count());
905 delegate1
.ResetCounts();
908 // The touch was cancelled when the other window
909 // attained a touch lock.
910 EXPECT_EQ(1, delegate1
.touch_event_count());
911 EXPECT_EQ(0, delegate2
.touch_event_count());
913 delegate1
.ResetCounts();
914 delegate2
.ResetCounts();
916 ui::TouchEvent
move(ui::ET_TOUCH_MOVED
, gfx::Point(10, 10), 0, getTime());
917 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move
);
919 // This touch id is now ignored, no scroll fired.
920 EXPECT_EQ(0, delegate1
.gesture_event_count());
921 EXPECT_EQ(0, delegate2
.gesture_event_count());
923 ui::TouchEvent
release(
924 ui::ET_TOUCH_RELEASED
, gfx::Point(10, 10), 0, getTime());
925 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release
);
926 EXPECT_EQ(0, delegate1
.gesture_event_count());
927 EXPECT_EQ(0, delegate2
.gesture_event_count());
929 // A new press is captured by w2.
931 ui::TouchEvent
press2(
932 ui::ET_TOUCH_PRESSED
, gfx::Point(10, 10), 0, getTime());
933 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2
);
934 EXPECT_EQ(0, delegate1
.gesture_event_count());
935 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
936 EXPECT_EQ(2, delegate2
.gesture_event_count());
939 TEST_F(WindowTest
, TouchCaptureDoesntCancelCapturedTouches
) {
940 CaptureWindowDelegateImpl delegate
;
941 scoped_ptr
<Window
> window(CreateTestWindowWithDelegate(
942 &delegate
, 0, gfx::Rect(0, 0, 20, 20), root_window()));
944 ui::TouchEvent
press(
945 ui::ET_TOUCH_PRESSED
, gfx::Point(10, 10), 0, getTime());
946 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press
);
948 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
949 EXPECT_EQ(2, delegate
.gesture_event_count());
950 delegate
.ResetCounts();
952 window
->SetCapture();
953 EXPECT_EQ(0, delegate
.gesture_event_count());
954 delegate
.ResetCounts();
956 // The move event should still create a gesture, as this touch was
957 // on the window which was captured.
958 ui::TouchEvent
release(ui::ET_TOUCH_RELEASED
,
959 gfx::Point(10, 10), 0, getTime() +
960 base::TimeDelta::FromMilliseconds(50));
961 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release
);
962 EXPECT_EQ(2, delegate
.gesture_event_count());
965 // Assertions around SetCapture() and touch/gestures.
966 TEST_F(WindowTest
, TransferCaptureTouchEvents
) {
968 CaptureWindowDelegateImpl d1
;
969 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(
970 &d1
, 0, gfx::Rect(0, 0, 20, 20), root_window()));
971 ui::TouchEvent
p1(ui::ET_TOUCH_PRESSED
, gfx::Point(10, 10), 0, getTime());
972 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&p1
);
973 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
974 EXPECT_EQ(2, d1
.gesture_event_count());
977 // Touch on |w2| with a different id.
978 CaptureWindowDelegateImpl d2
;
979 scoped_ptr
<Window
> w2(CreateTestWindowWithDelegate(
980 &d2
, 0, gfx::Rect(40, 0, 40, 20), root_window()));
981 ui::TouchEvent
p2(ui::ET_TOUCH_PRESSED
, gfx::Point(41, 10), 1, getTime());
982 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&p2
);
983 EXPECT_EQ(0, d1
.gesture_event_count());
984 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN for new target window.
985 EXPECT_EQ(2, d2
.gesture_event_count());
989 // Set capture on |w2|, this should send a cancel (TAP_CANCEL, END) to |w1|
992 EXPECT_EQ(2, d1
.gesture_event_count());
993 EXPECT_EQ(0, d2
.gesture_event_count());
997 CaptureWindowDelegateImpl d3
;
998 scoped_ptr
<Window
> w3(CreateTestWindowWithDelegate(
999 &d3
, 0, gfx::Rect(0, 0, 100, 101), root_window()));
1000 // Set capture on w3. No new events should be received.
1002 EXPECT_EQ(0, d1
.gesture_event_count());
1003 EXPECT_EQ(0, d2
.gesture_event_count());
1004 EXPECT_EQ(0, d3
.gesture_event_count());
1006 // Move touch id originally associated with |w2|. Since capture was transfered
1007 // from 2 to 3 only |w3| should get the event.
1008 ui::TouchEvent
m3(ui::ET_TOUCH_MOVED
, gfx::Point(110, 105), 1, getTime());
1009 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&m3
);
1010 EXPECT_EQ(0, d1
.gesture_event_count());
1011 EXPECT_EQ(0, d2
.gesture_event_count());
1012 // |w3| gets a TAP_CANCEL and two scroll related events.
1013 EXPECT_EQ(3, d3
.gesture_event_count());
1016 // Changes capture while capture is already ongoing.
1017 TEST_F(WindowTest
, ChangeCaptureWhileMouseDown
) {
1018 CaptureWindowDelegateImpl delegate
;
1019 scoped_ptr
<Window
> window(CreateTestWindowWithDelegate(
1020 &delegate
, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1021 CaptureWindowDelegateImpl delegate2
;
1022 scoped_ptr
<Window
> w2(CreateTestWindowWithDelegate(
1023 &delegate2
, 0, gfx::Rect(20, 20, 20, 20), root_window()));
1025 // Execute the scheduled draws so that mouse events are not
1027 RunAllPendingInMessageLoop();
1029 EXPECT_FALSE(window
->HasCapture());
1032 delegate
.ResetCounts();
1033 window
->SetCapture();
1034 EXPECT_TRUE(window
->HasCapture());
1035 EXPECT_EQ(0, delegate
.capture_lost_count());
1036 EXPECT_EQ(0, delegate
.capture_changed_event_count());
1037 EventGenerator
generator(root_window(), gfx::Point(50, 50));
1038 generator
.PressLeftButton();
1039 EXPECT_EQ(0, delegate
.capture_lost_count());
1040 EXPECT_EQ(0, delegate
.capture_changed_event_count());
1041 EXPECT_EQ(1, delegate
.mouse_event_count());
1043 // Set capture to |w2|, should implicitly unset capture for |window|.
1044 delegate
.ResetCounts();
1045 delegate2
.ResetCounts();
1048 generator
.MoveMouseTo(gfx::Point(40, 40), 2);
1049 EXPECT_EQ(1, delegate
.capture_lost_count());
1050 EXPECT_EQ(1, delegate
.capture_changed_event_count());
1051 EXPECT_EQ(1, delegate
.mouse_event_count());
1052 EXPECT_EQ(2, delegate2
.mouse_event_count());
1055 // Verifies capture is reset when a window is destroyed.
1056 TEST_F(WindowTest
, ReleaseCaptureOnDestroy
) {
1057 CaptureWindowDelegateImpl delegate
;
1058 scoped_ptr
<Window
> window(CreateTestWindowWithDelegate(
1059 &delegate
, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1060 EXPECT_FALSE(window
->HasCapture());
1063 window
->SetCapture();
1064 EXPECT_TRUE(window
->HasCapture());
1066 // Destroy the window.
1069 // Make sure the root window doesn't reference the window anymore.
1070 EXPECT_EQ(NULL
, root_window()->mouse_pressed_handler());
1071 EXPECT_EQ(NULL
, aura::client::GetCaptureWindow(root_window()));
1074 TEST_F(WindowTest
, GetBoundsInRootWindow
) {
1075 scoped_ptr
<Window
> viewport(CreateTestWindowWithBounds(
1076 gfx::Rect(0, 0, 300, 300), root_window()));
1077 scoped_ptr
<Window
> child(CreateTestWindowWithBounds(
1078 gfx::Rect(0, 0, 100, 100), viewport
.get()));
1080 EXPECT_EQ("0,0 100x100", child
->GetBoundsInRootWindow().ToString());
1082 // The |child| window's screen bounds should move along with the |viewport|.
1083 viewport
->SetBounds(gfx::Rect(-100, -100, 300, 300));
1084 EXPECT_EQ("-100,-100 100x100", child
->GetBoundsInRootWindow().ToString());
1086 // The |child| window is moved to the 0,0 in screen coordinates.
1087 // |GetBoundsInRootWindow()| should return 0,0.
1088 child
->SetBounds(gfx::Rect(100, 100, 100, 100));
1089 EXPECT_EQ("0,0 100x100", child
->GetBoundsInRootWindow().ToString());
1092 class MouseEnterExitWindowDelegate
: public TestWindowDelegate
{
1094 MouseEnterExitWindowDelegate() : entered_(false), exited_(false) {}
1096 virtual void OnMouseEvent(ui::MouseEvent
* event
) OVERRIDE
{
1097 switch (event
->type()) {
1098 case ui::ET_MOUSE_ENTERED
:
1101 case ui::ET_MOUSE_EXITED
:
1109 bool entered() const { return entered_
; }
1110 bool exited() const { return exited_
; }
1112 // Clear the entered / exited states.
1113 void ResetExpectations() {
1122 DISALLOW_COPY_AND_ASSIGN(MouseEnterExitWindowDelegate
);
1126 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1127 // mouse transitions from window to window.
1128 TEST_F(WindowTest
, MouseEnterExit
) {
1129 MouseEnterExitWindowDelegate d1
;
1130 scoped_ptr
<Window
> w1(
1131 CreateTestWindowWithDelegate(&d1
, 1, gfx::Rect(10, 10, 50, 50),
1133 MouseEnterExitWindowDelegate d2
;
1134 scoped_ptr
<Window
> w2(
1135 CreateTestWindowWithDelegate(&d2
, 2, gfx::Rect(70, 70, 50, 50),
1138 test::EventGenerator
generator(root_window());
1139 generator
.MoveMouseToCenterOf(w1
.get());
1140 EXPECT_TRUE(d1
.entered());
1141 EXPECT_FALSE(d1
.exited());
1142 EXPECT_FALSE(d2
.entered());
1143 EXPECT_FALSE(d2
.exited());
1145 generator
.MoveMouseToCenterOf(w2
.get());
1146 EXPECT_TRUE(d1
.entered());
1147 EXPECT_TRUE(d1
.exited());
1148 EXPECT_TRUE(d2
.entered());
1149 EXPECT_FALSE(d2
.exited());
1152 // Verifies that the WindowDelegate receives MouseExit from ET_MOUSE_EXITED.
1153 TEST_F(WindowTest
, RootWindowHostExit
) {
1154 MouseEnterExitWindowDelegate d1
;
1155 scoped_ptr
<Window
> w1(
1156 CreateTestWindowWithDelegate(&d1
, 1, gfx::Rect(10, 10, 50, 50),
1159 test::EventGenerator
generator(root_window());
1160 generator
.MoveMouseToCenterOf(w1
.get());
1161 EXPECT_TRUE(d1
.entered());
1162 EXPECT_FALSE(d1
.exited());
1163 d1
.ResetExpectations();
1165 ui::MouseEvent
exit_event(
1166 ui::ET_MOUSE_EXITED
, gfx::Point(), gfx::Point(), 0);
1167 root_window()->AsRootWindowHostDelegate()->OnHostMouseEvent(&exit_event
);
1168 EXPECT_FALSE(d1
.entered());
1169 EXPECT_TRUE(d1
.exited());
1172 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1173 // mouse transitions from window to window, even if the entered window sets
1174 // and releases capture.
1175 TEST_F(WindowTest
, MouseEnterExitWithClick
) {
1176 MouseEnterExitWindowDelegate d1
;
1177 scoped_ptr
<Window
> w1(
1178 CreateTestWindowWithDelegate(&d1
, 1, gfx::Rect(10, 10, 50, 50),
1180 MouseEnterExitWindowDelegate d2
;
1181 scoped_ptr
<Window
> w2(
1182 CreateTestWindowWithDelegate(&d2
, 2, gfx::Rect(70, 70, 50, 50),
1185 test::EventGenerator
generator(root_window());
1186 generator
.MoveMouseToCenterOf(w1
.get());
1187 EXPECT_TRUE(d1
.entered());
1188 EXPECT_FALSE(d1
.exited());
1189 EXPECT_FALSE(d2
.entered());
1190 EXPECT_FALSE(d2
.exited());
1192 // Emmulate what Views does on a click by grabbing and releasing capture.
1193 generator
.PressLeftButton();
1195 w1
->ReleaseCapture();
1196 generator
.ReleaseLeftButton();
1198 generator
.MoveMouseToCenterOf(w2
.get());
1199 EXPECT_TRUE(d1
.entered());
1200 EXPECT_TRUE(d1
.exited());
1201 EXPECT_TRUE(d2
.entered());
1202 EXPECT_FALSE(d2
.exited());
1205 // Verifies that enter / exits are sent if windows appear and are deleted
1206 // under the current mouse position..
1207 TEST_F(WindowTest
, MouseEnterExitWithDelete
) {
1208 MouseEnterExitWindowDelegate d1
;
1209 scoped_ptr
<Window
> w1(
1210 CreateTestWindowWithDelegate(&d1
, 1, gfx::Rect(10, 10, 50, 50),
1213 test::EventGenerator
generator(root_window());
1214 generator
.MoveMouseToCenterOf(w1
.get());
1215 EXPECT_TRUE(d1
.entered());
1216 EXPECT_FALSE(d1
.exited());
1219 MouseEnterExitWindowDelegate d2
;
1220 scoped_ptr
<Window
> w2(
1221 CreateTestWindowWithDelegate(&d2
, 2, gfx::Rect(10, 10, 50, 50),
1223 // Enters / exits can be send asynchronously.
1224 RunAllPendingInMessageLoop();
1225 EXPECT_TRUE(d1
.entered());
1226 EXPECT_TRUE(d1
.exited());
1227 EXPECT_TRUE(d2
.entered());
1228 EXPECT_FALSE(d2
.exited());
1229 d1
.ResetExpectations();
1231 // Enters / exits can be send asynchronously.
1232 RunAllPendingInMessageLoop();
1233 EXPECT_TRUE(d1
.entered());
1236 // Verifies that enter / exits are sent if windows appear and are hidden
1237 // under the current mouse position..
1238 TEST_F(WindowTest
, MouseEnterExitWithHide
) {
1239 MouseEnterExitWindowDelegate d1
;
1240 scoped_ptr
<Window
> w1(
1241 CreateTestWindowWithDelegate(&d1
, 1, gfx::Rect(10, 10, 50, 50),
1244 test::EventGenerator
generator(root_window());
1245 generator
.MoveMouseToCenterOf(w1
.get());
1246 EXPECT_TRUE(d1
.entered());
1247 EXPECT_FALSE(d1
.exited());
1249 MouseEnterExitWindowDelegate d2
;
1250 scoped_ptr
<Window
> w2(
1251 CreateTestWindowWithDelegate(&d2
, 2, gfx::Rect(10, 10, 50, 50),
1253 // Enters / exits can be send asynchronously.
1254 RunAllPendingInMessageLoop();
1255 EXPECT_TRUE(d1
.entered());
1256 EXPECT_TRUE(d1
.exited());
1257 EXPECT_TRUE(d2
.entered());
1258 EXPECT_FALSE(d2
.exited());
1260 d1
.ResetExpectations();
1262 // Enters / exits can be send asynchronously.
1263 RunAllPendingInMessageLoop();
1264 EXPECT_TRUE(d1
.entered());
1267 // Creates a window with a delegate (w111) that can handle events at a lower
1268 // z-index than a window without a delegate (w12). w12 is sized to fill the
1269 // entire bounds of the container. This test verifies that
1270 // GetEventHandlerForPoint() skips w12 even though its bounds contain the event,
1271 // because it has no children that can handle the event and it has no delegate
1272 // allowing it to handle the event itself.
1273 TEST_F(WindowTest
, GetEventHandlerForPoint_NoDelegate
) {
1274 TestWindowDelegate d111
;
1275 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(NULL
, 1,
1276 gfx::Rect(0, 0, 500, 500), root_window()));
1277 scoped_ptr
<Window
> w11(CreateTestWindowWithDelegate(NULL
, 11,
1278 gfx::Rect(0, 0, 500, 500), w1
.get()));
1279 scoped_ptr
<Window
> w111(CreateTestWindowWithDelegate(&d111
, 111,
1280 gfx::Rect(50, 50, 450, 450), w11
.get()));
1281 scoped_ptr
<Window
> w12(CreateTestWindowWithDelegate(NULL
, 12,
1282 gfx::Rect(0, 0, 500, 500), w1
.get()));
1284 gfx::Point target_point
= w111
->bounds().CenterPoint();
1285 EXPECT_EQ(w111
.get(), w1
->GetEventHandlerForPoint(target_point
));
1288 class VisibilityWindowDelegate
: public TestWindowDelegate
{
1290 VisibilityWindowDelegate()
1295 int shown() const { return shown_
; }
1296 int hidden() const { return hidden_
; }
1302 virtual void OnWindowTargetVisibilityChanged(bool visible
) OVERRIDE
{
1313 DISALLOW_COPY_AND_ASSIGN(VisibilityWindowDelegate
);
1316 // Verifies show/hide propagate correctly to children and the layer.
1317 TEST_F(WindowTest
, Visibility
) {
1318 VisibilityWindowDelegate d
;
1319 VisibilityWindowDelegate d2
;
1320 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(&d
, 1, gfx::Rect(),
1322 scoped_ptr
<Window
> w2(
1323 CreateTestWindowWithDelegate(&d2
, 2, gfx::Rect(), w1
.get()));
1324 scoped_ptr
<Window
> w3(CreateTestWindowWithId(3, w2
.get()));
1326 // Create shows all the windows.
1327 EXPECT_TRUE(w1
->IsVisible());
1328 EXPECT_TRUE(w2
->IsVisible());
1329 EXPECT_TRUE(w3
->IsVisible());
1330 EXPECT_EQ(1, d
.shown());
1334 EXPECT_FALSE(w1
->IsVisible());
1335 EXPECT_FALSE(w2
->IsVisible());
1336 EXPECT_FALSE(w3
->IsVisible());
1337 EXPECT_EQ(1, d
.hidden());
1338 EXPECT_EQ(0, d
.shown());
1341 EXPECT_FALSE(w1
->IsVisible());
1342 EXPECT_FALSE(w2
->IsVisible());
1343 EXPECT_FALSE(w3
->IsVisible());
1346 EXPECT_FALSE(w1
->IsVisible());
1347 EXPECT_FALSE(w2
->IsVisible());
1348 EXPECT_FALSE(w3
->IsVisible());
1352 EXPECT_TRUE(w1
->IsVisible());
1353 EXPECT_TRUE(w2
->IsVisible());
1354 EXPECT_FALSE(w3
->IsVisible());
1355 EXPECT_EQ(0, d
.hidden());
1356 EXPECT_EQ(1, d
.shown());
1359 EXPECT_TRUE(w1
->IsVisible());
1360 EXPECT_TRUE(w2
->IsVisible());
1361 EXPECT_TRUE(w3
->IsVisible());
1363 // Verify that if an ancestor isn't visible and we change the visibility of a
1364 // child window that OnChildWindowVisibilityChanged() is still invoked.
1368 EXPECT_EQ(1, d2
.hidden());
1369 EXPECT_EQ(0, d2
.shown());
1372 EXPECT_EQ(0, d2
.hidden());
1373 EXPECT_EQ(1, d2
.shown());
1376 TEST_F(WindowTest
, IgnoreEventsTest
) {
1377 TestWindowDelegate d11
;
1378 TestWindowDelegate d12
;
1379 TestWindowDelegate d111
;
1380 TestWindowDelegate d121
;
1381 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(NULL
, 1,
1382 gfx::Rect(0, 0, 500, 500), root_window()));
1383 scoped_ptr
<Window
> w11(CreateTestWindowWithDelegate(&d11
, 11,
1384 gfx::Rect(0, 0, 500, 500), w1
.get()));
1385 scoped_ptr
<Window
> w111(CreateTestWindowWithDelegate(&d111
, 111,
1386 gfx::Rect(50, 50, 450, 450), w11
.get()));
1387 scoped_ptr
<Window
> w12(CreateTestWindowWithDelegate(&d12
, 12,
1388 gfx::Rect(0, 0, 500, 500), w1
.get()));
1389 scoped_ptr
<Window
> w121(CreateTestWindowWithDelegate(&d121
, 121,
1390 gfx::Rect(150, 150, 50, 50), w12
.get()));
1392 EXPECT_EQ(w12
.get(), w1
->GetEventHandlerForPoint(gfx::Point(10, 10)));
1393 w12
->set_ignore_events(true);
1394 EXPECT_EQ(w11
.get(), w1
->GetEventHandlerForPoint(gfx::Point(10, 10)));
1395 w12
->set_ignore_events(false);
1397 EXPECT_EQ(w121
.get(), w1
->GetEventHandlerForPoint(gfx::Point(160, 160)));
1398 w121
->set_ignore_events(true);
1399 EXPECT_EQ(w12
.get(), w1
->GetEventHandlerForPoint(gfx::Point(160, 160)));
1400 w12
->set_ignore_events(true);
1401 EXPECT_EQ(w111
.get(), w1
->GetEventHandlerForPoint(gfx::Point(160, 160)));
1402 w111
->set_ignore_events(true);
1403 EXPECT_EQ(w11
.get(), w1
->GetEventHandlerForPoint(gfx::Point(160, 160)));
1406 // Tests transformation on the root window.
1407 TEST_F(WindowTest
, Transform
) {
1408 gfx::Size size
= root_window()->GetHostSize();
1409 EXPECT_EQ(gfx::Rect(size
),
1410 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1411 gfx::Point()).bounds());
1413 // Rotate it clock-wise 90 degrees.
1414 gfx::Transform transform
;
1415 transform
.Translate(size
.height(), 0);
1416 transform
.Rotate(90.0);
1417 root_window()->SetTransform(transform
);
1419 // The size should be the transformed size.
1420 gfx::Size
transformed_size(size
.height(), size
.width());
1421 EXPECT_EQ(transformed_size
.ToString(),
1422 root_window()->bounds().size().ToString());
1424 gfx::Rect(transformed_size
).ToString(),
1425 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1426 gfx::Point()).bounds().ToString());
1428 // Host size shouldn't change.
1429 EXPECT_EQ(size
.ToString(),
1430 root_window()->GetHostSize().ToString());
1433 TEST_F(WindowTest
, TransformGesture
) {
1434 gfx::Size size
= root_window()->GetHostSize();
1436 scoped_ptr
<GestureTrackPositionDelegate
> delegate(
1437 new GestureTrackPositionDelegate
);
1438 scoped_ptr
<Window
> window(CreateTestWindowWithDelegate(delegate
.get(), -1234,
1439 gfx::Rect(0, 0, 20, 20), root_window()));
1441 // Rotate the root-window clock-wise 90 degrees.
1442 gfx::Transform transform
;
1443 transform
.Translate(size
.height(), 0.0);
1444 transform
.Rotate(90.0);
1445 root_window()->SetTransform(transform
);
1447 ui::TouchEvent
press(
1448 ui::ET_TOUCH_PRESSED
, gfx::Point(size
.height() - 10, 10), 0, getTime());
1449 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press
);
1450 EXPECT_EQ(gfx::Point(10, 10).ToString(), delegate
->position().ToString());
1453 // Various assertions for transient children.
1454 TEST_F(WindowTest
, TransientChildren
) {
1455 scoped_ptr
<Window
> parent(CreateTestWindowWithId(0, root_window()));
1456 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, parent
.get()));
1457 scoped_ptr
<Window
> w3(CreateTestWindowWithId(3, parent
.get()));
1458 Window
* w2
= CreateTestWindowWithId(2, parent
.get());
1459 w1
->AddTransientChild(w2
); // w2 is now owned by w1.
1460 // Stack w1 at the top (end), this should force w2 to be last (on top of w1).
1461 parent
->StackChildAtTop(w1
.get());
1462 ASSERT_EQ(3u, parent
->children().size());
1463 EXPECT_EQ(w2
, parent
->children().back());
1465 // Destroy w1, which should also destroy w3 (since it's a transient child).
1468 ASSERT_EQ(1u, parent
->children().size());
1469 EXPECT_EQ(w3
.get(), parent
->children()[0]);
1471 w1
.reset(CreateTestWindowWithId(4, parent
.get()));
1472 w2
= CreateTestWindowWithId(5, w3
.get());
1473 w1
->AddTransientChild(w2
);
1474 parent
->StackChildAtTop(w3
.get());
1475 // Stack w1 at the top (end), this shouldn't affect w2 since it has a
1476 // different parent.
1477 parent
->StackChildAtTop(w1
.get());
1478 ASSERT_EQ(2u, parent
->children().size());
1479 EXPECT_EQ(w3
.get(), parent
->children()[0]);
1480 EXPECT_EQ(w1
.get(), parent
->children()[1]);
1482 // Hiding parent should hide transient children.
1483 EXPECT_TRUE(w2
->IsVisible());
1485 EXPECT_FALSE(w2
->IsVisible());
1488 // Tests that when a focused window is closed, its parent inherits the focus.
1489 TEST_F(WindowTest
, FocusedWindowTest
) {
1490 scoped_ptr
<Window
> parent(CreateTestWindowWithId(0, root_window()));
1491 scoped_ptr
<Window
> child(CreateTestWindowWithId(1, parent
.get()));
1496 EXPECT_TRUE(child
->HasFocus());
1497 EXPECT_FALSE(parent
->HasFocus());
1500 EXPECT_TRUE(parent
->HasFocus());
1503 // Tests that the previously-focused window is passed to OnWindowFocused.
1504 // TODO(beng): Remove once the FocusController lands.
1505 TEST_F(WindowTest
, OldFocusedWindowTest
) {
1506 const gfx::Rect
kBounds(0, 0, 100, 100);
1508 FocusDelegate delegate1
;
1509 scoped_ptr
<Window
> window1(
1510 CreateTestWindowWithDelegate(&delegate1
, 0, kBounds
, root_window()));
1511 client::SetFocusChangeObserver(window1
.get(), &delegate1
);
1513 ASSERT_TRUE(window1
->HasFocus());
1514 EXPECT_TRUE(delegate1
.previous_focused_window() == NULL
);
1516 FocusDelegate delegate2
;
1517 scoped_ptr
<Window
> window2(
1518 CreateTestWindowWithDelegate(&delegate2
, 1, kBounds
, root_window()));
1519 client::SetFocusChangeObserver(window2
.get(), &delegate2
);
1521 ASSERT_TRUE(window2
->HasFocus());
1522 EXPECT_FALSE(window1
->HasFocus());
1523 EXPECT_EQ(window1
.get(), delegate2
.previous_focused_window());
1527 DEFINE_WINDOW_PROPERTY_KEY(int, kIntKey
, -2);
1528 DEFINE_WINDOW_PROPERTY_KEY(const char*, kStringKey
, "squeamish");
1531 TEST_F(WindowTest
, Property
) {
1532 scoped_ptr
<Window
> w(CreateTestWindowWithId(0, root_window()));
1534 static const char native_prop_key
[] = "fnord";
1536 // Non-existent properties should return the default values.
1537 EXPECT_EQ(-2, w
->GetProperty(kIntKey
));
1538 EXPECT_EQ(std::string("squeamish"), w
->GetProperty(kStringKey
));
1539 EXPECT_EQ(NULL
, w
->GetNativeWindowProperty(native_prop_key
));
1541 // A set property value should be returned again (even if it's the default
1543 w
->SetProperty(kIntKey
, INT_MAX
);
1544 EXPECT_EQ(INT_MAX
, w
->GetProperty(kIntKey
));
1545 w
->SetProperty(kIntKey
, -2);
1546 EXPECT_EQ(-2, w
->GetProperty(kIntKey
));
1547 w
->SetProperty(kIntKey
, INT_MIN
);
1548 EXPECT_EQ(INT_MIN
, w
->GetProperty(kIntKey
));
1550 w
->SetProperty(kStringKey
, static_cast<const char*>(NULL
));
1551 EXPECT_EQ(NULL
, w
->GetProperty(kStringKey
));
1552 w
->SetProperty(kStringKey
, "squeamish");
1553 EXPECT_EQ(std::string("squeamish"), w
->GetProperty(kStringKey
));
1554 w
->SetProperty(kStringKey
, "ossifrage");
1555 EXPECT_EQ(std::string("ossifrage"), w
->GetProperty(kStringKey
));
1557 w
->SetNativeWindowProperty(native_prop_key
, &*w
);
1558 EXPECT_EQ(&*w
, w
->GetNativeWindowProperty(native_prop_key
));
1559 w
->SetNativeWindowProperty(native_prop_key
, NULL
);
1560 EXPECT_EQ(NULL
, w
->GetNativeWindowProperty(native_prop_key
));
1562 // ClearProperty should restore the default value.
1563 w
->ClearProperty(kIntKey
);
1564 EXPECT_EQ(-2, w
->GetProperty(kIntKey
));
1565 w
->ClearProperty(kStringKey
);
1566 EXPECT_EQ(std::string("squeamish"), w
->GetProperty(kStringKey
));
1571 class TestProperty
{
1574 virtual ~TestProperty() {
1575 last_deleted_
= this;
1577 static TestProperty
* last_deleted() { return last_deleted_
; }
1580 static TestProperty
* last_deleted_
;
1581 DISALLOW_COPY_AND_ASSIGN(TestProperty
);
1584 TestProperty
* TestProperty::last_deleted_
= NULL
;
1586 DEFINE_OWNED_WINDOW_PROPERTY_KEY(TestProperty
, kOwnedKey
, NULL
);
1590 TEST_F(WindowTest
, OwnedProperty
) {
1591 scoped_ptr
<Window
> w(CreateTestWindowWithId(0, root_window()));
1592 EXPECT_EQ(NULL
, w
->GetProperty(kOwnedKey
));
1593 TestProperty
* p1
= new TestProperty();
1594 w
->SetProperty(kOwnedKey
, p1
);
1595 EXPECT_EQ(p1
, w
->GetProperty(kOwnedKey
));
1596 EXPECT_EQ(NULL
, TestProperty::last_deleted());
1598 TestProperty
* p2
= new TestProperty();
1599 w
->SetProperty(kOwnedKey
, p2
);
1600 EXPECT_EQ(p2
, w
->GetProperty(kOwnedKey
));
1601 EXPECT_EQ(p1
, TestProperty::last_deleted());
1603 w
->ClearProperty(kOwnedKey
);
1604 EXPECT_EQ(NULL
, w
->GetProperty(kOwnedKey
));
1605 EXPECT_EQ(p2
, TestProperty::last_deleted());
1607 TestProperty
* p3
= new TestProperty();
1608 w
->SetProperty(kOwnedKey
, p3
);
1609 EXPECT_EQ(p3
, w
->GetProperty(kOwnedKey
));
1610 EXPECT_EQ(p2
, TestProperty::last_deleted());
1612 EXPECT_EQ(p3
, TestProperty::last_deleted());
1615 TEST_F(WindowTest
, SetBoundsInternalShouldCheckTargetBounds
) {
1616 // We cannot short-circuit animations in this test.
1617 ui::ScopedAnimationDurationScaleMode
normal_duration_mode(
1618 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION
);
1620 scoped_ptr
<Window
> w1(
1621 CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), root_window()));
1623 EXPECT_FALSE(!w1
->layer());
1624 w1
->layer()->GetAnimator()->set_disable_timer_for_test(true);
1625 ui::AnimationContainerElement
* element
= w1
->layer()->GetAnimator();
1627 EXPECT_EQ("0,0 100x100", w1
->bounds().ToString());
1628 EXPECT_EQ("0,0 100x100", w1
->layer()->GetTargetBounds().ToString());
1630 // Animate to a different position.
1632 ui::ScopedLayerAnimationSettings
settings(w1
->layer()->GetAnimator());
1633 w1
->SetBounds(gfx::Rect(100, 100, 100, 100));
1636 EXPECT_EQ("0,0 100x100", w1
->bounds().ToString());
1637 EXPECT_EQ("100,100 100x100", w1
->layer()->GetTargetBounds().ToString());
1639 // Animate back to the first position. The animation hasn't started yet, so
1640 // the current bounds are still (0, 0, 100, 100), but the target bounds are
1641 // (100, 100, 100, 100). If we step the animator ahead, we should find that
1642 // we're at (0, 0, 100, 100). That is, the second animation should be applied.
1644 ui::ScopedLayerAnimationSettings
settings(w1
->layer()->GetAnimator());
1645 w1
->SetBounds(gfx::Rect(0, 0, 100, 100));
1648 EXPECT_EQ("0,0 100x100", w1
->bounds().ToString());
1649 EXPECT_EQ("0,0 100x100", w1
->layer()->GetTargetBounds().ToString());
1651 // Confirm that the target bounds are reached.
1652 base::TimeTicks start_time
=
1653 w1
->layer()->GetAnimator()->last_step_time();
1655 element
->Step(start_time
+ base::TimeDelta::FromMilliseconds(1000));
1657 EXPECT_EQ("0,0 100x100", w1
->bounds().ToString());
1661 typedef std::pair
<const void*, intptr_t> PropertyChangeInfo
;
1663 class WindowObserverTest
: public WindowTest
,
1664 public WindowObserver
{
1666 struct VisibilityInfo
{
1667 bool window_visible
;
1671 WindowObserverTest()
1674 destroyed_count_(0),
1675 old_property_value_(-3) {
1678 virtual ~WindowObserverTest() {}
1680 const VisibilityInfo
* GetVisibilityInfo() const {
1681 return visibility_info_
.get();
1684 void ResetVisibilityInfo() {
1685 visibility_info_
.reset();
1688 // Returns a description of the WindowObserver methods that have been invoked.
1689 std::string
WindowObserverCountStateAndClear() {
1691 base::StringPrintf("added=%d removed=%d",
1692 added_count_
, removed_count_
));
1693 added_count_
= removed_count_
= 0;
1697 int DestroyedCountAndClear() {
1698 int result
= destroyed_count_
;
1699 destroyed_count_
= 0;
1703 // Return a tuple of the arguments passed in OnPropertyChanged callback.
1704 PropertyChangeInfo
PropertyChangeInfoAndClear() {
1705 PropertyChangeInfo
result(property_key_
, old_property_value_
);
1706 property_key_
= NULL
;
1707 old_property_value_
= -3;
1712 virtual void OnWindowAdded(Window
* new_window
) OVERRIDE
{
1716 virtual void OnWillRemoveWindow(Window
* window
) OVERRIDE
{
1720 virtual void OnWindowVisibilityChanged(Window
* window
,
1721 bool visible
) OVERRIDE
{
1722 visibility_info_
.reset(new VisibilityInfo
);
1723 visibility_info_
->window_visible
= window
->IsVisible();
1724 visibility_info_
->visible_param
= visible
;
1727 virtual void OnWindowDestroyed(Window
* window
) OVERRIDE
{
1728 EXPECT_FALSE(window
->parent());
1732 virtual void OnWindowPropertyChanged(Window
* window
,
1734 intptr_t old
) OVERRIDE
{
1735 property_key_
= key
;
1736 old_property_value_
= old
;
1741 int destroyed_count_
;
1742 scoped_ptr
<VisibilityInfo
> visibility_info_
;
1743 const void* property_key_
;
1744 intptr_t old_property_value_
;
1746 DISALLOW_COPY_AND_ASSIGN(WindowObserverTest
);
1749 // Various assertions for WindowObserver.
1750 TEST_F(WindowObserverTest
, WindowObserver
) {
1751 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
1752 w1
->AddObserver(this);
1754 // Create a new window as a child of w1, our observer should be notified.
1755 scoped_ptr
<Window
> w2(CreateTestWindowWithId(2, w1
.get()));
1756 EXPECT_EQ("added=1 removed=0", WindowObserverCountStateAndClear());
1758 // Delete w2, which should result in the remove notification.
1760 EXPECT_EQ("added=0 removed=1", WindowObserverCountStateAndClear());
1762 // Create a window that isn't parented to w1, we shouldn't get any
1764 scoped_ptr
<Window
> w3(CreateTestWindowWithId(3, root_window()));
1765 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1767 // Similarly destroying w3 shouldn't notify us either.
1769 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1770 w1
->RemoveObserver(this);
1773 // Test if OnWindowVisibilityChagned is invoked with expected
1775 TEST_F(WindowObserverTest
, WindowVisibility
) {
1776 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
1777 scoped_ptr
<Window
> w2(CreateTestWindowWithId(1, w1
.get()));
1778 w2
->AddObserver(this);
1780 // Hide should make the window invisible and the passed visible
1781 // parameter is false.
1783 EXPECT_FALSE(!GetVisibilityInfo());
1784 EXPECT_FALSE(!GetVisibilityInfo());
1785 if (!GetVisibilityInfo())
1787 EXPECT_FALSE(GetVisibilityInfo()->window_visible
);
1788 EXPECT_FALSE(GetVisibilityInfo()->visible_param
);
1790 // If parent isn't visible, showing window won't make the window visible, but
1791 // passed visible value must be true.
1793 ResetVisibilityInfo();
1794 EXPECT_TRUE(!GetVisibilityInfo());
1796 EXPECT_FALSE(!GetVisibilityInfo());
1797 if (!GetVisibilityInfo())
1799 EXPECT_FALSE(GetVisibilityInfo()->window_visible
);
1800 EXPECT_TRUE(GetVisibilityInfo()->visible_param
);
1802 // If parent is visible, showing window will make the window
1803 // visible and the passed visible value is true.
1806 ResetVisibilityInfo();
1808 EXPECT_FALSE(!GetVisibilityInfo());
1809 if (!GetVisibilityInfo())
1811 EXPECT_TRUE(GetVisibilityInfo()->window_visible
);
1812 EXPECT_TRUE(GetVisibilityInfo()->visible_param
);
1815 // Test if OnWindowDestroyed is invoked as expected.
1816 TEST_F(WindowObserverTest
, WindowDestroyed
) {
1817 // Delete a window should fire a destroyed notification.
1818 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
1819 w1
->AddObserver(this);
1821 EXPECT_EQ(1, DestroyedCountAndClear());
1823 // Observe on child and delete parent window should fire a notification.
1824 scoped_ptr
<Window
> parent(CreateTestWindowWithId(1, root_window()));
1825 Window
* child
= CreateTestWindowWithId(1, parent
.get()); // owned by parent
1826 child
->AddObserver(this);
1828 EXPECT_EQ(1, DestroyedCountAndClear());
1831 TEST_F(WindowObserverTest
, PropertyChanged
) {
1832 // Setting property should fire a property change notification.
1833 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
1834 w1
->AddObserver(this);
1836 static const WindowProperty
<int> prop
= {-2};
1837 static const char native_prop_key
[] = "fnord";
1839 w1
->SetProperty(&prop
, 1);
1840 EXPECT_EQ(PropertyChangeInfo(&prop
, -2), PropertyChangeInfoAndClear());
1841 w1
->SetProperty(&prop
, -2);
1842 EXPECT_EQ(PropertyChangeInfo(&prop
, 1), PropertyChangeInfoAndClear());
1843 w1
->SetProperty(&prop
, 3);
1844 EXPECT_EQ(PropertyChangeInfo(&prop
, -2), PropertyChangeInfoAndClear());
1845 w1
->ClearProperty(&prop
);
1846 EXPECT_EQ(PropertyChangeInfo(&prop
, 3), PropertyChangeInfoAndClear());
1848 w1
->SetNativeWindowProperty(native_prop_key
, &*w1
);
1849 EXPECT_EQ(PropertyChangeInfo(native_prop_key
, 0),
1850 PropertyChangeInfoAndClear());
1851 w1
->SetNativeWindowProperty(native_prop_key
, NULL
);
1852 EXPECT_EQ(PropertyChangeInfo(native_prop_key
,
1853 reinterpret_cast<intptr_t>(&*w1
)),
1854 PropertyChangeInfoAndClear());
1856 // Sanity check to see if |PropertyChangeInfoAndClear| really clears.
1857 EXPECT_EQ(PropertyChangeInfo(
1858 reinterpret_cast<const void*>(NULL
), -3), PropertyChangeInfoAndClear());
1861 TEST_F(WindowTest
, AcquireLayer
) {
1862 scoped_ptr
<Window
> window1(CreateTestWindowWithId(1, root_window()));
1863 scoped_ptr
<Window
> window2(CreateTestWindowWithId(2, root_window()));
1864 ui::Layer
* parent
= window1
->parent()->layer();
1865 EXPECT_EQ(2U, parent
->children().size());
1867 WindowTestApi
window1_test_api(window1
.get());
1868 WindowTestApi
window2_test_api(window2
.get());
1870 EXPECT_TRUE(window1_test_api
.OwnsLayer());
1871 EXPECT_TRUE(window2_test_api
.OwnsLayer());
1873 // After acquisition, window1 should not own its layer, but it should still
1874 // be available to the window.
1875 scoped_ptr
<ui::Layer
> window1_layer(window1
->AcquireLayer());
1876 EXPECT_FALSE(window1_test_api
.OwnsLayer());
1877 EXPECT_TRUE(window1_layer
.get() == window1
->layer());
1879 // Upon destruction, window1's layer should still be valid, and in the layer
1880 // hierarchy, but window2's should be gone, and no longer in the hierarchy.
1884 // This should be set by the window's destructor.
1885 EXPECT_TRUE(window1_layer
->delegate() == NULL
);
1886 EXPECT_EQ(1U, parent
->children().size());
1889 // Make sure that properties which should persist from the old layer to the new
1890 // layer actually do.
1891 TEST_F(WindowTest
, RecreateLayer
) {
1892 // Set properties to non default values.
1893 Window
w(new ColorTestWindowDelegate(SK_ColorWHITE
));
1895 w
.Init(ui::LAYER_SOLID_COLOR
);
1896 w
.SetBounds(gfx::Rect(0, 0, 100, 100));
1898 ui::Layer
* layer
= w
.layer();
1899 layer
->set_scale_content(false);
1900 layer
->SetVisible(false);
1901 layer
->SetMasksToBounds(true);
1903 ui::Layer child_layer
;
1904 layer
->Add(&child_layer
);
1906 scoped_ptr
<ui::Layer
> old_layer(w
.RecreateLayer());
1908 EXPECT_EQ(ui::LAYER_SOLID_COLOR
, layer
->type());
1909 EXPECT_FALSE(layer
->scale_content());
1910 EXPECT_FALSE(layer
->visible());
1911 EXPECT_EQ(1u, layer
->children().size());
1912 EXPECT_TRUE(layer
->GetMasksToBounds());
1915 // Ensure that acquiring a layer then recreating a layer does not crash
1916 // and that RecreateLayer returns null.
1917 TEST_F(WindowTest
, AcquireThenRecreateLayer
) {
1918 scoped_ptr
<Window
> w(
1919 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(0, 0, 100, 100),
1921 scoped_ptr
<ui::Layer
>acquired_layer(w
->AcquireLayer());
1922 scoped_ptr
<ui::Layer
>doubly_acquired_layer(w
->RecreateLayer());
1923 EXPECT_EQ(NULL
, doubly_acquired_layer
.get());
1925 // Destroy window before layer gets destroyed.
1929 TEST_F(WindowTest
, StackWindowsWhoseLayersHaveNoDelegate
) {
1930 scoped_ptr
<Window
> window1(CreateTestWindowWithId(1, root_window()));
1931 scoped_ptr
<Window
> window2(CreateTestWindowWithId(2, root_window()));
1933 // This brings window1 (and its layer) to the front.
1934 root_window()->StackChildAbove(window1
.get(), window2
.get());
1935 EXPECT_EQ(root_window()->children().front(), window2
.get());
1936 EXPECT_EQ(root_window()->children().back(), window1
.get());
1937 EXPECT_EQ(root_window()->layer()->children().front(), window2
->layer());
1938 EXPECT_EQ(root_window()->layer()->children().back(), window1
->layer());
1940 // Since window1 does not have a delegate, window2 should not move in
1941 // front of it, nor should its layer.
1942 window1
->layer()->set_delegate(NULL
);
1943 root_window()->StackChildAbove(window2
.get(), window1
.get());
1944 EXPECT_EQ(root_window()->children().front(), window2
.get());
1945 EXPECT_EQ(root_window()->children().back(), window1
.get());
1946 EXPECT_EQ(root_window()->layer()->children().front(), window2
->layer());
1947 EXPECT_EQ(root_window()->layer()->children().back(), window1
->layer());
1950 TEST_F(WindowTest
, StackTransientsWhoseLayersHaveNoDelegate
) {
1951 RootWindow
* root
= root_window();
1953 // Create a window with several transients, then a couple windows on top.
1954 scoped_ptr
<Window
> window1(CreateTestWindowWithId(1, root_window()));
1955 scoped_ptr
<Window
> window11(CreateTransientChild(11, window1
.get()));
1956 scoped_ptr
<Window
> window12(CreateTransientChild(12, window1
.get()));
1957 scoped_ptr
<Window
> window13(CreateTransientChild(13, window1
.get()));
1958 scoped_ptr
<Window
> window2(CreateTestWindowWithId(2, root_window()));
1959 scoped_ptr
<Window
> window3(CreateTestWindowWithId(3, root_window()));
1961 EXPECT_EQ("1 11 12 13 2 3", ChildWindowIDsAsString(root
));
1963 // Remove the delegates of a couple of transients, as if they are closing
1964 // and animating out.
1965 window11
->layer()->set_delegate(NULL
);
1966 window13
->layer()->set_delegate(NULL
);
1968 // Move window1 to the front. All transients should move with it, and their
1969 // order should be preserved.
1970 root
->StackChildAtTop(window1
.get());
1972 EXPECT_EQ("2 3 1 11 12 13", ChildWindowIDsAsString(root
));
1975 class TestVisibilityClient
: public client::VisibilityClient
{
1977 explicit TestVisibilityClient(RootWindow
* root_window
)
1978 : ignore_visibility_changes_(false) {
1979 client::SetVisibilityClient(root_window
, this);
1981 virtual ~TestVisibilityClient() {
1984 void set_ignore_visibility_changes(bool ignore_visibility_changes
) {
1985 ignore_visibility_changes_
= ignore_visibility_changes
;
1988 // Overridden from client::VisibilityClient:
1989 virtual void UpdateLayerVisibility(aura::Window
* window
,
1990 bool visible
) OVERRIDE
{
1991 if (!ignore_visibility_changes_
)
1992 window
->layer()->SetVisible(visible
);
1996 bool ignore_visibility_changes_
;
1997 DISALLOW_COPY_AND_ASSIGN(TestVisibilityClient
);
2000 TEST_F(WindowTest
, VisibilityClientIsVisible
) {
2001 TestVisibilityClient
client(root_window());
2003 scoped_ptr
<Window
> window(CreateTestWindowWithId(1, root_window()));
2004 EXPECT_TRUE(window
->IsVisible());
2005 EXPECT_TRUE(window
->layer()->visible());
2008 EXPECT_FALSE(window
->IsVisible());
2009 EXPECT_FALSE(window
->layer()->visible());
2012 client
.set_ignore_visibility_changes(true);
2014 EXPECT_FALSE(window
->IsVisible());
2015 EXPECT_TRUE(window
->layer()->visible());
2018 // Tests mouse events on window change.
2019 TEST_F(WindowTest
, MouseEventsOnWindowChange
) {
2020 gfx::Size size
= root_window()->GetHostSize();
2022 EventGenerator
generator(root_window());
2023 generator
.MoveMouseTo(50, 50);
2025 EventCountDelegate d1
;
2026 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(&d1
, 1,
2027 gfx::Rect(0, 0, 100, 100), root_window()));
2028 RunAllPendingInMessageLoop();
2029 // The format of result is "Enter/Mouse/Leave".
2030 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2032 // Adding new window.
2033 EventCountDelegate d11
;
2034 scoped_ptr
<Window
> w11(CreateTestWindowWithDelegate(
2035 &d11
, 1, gfx::Rect(0, 0, 100, 100), w1
.get()));
2036 RunAllPendingInMessageLoop();
2037 EXPECT_EQ("0 0 1", d1
.GetMouseMotionCountsAndReset());
2038 EXPECT_EQ("1 1 0", d11
.GetMouseMotionCountsAndReset());
2041 w11
->SetBounds(gfx::Rect(0, 0, 10, 10));
2042 RunAllPendingInMessageLoop();
2043 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2044 EXPECT_EQ("0 0 1", d11
.GetMouseMotionCountsAndReset());
2046 w11
->SetBounds(gfx::Rect(0, 0, 60, 60));
2047 RunAllPendingInMessageLoop();
2048 EXPECT_EQ("0 0 1", d1
.GetMouseMotionCountsAndReset());
2049 EXPECT_EQ("1 1 0", d11
.GetMouseMotionCountsAndReset());
2051 // Detach, then re-attach.
2052 w1
->RemoveChild(w11
.get());
2053 RunAllPendingInMessageLoop();
2054 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2055 // Window is detached, so no event is set.
2056 EXPECT_EQ("0 0 0", d11
.GetMouseMotionCountsAndReset());
2058 w1
->AddChild(w11
.get());
2059 RunAllPendingInMessageLoop();
2060 EXPECT_EQ("0 0 1", d1
.GetMouseMotionCountsAndReset());
2061 // Window is detached, so no event is set.
2062 EXPECT_EQ("1 1 0", d11
.GetMouseMotionCountsAndReset());
2064 // Visibility Change
2066 RunAllPendingInMessageLoop();
2067 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2068 EXPECT_EQ("0 0 0", d11
.GetMouseMotionCountsAndReset());
2071 RunAllPendingInMessageLoop();
2072 EXPECT_EQ("0 0 1", d1
.GetMouseMotionCountsAndReset());
2073 EXPECT_EQ("1 1 0", d11
.GetMouseMotionCountsAndReset());
2075 // Transform: move d11 by 100 100.
2076 gfx::Transform transform
;
2077 transform
.Translate(100, 100);
2078 w11
->SetTransform(transform
);
2079 RunAllPendingInMessageLoop();
2080 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2081 EXPECT_EQ("0 0 1", d11
.GetMouseMotionCountsAndReset());
2083 w11
->SetTransform(gfx::Transform());
2084 RunAllPendingInMessageLoop();
2085 EXPECT_EQ("0 0 1", d1
.GetMouseMotionCountsAndReset());
2086 EXPECT_EQ("1 1 0", d11
.GetMouseMotionCountsAndReset());
2088 // Closing a window.
2090 RunAllPendingInMessageLoop();
2091 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2093 // Make sure we don't synthesize events if the mouse
2094 // is outside of the root window.
2095 generator
.MoveMouseTo(-10, -10);
2096 EXPECT_EQ("0 0 1", d1
.GetMouseMotionCountsAndReset());
2098 // Adding new windows.
2099 w11
.reset(CreateTestWindowWithDelegate(
2100 &d11
, 1, gfx::Rect(0, 0, 100, 100), w1
.get()));
2101 RunAllPendingInMessageLoop();
2102 EXPECT_EQ("0 0 0", d1
.GetMouseMotionCountsAndReset());
2103 EXPECT_EQ("0 0 0", d11
.GetMouseMotionCountsAndReset());
2107 RunAllPendingInMessageLoop();
2108 EXPECT_EQ("0 0 0", d1
.GetMouseMotionCountsAndReset());
2109 EXPECT_EQ("0 0 0", d11
.GetMouseMotionCountsAndReset());
2112 class StackingMadrigalLayoutManager
: public LayoutManager
{
2114 explicit StackingMadrigalLayoutManager(RootWindow
* root_window
)
2115 : root_window_(root_window
) {
2116 root_window_
->SetLayoutManager(this);
2118 virtual ~StackingMadrigalLayoutManager() {
2122 // Overridden from LayoutManager:
2123 virtual void OnWindowResized() OVERRIDE
{}
2124 virtual void OnWindowAddedToLayout(Window
* child
) OVERRIDE
{}
2125 virtual void OnWillRemoveWindowFromLayout(Window
* child
) OVERRIDE
{}
2126 virtual void OnWindowRemovedFromLayout(Window
* child
) OVERRIDE
{}
2127 virtual void OnChildWindowVisibilityChanged(Window
* child
,
2128 bool visible
) OVERRIDE
{
2129 Window::Windows::const_iterator it
= root_window_
->children().begin();
2130 Window
* last_window
= NULL
;
2131 for (; it
!= root_window_
->children().end(); ++it
) {
2132 if (*it
== child
&& last_window
) {
2134 root_window_
->StackChildAbove(last_window
, *it
);
2136 root_window_
->StackChildAbove(*it
, last_window
);
2142 virtual void SetChildBounds(Window
* child
,
2143 const gfx::Rect
& requested_bounds
) OVERRIDE
{
2144 SetChildBoundsDirect(child
, requested_bounds
);
2147 RootWindow
* root_window_
;
2149 DISALLOW_COPY_AND_ASSIGN(StackingMadrigalLayoutManager
);
2152 class StackingMadrigalVisibilityClient
: public client::VisibilityClient
{
2154 explicit StackingMadrigalVisibilityClient(RootWindow
* root_window
)
2155 : ignored_window_(NULL
) {
2156 client::SetVisibilityClient(root_window
, this);
2158 virtual ~StackingMadrigalVisibilityClient() {
2161 void set_ignored_window(Window
* ignored_window
) {
2162 ignored_window_
= ignored_window
;
2166 // Overridden from client::VisibilityClient:
2167 virtual void UpdateLayerVisibility(Window
* window
, bool visible
) OVERRIDE
{
2169 if (window
== ignored_window_
)
2170 window
->layer()->set_delegate(NULL
);
2172 window
->layer()->SetVisible(visible
);
2174 window
->layer()->SetVisible(visible
);
2178 Window
* ignored_window_
;
2180 DISALLOW_COPY_AND_ASSIGN(StackingMadrigalVisibilityClient
);
2183 // This test attempts to reconstruct a circumstance that can happen when the
2184 // aura client attempts to manipulate the visibility and delegate of a layer
2185 // independent of window visibility.
2186 // A use case is where the client attempts to keep a window visible onscreen
2187 // even after code has called Hide() on the window. The use case for this would
2188 // be that window hides are animated (e.g. the window fades out). To prevent
2189 // spurious updating the client code may also clear window's layer's delegate,
2190 // so that the window cannot attempt to paint or update it further. The window
2191 // uses the presence of a NULL layer delegate as a signal in stacking to note
2192 // that the window is being manipulated by such a use case and its stacking
2193 // should not be adjusted.
2194 // One issue that can arise when a window opens two transient children, and the
2195 // first is hidden. Subsequent attempts to activate the transient parent can
2196 // result in the transient parent being stacked above the second transient
2197 // child. A fix is made to Window::StackAbove to prevent this, and this test
2198 // verifies this fix.
2199 TEST_F(WindowTest
, StackingMadrigal
) {
2200 new StackingMadrigalLayoutManager(root_window());
2201 StackingMadrigalVisibilityClient
visibility_client(root_window());
2203 scoped_ptr
<Window
> window1(CreateTestWindowWithId(1, root_window()));
2204 scoped_ptr
<Window
> window11(CreateTransientChild(11, window1
.get()));
2206 visibility_client
.set_ignored_window(window11
.get());
2211 // As a transient, window11 should still be stacked above window1, even when
2213 EXPECT_TRUE(WindowIsAbove(window11
.get(), window1
.get()));
2214 EXPECT_TRUE(LayerIsAbove(window11
.get(), window1
.get()));
2216 // A new transient should still be above window1. It will appear behind
2217 // window11 because we don't stack windows on top of targets with NULL
2219 scoped_ptr
<Window
> window12(CreateTransientChild(12, window1
.get()));
2222 EXPECT_TRUE(WindowIsAbove(window12
.get(), window1
.get()));
2223 EXPECT_TRUE(LayerIsAbove(window12
.get(), window1
.get()));
2225 // In earlier versions of the StackChildAbove() method, attempting to stack
2226 // window1 above window12 at this point would actually restack the layers
2227 // resulting in window12's layer being below window1's layer (though the
2228 // windows themselves would still be correctly stacked, so events would pass
2230 root_window()->StackChildAbove(window1
.get(), window12
.get());
2232 // Both window12 and its layer should be stacked above window1.
2233 EXPECT_TRUE(WindowIsAbove(window12
.get(), window1
.get()));
2234 EXPECT_TRUE(LayerIsAbove(window12
.get(), window1
.get()));
2237 // Test for an issue where attempting to stack a primary window on top of a
2238 // transient with a NULL layer delegate causes that primary window to be moved,
2239 // but the layer order not changed to match. http://crbug.com/112562
2240 TEST_F(WindowTest
, StackOverClosingTransient
) {
2241 scoped_ptr
<Window
> window1(CreateTestWindowWithId(1, root_window()));
2242 scoped_ptr
<Window
> transient1(CreateTransientChild(11, window1
.get()));
2243 scoped_ptr
<Window
> window2(CreateTestWindowWithId(2, root_window()));
2244 scoped_ptr
<Window
> transient2(CreateTransientChild(21, window2
.get()));
2246 // Both windows and layers are stacked in creation order.
2247 RootWindow
* root
= root_window();
2248 ASSERT_EQ(4u, root
->children().size());
2249 EXPECT_EQ(root
->children()[0], window1
.get());
2250 EXPECT_EQ(root
->children()[1], transient1
.get());
2251 EXPECT_EQ(root
->children()[2], window2
.get());
2252 EXPECT_EQ(root
->children()[3], transient2
.get());
2253 ASSERT_EQ(4u, root
->layer()->children().size());
2254 EXPECT_EQ(root
->layer()->children()[0], window1
->layer());
2255 EXPECT_EQ(root
->layer()->children()[1], transient1
->layer());
2256 EXPECT_EQ(root
->layer()->children()[2], window2
->layer());
2257 EXPECT_EQ(root
->layer()->children()[3], transient2
->layer());
2259 // This brings window1 and its transient to the front.
2260 // root_window()->StackChildAbove(window1.get(), window2.get());
2261 root
->StackChildAtTop(window1
.get());
2263 EXPECT_EQ(root
->children()[0], window2
.get());
2264 EXPECT_EQ(root
->children()[1], transient2
.get());
2265 EXPECT_EQ(root
->children()[2], window1
.get());
2266 EXPECT_EQ(root
->children()[3], transient1
.get());
2267 EXPECT_EQ(root
->layer()->children()[0], window2
->layer());
2268 EXPECT_EQ(root
->layer()->children()[1], transient2
->layer());
2269 EXPECT_EQ(root
->layer()->children()[2], window1
->layer());
2270 EXPECT_EQ(root
->layer()->children()[3], transient1
->layer());
2272 // Pretend we're closing the top-most transient, then bring window2 to the
2273 // front. This mimics activating a browser window while the status bubble
2274 // is fading out. The transient should stay topmost.
2275 transient1
->layer()->set_delegate(NULL
);
2276 root
->StackChildAtTop(window2
.get());
2278 EXPECT_EQ(root
->children()[0], window1
.get());
2279 EXPECT_EQ(root
->children()[1], window2
.get());
2280 EXPECT_EQ(root
->children()[2], transient2
.get());
2281 EXPECT_EQ(root
->children()[3], transient1
.get());
2282 EXPECT_EQ(root
->layer()->children()[0], window1
->layer());
2283 EXPECT_EQ(root
->layer()->children()[1], window2
->layer());
2284 EXPECT_EQ(root
->layer()->children()[2], transient2
->layer());
2285 EXPECT_EQ(root
->layer()->children()[3], transient1
->layer());
2287 // Close the transient. Remaining windows are stable.
2290 ASSERT_EQ(3u, root
->children().size());
2291 EXPECT_EQ(root
->children()[0], window1
.get());
2292 EXPECT_EQ(root
->children()[1], window2
.get());
2293 EXPECT_EQ(root
->children()[2], transient2
.get());
2294 ASSERT_EQ(3u, root
->layer()->children().size());
2295 EXPECT_EQ(root
->layer()->children()[0], window1
->layer());
2296 EXPECT_EQ(root
->layer()->children()[1], window2
->layer());
2297 EXPECT_EQ(root
->layer()->children()[2], transient2
->layer());
2299 // Open another window on top.
2300 scoped_ptr
<Window
> window3(CreateTestWindowWithId(3, root_window()));
2302 ASSERT_EQ(4u, root
->children().size());
2303 EXPECT_EQ(root
->children()[0], window1
.get());
2304 EXPECT_EQ(root
->children()[1], window2
.get());
2305 EXPECT_EQ(root
->children()[2], transient2
.get());
2306 EXPECT_EQ(root
->children()[3], window3
.get());
2307 ASSERT_EQ(4u, root
->layer()->children().size());
2308 EXPECT_EQ(root
->layer()->children()[0], window1
->layer());
2309 EXPECT_EQ(root
->layer()->children()[1], window2
->layer());
2310 EXPECT_EQ(root
->layer()->children()[2], transient2
->layer());
2311 EXPECT_EQ(root
->layer()->children()[3], window3
->layer());
2313 // Pretend we're closing the topmost non-transient window, then bring
2314 // window2 to the top. It should not move.
2315 window3
->layer()->set_delegate(NULL
);
2316 root
->StackChildAtTop(window2
.get());
2318 ASSERT_EQ(4u, root
->children().size());
2319 EXPECT_EQ(root
->children()[0], window1
.get());
2320 EXPECT_EQ(root
->children()[1], window2
.get());
2321 EXPECT_EQ(root
->children()[2], transient2
.get());
2322 EXPECT_EQ(root
->children()[3], window3
.get());
2323 ASSERT_EQ(4u, root
->layer()->children().size());
2324 EXPECT_EQ(root
->layer()->children()[0], window1
->layer());
2325 EXPECT_EQ(root
->layer()->children()[1], window2
->layer());
2326 EXPECT_EQ(root
->layer()->children()[2], transient2
->layer());
2327 EXPECT_EQ(root
->layer()->children()[3], window3
->layer());
2329 // Bring window1 to the top. It should move ahead of window2, but not
2330 // ahead of window3 (with NULL delegate).
2331 root
->StackChildAtTop(window1
.get());
2333 ASSERT_EQ(4u, root
->children().size());
2334 EXPECT_EQ(root
->children()[0], window2
.get());
2335 EXPECT_EQ(root
->children()[1], transient2
.get());
2336 EXPECT_EQ(root
->children()[2], window1
.get());
2337 EXPECT_EQ(root
->children()[3], window3
.get());
2338 ASSERT_EQ(4u, root
->layer()->children().size());
2339 EXPECT_EQ(root
->layer()->children()[0], window2
->layer());
2340 EXPECT_EQ(root
->layer()->children()[1], transient2
->layer());
2341 EXPECT_EQ(root
->layer()->children()[2], window1
->layer());
2342 EXPECT_EQ(root
->layer()->children()[3], window3
->layer());
2345 class RootWindowAttachmentObserver
: public WindowObserver
{
2347 RootWindowAttachmentObserver() : added_count_(0), removed_count_(0) {}
2348 virtual ~RootWindowAttachmentObserver() {}
2350 int added_count() const { return added_count_
; }
2351 int removed_count() const { return removed_count_
; }
2358 // Overridden from WindowObserver:
2359 virtual void OnWindowAddedToRootWindow(Window
* window
) OVERRIDE
{
2362 virtual void OnWindowRemovingFromRootWindow(Window
* window
) OVERRIDE
{
2370 DISALLOW_COPY_AND_ASSIGN(RootWindowAttachmentObserver
);
2373 TEST_F(WindowTest
, RootWindowAttachment
) {
2374 RootWindowAttachmentObserver observer
;
2376 // Test a direct add/remove from the RootWindow.
2377 scoped_ptr
<Window
> w1(new Window(NULL
));
2378 w1
->Init(ui::LAYER_NOT_DRAWN
);
2379 w1
->AddObserver(&observer
);
2381 SetDefaultParentByPrimaryRootWindow(w1
.get());
2382 EXPECT_EQ(1, observer
.added_count());
2383 EXPECT_EQ(0, observer
.removed_count());
2386 EXPECT_EQ(1, observer
.added_count());
2387 EXPECT_EQ(1, observer
.removed_count());
2391 // Test an indirect add/remove from the RootWindow.
2392 w1
.reset(new Window(NULL
));
2393 w1
->Init(ui::LAYER_NOT_DRAWN
);
2394 Window
* w11
= new Window(NULL
);
2395 w11
->Init(ui::LAYER_NOT_DRAWN
);
2396 w11
->AddObserver(&observer
);
2398 EXPECT_EQ(0, observer
.added_count());
2399 EXPECT_EQ(0, observer
.removed_count());
2401 SetDefaultParentByPrimaryRootWindow(w1
.get());
2402 EXPECT_EQ(1, observer
.added_count());
2403 EXPECT_EQ(0, observer
.removed_count());
2405 w1
.reset(); // Deletes w11.
2407 EXPECT_EQ(1, observer
.added_count());
2408 EXPECT_EQ(1, observer
.removed_count());
2412 // Test an indirect add/remove with nested observers.
2413 w1
.reset(new Window(NULL
));
2414 w1
->Init(ui::LAYER_NOT_DRAWN
);
2415 w11
= new Window(NULL
);
2416 w11
->Init(ui::LAYER_NOT_DRAWN
);
2417 w11
->AddObserver(&observer
);
2419 Window
* w111
= new Window(NULL
);
2420 w111
->Init(ui::LAYER_NOT_DRAWN
);
2421 w111
->AddObserver(&observer
);
2422 w11
->AddChild(w111
);
2424 EXPECT_EQ(0, observer
.added_count());
2425 EXPECT_EQ(0, observer
.removed_count());
2427 SetDefaultParentByPrimaryRootWindow(w1
.get());
2428 EXPECT_EQ(2, observer
.added_count());
2429 EXPECT_EQ(0, observer
.removed_count());
2431 w1
.reset(); // Deletes w11 and w111.
2434 EXPECT_EQ(2, observer
.added_count());
2435 EXPECT_EQ(2, observer
.removed_count());
2438 TEST_F(WindowTest
, OwnedByParentFalse
) {
2439 // By default, a window is owned by its parent. If this is set to false, the
2440 // window will not be destroyed when its parent is.
2442 scoped_ptr
<Window
> w1(new Window(NULL
));
2443 w1
->Init(ui::LAYER_NOT_DRAWN
);
2444 scoped_ptr
<Window
> w2(new Window(NULL
));
2445 w2
->set_owned_by_parent(false);
2446 w2
->Init(ui::LAYER_NOT_DRAWN
);
2447 w1
->AddChild(w2
.get());
2451 // We should be able to deref w2 still, but its parent should now be NULL.
2452 EXPECT_EQ(NULL
, w2
->parent());
2457 // Used By DeleteWindowFromOnWindowDestroyed. Destroys a Window from
2458 // OnWindowDestroyed().
2459 class OwningWindowDelegate
: public TestWindowDelegate
{
2461 OwningWindowDelegate() {}
2463 void SetOwnedWindow(Window
* window
) {
2464 owned_window_
.reset(window
);
2467 virtual void OnWindowDestroyed() OVERRIDE
{
2468 owned_window_
.reset(NULL
);
2472 scoped_ptr
<Window
> owned_window_
;
2474 DISALLOW_COPY_AND_ASSIGN(OwningWindowDelegate
);
2479 // Creates a window with two child windows. When the first child window is
2480 // destroyed (WindowDelegate::OnWindowDestroyed) it deletes the second child.
2481 // This synthesizes BrowserView and the status bubble. Both are children of the
2482 // same parent and destroying BrowserView triggers it destroying the status
2484 TEST_F(WindowTest
, DeleteWindowFromOnWindowDestroyed
) {
2485 scoped_ptr
<Window
> parent(new Window(NULL
));
2486 parent
->Init(ui::LAYER_NOT_DRAWN
);
2487 OwningWindowDelegate delegate
;
2488 Window
* c1
= new Window(&delegate
);
2489 c1
->Init(ui::LAYER_NOT_DRAWN
);
2490 parent
->AddChild(c1
);
2491 Window
* c2
= new Window(NULL
);
2492 c2
->Init(ui::LAYER_NOT_DRAWN
);
2493 parent
->AddChild(c2
);
2494 delegate
.SetOwnedWindow(c2
);
2500 // Used by DelegateNotifiedAsBoundsChange to verify OnBoundsChanged() is
2502 class BoundsChangeDelegate
: public TestWindowDelegate
{
2504 BoundsChangeDelegate() : bounds_changed_(false) {}
2506 void clear_bounds_changed() { bounds_changed_
= false; }
2507 bool bounds_changed() const {
2508 return bounds_changed_
;
2512 virtual void OnBoundsChanged(const gfx::Rect
& old_bounds
,
2513 const gfx::Rect
& new_bounds
) OVERRIDE
{
2514 bounds_changed_
= true;
2518 // Was OnBoundsChanged() invoked?
2519 bool bounds_changed_
;
2521 DISALLOW_COPY_AND_ASSIGN(BoundsChangeDelegate
);
2526 // Verifies the delegate is notified when the actual bounds of the layer
2528 TEST_F(WindowTest
, DelegateNotifiedAsBoundsChange
) {
2529 BoundsChangeDelegate delegate
;
2531 // We cannot short-circuit animations in this test.
2532 ui::ScopedAnimationDurationScaleMode
normal_duration_mode(
2533 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION
);
2535 scoped_ptr
<Window
> window(
2536 CreateTestWindowWithDelegate(&delegate
, 1,
2537 gfx::Rect(0, 0, 100, 100), root_window()));
2538 window
->layer()->GetAnimator()->set_disable_timer_for_test(true);
2540 delegate
.clear_bounds_changed();
2542 // Animate to a different position.
2544 ui::ScopedLayerAnimationSettings
settings(window
->layer()->GetAnimator());
2545 window
->SetBounds(gfx::Rect(100, 100, 100, 100));
2548 // Bounds shouldn't immediately have changed.
2549 EXPECT_EQ("0,0 100x100", window
->bounds().ToString());
2550 EXPECT_FALSE(delegate
.bounds_changed());
2552 // Animate to the end, which should notify of the change.
2553 base::TimeTicks start_time
=
2554 window
->layer()->GetAnimator()->last_step_time();
2555 ui::AnimationContainerElement
* element
= window
->layer()->GetAnimator();
2556 element
->Step(start_time
+ base::TimeDelta::FromMilliseconds(1000));
2557 EXPECT_TRUE(delegate
.bounds_changed());
2558 EXPECT_NE("0,0 100x100", window
->bounds().ToString());
2561 // Verifies the delegate is notified when the actual bounds of the layer
2562 // change even when the window is not the layer's delegate
2563 TEST_F(WindowTest
, DelegateNotifiedAsBoundsChangeInHiddenLayer
) {
2564 BoundsChangeDelegate delegate
;
2566 // We cannot short-circuit animations in this test.
2567 ui::ScopedAnimationDurationScaleMode
normal_duration_mode(
2568 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION
);
2570 scoped_ptr
<Window
> window(
2571 CreateTestWindowWithDelegate(&delegate
, 1,
2572 gfx::Rect(0, 0, 100, 100), root_window()));
2573 window
->layer()->GetAnimator()->set_disable_timer_for_test(true);
2575 delegate
.clear_bounds_changed();
2577 // Suppress paint on the window since it is hidden (should reset the layer's
2578 // delegate to NULL)
2579 window
->SuppressPaint();
2580 EXPECT_EQ(NULL
, window
->layer()->delegate());
2582 // Animate to a different position.
2584 ui::ScopedLayerAnimationSettings
settings(window
->layer()->GetAnimator());
2585 window
->SetBounds(gfx::Rect(100, 100, 110, 100));
2588 // Layer delegate is NULL but we should still get bounds changed notification.
2589 EXPECT_EQ("100,100 110x100", window
->GetTargetBounds().ToString());
2590 EXPECT_TRUE(delegate
.bounds_changed());
2592 delegate
.clear_bounds_changed();
2594 // Animate to the end: will *not* notify of the change since we are hidden.
2595 base::TimeTicks start_time
=
2596 window
->layer()->GetAnimator()->last_step_time();
2597 ui::AnimationContainerElement
* element
= window
->layer()->GetAnimator();
2598 element
->Step(start_time
+ base::TimeDelta::FromMilliseconds(1000));
2600 // No bounds changed notification at the end of animation since layer
2601 // delegate is NULL.
2602 EXPECT_FALSE(delegate
.bounds_changed());
2603 EXPECT_NE("0,0 100x100", window
->bounds().ToString());
2608 // Used by AddChildNotifications to track notification counts.
2609 class AddChildNotificationsObserver
: public WindowObserver
{
2611 AddChildNotificationsObserver() : added_count_(0), removed_count_(0) {}
2613 std::string
CountStringAndReset() {
2614 std::string result
= base::IntToString(added_count_
) + " " +
2615 base::IntToString(removed_count_
);
2616 added_count_
= removed_count_
= 0;
2620 // WindowObserver overrides:
2621 virtual void OnWindowAddedToRootWindow(Window
* window
) OVERRIDE
{
2624 virtual void OnWindowRemovingFromRootWindow(Window
* window
) OVERRIDE
{
2632 DISALLOW_COPY_AND_ASSIGN(AddChildNotificationsObserver
);
2637 // Assertions around when root window notifications are sent.
2638 TEST_F(WindowTest
, AddChildNotifications
) {
2639 AddChildNotificationsObserver observer
;
2640 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
2641 scoped_ptr
<Window
> w2(CreateTestWindowWithId(1, root_window()));
2642 w2
->AddObserver(&observer
);
2644 EXPECT_TRUE(w2
->HasFocus());
2646 // Move |w2| to be a child of |w1|.
2647 w1
->AddChild(w2
.get());
2648 // Sine we moved in the same root, observer shouldn't be notified.
2649 EXPECT_EQ("0 0", observer
.CountStringAndReset());
2650 // |w2| should still have focus after moving.
2651 EXPECT_TRUE(w2
->HasFocus());
2654 // Tests that a delegate that destroys itself when the window is destroyed does
2656 TEST_F(WindowTest
, DelegateDestroysSelfOnWindowDestroy
) {
2657 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(
2658 new DestroyWindowDelegate(),
2660 gfx::Rect(10, 20, 30, 40),
2664 class HierarchyObserver
: public WindowObserver
{
2666 HierarchyObserver(Window
* target
) : target_(target
) {
2667 target_
->AddObserver(this);
2669 virtual ~HierarchyObserver() {
2670 target_
->RemoveObserver(this);
2675 const WindowObserver::HierarchyChangeParams
& params
) const {
2676 ParamsMatch(params_
[index
], params
);
2684 // Overridden from WindowObserver:
2685 virtual void OnWindowHierarchyChanging(
2686 const HierarchyChangeParams
& params
) OVERRIDE
{
2687 params_
.push_back(params
);
2689 virtual void OnWindowHierarchyChanged(
2690 const HierarchyChangeParams
& params
) OVERRIDE
{
2691 params_
.push_back(params
);
2694 void ParamsMatch(const WindowObserver::HierarchyChangeParams
& p1
,
2695 const WindowObserver::HierarchyChangeParams
& p2
) const {
2696 EXPECT_EQ(p1
.phase
, p2
.phase
);
2697 EXPECT_EQ(p1
.target
, p2
.target
);
2698 EXPECT_EQ(p1
.new_parent
, p2
.new_parent
);
2699 EXPECT_EQ(p1
.old_parent
, p2
.old_parent
);
2700 EXPECT_EQ(p1
.receiver
, p2
.receiver
);
2704 std::vector
<WindowObserver::HierarchyChangeParams
> params_
;
2706 DISALLOW_COPY_AND_ASSIGN(HierarchyObserver
);
2709 // Tests hierarchy change notifications.
2710 TEST_F(WindowTest
, OnWindowHierarchyChange
) {
2712 // Simple add & remove.
2713 HierarchyObserver
oroot(root_window());
2715 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, NULL
));
2716 HierarchyObserver
o1(w1
.get());
2719 root_window()->AddChild(w1
.get());
2721 WindowObserver::HierarchyChangeParams params
;
2722 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING
;
2723 params
.target
= w1
.get();
2724 params
.old_parent
= NULL
;
2725 params
.new_parent
= root_window();
2726 params
.receiver
= w1
.get();
2727 o1
.ValidateState(0, params
);
2729 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED
;
2730 params
.receiver
= w1
.get();
2731 o1
.ValidateState(1, params
);
2733 params
.receiver
= root_window();
2734 oroot
.ValidateState(0, params
);
2740 root_window()->RemoveChild(w1
.get());
2742 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING
;
2743 params
.old_parent
= root_window();
2744 params
.new_parent
= NULL
;
2745 params
.receiver
= w1
.get();
2747 o1
.ValidateState(0, params
);
2749 params
.receiver
= root_window();
2750 oroot
.ValidateState(0, params
);
2752 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED
;
2753 params
.receiver
= w1
.get();
2754 o1
.ValidateState(1, params
);
2758 // Add & remove of hierarchy. Tests notification order per documentation in
2760 HierarchyObserver
o(root_window());
2761 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, NULL
));
2762 Window
* w11
= CreateTestWindowWithId(11, w1
.get());
2763 w1
->AddObserver(&o
);
2764 w11
->AddObserver(&o
);
2767 root_window()->AddChild(w1
.get());
2769 // Dispatched to target first.
2771 WindowObserver::HierarchyChangeParams params
;
2772 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING
;
2773 params
.target
= w1
.get();
2774 params
.old_parent
= NULL
;
2775 params
.new_parent
= root_window();
2776 params
.receiver
= w1
.get();
2777 o
.ValidateState(index
++, params
);
2779 // Dispatched to target's children.
2780 params
.receiver
= w11
;
2781 o
.ValidateState(index
++, params
);
2783 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED
;
2785 // Now process the "changed" phase.
2786 params
.receiver
= w1
.get();
2787 o
.ValidateState(index
++, params
);
2788 params
.receiver
= w11
;
2789 o
.ValidateState(index
++, params
);
2790 params
.receiver
= root_window();
2791 o
.ValidateState(index
++, params
);
2794 root_window()->RemoveChild(w1
.get());
2795 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING
;
2796 params
.old_parent
= root_window();
2797 params
.new_parent
= NULL
;
2798 params
.receiver
= w1
.get();
2799 o
.ValidateState(index
++, params
);
2800 params
.receiver
= w11
;
2801 o
.ValidateState(index
++, params
);
2802 params
.receiver
= root_window();
2803 o
.ValidateState(index
++, params
);
2804 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED
;
2805 params
.receiver
= w1
.get();
2806 o
.ValidateState(index
++, params
);
2807 params
.receiver
= w11
;
2808 o
.ValidateState(index
++, params
);
2814 // Reparent. Tests notification order per documentation in WindowObserver.
2815 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
2816 Window
* w11
= CreateTestWindowWithId(11, w1
.get());
2817 Window
* w111
= CreateTestWindowWithId(111, w11
);
2818 scoped_ptr
<Window
> w2(CreateTestWindowWithId(2, root_window()));
2820 HierarchyObserver
o(root_window());
2821 w1
->AddObserver(&o
);
2822 w11
->AddObserver(&o
);
2823 w111
->AddObserver(&o
);
2824 w2
->AddObserver(&o
);
2828 // Dispatched to target first.
2830 WindowObserver::HierarchyChangeParams params
;
2831 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING
;
2832 params
.target
= w11
;
2833 params
.old_parent
= w1
.get();
2834 params
.new_parent
= w2
.get();
2835 params
.receiver
= w11
;
2836 o
.ValidateState(index
++, params
);
2838 // Then to target's children.
2839 params
.receiver
= w111
;
2840 o
.ValidateState(index
++, params
);
2842 // Then to target's old parent chain.
2843 params
.receiver
= w1
.get();
2844 o
.ValidateState(index
++, params
);
2845 params
.receiver
= root_window();
2846 o
.ValidateState(index
++, params
);
2849 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED
;
2850 params
.receiver
= w11
;
2851 o
.ValidateState(index
++, params
);
2852 params
.receiver
= w111
;
2853 o
.ValidateState(index
++, params
);
2854 params
.receiver
= w2
.get();
2855 o
.ValidateState(index
++, params
);
2856 params
.receiver
= root_window();
2857 o
.ValidateState(index
++, params
);