1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/aura/window.h"
11 #include "base/basictypes.h"
12 #include "base/compiler_specific.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "ui/aura/client/capture_client.h"
18 #include "ui/aura/client/focus_change_observer.h"
19 #include "ui/aura/client/visibility_client.h"
20 #include "ui/aura/client/window_tree_client.h"
21 #include "ui/aura/test/aura_test_base.h"
22 #include "ui/aura/test/aura_test_utils.h"
23 #include "ui/aura/test/test_window_delegate.h"
24 #include "ui/aura/test/test_windows.h"
25 #include "ui/aura/test/window_test_api.h"
26 #include "ui/aura/window_delegate.h"
27 #include "ui/aura/window_event_dispatcher.h"
28 #include "ui/aura/window_observer.h"
29 #include "ui/aura/window_property.h"
30 #include "ui/aura/window_tree_host.h"
31 #include "ui/base/hit_test.h"
32 #include "ui/compositor/layer.h"
33 #include "ui/compositor/layer_animation_observer.h"
34 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
35 #include "ui/compositor/scoped_layer_animation_settings.h"
36 #include "ui/compositor/test/test_layers.h"
37 #include "ui/events/event.h"
38 #include "ui/events/event_utils.h"
39 #include "ui/events/gestures/gesture_configuration.h"
40 #include "ui/events/keycodes/keyboard_codes.h"
41 #include "ui/events/test/event_generator.h"
42 #include "ui/gfx/canvas.h"
43 #include "ui/gfx/screen.h"
44 #include "ui/gfx/skia_util.h"
45 #include "ui/gfx/vector2d.h"
47 DECLARE_WINDOW_PROPERTY_TYPE(const char*)
48 DECLARE_WINDOW_PROPERTY_TYPE(int)
53 class WindowTest
: public AuraTestBase
{
55 WindowTest() : max_separation_(0) {
58 virtual void SetUp() OVERRIDE
{
59 AuraTestBase::SetUp();
60 // TODO: there needs to be an easier way to do this.
61 max_separation_
= ui::GestureConfiguration::
62 max_separation_for_gesture_touches_in_pixels();
63 ui::GestureConfiguration::
64 set_max_separation_for_gesture_touches_in_pixels(0);
67 virtual void TearDown() OVERRIDE
{
68 AuraTestBase::TearDown();
69 ui::GestureConfiguration::
70 set_max_separation_for_gesture_touches_in_pixels(max_separation_
);
76 DISALLOW_COPY_AND_ASSIGN(WindowTest
);
81 // Used for verifying destruction methods are invoked.
82 class DestroyTrackingDelegateImpl
: public TestWindowDelegate
{
84 DestroyTrackingDelegateImpl()
85 : destroying_count_(0),
87 in_destroying_(false) {}
89 void clear_destroying_count() { destroying_count_
= 0; }
90 int destroying_count() const { return destroying_count_
; }
92 void clear_destroyed_count() { destroyed_count_
= 0; }
93 int destroyed_count() const { return destroyed_count_
; }
95 bool in_destroying() const { return in_destroying_
; }
97 virtual void OnWindowDestroying(Window
* window
) OVERRIDE
{
98 EXPECT_FALSE(in_destroying_
);
99 in_destroying_
= true;
103 virtual void OnWindowDestroyed(Window
* window
) OVERRIDE
{
104 EXPECT_TRUE(in_destroying_
);
105 in_destroying_
= false;
110 int destroying_count_
;
111 int destroyed_count_
;
114 DISALLOW_COPY_AND_ASSIGN(DestroyTrackingDelegateImpl
);
117 // Used to verify that when OnWindowDestroying is invoked the parent is also
118 // is in the process of being destroyed.
119 class ChildWindowDelegateImpl
: public DestroyTrackingDelegateImpl
{
121 explicit ChildWindowDelegateImpl(
122 DestroyTrackingDelegateImpl
* parent_delegate
)
123 : parent_delegate_(parent_delegate
) {
126 virtual void OnWindowDestroying(Window
* window
) OVERRIDE
{
127 EXPECT_TRUE(parent_delegate_
->in_destroying());
128 DestroyTrackingDelegateImpl::OnWindowDestroying(window
);
132 DestroyTrackingDelegateImpl
* parent_delegate_
;
134 DISALLOW_COPY_AND_ASSIGN(ChildWindowDelegateImpl
);
137 // Used to verify that a Window is removed from its parent when
138 // OnWindowDestroyed is called.
139 class DestroyOrphanDelegate
: public TestWindowDelegate
{
141 DestroyOrphanDelegate() : window_(NULL
) {
144 void set_window(Window
* window
) { window_
= window
; }
146 virtual void OnWindowDestroyed(Window
* window
) OVERRIDE
{
147 EXPECT_FALSE(window_
->parent());
152 DISALLOW_COPY_AND_ASSIGN(DestroyOrphanDelegate
);
155 // Used in verifying mouse capture.
156 class CaptureWindowDelegateImpl
: public TestWindowDelegate
{
158 CaptureWindowDelegateImpl() {
163 capture_changed_event_count_
= 0;
164 capture_lost_count_
= 0;
165 mouse_event_count_
= 0;
166 touch_event_count_
= 0;
167 gesture_event_count_
= 0;
170 int capture_changed_event_count() const {
171 return capture_changed_event_count_
;
173 int capture_lost_count() const { return capture_lost_count_
; }
174 int mouse_event_count() const { return mouse_event_count_
; }
175 int touch_event_count() const { return touch_event_count_
; }
176 int gesture_event_count() const { return gesture_event_count_
; }
178 virtual void OnMouseEvent(ui::MouseEvent
* event
) OVERRIDE
{
179 if (event
->type() == ui::ET_MOUSE_CAPTURE_CHANGED
)
180 capture_changed_event_count_
++;
181 mouse_event_count_
++;
183 virtual void OnTouchEvent(ui::TouchEvent
* event
) OVERRIDE
{
184 touch_event_count_
++;
186 virtual void OnGestureEvent(ui::GestureEvent
* event
) OVERRIDE
{
187 gesture_event_count_
++;
189 virtual void OnCaptureLost() OVERRIDE
{
190 capture_lost_count_
++;
194 int capture_changed_event_count_
;
195 int capture_lost_count_
;
196 int mouse_event_count_
;
197 int touch_event_count_
;
198 int gesture_event_count_
;
200 DISALLOW_COPY_AND_ASSIGN(CaptureWindowDelegateImpl
);
203 // Keeps track of the location of the gesture.
204 class GestureTrackPositionDelegate
: public TestWindowDelegate
{
206 GestureTrackPositionDelegate() {}
208 virtual void OnGestureEvent(ui::GestureEvent
* event
) OVERRIDE
{
209 position_
= event
->location();
210 event
->StopPropagation();
213 const gfx::Point
& position() const { return position_
; }
216 gfx::Point position_
;
218 DISALLOW_COPY_AND_ASSIGN(GestureTrackPositionDelegate
);
221 base::TimeDelta
getTime() {
222 return ui::EventTimeForNow();
225 class SelfEventHandlingWindowDelegate
: public TestWindowDelegate
{
227 SelfEventHandlingWindowDelegate() {}
229 virtual bool ShouldDescendIntoChildForEventHandling(
231 const gfx::Point
& location
) OVERRIDE
{
236 DISALLOW_COPY_AND_ASSIGN(SelfEventHandlingWindowDelegate
);
239 // The delegate deletes itself when the window is being destroyed.
240 class DestroyWindowDelegate
: public TestWindowDelegate
{
242 DestroyWindowDelegate() {}
245 virtual ~DestroyWindowDelegate() {}
247 // Overridden from WindowDelegate.
248 virtual void OnWindowDestroyed(Window
* window
) OVERRIDE
{
252 DISALLOW_COPY_AND_ASSIGN(DestroyWindowDelegate
);
257 TEST_F(WindowTest
, GetChildById
) {
258 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
259 scoped_ptr
<Window
> w11(CreateTestWindowWithId(11, w1
.get()));
260 scoped_ptr
<Window
> w111(CreateTestWindowWithId(111, w11
.get()));
261 scoped_ptr
<Window
> w12(CreateTestWindowWithId(12, w1
.get()));
263 EXPECT_EQ(NULL
, w1
->GetChildById(57));
264 EXPECT_EQ(w12
.get(), w1
->GetChildById(12));
265 EXPECT_EQ(w111
.get(), w1
->GetChildById(111));
268 // Make sure that Window::Contains correctly handles children, grandchildren,
269 // and not containing NULL or parents.
270 TEST_F(WindowTest
, Contains
) {
272 parent
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
274 child1
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
276 child2
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
278 parent
.AddChild(&child1
);
279 child1
.AddChild(&child2
);
281 EXPECT_TRUE(parent
.Contains(&parent
));
282 EXPECT_TRUE(parent
.Contains(&child1
));
283 EXPECT_TRUE(parent
.Contains(&child2
));
285 EXPECT_FALSE(parent
.Contains(NULL
));
286 EXPECT_FALSE(child1
.Contains(&parent
));
287 EXPECT_FALSE(child2
.Contains(&child1
));
290 TEST_F(WindowTest
, ContainsPointInRoot
) {
291 scoped_ptr
<Window
> w(
292 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(10, 10, 5, 5),
294 EXPECT_FALSE(w
->ContainsPointInRoot(gfx::Point(9, 9)));
295 EXPECT_TRUE(w
->ContainsPointInRoot(gfx::Point(10, 10)));
296 EXPECT_TRUE(w
->ContainsPointInRoot(gfx::Point(14, 14)));
297 EXPECT_FALSE(w
->ContainsPointInRoot(gfx::Point(15, 15)));
298 EXPECT_FALSE(w
->ContainsPointInRoot(gfx::Point(20, 20)));
301 TEST_F(WindowTest
, ContainsPoint
) {
302 scoped_ptr
<Window
> w(
303 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(10, 10, 5, 5),
305 EXPECT_TRUE(w
->ContainsPoint(gfx::Point(0, 0)));
306 EXPECT_TRUE(w
->ContainsPoint(gfx::Point(4, 4)));
307 EXPECT_FALSE(w
->ContainsPoint(gfx::Point(5, 5)));
308 EXPECT_FALSE(w
->ContainsPoint(gfx::Point(10, 10)));
311 TEST_F(WindowTest
, ConvertPointToWindow
) {
312 // Window::ConvertPointToWindow is mostly identical to
313 // Layer::ConvertPointToLayer, except NULL values for |source| are permitted,
314 // in which case the function just returns.
315 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
316 gfx::Point
reference_point(100, 100);
317 gfx::Point test_point
= reference_point
;
318 Window::ConvertPointToTarget(NULL
, w1
.get(), &test_point
);
319 EXPECT_EQ(reference_point
, test_point
);
322 TEST_F(WindowTest
, MoveCursorTo
) {
323 scoped_ptr
<Window
> w1(
324 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(10, 10, 500, 500),
326 scoped_ptr
<Window
> w11(
327 CreateTestWindow(SK_ColorGREEN
, 11, gfx::Rect(5, 5, 100, 100), w1
.get()));
328 scoped_ptr
<Window
> w111(
329 CreateTestWindow(SK_ColorCYAN
, 111, gfx::Rect(5, 5, 75, 75), w11
.get()));
330 scoped_ptr
<Window
> w1111(
331 CreateTestWindow(SK_ColorRED
, 1111, gfx::Rect(5, 5, 50, 50), w111
.get()));
333 Window
* root
= root_window();
334 root
->MoveCursorTo(gfx::Point(10, 10));
336 gfx::Screen::GetScreenFor(root
)->GetCursorScreenPoint().ToString());
337 w1
->MoveCursorTo(gfx::Point(10, 10));
339 gfx::Screen::GetScreenFor(root
)->GetCursorScreenPoint().ToString());
340 w11
->MoveCursorTo(gfx::Point(10, 10));
342 gfx::Screen::GetScreenFor(root
)->GetCursorScreenPoint().ToString());
343 w111
->MoveCursorTo(gfx::Point(10, 10));
345 gfx::Screen::GetScreenFor(root
)->GetCursorScreenPoint().ToString());
346 w1111
->MoveCursorTo(gfx::Point(10, 10));
348 gfx::Screen::GetScreenFor(root
)->GetCursorScreenPoint().ToString());
351 TEST_F(WindowTest
, ContainsMouse
) {
352 scoped_ptr
<Window
> w(
353 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(10, 10, 500, 500),
356 WindowTestApi
w_test_api(w
.get());
357 Window
* root
= root_window();
358 root
->MoveCursorTo(gfx::Point(10, 10));
359 EXPECT_TRUE(w_test_api
.ContainsMouse());
360 root
->MoveCursorTo(gfx::Point(9, 10));
361 EXPECT_FALSE(w_test_api
.ContainsMouse());
364 // Test Window::ConvertPointToWindow() with transform to root_window.
365 TEST_F(WindowTest
, MoveCursorToWithTransformRootWindow
) {
366 gfx::Transform transform
;
367 transform
.Translate(100.0, 100.0);
368 transform
.Rotate(90.0);
369 transform
.Scale(2.0, 5.0);
370 host()->SetRootTransform(transform
);
371 host()->MoveCursorTo(gfx::Point(10, 10));
373 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.OD
374 EXPECT_EQ("50,120", QueryLatestMousePositionRequestInHost(host()).ToString());
376 EXPECT_EQ("10,10", gfx::Screen::GetScreenFor(
377 root_window())->GetCursorScreenPoint().ToString());
380 // Tests Window::ConvertPointToWindow() with transform to non-root windows.
381 TEST_F(WindowTest
, MoveCursorToWithTransformWindow
) {
382 scoped_ptr
<Window
> w1(
383 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(10, 10, 500, 500),
386 gfx::Transform transform1
;
387 transform1
.Scale(2, 2);
388 w1
->SetTransform(transform1
);
389 w1
->MoveCursorTo(gfx::Point(10, 10));
391 gfx::Screen::GetScreenFor(w1
.get())->GetCursorScreenPoint().ToString());
393 gfx::Transform transform2
;
394 transform2
.Translate(-10, 20);
395 w1
->SetTransform(transform2
);
396 w1
->MoveCursorTo(gfx::Point(10, 10));
398 gfx::Screen::GetScreenFor(w1
.get())->GetCursorScreenPoint().ToString());
400 gfx::Transform transform3
;
401 transform3
.Rotate(90.0);
402 w1
->SetTransform(transform3
);
403 w1
->MoveCursorTo(gfx::Point(5, 5));
405 gfx::Screen::GetScreenFor(w1
.get())->GetCursorScreenPoint().ToString());
407 gfx::Transform transform4
;
408 transform4
.Translate(100.0, 100.0);
409 transform4
.Rotate(90.0);
410 transform4
.Scale(2.0, 5.0);
411 w1
->SetTransform(transform4
);
412 w1
->MoveCursorTo(gfx::Point(10, 10));
414 gfx::Screen::GetScreenFor(w1
.get())->GetCursorScreenPoint().ToString());
417 // Test Window::ConvertPointToWindow() with complex transforms to both root and
419 // Test Window::ConvertPointToWindow() with transform to root_window.
420 TEST_F(WindowTest
, MoveCursorToWithComplexTransform
) {
421 scoped_ptr
<Window
> w1(
422 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(10, 10, 500, 500),
424 scoped_ptr
<Window
> w11(
425 CreateTestWindow(SK_ColorGREEN
, 11, gfx::Rect(5, 5, 100, 100), w1
.get()));
426 scoped_ptr
<Window
> w111(
427 CreateTestWindow(SK_ColorCYAN
, 111, gfx::Rect(5, 5, 75, 75), w11
.get()));
428 scoped_ptr
<Window
> w1111(
429 CreateTestWindow(SK_ColorRED
, 1111, gfx::Rect(5, 5, 50, 50), w111
.get()));
431 Window
* root
= root_window();
433 // The root window expects transforms that produce integer rects.
434 gfx::Transform root_transform
;
435 root_transform
.Translate(60.0, 70.0);
436 root_transform
.Rotate(-90.0);
437 root_transform
.Translate(-50.0, -50.0);
438 root_transform
.Scale(2.0, 3.0);
440 gfx::Transform transform
;
441 transform
.Translate(10.0, 20.0);
442 transform
.Rotate(10.0);
443 transform
.Scale(0.3f
, 0.5f
);
444 host()->SetRootTransform(root_transform
);
445 w1
->SetTransform(transform
);
446 w11
->SetTransform(transform
);
447 w111
->SetTransform(transform
);
448 w1111
->SetTransform(transform
);
450 w1111
->MoveCursorTo(gfx::Point(10, 10));
453 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.
454 EXPECT_EQ("169,80", QueryLatestMousePositionRequestInHost(host()).ToString());
457 gfx::Screen::GetScreenFor(root
)->GetCursorScreenPoint().ToString());
460 TEST_F(WindowTest
, GetEventHandlerForPoint
) {
461 scoped_ptr
<Window
> w1(
462 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(10, 10, 500, 500),
464 scoped_ptr
<Window
> w11(
465 CreateTestWindow(SK_ColorGREEN
, 11, gfx::Rect(5, 5, 100, 100), w1
.get()));
466 scoped_ptr
<Window
> w111(
467 CreateTestWindow(SK_ColorCYAN
, 111, gfx::Rect(5, 5, 75, 75), w11
.get()));
468 scoped_ptr
<Window
> w1111(
469 CreateTestWindow(SK_ColorRED
, 1111, gfx::Rect(5, 5, 50, 50), w111
.get()));
470 scoped_ptr
<Window
> w12(
471 CreateTestWindow(SK_ColorMAGENTA
, 12, gfx::Rect(10, 420, 25, 25),
473 scoped_ptr
<Window
> w121(
474 CreateTestWindow(SK_ColorYELLOW
, 121, gfx::Rect(5, 5, 5, 5), w12
.get()));
475 scoped_ptr
<Window
> w13(
476 CreateTestWindow(SK_ColorGRAY
, 13, gfx::Rect(5, 470, 50, 50), w1
.get()));
478 Window
* root
= root_window();
479 w1
->parent()->SetBounds(gfx::Rect(500, 500));
480 EXPECT_EQ(NULL
, root
->GetEventHandlerForPoint(gfx::Point(5, 5)));
481 EXPECT_EQ(w1
.get(), root
->GetEventHandlerForPoint(gfx::Point(11, 11)));
482 EXPECT_EQ(w11
.get(), root
->GetEventHandlerForPoint(gfx::Point(16, 16)));
483 EXPECT_EQ(w111
.get(), root
->GetEventHandlerForPoint(gfx::Point(21, 21)));
484 EXPECT_EQ(w1111
.get(), root
->GetEventHandlerForPoint(gfx::Point(26, 26)));
485 EXPECT_EQ(w12
.get(), root
->GetEventHandlerForPoint(gfx::Point(21, 431)));
486 EXPECT_EQ(w121
.get(), root
->GetEventHandlerForPoint(gfx::Point(26, 436)));
487 EXPECT_EQ(w13
.get(), root
->GetEventHandlerForPoint(gfx::Point(26, 481)));
490 TEST_F(WindowTest
, GetEventHandlerForPointWithOverride
) {
491 // If our child is flush to our top-left corner he gets events just inside the
493 scoped_ptr
<Window
> parent(
494 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(10, 20, 400, 500),
496 scoped_ptr
<Window
> child(
497 CreateTestWindow(SK_ColorRED
, 2, gfx::Rect(0, 0, 60, 70), parent
.get()));
498 EXPECT_EQ(child
.get(), parent
->GetEventHandlerForPoint(gfx::Point(0, 0)));
499 EXPECT_EQ(child
.get(), parent
->GetEventHandlerForPoint(gfx::Point(1, 1)));
501 // We can override the hit test bounds of the parent to make the parent grab
502 // events along that edge.
503 parent
->set_hit_test_bounds_override_inner(gfx::Insets(1, 1, 1, 1));
504 EXPECT_EQ(parent
.get(), parent
->GetEventHandlerForPoint(gfx::Point(0, 0)));
505 EXPECT_EQ(child
.get(), parent
->GetEventHandlerForPoint(gfx::Point(1, 1)));
508 TEST_F(WindowTest
, GetEventHandlerForPointWithOverrideDescendingOrder
) {
509 scoped_ptr
<SelfEventHandlingWindowDelegate
> parent_delegate(
510 new SelfEventHandlingWindowDelegate
);
511 scoped_ptr
<Window
> parent(CreateTestWindowWithDelegate(
512 parent_delegate
.get(), 1, gfx::Rect(10, 20, 400, 500), root_window()));
513 scoped_ptr
<Window
> child(
514 CreateTestWindow(SK_ColorRED
, 2, gfx::Rect(0, 0, 390, 480),
517 // We can override ShouldDescendIntoChildForEventHandling to make the parent
519 EXPECT_EQ(parent
.get(), parent
->GetEventHandlerForPoint(gfx::Point(0, 0)));
520 EXPECT_EQ(parent
.get(), parent
->GetEventHandlerForPoint(gfx::Point(50, 50)));
523 TEST_F(WindowTest
, GetTopWindowContainingPoint
) {
524 Window
* root
= root_window();
525 root
->SetBounds(gfx::Rect(0, 0, 300, 300));
527 scoped_ptr
<Window
> w1(
528 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(10, 10, 100, 100),
530 scoped_ptr
<Window
> w11(
531 CreateTestWindow(SK_ColorGREEN
, 11, gfx::Rect(0, 0, 120, 120), w1
.get()));
533 scoped_ptr
<Window
> w2(
534 CreateTestWindow(SK_ColorRED
, 2, gfx::Rect(5, 5, 55, 55),
537 scoped_ptr
<Window
> w3(
538 CreateTestWindowWithDelegate(
539 NULL
, 3, gfx::Rect(200, 200, 100, 100), root_window()));
540 scoped_ptr
<Window
> w31(
541 CreateTestWindow(SK_ColorCYAN
, 31, gfx::Rect(0, 0, 50, 50), w3
.get()));
542 scoped_ptr
<Window
> w311(
543 CreateTestWindow(SK_ColorBLUE
, 311, gfx::Rect(0, 0, 10, 10), w31
.get()));
545 EXPECT_EQ(NULL
, root
->GetTopWindowContainingPoint(gfx::Point(0, 0)));
546 EXPECT_EQ(w2
.get(), root
->GetTopWindowContainingPoint(gfx::Point(5, 5)));
547 EXPECT_EQ(w2
.get(), root
->GetTopWindowContainingPoint(gfx::Point(10, 10)));
548 EXPECT_EQ(w2
.get(), root
->GetTopWindowContainingPoint(gfx::Point(59, 59)));
549 EXPECT_EQ(w1
.get(), root
->GetTopWindowContainingPoint(gfx::Point(60, 60)));
550 EXPECT_EQ(w1
.get(), root
->GetTopWindowContainingPoint(gfx::Point(109, 109)));
551 EXPECT_EQ(NULL
, root
->GetTopWindowContainingPoint(gfx::Point(110, 110)));
552 EXPECT_EQ(w31
.get(), root
->GetTopWindowContainingPoint(gfx::Point(200, 200)));
553 EXPECT_EQ(w31
.get(), root
->GetTopWindowContainingPoint(gfx::Point(220, 220)));
554 EXPECT_EQ(NULL
, root
->GetTopWindowContainingPoint(gfx::Point(260, 260)));
557 TEST_F(WindowTest
, GetToplevelWindow
) {
558 const gfx::Rect
kBounds(0, 0, 10, 10);
559 TestWindowDelegate delegate
;
561 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
562 scoped_ptr
<Window
> w11(
563 CreateTestWindowWithDelegate(&delegate
, 11, kBounds
, w1
.get()));
564 scoped_ptr
<Window
> w111(CreateTestWindowWithId(111, w11
.get()));
565 scoped_ptr
<Window
> w1111(
566 CreateTestWindowWithDelegate(&delegate
, 1111, kBounds
, w111
.get()));
568 EXPECT_TRUE(root_window()->GetToplevelWindow() == NULL
);
569 EXPECT_TRUE(w1
->GetToplevelWindow() == NULL
);
570 EXPECT_EQ(w11
.get(), w11
->GetToplevelWindow());
571 EXPECT_EQ(w11
.get(), w111
->GetToplevelWindow());
572 EXPECT_EQ(w11
.get(), w1111
->GetToplevelWindow());
575 class AddedToRootWindowObserver
: public WindowObserver
{
577 AddedToRootWindowObserver() : called_(false) {}
579 virtual void OnWindowAddedToRootWindow(Window
* window
) OVERRIDE
{
583 bool called() const { return called_
; }
588 DISALLOW_COPY_AND_ASSIGN(AddedToRootWindowObserver
);
591 TEST_F(WindowTest
, WindowAddedToRootWindowShouldNotifyChildAndNotParent
) {
592 AddedToRootWindowObserver parent_observer
;
593 AddedToRootWindowObserver child_observer
;
594 scoped_ptr
<Window
> parent_window(CreateTestWindowWithId(1, root_window()));
595 scoped_ptr
<Window
> child_window(new Window(NULL
));
596 child_window
->Init(aura::WINDOW_LAYER_TEXTURED
);
597 child_window
->Show();
599 parent_window
->AddObserver(&parent_observer
);
600 child_window
->AddObserver(&child_observer
);
602 parent_window
->AddChild(child_window
.get());
604 EXPECT_FALSE(parent_observer
.called());
605 EXPECT_TRUE(child_observer
.called());
607 parent_window
->RemoveObserver(&parent_observer
);
608 child_window
->RemoveObserver(&child_observer
);
611 // Various destruction assertions.
612 TEST_F(WindowTest
, DestroyTest
) {
613 DestroyTrackingDelegateImpl parent_delegate
;
614 ChildWindowDelegateImpl
child_delegate(&parent_delegate
);
616 scoped_ptr
<Window
> parent(
617 CreateTestWindowWithDelegate(&parent_delegate
, 0, gfx::Rect(),
619 CreateTestWindowWithDelegate(&child_delegate
, 0, gfx::Rect(), parent
.get());
621 // Both the parent and child should have been destroyed.
622 EXPECT_EQ(1, parent_delegate
.destroying_count());
623 EXPECT_EQ(1, parent_delegate
.destroyed_count());
624 EXPECT_EQ(1, child_delegate
.destroying_count());
625 EXPECT_EQ(1, child_delegate
.destroyed_count());
628 // Tests that a window is orphaned before OnWindowDestroyed is called.
629 TEST_F(WindowTest
, OrphanedBeforeOnDestroyed
) {
630 TestWindowDelegate parent_delegate
;
631 DestroyOrphanDelegate child_delegate
;
633 scoped_ptr
<Window
> parent(
634 CreateTestWindowWithDelegate(&parent_delegate
, 0, gfx::Rect(),
636 scoped_ptr
<Window
> child(CreateTestWindowWithDelegate(&child_delegate
, 0,
637 gfx::Rect(), parent
.get()));
638 child_delegate
.set_window(child
.get());
642 // Make sure StackChildAtTop moves both the window and layer to the front.
643 TEST_F(WindowTest
, StackChildAtTop
) {
645 parent
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
647 child1
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
649 child2
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
651 parent
.AddChild(&child1
);
652 parent
.AddChild(&child2
);
653 ASSERT_EQ(2u, parent
.children().size());
654 EXPECT_EQ(&child1
, parent
.children()[0]);
655 EXPECT_EQ(&child2
, parent
.children()[1]);
656 ASSERT_EQ(2u, parent
.layer()->children().size());
657 EXPECT_EQ(child1
.layer(), parent
.layer()->children()[0]);
658 EXPECT_EQ(child2
.layer(), parent
.layer()->children()[1]);
660 parent
.StackChildAtTop(&child1
);
661 ASSERT_EQ(2u, parent
.children().size());
662 EXPECT_EQ(&child1
, parent
.children()[1]);
663 EXPECT_EQ(&child2
, parent
.children()[0]);
664 ASSERT_EQ(2u, parent
.layer()->children().size());
665 EXPECT_EQ(child1
.layer(), parent
.layer()->children()[1]);
666 EXPECT_EQ(child2
.layer(), parent
.layer()->children()[0]);
669 // Make sure StackChildBelow works.
670 TEST_F(WindowTest
, StackChildBelow
) {
672 parent
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
674 child1
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
677 child2
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
680 child3
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
683 parent
.AddChild(&child1
);
684 parent
.AddChild(&child2
);
685 parent
.AddChild(&child3
);
686 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent
));
688 parent
.StackChildBelow(&child1
, &child2
);
689 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent
));
691 parent
.StackChildBelow(&child2
, &child1
);
692 EXPECT_EQ("2 1 3", ChildWindowIDsAsString(&parent
));
694 parent
.StackChildBelow(&child3
, &child2
);
695 EXPECT_EQ("3 2 1", ChildWindowIDsAsString(&parent
));
697 parent
.StackChildBelow(&child3
, &child1
);
698 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(&parent
));
701 // Various assertions for StackChildAbove.
702 TEST_F(WindowTest
, StackChildAbove
) {
704 parent
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
706 child1
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
708 child2
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
710 child3
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
712 parent
.AddChild(&child1
);
713 parent
.AddChild(&child2
);
715 // Move 1 in front of 2.
716 parent
.StackChildAbove(&child1
, &child2
);
717 ASSERT_EQ(2u, parent
.children().size());
718 EXPECT_EQ(&child2
, parent
.children()[0]);
719 EXPECT_EQ(&child1
, parent
.children()[1]);
720 ASSERT_EQ(2u, parent
.layer()->children().size());
721 EXPECT_EQ(child2
.layer(), parent
.layer()->children()[0]);
722 EXPECT_EQ(child1
.layer(), parent
.layer()->children()[1]);
724 // Add 3, resulting in order [2, 1, 3], then move 2 in front of 1, resulting
726 parent
.AddChild(&child3
);
727 parent
.StackChildAbove(&child2
, &child1
);
728 ASSERT_EQ(3u, parent
.children().size());
729 EXPECT_EQ(&child1
, parent
.children()[0]);
730 EXPECT_EQ(&child2
, parent
.children()[1]);
731 EXPECT_EQ(&child3
, parent
.children()[2]);
732 ASSERT_EQ(3u, parent
.layer()->children().size());
733 EXPECT_EQ(child1
.layer(), parent
.layer()->children()[0]);
734 EXPECT_EQ(child2
.layer(), parent
.layer()->children()[1]);
735 EXPECT_EQ(child3
.layer(), parent
.layer()->children()[2]);
737 // Move 1 in front of 3, resulting in [2, 3, 1].
738 parent
.StackChildAbove(&child1
, &child3
);
739 ASSERT_EQ(3u, parent
.children().size());
740 EXPECT_EQ(&child2
, parent
.children()[0]);
741 EXPECT_EQ(&child3
, parent
.children()[1]);
742 EXPECT_EQ(&child1
, parent
.children()[2]);
743 ASSERT_EQ(3u, parent
.layer()->children().size());
744 EXPECT_EQ(child2
.layer(), parent
.layer()->children()[0]);
745 EXPECT_EQ(child3
.layer(), parent
.layer()->children()[1]);
746 EXPECT_EQ(child1
.layer(), parent
.layer()->children()[2]);
748 // Moving 1 in front of 2 should lower it, resulting in [2, 1, 3].
749 parent
.StackChildAbove(&child1
, &child2
);
750 ASSERT_EQ(3u, parent
.children().size());
751 EXPECT_EQ(&child2
, parent
.children()[0]);
752 EXPECT_EQ(&child1
, parent
.children()[1]);
753 EXPECT_EQ(&child3
, parent
.children()[2]);
754 ASSERT_EQ(3u, parent
.layer()->children().size());
755 EXPECT_EQ(child2
.layer(), parent
.layer()->children()[0]);
756 EXPECT_EQ(child1
.layer(), parent
.layer()->children()[1]);
757 EXPECT_EQ(child3
.layer(), parent
.layer()->children()[2]);
760 // Various capture assertions.
761 TEST_F(WindowTest
, CaptureTests
) {
762 CaptureWindowDelegateImpl delegate
;
763 scoped_ptr
<Window
> window(CreateTestWindowWithDelegate(
764 &delegate
, 0, gfx::Rect(0, 0, 20, 20), root_window()));
765 EXPECT_FALSE(window
->HasCapture());
767 delegate
.ResetCounts();
770 window
->SetCapture();
771 EXPECT_TRUE(window
->HasCapture());
772 EXPECT_EQ(0, delegate
.capture_lost_count());
773 EXPECT_EQ(0, delegate
.capture_changed_event_count());
774 ui::test::EventGenerator
generator(root_window(), gfx::Point(50, 50));
775 generator
.PressLeftButton();
776 EXPECT_EQ(1, delegate
.mouse_event_count());
777 generator
.ReleaseLeftButton();
779 EXPECT_EQ(2, delegate
.mouse_event_count());
780 delegate
.ResetCounts();
782 ui::TouchEvent
touchev(
783 ui::ET_TOUCH_PRESSED
, gfx::Point(50, 50), 0, getTime());
784 DispatchEventUsingWindowDispatcher(&touchev
);
785 EXPECT_EQ(1, delegate
.touch_event_count());
786 delegate
.ResetCounts();
788 window
->ReleaseCapture();
789 EXPECT_FALSE(window
->HasCapture());
790 EXPECT_EQ(1, delegate
.capture_lost_count());
791 EXPECT_EQ(1, delegate
.capture_changed_event_count());
792 EXPECT_EQ(1, delegate
.mouse_event_count());
793 EXPECT_EQ(0, delegate
.touch_event_count());
795 generator
.PressLeftButton();
796 EXPECT_EQ(1, delegate
.mouse_event_count());
798 ui::TouchEvent
touchev2(
799 ui::ET_TOUCH_PRESSED
, gfx::Point(250, 250), 1, getTime());
800 DispatchEventUsingWindowDispatcher(&touchev2
);
801 EXPECT_EQ(0, delegate
.touch_event_count());
803 // Removing the capture window from parent should reset the capture window
804 // in the root window.
805 window
->SetCapture();
806 EXPECT_EQ(window
.get(), aura::client::GetCaptureWindow(root_window()));
807 window
->parent()->RemoveChild(window
.get());
808 EXPECT_FALSE(window
->HasCapture());
809 EXPECT_EQ(NULL
, aura::client::GetCaptureWindow(root_window()));
812 TEST_F(WindowTest
, TouchCaptureCancelsOtherTouches
) {
813 CaptureWindowDelegateImpl delegate1
;
814 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(
815 &delegate1
, 0, gfx::Rect(0, 0, 50, 50), root_window()));
816 CaptureWindowDelegateImpl delegate2
;
817 scoped_ptr
<Window
> w2(CreateTestWindowWithDelegate(
818 &delegate2
, 0, gfx::Rect(50, 50, 50, 50), root_window()));
821 ui::TouchEvent
press1(
822 ui::ET_TOUCH_PRESSED
, gfx::Point(10, 10), 0, getTime());
823 DispatchEventUsingWindowDispatcher(&press1
);
824 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
825 EXPECT_EQ(2, delegate1
.gesture_event_count());
826 delegate1
.ResetCounts();
828 // Capturing to w2 should cause the touch to be canceled.
830 EXPECT_EQ(1, delegate1
.touch_event_count());
831 EXPECT_EQ(0, delegate2
.touch_event_count());
832 delegate1
.ResetCounts();
833 delegate2
.ResetCounts();
835 // Events are ignored by w2, as it's receiving a partial touch stream.
836 ui::TouchEvent
move(ui::ET_TOUCH_MOVED
, gfx::Point(10, 20), 0, getTime());
837 DispatchEventUsingWindowDispatcher(&move
);
838 EXPECT_EQ(0, delegate1
.gesture_event_count());
839 EXPECT_EQ(0, delegate1
.touch_event_count());
840 EXPECT_EQ(0, delegate2
.gesture_event_count());
841 EXPECT_EQ(0, delegate2
.touch_event_count());
843 ui::TouchEvent
release(
844 ui::ET_TOUCH_RELEASED
, gfx::Point(10, 20), 0, getTime());
845 DispatchEventUsingWindowDispatcher(&release
);
846 EXPECT_EQ(0, delegate1
.gesture_event_count());
847 EXPECT_EQ(0, delegate2
.gesture_event_count());
849 // A new press is captured by w2.
850 ui::TouchEvent
press2(
851 ui::ET_TOUCH_PRESSED
, gfx::Point(10, 10), 0, getTime());
852 DispatchEventUsingWindowDispatcher(&press2
);
853 EXPECT_EQ(0, delegate1
.gesture_event_count());
854 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
855 EXPECT_EQ(2, delegate2
.gesture_event_count());
856 delegate1
.ResetCounts();
857 delegate2
.ResetCounts();
859 // And releasing capture changes nothing.
860 w2
->ReleaseCapture();
861 EXPECT_EQ(0, delegate1
.gesture_event_count());
862 EXPECT_EQ(0, delegate1
.touch_event_count());
863 EXPECT_EQ(0, delegate2
.gesture_event_count());
864 EXPECT_EQ(0, delegate2
.touch_event_count());
867 TEST_F(WindowTest
, TouchCaptureDoesntCancelCapturedTouches
) {
868 CaptureWindowDelegateImpl delegate
;
869 scoped_ptr
<Window
> window(CreateTestWindowWithDelegate(
870 &delegate
, 0, gfx::Rect(0, 0, 50, 50), root_window()));
871 base::TimeDelta time
= getTime();
872 const int kTimeDelta
= 100;
874 ui::TouchEvent
press(
875 ui::ET_TOUCH_PRESSED
, gfx::Point(10, 10), 0, time
);
876 DispatchEventUsingWindowDispatcher(&press
);
878 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
879 EXPECT_EQ(2, delegate
.gesture_event_count());
880 EXPECT_EQ(1, delegate
.touch_event_count());
881 delegate
.ResetCounts();
883 window
->SetCapture();
884 EXPECT_EQ(0, delegate
.gesture_event_count());
885 EXPECT_EQ(0, delegate
.touch_event_count());
886 delegate
.ResetCounts();
888 // On move We will get TOUCH_MOVED, GESTURE_TAP_CANCEL,
889 // GESTURE_SCROLL_START and GESTURE_SCROLL_UPDATE.
890 time
+= base::TimeDelta::FromMilliseconds(kTimeDelta
);
891 ui::TouchEvent
move(ui::ET_TOUCH_MOVED
, gfx::Point(10, 20), 0, time
);
892 DispatchEventUsingWindowDispatcher(&move
);
893 EXPECT_EQ(1, delegate
.touch_event_count());
894 EXPECT_EQ(3, delegate
.gesture_event_count());
895 delegate
.ResetCounts();
897 // Release capture shouldn't change anything.
898 window
->ReleaseCapture();
899 EXPECT_EQ(0, delegate
.touch_event_count());
900 EXPECT_EQ(0, delegate
.gesture_event_count());
901 delegate
.ResetCounts();
903 // On move we still get TOUCH_MOVED and GESTURE_SCROLL_UPDATE.
904 time
+= base::TimeDelta::FromMilliseconds(kTimeDelta
);
905 ui::TouchEvent
move2(ui::ET_TOUCH_MOVED
, gfx::Point(10, 30), 0, time
);
906 DispatchEventUsingWindowDispatcher(&move2
);
907 EXPECT_EQ(1, delegate
.touch_event_count());
908 EXPECT_EQ(1, delegate
.gesture_event_count());
909 delegate
.ResetCounts();
911 // And on release we get TOUCH_RELEASED, GESTURE_SCROLL_END, GESTURE_END
912 time
+= base::TimeDelta::FromMilliseconds(kTimeDelta
);
913 ui::TouchEvent
release(
914 ui::ET_TOUCH_RELEASED
, gfx::Point(10, 20), 0, time
);
915 DispatchEventUsingWindowDispatcher(&release
);
916 EXPECT_EQ(1, delegate
.touch_event_count());
917 EXPECT_EQ(2, delegate
.gesture_event_count());
921 // Assertions around SetCapture() and touch/gestures.
922 TEST_F(WindowTest
, TransferCaptureTouchEvents
) {
924 CaptureWindowDelegateImpl d1
;
925 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(
926 &d1
, 0, gfx::Rect(0, 0, 20, 20), root_window()));
927 ui::TouchEvent
p1(ui::ET_TOUCH_PRESSED
, gfx::Point(10, 10), 0, getTime());
928 DispatchEventUsingWindowDispatcher(&p1
);
929 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
930 EXPECT_EQ(1, d1
.touch_event_count());
931 EXPECT_EQ(2, d1
.gesture_event_count());
934 // Touch on |w2| with a different id.
935 CaptureWindowDelegateImpl d2
;
936 scoped_ptr
<Window
> w2(CreateTestWindowWithDelegate(
937 &d2
, 0, gfx::Rect(40, 0, 40, 20), root_window()));
938 ui::TouchEvent
p2(ui::ET_TOUCH_PRESSED
, gfx::Point(41, 10), 1, getTime());
939 DispatchEventUsingWindowDispatcher(&p2
);
940 EXPECT_EQ(0, d1
.touch_event_count());
941 EXPECT_EQ(0, d1
.gesture_event_count());
942 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN for new target window.
943 EXPECT_EQ(1, d2
.touch_event_count());
944 EXPECT_EQ(2, d2
.gesture_event_count());
948 // Set capture on |w2|, this should send a cancel (TAP_CANCEL, END) to |w1|
951 EXPECT_EQ(1, d1
.touch_event_count());
952 EXPECT_EQ(2, d1
.gesture_event_count());
953 EXPECT_EQ(0, d2
.touch_event_count());
954 EXPECT_EQ(0, d2
.gesture_event_count());
958 CaptureWindowDelegateImpl d3
;
959 scoped_ptr
<Window
> w3(CreateTestWindowWithDelegate(
960 &d3
, 0, gfx::Rect(0, 0, 100, 101), root_window()));
961 // Set capture on w3. No new events should be received.
962 // Note this difference in behavior between the first and second capture
963 // is confusing and error prone. http://crbug.com/236930
965 EXPECT_EQ(0, d1
.touch_event_count());
966 EXPECT_EQ(0, d1
.gesture_event_count());
967 EXPECT_EQ(0, d2
.touch_event_count());
968 EXPECT_EQ(0, d2
.gesture_event_count());
969 EXPECT_EQ(0, d3
.touch_event_count());
970 EXPECT_EQ(0, d3
.gesture_event_count());
972 // Move touch id originally associated with |w2|. Since capture was transfered
973 // from 2 to 3 only |w3| should get the event.
974 ui::TouchEvent
m3(ui::ET_TOUCH_MOVED
, gfx::Point(110, 105), 1, getTime());
975 DispatchEventUsingWindowDispatcher(&m3
);
976 EXPECT_EQ(0, d1
.touch_event_count());
977 EXPECT_EQ(0, d1
.gesture_event_count());
978 EXPECT_EQ(0, d2
.touch_event_count());
979 EXPECT_EQ(0, d2
.gesture_event_count());
980 // |w3| gets a TOUCH_MOVE, TAP_CANCEL and two scroll related events.
981 EXPECT_EQ(1, d3
.touch_event_count());
982 EXPECT_EQ(3, d3
.gesture_event_count());
987 // When we release capture, no touches are canceled.
988 w3
->ReleaseCapture();
989 EXPECT_EQ(0, d1
.touch_event_count());
990 EXPECT_EQ(0, d1
.gesture_event_count());
991 EXPECT_EQ(0, d2
.touch_event_count());
992 EXPECT_EQ(0, d2
.gesture_event_count());
993 EXPECT_EQ(0, d3
.touch_event_count());
994 EXPECT_EQ(0, d3
.gesture_event_count());
996 // And when we move the touch again, |w3| still gets the events.
997 ui::TouchEvent
m4(ui::ET_TOUCH_MOVED
, gfx::Point(120, 105), 1, getTime());
998 DispatchEventUsingWindowDispatcher(&m4
);
999 EXPECT_EQ(0, d1
.touch_event_count());
1000 EXPECT_EQ(0, d1
.gesture_event_count());
1001 EXPECT_EQ(0, d2
.touch_event_count());
1002 EXPECT_EQ(0, d2
.gesture_event_count());
1003 EXPECT_EQ(1, d3
.touch_event_count());
1004 EXPECT_EQ(1, d3
.gesture_event_count());
1010 // Changes capture while capture is already ongoing.
1011 TEST_F(WindowTest
, ChangeCaptureWhileMouseDown
) {
1012 CaptureWindowDelegateImpl delegate
;
1013 scoped_ptr
<Window
> window(CreateTestWindowWithDelegate(
1014 &delegate
, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1015 CaptureWindowDelegateImpl delegate2
;
1016 scoped_ptr
<Window
> w2(CreateTestWindowWithDelegate(
1017 &delegate2
, 0, gfx::Rect(20, 20, 20, 20), root_window()));
1019 // Execute the scheduled draws so that mouse events are not
1021 RunAllPendingInMessageLoop();
1023 EXPECT_FALSE(window
->HasCapture());
1026 delegate
.ResetCounts();
1027 window
->SetCapture();
1028 EXPECT_TRUE(window
->HasCapture());
1029 EXPECT_EQ(0, delegate
.capture_lost_count());
1030 EXPECT_EQ(0, delegate
.capture_changed_event_count());
1031 ui::test::EventGenerator
generator(root_window(), gfx::Point(50, 50));
1032 generator
.PressLeftButton();
1033 EXPECT_EQ(0, delegate
.capture_lost_count());
1034 EXPECT_EQ(0, delegate
.capture_changed_event_count());
1035 EXPECT_EQ(1, delegate
.mouse_event_count());
1037 // Set capture to |w2|, should implicitly unset capture for |window|.
1038 delegate
.ResetCounts();
1039 delegate2
.ResetCounts();
1042 generator
.MoveMouseTo(gfx::Point(40, 40), 2);
1043 EXPECT_EQ(1, delegate
.capture_lost_count());
1044 EXPECT_EQ(1, delegate
.capture_changed_event_count());
1045 EXPECT_EQ(1, delegate
.mouse_event_count());
1046 EXPECT_EQ(2, delegate2
.mouse_event_count());
1049 // Verifies capture is reset when a window is destroyed.
1050 TEST_F(WindowTest
, ReleaseCaptureOnDestroy
) {
1051 CaptureWindowDelegateImpl delegate
;
1052 scoped_ptr
<Window
> window(CreateTestWindowWithDelegate(
1053 &delegate
, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1054 EXPECT_FALSE(window
->HasCapture());
1057 window
->SetCapture();
1058 EXPECT_TRUE(window
->HasCapture());
1060 // Destroy the window.
1063 // Make sure the root window doesn't reference the window anymore.
1064 EXPECT_EQ(NULL
, host()->dispatcher()->mouse_pressed_handler());
1065 EXPECT_EQ(NULL
, aura::client::GetCaptureWindow(root_window()));
1068 TEST_F(WindowTest
, GetBoundsInRootWindow
) {
1069 scoped_ptr
<Window
> viewport(CreateTestWindowWithBounds(
1070 gfx::Rect(0, 0, 300, 300), root_window()));
1071 scoped_ptr
<Window
> child(CreateTestWindowWithBounds(
1072 gfx::Rect(0, 0, 100, 100), viewport
.get()));
1074 EXPECT_EQ("0,0 100x100", child
->GetBoundsInRootWindow().ToString());
1076 // The |child| window's screen bounds should move along with the |viewport|.
1077 viewport
->SetBounds(gfx::Rect(-100, -100, 300, 300));
1078 EXPECT_EQ("-100,-100 100x100", child
->GetBoundsInRootWindow().ToString());
1080 // The |child| window is moved to the 0,0 in screen coordinates.
1081 // |GetBoundsInRootWindow()| should return 0,0.
1082 child
->SetBounds(gfx::Rect(100, 100, 100, 100));
1083 EXPECT_EQ("0,0 100x100", child
->GetBoundsInRootWindow().ToString());
1086 class MouseEnterExitWindowDelegate
: public TestWindowDelegate
{
1088 MouseEnterExitWindowDelegate() : entered_(false), exited_(false) {}
1090 virtual void OnMouseEvent(ui::MouseEvent
* event
) OVERRIDE
{
1091 switch (event
->type()) {
1092 case ui::ET_MOUSE_ENTERED
:
1093 EXPECT_TRUE(event
->flags() & ui::EF_IS_SYNTHESIZED
);
1096 case ui::ET_MOUSE_EXITED
:
1097 EXPECT_TRUE(event
->flags() & ui::EF_IS_SYNTHESIZED
);
1105 bool entered() const { return entered_
; }
1106 bool exited() const { return exited_
; }
1108 // Clear the entered / exited states.
1109 void ResetExpectations() {
1118 DISALLOW_COPY_AND_ASSIGN(MouseEnterExitWindowDelegate
);
1122 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1123 // mouse transitions from window to window.
1124 TEST_F(WindowTest
, MouseEnterExit
) {
1125 MouseEnterExitWindowDelegate d1
;
1126 scoped_ptr
<Window
> w1(
1127 CreateTestWindowWithDelegate(&d1
, 1, gfx::Rect(10, 10, 50, 50),
1129 MouseEnterExitWindowDelegate d2
;
1130 scoped_ptr
<Window
> w2(
1131 CreateTestWindowWithDelegate(&d2
, 2, gfx::Rect(70, 70, 50, 50),
1134 ui::test::EventGenerator
generator(root_window());
1135 generator
.MoveMouseToCenterOf(w1
.get());
1136 EXPECT_TRUE(d1
.entered());
1137 EXPECT_FALSE(d1
.exited());
1138 EXPECT_FALSE(d2
.entered());
1139 EXPECT_FALSE(d2
.exited());
1141 generator
.MoveMouseToCenterOf(w2
.get());
1142 EXPECT_TRUE(d1
.entered());
1143 EXPECT_TRUE(d1
.exited());
1144 EXPECT_TRUE(d2
.entered());
1145 EXPECT_FALSE(d2
.exited());
1148 // Verifies that the WindowDelegate receives MouseExit from ET_MOUSE_EXITED.
1149 TEST_F(WindowTest
, WindowTreeHostExit
) {
1150 MouseEnterExitWindowDelegate d1
;
1151 scoped_ptr
<Window
> w1(
1152 CreateTestWindowWithDelegate(&d1
, 1, gfx::Rect(10, 10, 50, 50),
1155 ui::test::EventGenerator
generator(root_window());
1156 generator
.MoveMouseToCenterOf(w1
.get());
1157 EXPECT_TRUE(d1
.entered());
1158 EXPECT_FALSE(d1
.exited());
1159 d1
.ResetExpectations();
1161 ui::MouseEvent
exit_event(
1162 ui::ET_MOUSE_EXITED
, gfx::Point(), gfx::Point(), 0, 0);
1163 DispatchEventUsingWindowDispatcher(&exit_event
);
1164 EXPECT_FALSE(d1
.entered());
1165 EXPECT_TRUE(d1
.exited());
1168 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1169 // mouse transitions from window to window, even if the entered window sets
1170 // and releases capture.
1171 TEST_F(WindowTest
, MouseEnterExitWithClick
) {
1172 MouseEnterExitWindowDelegate d1
;
1173 scoped_ptr
<Window
> w1(
1174 CreateTestWindowWithDelegate(&d1
, 1, gfx::Rect(10, 10, 50, 50),
1176 MouseEnterExitWindowDelegate d2
;
1177 scoped_ptr
<Window
> w2(
1178 CreateTestWindowWithDelegate(&d2
, 2, gfx::Rect(70, 70, 50, 50),
1181 ui::test::EventGenerator
generator(root_window());
1182 generator
.MoveMouseToCenterOf(w1
.get());
1183 EXPECT_TRUE(d1
.entered());
1184 EXPECT_FALSE(d1
.exited());
1185 EXPECT_FALSE(d2
.entered());
1186 EXPECT_FALSE(d2
.exited());
1188 // Emmulate what Views does on a click by grabbing and releasing capture.
1189 generator
.PressLeftButton();
1191 w1
->ReleaseCapture();
1192 generator
.ReleaseLeftButton();
1194 generator
.MoveMouseToCenterOf(w2
.get());
1195 EXPECT_TRUE(d1
.entered());
1196 EXPECT_TRUE(d1
.exited());
1197 EXPECT_TRUE(d2
.entered());
1198 EXPECT_FALSE(d2
.exited());
1201 TEST_F(WindowTest
, MouseEnterExitWhenDeleteWithCapture
) {
1202 MouseEnterExitWindowDelegate delegate
;
1203 scoped_ptr
<Window
> window(
1204 CreateTestWindowWithDelegate(&delegate
, 1, gfx::Rect(10, 10, 50, 50),
1207 ui::test::EventGenerator
generator(root_window());
1208 generator
.MoveMouseToCenterOf(window
.get());
1209 EXPECT_TRUE(delegate
.entered());
1210 EXPECT_FALSE(delegate
.exited());
1212 // Emmulate what Views does on a click by grabbing and releasing capture.
1213 generator
.PressLeftButton();
1214 window
->SetCapture();
1216 delegate
.ResetExpectations();
1217 generator
.MoveMouseTo(0, 0);
1218 EXPECT_FALSE(delegate
.entered());
1219 EXPECT_FALSE(delegate
.exited());
1221 delegate
.ResetExpectations();
1223 EXPECT_FALSE(delegate
.entered());
1224 EXPECT_FALSE(delegate
.exited());
1227 // Verifies that enter / exits are sent if windows appear and are deleted
1228 // under the current mouse position..
1229 TEST_F(WindowTest
, MouseEnterExitWithDelete
) {
1230 MouseEnterExitWindowDelegate d1
;
1231 scoped_ptr
<Window
> w1(
1232 CreateTestWindowWithDelegate(&d1
, 1, gfx::Rect(10, 10, 50, 50),
1235 ui::test::EventGenerator
generator(root_window());
1236 generator
.MoveMouseToCenterOf(w1
.get());
1237 EXPECT_TRUE(d1
.entered());
1238 EXPECT_FALSE(d1
.exited());
1239 d1
.ResetExpectations();
1241 MouseEnterExitWindowDelegate d2
;
1243 scoped_ptr
<Window
> w2(
1244 CreateTestWindowWithDelegate(&d2
, 2, gfx::Rect(10, 10, 50, 50),
1246 // Enters / exits can be sent asynchronously.
1247 RunAllPendingInMessageLoop();
1248 EXPECT_FALSE(d1
.entered());
1249 EXPECT_TRUE(d1
.exited());
1250 EXPECT_TRUE(d2
.entered());
1251 EXPECT_FALSE(d2
.exited());
1252 d1
.ResetExpectations();
1253 d2
.ResetExpectations();
1255 // Enters / exits can be sent asynchronously.
1256 RunAllPendingInMessageLoop();
1257 EXPECT_TRUE(d2
.exited());
1258 EXPECT_TRUE(d1
.entered());
1261 // Verifies that enter / exits are sent if windows appear and are hidden
1262 // under the current mouse position..
1263 TEST_F(WindowTest
, MouseEnterExitWithHide
) {
1264 MouseEnterExitWindowDelegate d1
;
1265 scoped_ptr
<Window
> w1(
1266 CreateTestWindowWithDelegate(&d1
, 1, gfx::Rect(10, 10, 50, 50),
1269 ui::test::EventGenerator
generator(root_window());
1270 generator
.MoveMouseToCenterOf(w1
.get());
1271 EXPECT_TRUE(d1
.entered());
1272 EXPECT_FALSE(d1
.exited());
1274 MouseEnterExitWindowDelegate d2
;
1275 scoped_ptr
<Window
> w2(
1276 CreateTestWindowWithDelegate(&d2
, 2, gfx::Rect(10, 10, 50, 50),
1278 // Enters / exits can be send asynchronously.
1279 RunAllPendingInMessageLoop();
1280 EXPECT_TRUE(d1
.entered());
1281 EXPECT_TRUE(d1
.exited());
1282 EXPECT_TRUE(d2
.entered());
1283 EXPECT_FALSE(d2
.exited());
1285 d1
.ResetExpectations();
1287 // Enters / exits can be send asynchronously.
1288 RunAllPendingInMessageLoop();
1289 EXPECT_TRUE(d2
.exited());
1290 EXPECT_TRUE(d1
.entered());
1293 TEST_F(WindowTest
, MouseEnterExitWithParentHide
) {
1294 MouseEnterExitWindowDelegate d1
;
1295 scoped_ptr
<Window
> w1(
1296 CreateTestWindowWithDelegate(&d1
, 1, gfx::Rect(10, 10, 50, 50),
1298 MouseEnterExitWindowDelegate d2
;
1299 Window
* w2
= CreateTestWindowWithDelegate(&d2
, 2, gfx::Rect(10, 10, 50, 50),
1301 ui::test::EventGenerator
generator(root_window());
1302 generator
.MoveMouseToCenterOf(w2
);
1303 // Enters / exits can be send asynchronously.
1304 RunAllPendingInMessageLoop();
1305 EXPECT_TRUE(d2
.entered());
1306 EXPECT_FALSE(d2
.exited());
1308 d2
.ResetExpectations();
1310 RunAllPendingInMessageLoop();
1311 EXPECT_FALSE(d2
.entered());
1312 EXPECT_TRUE(d2
.exited());
1317 TEST_F(WindowTest
, MouseEnterExitWithParentDelete
) {
1318 MouseEnterExitWindowDelegate d1
;
1319 scoped_ptr
<Window
> w1(
1320 CreateTestWindowWithDelegate(&d1
, 1, gfx::Rect(10, 10, 50, 50),
1322 MouseEnterExitWindowDelegate d2
;
1323 Window
* w2
= CreateTestWindowWithDelegate(&d2
, 2, gfx::Rect(10, 10, 50, 50),
1325 ui::test::EventGenerator
generator(root_window());
1326 generator
.MoveMouseToCenterOf(w2
);
1328 // Enters / exits can be send asynchronously.
1329 RunAllPendingInMessageLoop();
1330 EXPECT_TRUE(d2
.entered());
1331 EXPECT_FALSE(d2
.exited());
1333 d2
.ResetExpectations();
1335 RunAllPendingInMessageLoop();
1336 EXPECT_FALSE(d2
.entered());
1337 EXPECT_TRUE(d2
.exited());
1340 // Creates a window with a delegate (w111) that can handle events at a lower
1341 // z-index than a window without a delegate (w12). w12 is sized to fill the
1342 // entire bounds of the container. This test verifies that
1343 // GetEventHandlerForPoint() skips w12 even though its bounds contain the event,
1344 // because it has no children that can handle the event and it has no delegate
1345 // allowing it to handle the event itself.
1346 TEST_F(WindowTest
, GetEventHandlerForPoint_NoDelegate
) {
1347 TestWindowDelegate d111
;
1348 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(NULL
, 1,
1349 gfx::Rect(0, 0, 500, 500), root_window()));
1350 scoped_ptr
<Window
> w11(CreateTestWindowWithDelegate(NULL
, 11,
1351 gfx::Rect(0, 0, 500, 500), w1
.get()));
1352 scoped_ptr
<Window
> w111(CreateTestWindowWithDelegate(&d111
, 111,
1353 gfx::Rect(50, 50, 450, 450), w11
.get()));
1354 scoped_ptr
<Window
> w12(CreateTestWindowWithDelegate(NULL
, 12,
1355 gfx::Rect(0, 0, 500, 500), w1
.get()));
1357 gfx::Point target_point
= w111
->bounds().CenterPoint();
1358 EXPECT_EQ(w111
.get(), w1
->GetEventHandlerForPoint(target_point
));
1361 class VisibilityWindowDelegate
: public TestWindowDelegate
{
1363 VisibilityWindowDelegate()
1368 int shown() const { return shown_
; }
1369 int hidden() const { return hidden_
; }
1375 virtual void OnWindowTargetVisibilityChanged(bool visible
) OVERRIDE
{
1386 DISALLOW_COPY_AND_ASSIGN(VisibilityWindowDelegate
);
1389 // Verifies show/hide propagate correctly to children and the layer.
1390 TEST_F(WindowTest
, Visibility
) {
1391 VisibilityWindowDelegate d
;
1392 VisibilityWindowDelegate d2
;
1393 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(&d
, 1, gfx::Rect(),
1395 scoped_ptr
<Window
> w2(
1396 CreateTestWindowWithDelegate(&d2
, 2, gfx::Rect(), w1
.get()));
1397 scoped_ptr
<Window
> w3(CreateTestWindowWithId(3, w2
.get()));
1399 // Create shows all the windows.
1400 EXPECT_TRUE(w1
->IsVisible());
1401 EXPECT_TRUE(w2
->IsVisible());
1402 EXPECT_TRUE(w3
->IsVisible());
1403 EXPECT_EQ(1, d
.shown());
1407 EXPECT_FALSE(w1
->IsVisible());
1408 EXPECT_FALSE(w2
->IsVisible());
1409 EXPECT_FALSE(w3
->IsVisible());
1410 EXPECT_EQ(1, d
.hidden());
1411 EXPECT_EQ(0, d
.shown());
1414 EXPECT_FALSE(w1
->IsVisible());
1415 EXPECT_FALSE(w2
->IsVisible());
1416 EXPECT_FALSE(w3
->IsVisible());
1419 EXPECT_FALSE(w1
->IsVisible());
1420 EXPECT_FALSE(w2
->IsVisible());
1421 EXPECT_FALSE(w3
->IsVisible());
1425 EXPECT_TRUE(w1
->IsVisible());
1426 EXPECT_TRUE(w2
->IsVisible());
1427 EXPECT_FALSE(w3
->IsVisible());
1428 EXPECT_EQ(0, d
.hidden());
1429 EXPECT_EQ(1, d
.shown());
1432 EXPECT_TRUE(w1
->IsVisible());
1433 EXPECT_TRUE(w2
->IsVisible());
1434 EXPECT_TRUE(w3
->IsVisible());
1436 // Verify that if an ancestor isn't visible and we change the visibility of a
1437 // child window that OnChildWindowVisibilityChanged() is still invoked.
1441 EXPECT_EQ(1, d2
.hidden());
1442 EXPECT_EQ(0, d2
.shown());
1445 EXPECT_EQ(0, d2
.hidden());
1446 EXPECT_EQ(1, d2
.shown());
1449 TEST_F(WindowTest
, IgnoreEventsTest
) {
1450 TestWindowDelegate d11
;
1451 TestWindowDelegate d12
;
1452 TestWindowDelegate d111
;
1453 TestWindowDelegate d121
;
1454 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(NULL
, 1,
1455 gfx::Rect(0, 0, 500, 500), root_window()));
1456 scoped_ptr
<Window
> w11(CreateTestWindowWithDelegate(&d11
, 11,
1457 gfx::Rect(0, 0, 500, 500), w1
.get()));
1458 scoped_ptr
<Window
> w111(CreateTestWindowWithDelegate(&d111
, 111,
1459 gfx::Rect(50, 50, 450, 450), w11
.get()));
1460 scoped_ptr
<Window
> w12(CreateTestWindowWithDelegate(&d12
, 12,
1461 gfx::Rect(0, 0, 500, 500), w1
.get()));
1462 scoped_ptr
<Window
> w121(CreateTestWindowWithDelegate(&d121
, 121,
1463 gfx::Rect(150, 150, 50, 50), w12
.get()));
1465 EXPECT_EQ(w12
.get(), w1
->GetEventHandlerForPoint(gfx::Point(10, 10)));
1466 w12
->set_ignore_events(true);
1467 EXPECT_EQ(w11
.get(), w1
->GetEventHandlerForPoint(gfx::Point(10, 10)));
1468 w12
->set_ignore_events(false);
1470 EXPECT_EQ(w121
.get(), w1
->GetEventHandlerForPoint(gfx::Point(160, 160)));
1471 w121
->set_ignore_events(true);
1472 EXPECT_EQ(w12
.get(), w1
->GetEventHandlerForPoint(gfx::Point(160, 160)));
1473 w12
->set_ignore_events(true);
1474 EXPECT_EQ(w111
.get(), w1
->GetEventHandlerForPoint(gfx::Point(160, 160)));
1475 w111
->set_ignore_events(true);
1476 EXPECT_EQ(w11
.get(), w1
->GetEventHandlerForPoint(gfx::Point(160, 160)));
1479 // Tests transformation on the root window.
1480 TEST_F(WindowTest
, Transform
) {
1481 gfx::Size size
= host()->GetBounds().size();
1482 EXPECT_EQ(gfx::Rect(size
),
1483 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1484 gfx::Point()).bounds());
1486 // Rotate it clock-wise 90 degrees.
1487 gfx::Transform transform
;
1488 transform
.Translate(size
.height(), 0);
1489 transform
.Rotate(90.0);
1490 host()->SetRootTransform(transform
);
1492 // The size should be the transformed size.
1493 gfx::Size
transformed_size(size
.height(), size
.width());
1494 EXPECT_EQ(transformed_size
.ToString(),
1495 root_window()->bounds().size().ToString());
1497 gfx::Rect(transformed_size
).ToString(),
1498 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1499 gfx::Point()).bounds().ToString());
1501 // Host size shouldn't change.
1502 EXPECT_EQ(size
.ToString(), host()->GetBounds().size().ToString());
1505 TEST_F(WindowTest
, TransformGesture
) {
1506 gfx::Size size
= host()->GetBounds().size();
1508 scoped_ptr
<GestureTrackPositionDelegate
> delegate(
1509 new GestureTrackPositionDelegate
);
1510 scoped_ptr
<Window
> window(CreateTestWindowWithDelegate(delegate
.get(), -1234,
1511 gfx::Rect(0, 0, 20, 20), root_window()));
1513 // Rotate the root-window clock-wise 90 degrees.
1514 gfx::Transform transform
;
1515 transform
.Translate(size
.height(), 0.0);
1516 transform
.Rotate(90.0);
1517 host()->SetRootTransform(transform
);
1519 ui::TouchEvent
press(
1520 ui::ET_TOUCH_PRESSED
, gfx::Point(size
.height() - 10, 10), 0, getTime());
1521 DispatchEventUsingWindowDispatcher(&press
);
1522 EXPECT_EQ(gfx::Point(10, 10).ToString(), delegate
->position().ToString());
1526 DEFINE_WINDOW_PROPERTY_KEY(int, kIntKey
, -2);
1527 DEFINE_WINDOW_PROPERTY_KEY(const char*, kStringKey
, "squeamish");
1530 TEST_F(WindowTest
, Property
) {
1531 scoped_ptr
<Window
> w(CreateTestWindowWithId(0, root_window()));
1533 static const char native_prop_key
[] = "fnord";
1535 // Non-existent properties should return the default values.
1536 EXPECT_EQ(-2, w
->GetProperty(kIntKey
));
1537 EXPECT_EQ(std::string("squeamish"), w
->GetProperty(kStringKey
));
1538 EXPECT_EQ(NULL
, w
->GetNativeWindowProperty(native_prop_key
));
1540 // A set property value should be returned again (even if it's the default
1542 w
->SetProperty(kIntKey
, INT_MAX
);
1543 EXPECT_EQ(INT_MAX
, w
->GetProperty(kIntKey
));
1544 w
->SetProperty(kIntKey
, -2);
1545 EXPECT_EQ(-2, w
->GetProperty(kIntKey
));
1546 w
->SetProperty(kIntKey
, INT_MIN
);
1547 EXPECT_EQ(INT_MIN
, w
->GetProperty(kIntKey
));
1549 w
->SetProperty(kStringKey
, static_cast<const char*>(NULL
));
1550 EXPECT_EQ(NULL
, w
->GetProperty(kStringKey
));
1551 w
->SetProperty(kStringKey
, "squeamish");
1552 EXPECT_EQ(std::string("squeamish"), w
->GetProperty(kStringKey
));
1553 w
->SetProperty(kStringKey
, "ossifrage");
1554 EXPECT_EQ(std::string("ossifrage"), w
->GetProperty(kStringKey
));
1556 w
->SetNativeWindowProperty(native_prop_key
, &*w
);
1557 EXPECT_EQ(&*w
, w
->GetNativeWindowProperty(native_prop_key
));
1558 w
->SetNativeWindowProperty(native_prop_key
, NULL
);
1559 EXPECT_EQ(NULL
, w
->GetNativeWindowProperty(native_prop_key
));
1561 // ClearProperty should restore the default value.
1562 w
->ClearProperty(kIntKey
);
1563 EXPECT_EQ(-2, w
->GetProperty(kIntKey
));
1564 w
->ClearProperty(kStringKey
);
1565 EXPECT_EQ(std::string("squeamish"), w
->GetProperty(kStringKey
));
1570 class TestProperty
{
1573 virtual ~TestProperty() {
1574 last_deleted_
= this;
1576 static TestProperty
* last_deleted() { return last_deleted_
; }
1579 static TestProperty
* last_deleted_
;
1580 DISALLOW_COPY_AND_ASSIGN(TestProperty
);
1583 TestProperty
* TestProperty::last_deleted_
= NULL
;
1585 DEFINE_OWNED_WINDOW_PROPERTY_KEY(TestProperty
, kOwnedKey
, NULL
);
1589 TEST_F(WindowTest
, OwnedProperty
) {
1590 scoped_ptr
<Window
> w(CreateTestWindowWithId(0, root_window()));
1591 EXPECT_EQ(NULL
, w
->GetProperty(kOwnedKey
));
1592 TestProperty
* p1
= new TestProperty();
1593 w
->SetProperty(kOwnedKey
, p1
);
1594 EXPECT_EQ(p1
, w
->GetProperty(kOwnedKey
));
1595 EXPECT_EQ(NULL
, TestProperty::last_deleted());
1597 TestProperty
* p2
= new TestProperty();
1598 w
->SetProperty(kOwnedKey
, p2
);
1599 EXPECT_EQ(p2
, w
->GetProperty(kOwnedKey
));
1600 EXPECT_EQ(p1
, TestProperty::last_deleted());
1602 w
->ClearProperty(kOwnedKey
);
1603 EXPECT_EQ(NULL
, w
->GetProperty(kOwnedKey
));
1604 EXPECT_EQ(p2
, TestProperty::last_deleted());
1606 TestProperty
* p3
= new TestProperty();
1607 w
->SetProperty(kOwnedKey
, p3
);
1608 EXPECT_EQ(p3
, w
->GetProperty(kOwnedKey
));
1609 EXPECT_EQ(p2
, TestProperty::last_deleted());
1611 EXPECT_EQ(p3
, TestProperty::last_deleted());
1614 TEST_F(WindowTest
, SetBoundsInternalShouldCheckTargetBounds
) {
1615 // We cannot short-circuit animations in this test.
1616 ui::ScopedAnimationDurationScaleMode
test_duration_mode(
1617 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION
);
1619 scoped_ptr
<Window
> w1(
1620 CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), root_window()));
1622 EXPECT_FALSE(!w1
->layer());
1623 w1
->layer()->GetAnimator()->set_disable_timer_for_test(true);
1624 ui::LayerAnimator
* animator
= w1
->layer()->GetAnimator();
1626 EXPECT_EQ("0,0 100x100", w1
->bounds().ToString());
1627 EXPECT_EQ("0,0 100x100", w1
->layer()->GetTargetBounds().ToString());
1629 // Animate to a different position.
1631 ui::ScopedLayerAnimationSettings
settings(w1
->layer()->GetAnimator());
1632 w1
->SetBounds(gfx::Rect(100, 100, 100, 100));
1635 EXPECT_EQ("0,0 100x100", w1
->bounds().ToString());
1636 EXPECT_EQ("100,100 100x100", w1
->layer()->GetTargetBounds().ToString());
1638 // Animate back to the first position. The animation hasn't started yet, so
1639 // the current bounds are still (0, 0, 100, 100), but the target bounds are
1640 // (100, 100, 100, 100). If we step the animator ahead, we should find that
1641 // we're at (0, 0, 100, 100). That is, the second animation should be applied.
1643 ui::ScopedLayerAnimationSettings
settings(w1
->layer()->GetAnimator());
1644 w1
->SetBounds(gfx::Rect(0, 0, 100, 100));
1647 EXPECT_EQ("0,0 100x100", w1
->bounds().ToString());
1648 EXPECT_EQ("0,0 100x100", w1
->layer()->GetTargetBounds().ToString());
1650 // Confirm that the target bounds are reached.
1651 base::TimeTicks start_time
=
1652 w1
->layer()->GetAnimator()->last_step_time();
1654 animator
->Step(start_time
+ base::TimeDelta::FromMilliseconds(1000));
1656 EXPECT_EQ("0,0 100x100", w1
->bounds().ToString());
1660 typedef std::pair
<const void*, intptr_t> PropertyChangeInfo
;
1662 class WindowObserverTest
: public WindowTest
,
1663 public WindowObserver
{
1665 struct VisibilityInfo
{
1666 bool window_visible
;
1670 WindowObserverTest()
1673 destroyed_count_(0),
1674 old_property_value_(-3) {
1677 virtual ~WindowObserverTest() {}
1679 const VisibilityInfo
* GetVisibilityInfo() const {
1680 return visibility_info_
.get();
1683 void ResetVisibilityInfo() {
1684 visibility_info_
.reset();
1687 // Returns a description of the WindowObserver methods that have been invoked.
1688 std::string
WindowObserverCountStateAndClear() {
1690 base::StringPrintf("added=%d removed=%d",
1691 added_count_
, removed_count_
));
1692 added_count_
= removed_count_
= 0;
1696 int DestroyedCountAndClear() {
1697 int result
= destroyed_count_
;
1698 destroyed_count_
= 0;
1702 // Return a tuple of the arguments passed in OnPropertyChanged callback.
1703 PropertyChangeInfo
PropertyChangeInfoAndClear() {
1704 PropertyChangeInfo
result(property_key_
, old_property_value_
);
1705 property_key_
= NULL
;
1706 old_property_value_
= -3;
1711 virtual void OnWindowAdded(Window
* new_window
) OVERRIDE
{
1715 virtual void OnWillRemoveWindow(Window
* window
) OVERRIDE
{
1719 virtual void OnWindowVisibilityChanged(Window
* window
,
1720 bool visible
) OVERRIDE
{
1721 visibility_info_
.reset(new VisibilityInfo
);
1722 visibility_info_
->window_visible
= window
->IsVisible();
1723 visibility_info_
->visible_param
= visible
;
1726 virtual void OnWindowDestroyed(Window
* window
) OVERRIDE
{
1727 EXPECT_FALSE(window
->parent());
1731 virtual void OnWindowPropertyChanged(Window
* window
,
1733 intptr_t old
) OVERRIDE
{
1734 property_key_
= key
;
1735 old_property_value_
= old
;
1740 int destroyed_count_
;
1741 scoped_ptr
<VisibilityInfo
> visibility_info_
;
1742 const void* property_key_
;
1743 intptr_t old_property_value_
;
1745 DISALLOW_COPY_AND_ASSIGN(WindowObserverTest
);
1748 // Various assertions for WindowObserver.
1749 TEST_F(WindowObserverTest
, WindowObserver
) {
1750 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
1751 w1
->AddObserver(this);
1753 // Create a new window as a child of w1, our observer should be notified.
1754 scoped_ptr
<Window
> w2(CreateTestWindowWithId(2, w1
.get()));
1755 EXPECT_EQ("added=1 removed=0", WindowObserverCountStateAndClear());
1757 // Delete w2, which should result in the remove notification.
1759 EXPECT_EQ("added=0 removed=1", WindowObserverCountStateAndClear());
1761 // Create a window that isn't parented to w1, we shouldn't get any
1763 scoped_ptr
<Window
> w3(CreateTestWindowWithId(3, root_window()));
1764 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1766 // Similarly destroying w3 shouldn't notify us either.
1768 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1769 w1
->RemoveObserver(this);
1772 // Test if OnWindowVisibilityChagned is invoked with expected
1774 TEST_F(WindowObserverTest
, WindowVisibility
) {
1775 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
1776 scoped_ptr
<Window
> w2(CreateTestWindowWithId(1, w1
.get()));
1777 w2
->AddObserver(this);
1779 // Hide should make the window invisible and the passed visible
1780 // parameter is false.
1782 EXPECT_FALSE(!GetVisibilityInfo());
1783 EXPECT_FALSE(!GetVisibilityInfo());
1784 if (!GetVisibilityInfo())
1786 EXPECT_FALSE(GetVisibilityInfo()->window_visible
);
1787 EXPECT_FALSE(GetVisibilityInfo()->visible_param
);
1789 // If parent isn't visible, showing window won't make the window visible, but
1790 // passed visible value must be true.
1792 ResetVisibilityInfo();
1793 EXPECT_TRUE(!GetVisibilityInfo());
1795 EXPECT_FALSE(!GetVisibilityInfo());
1796 if (!GetVisibilityInfo())
1798 EXPECT_FALSE(GetVisibilityInfo()->window_visible
);
1799 EXPECT_TRUE(GetVisibilityInfo()->visible_param
);
1801 // If parent is visible, showing window will make the window
1802 // visible and the passed visible value is true.
1805 ResetVisibilityInfo();
1807 EXPECT_FALSE(!GetVisibilityInfo());
1808 if (!GetVisibilityInfo())
1810 EXPECT_TRUE(GetVisibilityInfo()->window_visible
);
1811 EXPECT_TRUE(GetVisibilityInfo()->visible_param
);
1814 // Test if OnWindowDestroyed is invoked as expected.
1815 TEST_F(WindowObserverTest
, WindowDestroyed
) {
1816 // Delete a window should fire a destroyed notification.
1817 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
1818 w1
->AddObserver(this);
1820 EXPECT_EQ(1, DestroyedCountAndClear());
1822 // Observe on child and delete parent window should fire a notification.
1823 scoped_ptr
<Window
> parent(CreateTestWindowWithId(1, root_window()));
1824 Window
* child
= CreateTestWindowWithId(1, parent
.get()); // owned by parent
1825 child
->AddObserver(this);
1827 EXPECT_EQ(1, DestroyedCountAndClear());
1830 TEST_F(WindowObserverTest
, PropertyChanged
) {
1831 // Setting property should fire a property change notification.
1832 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
1833 w1
->AddObserver(this);
1835 static const WindowProperty
<int> prop
= {-2};
1836 static const char native_prop_key
[] = "fnord";
1838 w1
->SetProperty(&prop
, 1);
1839 EXPECT_EQ(PropertyChangeInfo(&prop
, -2), PropertyChangeInfoAndClear());
1840 w1
->SetProperty(&prop
, -2);
1841 EXPECT_EQ(PropertyChangeInfo(&prop
, 1), PropertyChangeInfoAndClear());
1842 w1
->SetProperty(&prop
, 3);
1843 EXPECT_EQ(PropertyChangeInfo(&prop
, -2), PropertyChangeInfoAndClear());
1844 w1
->ClearProperty(&prop
);
1845 EXPECT_EQ(PropertyChangeInfo(&prop
, 3), PropertyChangeInfoAndClear());
1847 w1
->SetNativeWindowProperty(native_prop_key
, &*w1
);
1848 EXPECT_EQ(PropertyChangeInfo(native_prop_key
, 0),
1849 PropertyChangeInfoAndClear());
1850 w1
->SetNativeWindowProperty(native_prop_key
, NULL
);
1851 EXPECT_EQ(PropertyChangeInfo(native_prop_key
,
1852 reinterpret_cast<intptr_t>(&*w1
)),
1853 PropertyChangeInfoAndClear());
1855 // Sanity check to see if |PropertyChangeInfoAndClear| really clears.
1856 EXPECT_EQ(PropertyChangeInfo(
1857 reinterpret_cast<const void*>(NULL
), -3), PropertyChangeInfoAndClear());
1860 TEST_F(WindowTest
, AcquireLayer
) {
1861 scoped_ptr
<Window
> window1(CreateTestWindowWithId(1, root_window()));
1862 scoped_ptr
<Window
> window2(CreateTestWindowWithId(2, root_window()));
1863 ui::Layer
* parent
= window1
->parent()->layer();
1864 EXPECT_EQ(2U, parent
->children().size());
1866 WindowTestApi
window1_test_api(window1
.get());
1867 WindowTestApi
window2_test_api(window2
.get());
1869 EXPECT_TRUE(window1_test_api
.OwnsLayer());
1870 EXPECT_TRUE(window2_test_api
.OwnsLayer());
1872 // After acquisition, window1 should not own its layer, but it should still
1873 // be available to the window.
1874 scoped_ptr
<ui::Layer
> window1_layer(window1
->AcquireLayer());
1875 EXPECT_FALSE(window1_test_api
.OwnsLayer());
1876 EXPECT_TRUE(window1_layer
.get() == window1
->layer());
1878 // The acquired layer's owner should be set NULL and re-acquring
1879 // should return NULL.
1880 EXPECT_FALSE(window1_layer
->owner());
1881 scoped_ptr
<ui::Layer
> window1_layer_reacquired(window1
->AcquireLayer());
1882 EXPECT_FALSE(window1_layer_reacquired
.get());
1884 // Upon destruction, window1's layer should still be valid, and in the layer
1885 // hierarchy, but window2's should be gone, and no longer in the hierarchy.
1889 // This should be set by the window's destructor.
1890 EXPECT_TRUE(window1_layer
->delegate() == NULL
);
1891 EXPECT_EQ(1U, parent
->children().size());
1894 // Make sure that properties which should persist from the old layer to the new
1895 // layer actually do.
1896 TEST_F(WindowTest
, RecreateLayer
) {
1897 // Set properties to non default values.
1898 Window
w(new ColorTestWindowDelegate(SK_ColorWHITE
));
1900 w
.Init(aura::WINDOW_LAYER_SOLID_COLOR
);
1901 w
.SetBounds(gfx::Rect(0, 0, 100, 100));
1903 ui::Layer
* layer
= w
.layer();
1904 layer
->SetVisible(false);
1905 layer
->SetMasksToBounds(true);
1907 ui::Layer child_layer
;
1908 layer
->Add(&child_layer
);
1910 scoped_ptr
<ui::Layer
> old_layer(w
.RecreateLayer());
1912 EXPECT_EQ(ui::LAYER_SOLID_COLOR
, layer
->type());
1913 EXPECT_FALSE(layer
->visible());
1914 EXPECT_EQ(1u, layer
->children().size());
1915 EXPECT_TRUE(layer
->GetMasksToBounds());
1916 EXPECT_EQ("0,0 100x100", w
.bounds().ToString());
1917 EXPECT_EQ("0,0 100x100", layer
->bounds().ToString());
1920 // Verify that RecreateLayer() stacks the old layer above the newly creatd
1922 TEST_F(WindowTest
, RecreateLayerZOrder
) {
1923 scoped_ptr
<Window
> w(
1924 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(0, 0, 100, 100),
1926 scoped_ptr
<ui::Layer
> old_layer(w
->RecreateLayer());
1928 const std::vector
<ui::Layer
*>& child_layers
=
1929 root_window()->layer()->children();
1930 ASSERT_EQ(2u, child_layers
.size());
1931 EXPECT_EQ(w
->layer(), child_layers
[0]);
1932 EXPECT_EQ(old_layer
.get(), child_layers
[1]);
1935 // Ensure that acquiring a layer then recreating a layer does not crash
1936 // and that RecreateLayer returns null.
1937 TEST_F(WindowTest
, AcquireThenRecreateLayer
) {
1938 scoped_ptr
<Window
> w(
1939 CreateTestWindow(SK_ColorWHITE
, 1, gfx::Rect(0, 0, 100, 100),
1941 scoped_ptr
<ui::Layer
> acquired_layer(w
->AcquireLayer());
1942 scoped_ptr
<ui::Layer
> doubly_acquired_layer(w
->RecreateLayer());
1943 EXPECT_EQ(NULL
, doubly_acquired_layer
.get());
1945 // Destroy window before layer gets destroyed.
1949 TEST_F(WindowTest
, StackWindowAtBottomBelowWindowWhoseLayerHasNoDelegate
) {
1950 scoped_ptr
<Window
> window1(CreateTestWindowWithId(1, root_window()));
1951 window1
->layer()->set_name("1");
1952 scoped_ptr
<Window
> window2(CreateTestWindowWithId(2, root_window()));
1953 window2
->layer()->set_name("2");
1954 scoped_ptr
<Window
> window3(CreateTestWindowWithId(3, root_window()));
1955 window3
->layer()->set_name("3");
1957 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(root_window()));
1959 ui::test::ChildLayerNamesAsString(*root_window()->layer()));
1960 window1
->layer()->set_delegate(NULL
);
1961 root_window()->StackChildAtBottom(window3
.get());
1963 // Window 3 should have moved to the bottom.
1964 EXPECT_EQ("3 1 2", ChildWindowIDsAsString(root_window()));
1966 ui::test::ChildLayerNamesAsString(*root_window()->layer()));
1969 class TestVisibilityClient
: public client::VisibilityClient
{
1971 explicit TestVisibilityClient(Window
* root_window
)
1972 : ignore_visibility_changes_(false) {
1973 client::SetVisibilityClient(root_window
, this);
1975 virtual ~TestVisibilityClient() {
1978 void set_ignore_visibility_changes(bool ignore_visibility_changes
) {
1979 ignore_visibility_changes_
= ignore_visibility_changes
;
1982 // Overridden from client::VisibilityClient:
1983 virtual void UpdateLayerVisibility(aura::Window
* window
,
1984 bool visible
) OVERRIDE
{
1985 if (!ignore_visibility_changes_
)
1986 window
->layer()->SetVisible(visible
);
1990 bool ignore_visibility_changes_
;
1991 DISALLOW_COPY_AND_ASSIGN(TestVisibilityClient
);
1994 TEST_F(WindowTest
, VisibilityClientIsVisible
) {
1995 TestVisibilityClient
client(root_window());
1997 scoped_ptr
<Window
> window(CreateTestWindowWithId(1, root_window()));
1998 EXPECT_TRUE(window
->IsVisible());
1999 EXPECT_TRUE(window
->layer()->visible());
2002 EXPECT_FALSE(window
->IsVisible());
2003 EXPECT_FALSE(window
->layer()->visible());
2006 client
.set_ignore_visibility_changes(true);
2008 EXPECT_FALSE(window
->IsVisible());
2009 EXPECT_TRUE(window
->layer()->visible());
2012 // Tests mouse events on window change.
2013 TEST_F(WindowTest
, MouseEventsOnWindowChange
) {
2014 gfx::Size size
= host()->GetBounds().size();
2016 ui::test::EventGenerator
generator(root_window());
2017 generator
.MoveMouseTo(50, 50);
2019 EventCountDelegate d1
;
2020 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(&d1
, 1,
2021 gfx::Rect(0, 0, 100, 100), root_window()));
2022 RunAllPendingInMessageLoop();
2023 // The format of result is "Enter/Mouse/Leave".
2024 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2026 // Adding new window.
2027 EventCountDelegate d11
;
2028 scoped_ptr
<Window
> w11(CreateTestWindowWithDelegate(
2029 &d11
, 1, gfx::Rect(0, 0, 100, 100), w1
.get()));
2030 RunAllPendingInMessageLoop();
2031 EXPECT_EQ("0 0 1", d1
.GetMouseMotionCountsAndReset());
2032 EXPECT_EQ("1 1 0", d11
.GetMouseMotionCountsAndReset());
2035 w11
->SetBounds(gfx::Rect(0, 0, 10, 10));
2036 RunAllPendingInMessageLoop();
2037 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2038 EXPECT_EQ("0 0 1", d11
.GetMouseMotionCountsAndReset());
2040 w11
->SetBounds(gfx::Rect(0, 0, 60, 60));
2041 RunAllPendingInMessageLoop();
2042 EXPECT_EQ("0 0 1", d1
.GetMouseMotionCountsAndReset());
2043 EXPECT_EQ("1 1 0", d11
.GetMouseMotionCountsAndReset());
2045 // Detach, then re-attach.
2046 w1
->RemoveChild(w11
.get());
2047 RunAllPendingInMessageLoop();
2048 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2049 // Window is detached, so no event is set.
2050 EXPECT_EQ("0 0 1", d11
.GetMouseMotionCountsAndReset());
2052 w1
->AddChild(w11
.get());
2053 RunAllPendingInMessageLoop();
2054 EXPECT_EQ("0 0 1", d1
.GetMouseMotionCountsAndReset());
2055 // Window is detached, so no event is set.
2056 EXPECT_EQ("1 1 0", d11
.GetMouseMotionCountsAndReset());
2058 // Visibility Change
2060 RunAllPendingInMessageLoop();
2061 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2062 EXPECT_EQ("0 0 1", d11
.GetMouseMotionCountsAndReset());
2065 RunAllPendingInMessageLoop();
2066 EXPECT_EQ("0 0 1", d1
.GetMouseMotionCountsAndReset());
2067 EXPECT_EQ("1 1 0", d11
.GetMouseMotionCountsAndReset());
2069 // Transform: move d11 by 100 100.
2070 gfx::Transform transform
;
2071 transform
.Translate(100, 100);
2072 w11
->SetTransform(transform
);
2073 RunAllPendingInMessageLoop();
2074 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2075 EXPECT_EQ("0 0 1", d11
.GetMouseMotionCountsAndReset());
2077 w11
->SetTransform(gfx::Transform());
2078 RunAllPendingInMessageLoop();
2079 EXPECT_EQ("0 0 1", d1
.GetMouseMotionCountsAndReset());
2080 EXPECT_EQ("1 1 0", d11
.GetMouseMotionCountsAndReset());
2082 // Closing a window.
2084 RunAllPendingInMessageLoop();
2085 EXPECT_EQ("1 1 0", d1
.GetMouseMotionCountsAndReset());
2087 // Make sure we don't synthesize events if the mouse
2088 // is outside of the root window.
2089 generator
.MoveMouseTo(-10, -10);
2090 EXPECT_EQ("0 0 1", d1
.GetMouseMotionCountsAndReset());
2092 // Adding new windows.
2093 w11
.reset(CreateTestWindowWithDelegate(
2094 &d11
, 1, gfx::Rect(0, 0, 100, 100), w1
.get()));
2095 RunAllPendingInMessageLoop();
2096 EXPECT_EQ("0 0 0", d1
.GetMouseMotionCountsAndReset());
2097 EXPECT_EQ("0 0 1", d11
.GetMouseMotionCountsAndReset());
2101 RunAllPendingInMessageLoop();
2102 EXPECT_EQ("0 0 0", d1
.GetMouseMotionCountsAndReset());
2103 EXPECT_EQ("0 0 0", d11
.GetMouseMotionCountsAndReset());
2106 class RootWindowAttachmentObserver
: public WindowObserver
{
2108 RootWindowAttachmentObserver() : added_count_(0), removed_count_(0) {}
2109 virtual ~RootWindowAttachmentObserver() {}
2111 int added_count() const { return added_count_
; }
2112 int removed_count() const { return removed_count_
; }
2119 // Overridden from WindowObserver:
2120 virtual void OnWindowAddedToRootWindow(Window
* window
) OVERRIDE
{
2123 virtual void OnWindowRemovingFromRootWindow(Window
* window
,
2124 Window
* new_root
) OVERRIDE
{
2132 DISALLOW_COPY_AND_ASSIGN(RootWindowAttachmentObserver
);
2135 TEST_F(WindowTest
, RootWindowAttachment
) {
2136 RootWindowAttachmentObserver observer
;
2138 // Test a direct add/remove from the RootWindow.
2139 scoped_ptr
<Window
> w1(new Window(NULL
));
2140 w1
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2141 w1
->AddObserver(&observer
);
2143 ParentWindow(w1
.get());
2144 EXPECT_EQ(1, observer
.added_count());
2145 EXPECT_EQ(0, observer
.removed_count());
2148 EXPECT_EQ(1, observer
.added_count());
2149 EXPECT_EQ(1, observer
.removed_count());
2153 // Test an indirect add/remove from the RootWindow.
2154 w1
.reset(new Window(NULL
));
2155 w1
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2156 Window
* w11
= new Window(NULL
);
2157 w11
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2158 w11
->AddObserver(&observer
);
2160 EXPECT_EQ(0, observer
.added_count());
2161 EXPECT_EQ(0, observer
.removed_count());
2163 ParentWindow(w1
.get());
2164 EXPECT_EQ(1, observer
.added_count());
2165 EXPECT_EQ(0, observer
.removed_count());
2167 w1
.reset(); // Deletes w11.
2169 EXPECT_EQ(1, observer
.added_count());
2170 EXPECT_EQ(1, observer
.removed_count());
2174 // Test an indirect add/remove with nested observers.
2175 w1
.reset(new Window(NULL
));
2176 w1
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2177 w11
= new Window(NULL
);
2178 w11
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2179 w11
->AddObserver(&observer
);
2181 Window
* w111
= new Window(NULL
);
2182 w111
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2183 w111
->AddObserver(&observer
);
2184 w11
->AddChild(w111
);
2186 EXPECT_EQ(0, observer
.added_count());
2187 EXPECT_EQ(0, observer
.removed_count());
2189 ParentWindow(w1
.get());
2190 EXPECT_EQ(2, observer
.added_count());
2191 EXPECT_EQ(0, observer
.removed_count());
2193 w1
.reset(); // Deletes w11 and w111.
2196 EXPECT_EQ(2, observer
.added_count());
2197 EXPECT_EQ(2, observer
.removed_count());
2200 class BoundsChangedWindowObserver
: public WindowObserver
{
2202 BoundsChangedWindowObserver() : root_set_(false) {}
2204 virtual void OnWindowBoundsChanged(Window
* window
,
2205 const gfx::Rect
& old_bounds
,
2206 const gfx::Rect
& new_bounds
) OVERRIDE
{
2207 root_set_
= window
->GetRootWindow() != NULL
;
2210 bool root_set() const { return root_set_
; }
2215 DISALLOW_COPY_AND_ASSIGN(BoundsChangedWindowObserver
);
2218 TEST_F(WindowTest
, RootWindowSetWhenReparenting
) {
2219 Window
parent1(NULL
);
2220 parent1
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2221 Window
parent2(NULL
);
2222 parent2
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2223 ParentWindow(&parent1
);
2224 ParentWindow(&parent2
);
2225 parent1
.SetBounds(gfx::Rect(10, 10, 300, 300));
2226 parent2
.SetBounds(gfx::Rect(20, 20, 300, 300));
2228 BoundsChangedWindowObserver observer
;
2230 child
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2231 child
.SetBounds(gfx::Rect(5, 5, 100, 100));
2232 parent1
.AddChild(&child
);
2234 // We need animations to start in order to observe the bounds changes.
2235 ui::ScopedAnimationDurationScaleMode
test_duration_mode(
2236 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION
);
2237 ui::ScopedLayerAnimationSettings
settings1(child
.layer()->GetAnimator());
2238 settings1
.SetTransitionDuration(base::TimeDelta::FromMilliseconds(100));
2239 gfx::Rect
new_bounds(gfx::Rect(35, 35, 50, 50));
2240 child
.SetBounds(new_bounds
);
2242 child
.AddObserver(&observer
);
2244 // Reparenting the |child| will cause it to get moved. During this move
2245 // the window should still have root window set.
2246 parent2
.AddChild(&child
);
2247 EXPECT_TRUE(observer
.root_set());
2249 // Animations should stop and the bounds should be as set before the |child|
2251 EXPECT_EQ(new_bounds
.ToString(), child
.GetTargetBounds().ToString());
2252 EXPECT_EQ(new_bounds
.ToString(), child
.bounds().ToString());
2253 EXPECT_EQ("55,55 50x50", child
.GetBoundsInRootWindow().ToString());
2256 TEST_F(WindowTest
, OwnedByParentFalse
) {
2257 // By default, a window is owned by its parent. If this is set to false, the
2258 // window will not be destroyed when its parent is.
2260 scoped_ptr
<Window
> w1(new Window(NULL
));
2261 w1
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2262 scoped_ptr
<Window
> w2(new Window(NULL
));
2263 w2
->set_owned_by_parent(false);
2264 w2
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2265 w1
->AddChild(w2
.get());
2269 // We should be able to deref w2 still, but its parent should now be NULL.
2270 EXPECT_EQ(NULL
, w2
->parent());
2275 // Used By DeleteWindowFromOnWindowDestroyed. Destroys a Window from
2276 // OnWindowDestroyed().
2277 class OwningWindowDelegate
: public TestWindowDelegate
{
2279 OwningWindowDelegate() {}
2281 void SetOwnedWindow(Window
* window
) {
2282 owned_window_
.reset(window
);
2285 virtual void OnWindowDestroyed(Window
* window
) OVERRIDE
{
2286 owned_window_
.reset(NULL
);
2290 scoped_ptr
<Window
> owned_window_
;
2292 DISALLOW_COPY_AND_ASSIGN(OwningWindowDelegate
);
2297 // Creates a window with two child windows. When the first child window is
2298 // destroyed (WindowDelegate::OnWindowDestroyed) it deletes the second child.
2299 // This synthesizes BrowserView and the status bubble. Both are children of the
2300 // same parent and destroying BrowserView triggers it destroying the status
2302 TEST_F(WindowTest
, DeleteWindowFromOnWindowDestroyed
) {
2303 scoped_ptr
<Window
> parent(new Window(NULL
));
2304 parent
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2305 OwningWindowDelegate delegate
;
2306 Window
* c1
= new Window(&delegate
);
2307 c1
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2308 parent
->AddChild(c1
);
2309 Window
* c2
= new Window(NULL
);
2310 c2
->Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2311 parent
->AddChild(c2
);
2312 delegate
.SetOwnedWindow(c2
);
2318 // Used by DelegateNotifiedAsBoundsChange to verify OnBoundsChanged() is
2320 class BoundsChangeDelegate
: public TestWindowDelegate
{
2322 BoundsChangeDelegate() : bounds_changed_(false) {}
2324 void clear_bounds_changed() { bounds_changed_
= false; }
2325 bool bounds_changed() const {
2326 return bounds_changed_
;
2330 virtual void OnBoundsChanged(const gfx::Rect
& old_bounds
,
2331 const gfx::Rect
& new_bounds
) OVERRIDE
{
2332 bounds_changed_
= true;
2336 // Was OnBoundsChanged() invoked?
2337 bool bounds_changed_
;
2339 DISALLOW_COPY_AND_ASSIGN(BoundsChangeDelegate
);
2344 // Verifies the delegate is notified when the actual bounds of the layer
2346 TEST_F(WindowTest
, DelegateNotifiedAsBoundsChange
) {
2347 BoundsChangeDelegate delegate
;
2349 // We cannot short-circuit animations in this test.
2350 ui::ScopedAnimationDurationScaleMode
test_duration_mode(
2351 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION
);
2353 scoped_ptr
<Window
> window(
2354 CreateTestWindowWithDelegate(&delegate
, 1,
2355 gfx::Rect(0, 0, 100, 100), root_window()));
2356 window
->layer()->GetAnimator()->set_disable_timer_for_test(true);
2358 delegate
.clear_bounds_changed();
2360 // Animate to a different position.
2362 ui::ScopedLayerAnimationSettings
settings(window
->layer()->GetAnimator());
2363 window
->SetBounds(gfx::Rect(100, 100, 100, 100));
2366 // Bounds shouldn't immediately have changed.
2367 EXPECT_EQ("0,0 100x100", window
->bounds().ToString());
2368 EXPECT_FALSE(delegate
.bounds_changed());
2370 // Animate to the end, which should notify of the change.
2371 base::TimeTicks start_time
=
2372 window
->layer()->GetAnimator()->last_step_time();
2373 ui::LayerAnimator
* animator
= window
->layer()->GetAnimator();
2374 animator
->Step(start_time
+ base::TimeDelta::FromMilliseconds(1000));
2375 EXPECT_TRUE(delegate
.bounds_changed());
2376 EXPECT_NE("0,0 100x100", window
->bounds().ToString());
2379 // Verifies the delegate is notified when the actual bounds of the layer
2380 // change even when the window is not the layer's delegate
2381 TEST_F(WindowTest
, DelegateNotifiedAsBoundsChangeInHiddenLayer
) {
2382 BoundsChangeDelegate delegate
;
2384 // We cannot short-circuit animations in this test.
2385 ui::ScopedAnimationDurationScaleMode
test_duration_mode(
2386 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION
);
2388 scoped_ptr
<Window
> window(
2389 CreateTestWindowWithDelegate(&delegate
, 1,
2390 gfx::Rect(0, 0, 100, 100), root_window()));
2391 window
->layer()->GetAnimator()->set_disable_timer_for_test(true);
2393 delegate
.clear_bounds_changed();
2395 // Suppress paint on the window since it is hidden (should reset the layer's
2396 // delegate to NULL)
2397 window
->SuppressPaint();
2398 EXPECT_EQ(NULL
, window
->layer()->delegate());
2400 // Animate to a different position.
2402 ui::ScopedLayerAnimationSettings
settings(window
->layer()->GetAnimator());
2403 window
->SetBounds(gfx::Rect(100, 100, 110, 100));
2406 // Layer delegate is NULL but we should still get bounds changed notification.
2407 EXPECT_EQ("100,100 110x100", window
->GetTargetBounds().ToString());
2408 EXPECT_TRUE(delegate
.bounds_changed());
2410 delegate
.clear_bounds_changed();
2412 // Animate to the end: will *not* notify of the change since we are hidden.
2413 base::TimeTicks start_time
=
2414 window
->layer()->GetAnimator()->last_step_time();
2415 ui::LayerAnimator
* animator
= window
->layer()->GetAnimator();
2416 animator
->Step(start_time
+ base::TimeDelta::FromMilliseconds(1000));
2418 // No bounds changed notification at the end of animation since layer
2419 // delegate is NULL.
2420 EXPECT_FALSE(delegate
.bounds_changed());
2421 EXPECT_NE("0,0 100x100", window
->layer()->bounds().ToString());
2426 // Used by AddChildNotifications to track notification counts.
2427 class AddChildNotificationsObserver
: public WindowObserver
{
2429 AddChildNotificationsObserver() : added_count_(0), removed_count_(0) {}
2431 std::string
CountStringAndReset() {
2432 std::string result
= base::IntToString(added_count_
) + " " +
2433 base::IntToString(removed_count_
);
2434 added_count_
= removed_count_
= 0;
2438 // WindowObserver overrides:
2439 virtual void OnWindowAddedToRootWindow(Window
* window
) OVERRIDE
{
2442 virtual void OnWindowRemovingFromRootWindow(Window
* window
,
2443 Window
* new_root
) OVERRIDE
{
2451 DISALLOW_COPY_AND_ASSIGN(AddChildNotificationsObserver
);
2456 // Assertions around when root window notifications are sent.
2457 TEST_F(WindowTest
, AddChildNotifications
) {
2458 AddChildNotificationsObserver observer
;
2459 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
2460 scoped_ptr
<Window
> w2(CreateTestWindowWithId(1, root_window()));
2461 w2
->AddObserver(&observer
);
2463 EXPECT_TRUE(w2
->HasFocus());
2465 // Move |w2| to be a child of |w1|.
2466 w1
->AddChild(w2
.get());
2467 // Sine we moved in the same root, observer shouldn't be notified.
2468 EXPECT_EQ("0 0", observer
.CountStringAndReset());
2469 // |w2| should still have focus after moving.
2470 EXPECT_TRUE(w2
->HasFocus());
2473 // Tests that a delegate that destroys itself when the window is destroyed does
2475 TEST_F(WindowTest
, DelegateDestroysSelfOnWindowDestroy
) {
2476 scoped_ptr
<Window
> w1(CreateTestWindowWithDelegate(
2477 new DestroyWindowDelegate(),
2479 gfx::Rect(10, 20, 30, 40),
2483 class HierarchyObserver
: public WindowObserver
{
2485 HierarchyObserver(Window
* target
) : target_(target
) {
2486 target_
->AddObserver(this);
2488 virtual ~HierarchyObserver() {
2489 target_
->RemoveObserver(this);
2494 const WindowObserver::HierarchyChangeParams
& params
) const {
2495 ParamsMatch(params_
[index
], params
);
2503 // Overridden from WindowObserver:
2504 virtual void OnWindowHierarchyChanging(
2505 const HierarchyChangeParams
& params
) OVERRIDE
{
2506 params_
.push_back(params
);
2508 virtual void OnWindowHierarchyChanged(
2509 const HierarchyChangeParams
& params
) OVERRIDE
{
2510 params_
.push_back(params
);
2513 void ParamsMatch(const WindowObserver::HierarchyChangeParams
& p1
,
2514 const WindowObserver::HierarchyChangeParams
& p2
) const {
2515 EXPECT_EQ(p1
.phase
, p2
.phase
);
2516 EXPECT_EQ(p1
.target
, p2
.target
);
2517 EXPECT_EQ(p1
.new_parent
, p2
.new_parent
);
2518 EXPECT_EQ(p1
.old_parent
, p2
.old_parent
);
2519 EXPECT_EQ(p1
.receiver
, p2
.receiver
);
2523 std::vector
<WindowObserver::HierarchyChangeParams
> params_
;
2525 DISALLOW_COPY_AND_ASSIGN(HierarchyObserver
);
2528 // Tests hierarchy change notifications.
2529 TEST_F(WindowTest
, OnWindowHierarchyChange
) {
2531 // Simple add & remove.
2532 HierarchyObserver
oroot(root_window());
2534 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, NULL
));
2535 HierarchyObserver
o1(w1
.get());
2538 root_window()->AddChild(w1
.get());
2540 WindowObserver::HierarchyChangeParams params
;
2541 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING
;
2542 params
.target
= w1
.get();
2543 params
.old_parent
= NULL
;
2544 params
.new_parent
= root_window();
2545 params
.receiver
= w1
.get();
2546 o1
.ValidateState(0, params
);
2548 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED
;
2549 params
.receiver
= w1
.get();
2550 o1
.ValidateState(1, params
);
2552 params
.receiver
= root_window();
2553 oroot
.ValidateState(0, params
);
2559 root_window()->RemoveChild(w1
.get());
2561 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING
;
2562 params
.old_parent
= root_window();
2563 params
.new_parent
= NULL
;
2564 params
.receiver
= w1
.get();
2566 o1
.ValidateState(0, params
);
2568 params
.receiver
= root_window();
2569 oroot
.ValidateState(0, params
);
2571 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED
;
2572 params
.receiver
= w1
.get();
2573 o1
.ValidateState(1, params
);
2577 // Add & remove of hierarchy. Tests notification order per documentation in
2579 HierarchyObserver
o(root_window());
2580 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, NULL
));
2581 Window
* w11
= CreateTestWindowWithId(11, w1
.get());
2582 w1
->AddObserver(&o
);
2583 w11
->AddObserver(&o
);
2586 root_window()->AddChild(w1
.get());
2588 // Dispatched to target first.
2590 WindowObserver::HierarchyChangeParams params
;
2591 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING
;
2592 params
.target
= w1
.get();
2593 params
.old_parent
= NULL
;
2594 params
.new_parent
= root_window();
2595 params
.receiver
= w1
.get();
2596 o
.ValidateState(index
++, params
);
2598 // Dispatched to target's children.
2599 params
.receiver
= w11
;
2600 o
.ValidateState(index
++, params
);
2602 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED
;
2604 // Now process the "changed" phase.
2605 params
.receiver
= w1
.get();
2606 o
.ValidateState(index
++, params
);
2607 params
.receiver
= w11
;
2608 o
.ValidateState(index
++, params
);
2609 params
.receiver
= root_window();
2610 o
.ValidateState(index
++, params
);
2613 root_window()->RemoveChild(w1
.get());
2614 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING
;
2615 params
.old_parent
= root_window();
2616 params
.new_parent
= NULL
;
2617 params
.receiver
= w1
.get();
2618 o
.ValidateState(index
++, params
);
2619 params
.receiver
= w11
;
2620 o
.ValidateState(index
++, params
);
2621 params
.receiver
= root_window();
2622 o
.ValidateState(index
++, params
);
2623 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED
;
2624 params
.receiver
= w1
.get();
2625 o
.ValidateState(index
++, params
);
2626 params
.receiver
= w11
;
2627 o
.ValidateState(index
++, params
);
2633 // Reparent. Tests notification order per documentation in WindowObserver.
2634 scoped_ptr
<Window
> w1(CreateTestWindowWithId(1, root_window()));
2635 Window
* w11
= CreateTestWindowWithId(11, w1
.get());
2636 Window
* w111
= CreateTestWindowWithId(111, w11
);
2637 scoped_ptr
<Window
> w2(CreateTestWindowWithId(2, root_window()));
2639 HierarchyObserver
o(root_window());
2640 w1
->AddObserver(&o
);
2641 w11
->AddObserver(&o
);
2642 w111
->AddObserver(&o
);
2643 w2
->AddObserver(&o
);
2647 // Dispatched to target first.
2649 WindowObserver::HierarchyChangeParams params
;
2650 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING
;
2651 params
.target
= w11
;
2652 params
.old_parent
= w1
.get();
2653 params
.new_parent
= w2
.get();
2654 params
.receiver
= w11
;
2655 o
.ValidateState(index
++, params
);
2657 // Then to target's children.
2658 params
.receiver
= w111
;
2659 o
.ValidateState(index
++, params
);
2661 // Then to target's old parent chain.
2662 params
.receiver
= w1
.get();
2663 o
.ValidateState(index
++, params
);
2664 params
.receiver
= root_window();
2665 o
.ValidateState(index
++, params
);
2668 params
.phase
= WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED
;
2669 params
.receiver
= w11
;
2670 o
.ValidateState(index
++, params
);
2671 params
.receiver
= w111
;
2672 o
.ValidateState(index
++, params
);
2673 params
.receiver
= w2
.get();
2674 o
.ValidateState(index
++, params
);
2675 params
.receiver
= root_window();
2676 o
.ValidateState(index
++, params
);
2684 // Verifies SchedulePaint() on a layerless window results in damaging the right
2686 TEST_F(WindowTest
, LayerlessWindowSchedulePaint
) {
2688 root
.Init(aura::WINDOW_LAYER_NOT_DRAWN
);
2689 root
.SetBounds(gfx::Rect(0, 0, 100, 100));
2691 Window
* layerless_window
= new Window(NULL
); // Owned by |root|.
2692 layerless_window
->Init(WINDOW_LAYER_NONE
);
2693 layerless_window
->SetBounds(gfx::Rect(10, 11, 12, 13));
2694 root
.AddChild(layerless_window
);
2696 root
.layer()->SendDamagedRects();
2697 layerless_window
->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4));
2698 // Note the the region is clipped by the parent hence 100 going to 11.
2699 EXPECT_EQ("11,13 11x4",
2700 gfx::SkIRectToRect(root
.layer()->damaged_region().getBounds()).
2703 Window
* layerless_window2
= new Window(NULL
); // Owned by |layerless_window|.
2704 layerless_window2
->Init(WINDOW_LAYER_NONE
);
2705 layerless_window2
->SetBounds(gfx::Rect(1, 2, 3, 4));
2706 layerless_window
->AddChild(layerless_window2
);
2708 root
.layer()->SendDamagedRects();
2709 layerless_window2
->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4));
2710 // Note the the region is clipped by the |layerless_window| hence 100 going to
2712 EXPECT_EQ("12,15 2x2",
2713 gfx::SkIRectToRect(root
.layer()->damaged_region().getBounds()).
2717 // Verifies bounds of layerless windows are correctly updated when adding
2719 TEST_F(WindowTest
, NestedLayerlessWindowsBoundsOnAddRemove
) {
2720 // Creates the following structure (all children owned by root):
2728 // ll: layer less, eg no layer
2730 root
.Init(WINDOW_LAYER_NOT_DRAWN
);
2731 root
.SetBounds(gfx::Rect(0, 0, 100, 100));
2733 Window
* w1ll
= new Window(NULL
);
2734 w1ll
->Init(WINDOW_LAYER_NONE
);
2735 w1ll
->SetBounds(gfx::Rect(1, 2, 100, 100));
2737 Window
* w11ll
= new Window(NULL
);
2738 w11ll
->Init(WINDOW_LAYER_NONE
);
2739 w11ll
->SetBounds(gfx::Rect(3, 4, 100, 100));
2740 w1ll
->AddChild(w11ll
);
2742 Window
* w111
= new Window(NULL
);
2743 w111
->Init(WINDOW_LAYER_NOT_DRAWN
);
2744 w111
->SetBounds(gfx::Rect(5, 6, 100, 100));
2745 w11ll
->AddChild(w111
);
2747 Window
* w12
= new Window(NULL
);
2748 w12
->Init(WINDOW_LAYER_NOT_DRAWN
);
2749 w12
->SetBounds(gfx::Rect(7, 8, 100, 100));
2750 w1ll
->AddChild(w12
);
2752 Window
* w121
= new Window(NULL
);
2753 w121
->Init(WINDOW_LAYER_NOT_DRAWN
);
2754 w121
->SetBounds(gfx::Rect(9, 10, 100, 100));
2755 w12
->AddChild(w121
);
2757 root
.AddChild(w1ll
);
2759 // All layers should be parented to the root.
2760 EXPECT_EQ(root
.layer(), w111
->layer()->parent());
2761 EXPECT_EQ(root
.layer(), w12
->layer()->parent());
2762 EXPECT_EQ(w12
->layer(), w121
->layer()->parent());
2764 // Ensure bounds are what we expect.
2765 EXPECT_EQ("1,2 100x100", w1ll
->bounds().ToString());
2766 EXPECT_EQ("3,4 100x100", w11ll
->bounds().ToString());
2767 EXPECT_EQ("5,6 100x100", w111
->bounds().ToString());
2768 EXPECT_EQ("7,8 100x100", w12
->bounds().ToString());
2769 EXPECT_EQ("9,10 100x100", w121
->bounds().ToString());
2771 // Bounds of layers are relative to the nearest ancestor with a layer.
2772 EXPECT_EQ("8,10 100x100", w12
->layer()->bounds().ToString());
2773 EXPECT_EQ("9,12 100x100", w111
->layer()->bounds().ToString());
2774 EXPECT_EQ("9,10 100x100", w121
->layer()->bounds().ToString());
2776 // Remove and repeat.
2777 root
.RemoveChild(w1ll
);
2779 EXPECT_TRUE(w111
->layer()->parent() == NULL
);
2780 EXPECT_TRUE(w12
->layer()->parent() == NULL
);
2782 // Verify bounds haven't changed again.
2783 EXPECT_EQ("1,2 100x100", w1ll
->bounds().ToString());
2784 EXPECT_EQ("3,4 100x100", w11ll
->bounds().ToString());
2785 EXPECT_EQ("5,6 100x100", w111
->bounds().ToString());
2786 EXPECT_EQ("7,8 100x100", w12
->bounds().ToString());
2787 EXPECT_EQ("9,10 100x100", w121
->bounds().ToString());
2789 // Bounds of layers should now match that of windows.
2790 EXPECT_EQ("7,8 100x100", w12
->layer()->bounds().ToString());
2791 EXPECT_EQ("5,6 100x100", w111
->layer()->bounds().ToString());
2792 EXPECT_EQ("9,10 100x100", w121
->layer()->bounds().ToString());
2797 // Verifies bounds of layerless windows are correctly updated when bounds
2798 // of ancestor changes.
2799 TEST_F(WindowTest
, NestedLayerlessWindowsBoundsOnSetBounds
) {
2800 // Creates the following structure (all children owned by root):
2808 // ll: layer less, eg no layer
2810 root
.Init(WINDOW_LAYER_NOT_DRAWN
);
2811 root
.SetBounds(gfx::Rect(0, 0, 100, 100));
2813 Window
* w1ll
= new Window(NULL
);
2814 w1ll
->Init(WINDOW_LAYER_NONE
);
2815 w1ll
->SetBounds(gfx::Rect(1, 2, 100, 100));
2817 Window
* w11ll
= new Window(NULL
);
2818 w11ll
->Init(WINDOW_LAYER_NONE
);
2819 w11ll
->SetBounds(gfx::Rect(3, 4, 100, 100));
2820 w1ll
->AddChild(w11ll
);
2822 Window
* w111
= new Window(NULL
);
2823 w111
->Init(WINDOW_LAYER_NOT_DRAWN
);
2824 w111
->SetBounds(gfx::Rect(5, 6, 100, 100));
2825 w11ll
->AddChild(w111
);
2827 Window
* w12
= new Window(NULL
);
2828 w12
->Init(WINDOW_LAYER_NOT_DRAWN
);
2829 w12
->SetBounds(gfx::Rect(7, 8, 100, 100));
2830 w1ll
->AddChild(w12
);
2832 Window
* w121
= new Window(NULL
);
2833 w121
->Init(WINDOW_LAYER_NOT_DRAWN
);
2834 w121
->SetBounds(gfx::Rect(9, 10, 100, 100));
2835 w12
->AddChild(w121
);
2837 root
.AddChild(w1ll
);
2839 w111
->SetBounds(gfx::Rect(7, 8, 11, 12));
2840 EXPECT_EQ("7,8 11x12", w111
->bounds().ToString());
2841 EXPECT_EQ("7,8 11x12", w111
->GetTargetBounds().ToString());
2842 EXPECT_EQ("11,14 11x12", w111
->layer()->bounds().ToString());
2845 w111
->SetBounds(gfx::Rect(5, 6, 100, 100));
2846 EXPECT_EQ("5,6 100x100", w111
->bounds().ToString());
2847 EXPECT_EQ("5,6 100x100", w111
->GetTargetBounds().ToString());
2848 EXPECT_EQ("9,12 100x100", w111
->layer()->bounds().ToString());
2850 // Setting the bounds of a layerless window needs to adjust the bounds of
2851 // layered children.
2852 w11ll
->SetBounds(gfx::Rect(5, 6, 100, 100));
2853 EXPECT_EQ("5,6 100x100", w11ll
->bounds().ToString());
2854 EXPECT_EQ("5,6 100x100", w11ll
->GetTargetBounds().ToString());
2855 EXPECT_EQ("5,6 100x100", w111
->bounds().ToString());
2856 EXPECT_EQ("5,6 100x100", w111
->GetTargetBounds().ToString());
2857 EXPECT_EQ("11,14 100x100", w111
->layer()->bounds().ToString());
2859 root
.RemoveChild(w1ll
);
2861 w111
->SetBounds(gfx::Rect(7, 8, 11, 12));
2862 EXPECT_EQ("7,8 11x12", w111
->bounds().ToString());
2863 EXPECT_EQ("7,8 11x12", w111
->GetTargetBounds().ToString());
2864 EXPECT_EQ("7,8 11x12", w111
->layer()->bounds().ToString());
2871 // Tracks the number of times paint is invoked along with what the clip and
2873 class PaintWindowDelegate
: public TestWindowDelegate
{
2875 PaintWindowDelegate() : paint_count_(0) {}
2876 virtual ~PaintWindowDelegate() {}
2878 const gfx::Rect
& most_recent_paint_clip_bounds() const {
2879 return most_recent_paint_clip_bounds_
;
2882 const gfx::Vector2d
& most_recent_paint_matrix_offset() const {
2883 return most_recent_paint_matrix_offset_
;
2886 void clear_paint_count() { paint_count_
= 0; }
2887 int paint_count() const { return paint_count_
; }
2889 // TestWindowDelegate::
2890 virtual void OnPaint(gfx::Canvas
* canvas
) OVERRIDE
{
2892 canvas
->GetClipBounds(&most_recent_paint_clip_bounds_
);
2893 const SkMatrix
& matrix
= canvas
->sk_canvas()->getTotalMatrix();
2894 most_recent_paint_matrix_offset_
= gfx::Vector2d(
2895 SkScalarFloorToInt(matrix
.getTranslateX()),
2896 SkScalarFloorToInt(matrix
.getTranslateY()));
2901 gfx::Rect most_recent_paint_clip_bounds_
;
2902 gfx::Vector2d most_recent_paint_matrix_offset_
;
2904 DISALLOW_COPY_AND_ASSIGN(PaintWindowDelegate
);
2909 // Assertions around layerless children being painted when non-layerless window
2911 TEST_F(WindowTest
, PaintLayerless
) {
2912 // Creates the following structure (all children owned by root):
2918 // ll: layer less, eg no layer
2919 PaintWindowDelegate w1ll_delegate
;
2920 PaintWindowDelegate w11ll_delegate
;
2921 PaintWindowDelegate w111_delegate
;
2924 root
.Init(WINDOW_LAYER_NOT_DRAWN
);
2925 root
.SetBounds(gfx::Rect(0, 0, 100, 100));
2927 Window
* w1ll
= new Window(&w1ll_delegate
);
2928 w1ll
->Init(WINDOW_LAYER_NONE
);
2929 w1ll
->SetBounds(gfx::Rect(1, 2, 40, 50));
2931 root
.AddChild(w1ll
);
2933 Window
* w11ll
= new Window(&w11ll_delegate
);
2934 w11ll
->Init(WINDOW_LAYER_NONE
);
2935 w11ll
->SetBounds(gfx::Rect(3, 4, 11, 12));
2937 w1ll
->AddChild(w11ll
);
2939 Window
* w111
= new Window(&w111_delegate
);
2940 w111
->Init(WINDOW_LAYER_NOT_DRAWN
);
2941 w111
->SetBounds(gfx::Rect(5, 6, 100, 100));
2943 w11ll
->AddChild(w111
);
2945 EXPECT_EQ(0, w1ll_delegate
.paint_count());
2946 EXPECT_EQ(0, w11ll_delegate
.paint_count());
2947 EXPECT_EQ(0, w111_delegate
.paint_count());
2949 // Paint the root, this should trigger painting of the two layerless
2950 // descendants but not the layered descendant.
2951 gfx::Canvas
canvas(gfx::Size(200, 200), 1.0f
, true);
2952 static_cast<ui::LayerDelegate
&>(root
).OnPaintLayer(&canvas
);
2954 // NOTE: SkCanvas::getClipBounds() extends the clip 1 pixel to the left and up
2955 // and 2 pixels down and to the right.
2956 EXPECT_EQ(1, w1ll_delegate
.paint_count());
2957 EXPECT_EQ("-1,-1 42x52",
2958 w1ll_delegate
.most_recent_paint_clip_bounds().ToString());
2960 w1ll_delegate
.most_recent_paint_matrix_offset().ToString());
2961 EXPECT_EQ(1, w11ll_delegate
.paint_count());
2962 EXPECT_EQ("-1,-1 13x14",
2963 w11ll_delegate
.most_recent_paint_clip_bounds().ToString());
2965 w11ll_delegate
.most_recent_paint_matrix_offset().ToString());
2966 EXPECT_EQ(0, w111_delegate
.paint_count());
2971 std::string
ConvertPointToTargetString(const Window
* source
,
2972 const Window
* target
) {
2973 gfx::Point location
;
2974 Window::ConvertPointToTarget(source
, target
, &location
);
2975 return location
.ToString();
2980 // Assertions around Window::ConvertPointToTarget() with layerless windows.
2981 TEST_F(WindowTest
, ConvertPointToTargetLayerless
) {
2982 // Creates the following structure (all children owned by root):
2990 // ll: layer less, eg no layer
2992 root
.Init(WINDOW_LAYER_NOT_DRAWN
);
2993 root
.SetBounds(gfx::Rect(0, 0, 100, 100));
2995 Window
* w1ll
= new Window(NULL
);
2996 w1ll
->Init(WINDOW_LAYER_NONE
);
2997 w1ll
->SetBounds(gfx::Rect(1, 2, 100, 100));
2999 Window
* w11ll
= new Window(NULL
);
3000 w11ll
->Init(WINDOW_LAYER_NONE
);
3001 w11ll
->SetBounds(gfx::Rect(3, 4, 100, 100));
3002 w1ll
->AddChild(w11ll
);
3004 Window
* w111
= new Window(NULL
);
3005 w111
->Init(WINDOW_LAYER_NOT_DRAWN
);
3006 w111
->SetBounds(gfx::Rect(5, 6, 100, 100));
3007 w11ll
->AddChild(w111
);
3009 Window
* w12
= new Window(NULL
);
3010 w12
->Init(WINDOW_LAYER_NOT_DRAWN
);
3011 w12
->SetBounds(gfx::Rect(7, 8, 100, 100));
3012 w1ll
->AddChild(w12
);
3014 Window
* w121
= new Window(NULL
);
3015 w121
->Init(WINDOW_LAYER_NOT_DRAWN
);
3016 w121
->SetBounds(gfx::Rect(9, 10, 100, 100));
3017 w12
->AddChild(w121
);
3019 root
.AddChild(w1ll
);
3022 EXPECT_EQ("5,6", ConvertPointToTargetString(w111
, w11ll
));
3025 EXPECT_EQ("8,10", ConvertPointToTargetString(w111
, w1ll
));
3028 EXPECT_EQ("9,12", ConvertPointToTargetString(w111
, &root
));
3031 EXPECT_EQ("1,2", ConvertPointToTargetString(w111
, w12
));
3034 EXPECT_EQ("-8,-8", ConvertPointToTargetString(w111
, w121
));
3037 EXPECT_EQ("-5,-6", ConvertPointToTargetString(w11ll
, w111
));
3040 EXPECT_EQ("3,4", ConvertPointToTargetString(w11ll
, w1ll
));
3043 EXPECT_EQ("4,6", ConvertPointToTargetString(w11ll
, &root
));
3046 EXPECT_EQ("-4,-4", ConvertPointToTargetString(w11ll
, w12
));
3049 #if !defined(NDEBUG)
3050 // Verifies PrintWindowHierarchy() doesn't crash with a layerless window.
3051 TEST_F(WindowTest
, PrintWindowHierarchyNotCrashLayerless
) {
3053 root
.Init(WINDOW_LAYER_NONE
);
3054 root
.SetBounds(gfx::Rect(0, 0, 100, 100));
3055 root
.PrintWindowHierarchy(0);
3061 // See AddWindowsFromString() for details.
3062 aura::Window
* CreateWindowFromDescription(const std::string
& description
,
3063 WindowDelegate
* delegate
) {
3064 WindowLayerType window_type
= WINDOW_LAYER_NOT_DRAWN
;
3065 std::vector
<std::string
> tokens
;
3066 Tokenize(description
, ":", &tokens
);
3067 DCHECK(!tokens
.empty());
3068 std::string
name(tokens
[0]);
3069 tokens
.erase(tokens
.begin());
3070 if (!tokens
.empty()) {
3071 if (tokens
[0] == "ll") {
3072 window_type
= WINDOW_LAYER_NONE
;
3073 tokens
.erase(tokens
.begin());
3075 DCHECK(tokens
.empty()) << "unknown tokens for creating window "
3078 Window
* window
= new Window(delegate
);
3079 window
->Init(window_type
);
3080 window
->SetName(name
);
3081 // Window name is only propagated to layer in debug builds.
3082 if (window
->layer())
3083 window
->layer()->set_name(name
);
3087 // Creates and adds a tree of windows to |parent|. |description| consists
3088 // of the following pieces:
3089 // X: Identifies a new window. Consists of a name and optionally ":ll" to
3090 // specify WINDOW_LAYER_NONE, eg "w1:ll".
3091 // []: optionally used to specify the children of the window. Contains any
3092 // number of window identifiers and their corresponding children.
3093 // For example: "[ a [ a1 a2:ll ] b c [ c1 ] ]" creates the tree:
3096 // a2 -> WINDOW_LAYER_NONE.
3100 // NOTE: you must have a space after every token.
3101 std::string::size_type
AddWindowsFromString(aura::Window
* parent
,
3102 const std::string
& description
,
3103 std::string::size_type start_pos
,
3104 WindowDelegate
* delegate
) {
3106 std::string::size_type end_pos
= description
.find(' ', start_pos
);
3107 while (end_pos
!= std::string::npos
) {
3108 const std::string::size_type part_length
= end_pos
- start_pos
;
3109 const std::string window_description
=
3110 description
.substr(start_pos
, part_length
);
3111 if (window_description
== "[") {
3112 start_pos
= AddWindowsFromString(parent
->children().back(),
3116 end_pos
= description
.find(' ', start_pos
);
3117 if (end_pos
== std::string::npos
&& start_pos
!= end_pos
)
3118 end_pos
= description
.length();
3119 } else if (window_description
== "]") {
3124 CreateWindowFromDescription(window_description
, delegate
);
3125 parent
->AddChild(window
);
3126 start_pos
= ++end_pos
;
3127 end_pos
= description
.find(' ', start_pos
);
3133 // Used by BuildRootWindowTreeDescription().
3134 std::string
BuildWindowTreeDescription(const aura::Window
& window
) {
3136 result
+= window
.name();
3137 if (window
.children().empty())
3141 for (size_t i
= 0; i
< window
.children().size(); ++i
) {
3144 result
+= BuildWindowTreeDescription(*(window
.children()[i
]));
3150 // Creates a string from |window|. See AddWindowsFromString() for details of the
3151 // returned string. This does *not* include the layer type in the description,
3153 std::string
BuildRootWindowTreeDescription(const aura::Window
& window
) {
3155 for (size_t i
= 0; i
< window
.children().size(); ++i
) {
3158 result
+= BuildWindowTreeDescription(*(window
.children()[i
]));
3163 // Used by BuildRootWindowTreeDescription().
3164 std::string
BuildLayerTreeDescription(const ui::Layer
& layer
) {
3166 result
+= layer
.name();
3167 if (layer
.children().empty())
3171 for (size_t i
= 0; i
< layer
.children().size(); ++i
) {
3174 result
+= BuildLayerTreeDescription(*(layer
.children()[i
]));
3180 // Builds a string for all the children of |layer|. The returned string is in
3181 // the same format as AddWindowsFromString() but only includes the name of the
3183 std::string
BuildRootLayerTreeDescription(const ui::Layer
& layer
) {
3185 for (size_t i
= 0; i
< layer
.children().size(); ++i
) {
3188 result
+= BuildLayerTreeDescription(*(layer
.children()[i
]));
3193 // Returns the first window whose name matches |name| in |parent|.
3194 aura::Window
* FindWindowByName(aura::Window
* parent
,
3195 const std::string
& name
) {
3196 if (parent
->name() == name
)
3198 for (size_t i
= 0; i
< parent
->children().size(); ++i
) {
3199 aura::Window
* child
= FindWindowByName(parent
->children()[i
], name
);
3208 // Direction to stack.
3216 // Permutations of StackChildAt with various data.
3217 TEST_F(WindowTest
, StackChildAtLayerless
) {
3219 // Describes the window tree to create. See AddWindowsFromString() for
3221 const std::string initial_description
;
3223 // Identifies the window to move.
3224 const std::string source_window
;
3226 // Window to move |source_window| relative to. Not used for STACK_AT_BOTTOM
3228 const std::string target_window
;
3230 StackType stack_type
;
3232 // Expected window and layer results.
3233 const std::string expected_description
;
3234 const std::string expected_layer_description
;
3238 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3242 "2 [ 21 ] 1 [ 11 12 ]",
3248 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3252 "1 [ 11 12 ] 2 [ 21 ]",
3258 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3262 "2 [ 21 ] 1 [ 11 12 ]",
3268 "1:ll [ 11 12 ] 2:ll [ 21 ] 3:ll",
3272 "1 [ 11 12 ] 3 2 [ 21 ]",
3278 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3282 "2 [ 21 ] 1 [ 11 12 ]",
3288 "1:ll [ 11 12 ] 2:ll [ 21 ] 3:ll",
3292 "2 [ 21 ] 3 1 [ 11 12 ]",
3298 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3302 "2 [ 21 ] 1 [ 11 12 ]",
3306 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(data
); ++i
) {
3307 test::TestWindowDelegate delegate
;
3309 root
.Init(WINDOW_LAYER_NOT_DRAWN
);
3310 root
.SetBounds(gfx::Rect(0, 0, 100, 100));
3311 AddWindowsFromString(
3313 data
[i
].initial_description
,
3314 static_cast<std::string::size_type
>(0), &delegate
);
3315 aura::Window
* source
= FindWindowByName(&root
, data
[i
].source_window
);
3316 ASSERT_TRUE(source
!= NULL
) << "unable to find source window "
3317 << data
[i
].source_window
<< " at " << i
;
3318 aura::Window
* target
= FindWindowByName(&root
, data
[i
].target_window
);
3319 switch (data
[i
].stack_type
) {
3321 ASSERT_TRUE(target
!= NULL
) << "unable to find target window "
3322 << data
[i
].target_window
<< " at " << i
;
3323 source
->parent()->StackChildAbove(source
, target
);
3326 ASSERT_TRUE(target
!= NULL
) << "unable to find target window "
3327 << data
[i
].target_window
<< " at " << i
;
3328 source
->parent()->StackChildBelow(source
, target
);
3330 case STACK_AT_BOTTOM
:
3331 source
->parent()->StackChildAtBottom(source
);
3334 source
->parent()->StackChildAtTop(source
);
3337 EXPECT_EQ(data
[i
].expected_layer_description
,
3338 BuildRootLayerTreeDescription(*root
.layer()))
3339 << "layer tree doesn't match at " << i
;
3340 EXPECT_EQ(data
[i
].expected_description
,
3341 BuildRootWindowTreeDescription(root
))
3342 << "window tree doesn't match at " << i
;
3348 class TestLayerAnimationObserver
: public ui::LayerAnimationObserver
{
3350 TestLayerAnimationObserver()
3351 : animation_completed_(false),
3352 animation_aborted_(false) {}
3353 virtual ~TestLayerAnimationObserver() {}
3355 bool animation_completed() const { return animation_completed_
; }
3356 bool animation_aborted() const { return animation_aborted_
; }
3359 animation_completed_
= false;
3360 animation_aborted_
= false;
3364 // ui::LayerAnimationObserver:
3365 virtual void OnLayerAnimationEnded(
3366 ui::LayerAnimationSequence
* sequence
) OVERRIDE
{
3367 animation_completed_
= true;
3370 virtual void OnLayerAnimationAborted(
3371 ui::LayerAnimationSequence
* sequence
) OVERRIDE
{
3372 animation_aborted_
= true;
3375 virtual void OnLayerAnimationScheduled(
3376 ui::LayerAnimationSequence
* sequence
) OVERRIDE
{
3379 bool animation_completed_
;
3380 bool animation_aborted_
;
3382 DISALLOW_COPY_AND_ASSIGN(TestLayerAnimationObserver
);
3387 TEST_F(WindowTest
, WindowDestroyCompletesAnimations
) {
3388 ui::ScopedAnimationDurationScaleMode
test_duration_mode(
3389 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION
);
3390 scoped_refptr
<ui::LayerAnimator
> animator
=
3391 ui::LayerAnimator::CreateImplicitAnimator();
3392 TestLayerAnimationObserver observer
;
3393 animator
->AddObserver(&observer
);
3394 // Make sure destroying a Window completes the animation.
3396 scoped_ptr
<Window
> window(CreateTestWindowWithId(1, root_window()));
3397 window
->layer()->SetAnimator(animator
.get());
3399 gfx::Transform transform
;
3400 transform
.Scale(0.5f
, 0.5f
);
3401 window
->SetTransform(transform
);
3403 EXPECT_TRUE(animator
->is_animating());
3404 EXPECT_FALSE(observer
.animation_completed());
3406 EXPECT_TRUE(animator
.get());
3407 EXPECT_FALSE(animator
->is_animating());
3408 EXPECT_TRUE(observer
.animation_completed());
3409 EXPECT_FALSE(observer
.animation_aborted());
3410 animator
->RemoveObserver(&observer
);
3413 animator
= ui::LayerAnimator::CreateImplicitAnimator();
3414 animator
->AddObserver(&observer
);
3416 layer
.SetAnimator(animator
.get());
3418 scoped_ptr
<Window
> window(CreateTestWindowWithId(1, root_window()));
3419 window
->layer()->Add(&layer
);
3421 gfx::Transform transform
;
3422 transform
.Scale(0.5f
, 0.5f
);
3423 layer
.SetTransform(transform
);
3425 EXPECT_TRUE(animator
->is_animating());
3426 EXPECT_FALSE(observer
.animation_completed());
3429 EXPECT_TRUE(animator
.get());
3430 EXPECT_FALSE(animator
->is_animating());
3431 EXPECT_TRUE(observer
.animation_completed());
3432 EXPECT_FALSE(observer
.animation_aborted());
3433 animator
->RemoveObserver(&observer
);