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/root_window.h"
22 #include "ui/aura/root_window_observer.h"
23 #include "ui/aura/test/aura_test_base.h"
24 #include "ui/aura/test/event_generator.h"
25 #include "ui/aura/test/test_window_delegate.h"
26 #include "ui/aura/test/test_windows.h"
27 #include "ui/aura/test/window_test_api.h"
28 #include "ui/aura/window_delegate.h"
29 #include "ui/aura/window_observer.h"
30 #include "ui/aura/window_property.h"
31 #include "ui/aura/window_tree_host.h"
32 #include "ui/base/hit_test.h"
33 #include "ui/compositor/layer.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/gfx/canvas.h"
42 #include "ui/gfx/screen.h"
43 #include "ui/gfx/skia_util.h"
44 #include "ui/gfx/vector2d.h"
46 DECLARE_WINDOW_PROPERTY_TYPE(const char*)
47 DECLARE_WINDOW_PROPERTY_TYPE(int)
52 class WindowTest : public AuraTestBase {
54 WindowTest() : max_separation_(0) {
57 virtual void SetUp() OVERRIDE {
58 AuraTestBase::SetUp();
59 // TODO: there needs to be an easier way to do this.
60 max_separation_ = ui::GestureConfiguration::
61 max_separation_for_gesture_touches_in_pixels();
62 ui::GestureConfiguration::
63 set_max_separation_for_gesture_touches_in_pixels(0);
66 virtual void TearDown() OVERRIDE {
67 AuraTestBase::TearDown();
68 ui::GestureConfiguration::
69 set_max_separation_for_gesture_touches_in_pixels(max_separation_);
75 DISALLOW_COPY_AND_ASSIGN(WindowTest);
80 // Used for verifying destruction methods are invoked.
81 class DestroyTrackingDelegateImpl : public TestWindowDelegate {
83 DestroyTrackingDelegateImpl()
84 : destroying_count_(0),
86 in_destroying_(false) {}
88 void clear_destroying_count() { destroying_count_ = 0; }
89 int destroying_count() const { return destroying_count_; }
91 void clear_destroyed_count() { destroyed_count_ = 0; }
92 int destroyed_count() const { return destroyed_count_; }
94 bool in_destroying() const { return in_destroying_; }
96 virtual void OnWindowDestroying() OVERRIDE {
97 EXPECT_FALSE(in_destroying_);
98 in_destroying_ = true;
102 virtual void OnWindowDestroyed() OVERRIDE {
103 EXPECT_TRUE(in_destroying_);
104 in_destroying_ = false;
109 int destroying_count_;
110 int destroyed_count_;
113 DISALLOW_COPY_AND_ASSIGN(DestroyTrackingDelegateImpl);
116 // Used to verify that when OnWindowDestroying is invoked the parent is also
117 // is in the process of being destroyed.
118 class ChildWindowDelegateImpl : public DestroyTrackingDelegateImpl {
120 explicit ChildWindowDelegateImpl(
121 DestroyTrackingDelegateImpl* parent_delegate)
122 : parent_delegate_(parent_delegate) {
125 virtual void OnWindowDestroying() OVERRIDE {
126 EXPECT_TRUE(parent_delegate_->in_destroying());
127 DestroyTrackingDelegateImpl::OnWindowDestroying();
131 DestroyTrackingDelegateImpl* parent_delegate_;
133 DISALLOW_COPY_AND_ASSIGN(ChildWindowDelegateImpl);
136 // Used to verify that a Window is removed from its parent when
137 // OnWindowDestroyed is called.
138 class DestroyOrphanDelegate : public TestWindowDelegate {
140 DestroyOrphanDelegate() : window_(NULL) {
143 void set_window(Window* window) { window_ = window; }
145 virtual void OnWindowDestroyed() OVERRIDE {
146 EXPECT_FALSE(window_->parent());
151 DISALLOW_COPY_AND_ASSIGN(DestroyOrphanDelegate);
154 // Used in verifying mouse capture.
155 class CaptureWindowDelegateImpl : public TestWindowDelegate {
157 CaptureWindowDelegateImpl() {
162 capture_changed_event_count_ = 0;
163 capture_lost_count_ = 0;
164 mouse_event_count_ = 0;
165 touch_event_count_ = 0;
166 gesture_event_count_ = 0;
169 int capture_changed_event_count() const {
170 return capture_changed_event_count_;
172 int capture_lost_count() const { return capture_lost_count_; }
173 int mouse_event_count() const { return mouse_event_count_; }
174 int touch_event_count() const { return touch_event_count_; }
175 int gesture_event_count() const { return gesture_event_count_; }
177 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
178 if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
179 capture_changed_event_count_++;
180 mouse_event_count_++;
182 virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
183 touch_event_count_++;
185 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
186 gesture_event_count_++;
188 virtual void OnCaptureLost() OVERRIDE {
189 capture_lost_count_++;
193 int capture_changed_event_count_;
194 int capture_lost_count_;
195 int mouse_event_count_;
196 int touch_event_count_;
197 int gesture_event_count_;
199 DISALLOW_COPY_AND_ASSIGN(CaptureWindowDelegateImpl);
202 // Keeps track of the location of the gesture.
203 class GestureTrackPositionDelegate : public TestWindowDelegate {
205 GestureTrackPositionDelegate() {}
207 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
208 position_ = event->location();
209 event->StopPropagation();
212 const gfx::Point& position() const { return position_; }
215 gfx::Point position_;
217 DISALLOW_COPY_AND_ASSIGN(GestureTrackPositionDelegate);
220 base::TimeDelta getTime() {
221 return ui::EventTimeForNow();
224 class SelfEventHandlingWindowDelegate : public TestWindowDelegate {
226 SelfEventHandlingWindowDelegate() {}
228 virtual bool ShouldDescendIntoChildForEventHandling(
230 const gfx::Point& location) OVERRIDE {
235 DISALLOW_COPY_AND_ASSIGN(SelfEventHandlingWindowDelegate);
238 // The delegate deletes itself when the window is being destroyed.
239 class DestroyWindowDelegate : public TestWindowDelegate {
241 DestroyWindowDelegate() {}
244 virtual ~DestroyWindowDelegate() {}
246 // Overridden from WindowDelegate.
247 virtual void OnWindowDestroyed() OVERRIDE {
251 DISALLOW_COPY_AND_ASSIGN(DestroyWindowDelegate);
256 TEST_F(WindowTest, GetChildById) {
257 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
258 scoped_ptr<Window> w11(CreateTestWindowWithId(11, w1.get()));
259 scoped_ptr<Window> w111(CreateTestWindowWithId(111, w11.get()));
260 scoped_ptr<Window> w12(CreateTestWindowWithId(12, w1.get()));
262 EXPECT_EQ(NULL, w1->GetChildById(57));
263 EXPECT_EQ(w12.get(), w1->GetChildById(12));
264 EXPECT_EQ(w111.get(), w1->GetChildById(111));
267 // Make sure that Window::Contains correctly handles children, grandchildren,
268 // and not containing NULL or parents.
269 TEST_F(WindowTest, Contains) {
271 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
273 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
275 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
277 parent.AddChild(&child1);
278 child1.AddChild(&child2);
280 EXPECT_TRUE(parent.Contains(&parent));
281 EXPECT_TRUE(parent.Contains(&child1));
282 EXPECT_TRUE(parent.Contains(&child2));
284 EXPECT_FALSE(parent.Contains(NULL));
285 EXPECT_FALSE(child1.Contains(&parent));
286 EXPECT_FALSE(child2.Contains(&child1));
289 TEST_F(WindowTest, ContainsPointInRoot) {
290 scoped_ptr<Window> w(
291 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 5, 5),
293 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(9, 9)));
294 EXPECT_TRUE(w->ContainsPointInRoot(gfx::Point(10, 10)));
295 EXPECT_TRUE(w->ContainsPointInRoot(gfx::Point(14, 14)));
296 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(15, 15)));
297 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(20, 20)));
300 TEST_F(WindowTest, ContainsPoint) {
301 scoped_ptr<Window> w(
302 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 5, 5),
304 EXPECT_TRUE(w->ContainsPoint(gfx::Point(0, 0)));
305 EXPECT_TRUE(w->ContainsPoint(gfx::Point(4, 4)));
306 EXPECT_FALSE(w->ContainsPoint(gfx::Point(5, 5)));
307 EXPECT_FALSE(w->ContainsPoint(gfx::Point(10, 10)));
310 TEST_F(WindowTest, ConvertPointToWindow) {
311 // Window::ConvertPointToWindow is mostly identical to
312 // Layer::ConvertPointToLayer, except NULL values for |source| are permitted,
313 // in which case the function just returns.
314 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
315 gfx::Point reference_point(100, 100);
316 gfx::Point test_point = reference_point;
317 Window::ConvertPointToTarget(NULL, w1.get(), &test_point);
318 EXPECT_EQ(reference_point, test_point);
321 TEST_F(WindowTest, MoveCursorTo) {
322 scoped_ptr<Window> w1(
323 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
325 scoped_ptr<Window> w11(
326 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
327 scoped_ptr<Window> w111(
328 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
329 scoped_ptr<Window> w1111(
330 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
332 Window* root = root_window();
333 root->MoveCursorTo(gfx::Point(10, 10));
335 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
336 w1->MoveCursorTo(gfx::Point(10, 10));
338 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
339 w11->MoveCursorTo(gfx::Point(10, 10));
341 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
342 w111->MoveCursorTo(gfx::Point(10, 10));
344 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
345 w1111->MoveCursorTo(gfx::Point(10, 10));
347 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
350 TEST_F(WindowTest, ContainsMouse) {
351 scoped_ptr<Window> w(
352 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
355 WindowTestApi w_test_api(w.get());
356 Window* root = root_window();
357 root->MoveCursorTo(gfx::Point(10, 10));
358 EXPECT_TRUE(w_test_api.ContainsMouse());
359 root->MoveCursorTo(gfx::Point(9, 10));
360 EXPECT_FALSE(w_test_api.ContainsMouse());
363 // Test Window::ConvertPointToWindow() with transform to root_window.
364 #if defined(USE_OZONE)
365 // TODO(rjkroege): Add cursor support in ozone: http://crbug.com/252315.
366 TEST_F(WindowTest, DISABLED_MoveCursorToWithTransformRootWindow) {
368 TEST_F(WindowTest, MoveCursorToWithTransformRootWindow) {
370 gfx::Transform transform;
371 transform.Translate(100.0, 100.0);
372 transform.Rotate(90.0);
373 transform.Scale(2.0, 5.0);
374 dispatcher()->host()->SetTransform(transform);
375 dispatcher()->host()->MoveCursorTo(gfx::Point(10, 10));
377 gfx::Point mouse_location;
378 EXPECT_TRUE(dispatcher()->host()->QueryMouseLocation(&mouse_location));
379 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.OD
380 EXPECT_EQ("50,120", mouse_location.ToString());
382 EXPECT_EQ("10,10", gfx::Screen::GetScreenFor(
383 root_window())->GetCursorScreenPoint().ToString());
386 // Tests Window::ConvertPointToWindow() with transform to non-root windows.
387 TEST_F(WindowTest, MoveCursorToWithTransformWindow) {
388 scoped_ptr<Window> w1(
389 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
392 gfx::Transform transform1;
393 transform1.Scale(2, 2);
394 w1->SetTransform(transform1);
395 w1->MoveCursorTo(gfx::Point(10, 10));
397 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
399 gfx::Transform transform2;
400 transform2.Translate(-10, 20);
401 w1->SetTransform(transform2);
402 w1->MoveCursorTo(gfx::Point(10, 10));
404 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
406 gfx::Transform transform3;
407 transform3.Rotate(90.0);
408 w1->SetTransform(transform3);
409 w1->MoveCursorTo(gfx::Point(5, 5));
411 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
413 gfx::Transform transform4;
414 transform4.Translate(100.0, 100.0);
415 transform4.Rotate(90.0);
416 transform4.Scale(2.0, 5.0);
417 w1->SetTransform(transform4);
418 w1->MoveCursorTo(gfx::Point(10, 10));
420 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
423 // Test Window::ConvertPointToWindow() with complex transforms to both root and
425 // Test Window::ConvertPointToWindow() with transform to root_window.
426 #if defined(USE_OZONE)
427 // TODO(rjkroege): Add cursor support in ozone: http://crbug.com/252315.
428 TEST_F(WindowTest, DISABLED_MoveCursorToWithComplexTransform) {
430 TEST_F(WindowTest, MoveCursorToWithComplexTransform) {
432 scoped_ptr<Window> w1(
433 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
435 scoped_ptr<Window> w11(
436 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
437 scoped_ptr<Window> w111(
438 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
439 scoped_ptr<Window> w1111(
440 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
442 Window* root = root_window();
444 // The root window expects transforms that produce integer rects.
445 gfx::Transform root_transform;
446 root_transform.Translate(60.0, 70.0);
447 root_transform.Rotate(-90.0);
448 root_transform.Translate(-50.0, -50.0);
449 root_transform.Scale(2.0, 3.0);
451 gfx::Transform transform;
452 transform.Translate(10.0, 20.0);
453 transform.Rotate(10.0);
454 transform.Scale(0.3f, 0.5f);
455 dispatcher()->host()->SetTransform(root_transform);
456 w1->SetTransform(transform);
457 w11->SetTransform(transform);
458 w111->SetTransform(transform);
459 w1111->SetTransform(transform);
461 w1111->MoveCursorTo(gfx::Point(10, 10));
464 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.
465 gfx::Point mouse_location;
466 EXPECT_TRUE(dispatcher()->host()->QueryMouseLocation(&mouse_location));
467 EXPECT_EQ("169,80", mouse_location.ToString());
470 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
473 TEST_F(WindowTest, HitTest) {
474 Window w1(new ColorTestWindowDelegate(SK_ColorWHITE));
476 w1.Init(aura::WINDOW_LAYER_TEXTURED);
477 w1.SetBounds(gfx::Rect(10, 20, 50, 60));
481 // Points are in the Window's coordinates.
482 EXPECT_TRUE(w1.HitTest(gfx::Point(1, 1)));
483 EXPECT_FALSE(w1.HitTest(gfx::Point(-1, -1)));
485 // TODO(beng): clip Window to parent.
488 TEST_F(WindowTest, HitTestMask) {
489 MaskedWindowDelegate d1(gfx::Rect(5, 6, 20, 30));
491 w1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
492 w1.SetBounds(gfx::Rect(10, 20, 50, 60));
496 // Points inside the mask.
497 EXPECT_TRUE(w1.HitTest(gfx::Point(5, 6))); // top-left
498 EXPECT_TRUE(w1.HitTest(gfx::Point(15, 21))); // center
499 EXPECT_TRUE(w1.HitTest(gfx::Point(24, 35))); // bottom-right
501 // Points outside the mask.
502 EXPECT_FALSE(w1.HitTest(gfx::Point(0, 0)));
503 EXPECT_FALSE(w1.HitTest(gfx::Point(60, 80)));
504 EXPECT_FALSE(w1.HitTest(gfx::Point(4, 6)));
505 EXPECT_FALSE(w1.HitTest(gfx::Point(5, 5)));
506 EXPECT_FALSE(w1.HitTest(gfx::Point(25, 36)));
509 TEST_F(WindowTest, GetEventHandlerForPoint) {
510 scoped_ptr<Window> w1(
511 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
513 scoped_ptr<Window> w11(
514 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
515 scoped_ptr<Window> w111(
516 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
517 scoped_ptr<Window> w1111(
518 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
519 scoped_ptr<Window> w12(
520 CreateTestWindow(SK_ColorMAGENTA, 12, gfx::Rect(10, 420, 25, 25),
522 scoped_ptr<Window> w121(
523 CreateTestWindow(SK_ColorYELLOW, 121, gfx::Rect(5, 5, 5, 5), w12.get()));
524 scoped_ptr<Window> w13(
525 CreateTestWindow(SK_ColorGRAY, 13, gfx::Rect(5, 470, 50, 50), w1.get()));
527 Window* root = root_window();
528 w1->parent()->SetBounds(gfx::Rect(500, 500));
529 EXPECT_EQ(NULL, root->GetEventHandlerForPoint(gfx::Point(5, 5)));
530 EXPECT_EQ(w1.get(), root->GetEventHandlerForPoint(gfx::Point(11, 11)));
531 EXPECT_EQ(w11.get(), root->GetEventHandlerForPoint(gfx::Point(16, 16)));
532 EXPECT_EQ(w111.get(), root->GetEventHandlerForPoint(gfx::Point(21, 21)));
533 EXPECT_EQ(w1111.get(), root->GetEventHandlerForPoint(gfx::Point(26, 26)));
534 EXPECT_EQ(w12.get(), root->GetEventHandlerForPoint(gfx::Point(21, 431)));
535 EXPECT_EQ(w121.get(), root->GetEventHandlerForPoint(gfx::Point(26, 436)));
536 EXPECT_EQ(w13.get(), root->GetEventHandlerForPoint(gfx::Point(26, 481)));
539 TEST_F(WindowTest, GetEventHandlerForPointWithOverride) {
540 // If our child is flush to our top-left corner he gets events just inside the
542 scoped_ptr<Window> parent(
543 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 20, 400, 500),
545 scoped_ptr<Window> child(
546 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(0, 0, 60, 70), parent.get()));
547 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
548 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(1, 1)));
550 // We can override the hit test bounds of the parent to make the parent grab
551 // events along that edge.
552 parent->set_hit_test_bounds_override_inner(gfx::Insets(1, 1, 1, 1));
553 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
554 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(1, 1)));
557 TEST_F(WindowTest, GetEventHandlerForPointWithOverrideDescendingOrder) {
558 scoped_ptr<SelfEventHandlingWindowDelegate> parent_delegate(
559 new SelfEventHandlingWindowDelegate);
560 scoped_ptr<Window> parent(CreateTestWindowWithDelegate(
561 parent_delegate.get(), 1, gfx::Rect(10, 20, 400, 500), root_window()));
562 scoped_ptr<Window> child(
563 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(0, 0, 390, 480),
566 // We can override ShouldDescendIntoChildForEventHandling to make the parent
568 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
569 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(50, 50)));
572 TEST_F(WindowTest, GetTopWindowContainingPoint) {
573 Window* root = root_window();
574 root->SetBounds(gfx::Rect(0, 0, 300, 300));
576 scoped_ptr<Window> w1(
577 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 100, 100),
579 scoped_ptr<Window> w11(
580 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(0, 0, 120, 120), w1.get()));
582 scoped_ptr<Window> w2(
583 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(5, 5, 55, 55),
586 scoped_ptr<Window> w3(
587 CreateTestWindowWithDelegate(
588 NULL, 3, gfx::Rect(200, 200, 100, 100), root_window()));
589 scoped_ptr<Window> w31(
590 CreateTestWindow(SK_ColorCYAN, 31, gfx::Rect(0, 0, 50, 50), w3.get()));
591 scoped_ptr<Window> w311(
592 CreateTestWindow(SK_ColorBLUE, 311, gfx::Rect(0, 0, 10, 10), w31.get()));
594 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(0, 0)));
595 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(5, 5)));
596 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(10, 10)));
597 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(59, 59)));
598 EXPECT_EQ(w1.get(), root->GetTopWindowContainingPoint(gfx::Point(60, 60)));
599 EXPECT_EQ(w1.get(), root->GetTopWindowContainingPoint(gfx::Point(109, 109)));
600 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(110, 110)));
601 EXPECT_EQ(w31.get(), root->GetTopWindowContainingPoint(gfx::Point(200, 200)));
602 EXPECT_EQ(w31.get(), root->GetTopWindowContainingPoint(gfx::Point(220, 220)));
603 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(260, 260)));
606 TEST_F(WindowTest, GetToplevelWindow) {
607 const gfx::Rect kBounds(0, 0, 10, 10);
608 TestWindowDelegate delegate;
610 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
611 scoped_ptr<Window> w11(
612 CreateTestWindowWithDelegate(&delegate, 11, kBounds, w1.get()));
613 scoped_ptr<Window> w111(CreateTestWindowWithId(111, w11.get()));
614 scoped_ptr<Window> w1111(
615 CreateTestWindowWithDelegate(&delegate, 1111, kBounds, w111.get()));
617 EXPECT_TRUE(root_window()->GetToplevelWindow() == NULL);
618 EXPECT_TRUE(w1->GetToplevelWindow() == NULL);
619 EXPECT_EQ(w11.get(), w11->GetToplevelWindow());
620 EXPECT_EQ(w11.get(), w111->GetToplevelWindow());
621 EXPECT_EQ(w11.get(), w1111->GetToplevelWindow());
624 class AddedToRootWindowObserver : public WindowObserver {
626 AddedToRootWindowObserver() : called_(false) {}
628 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
632 bool called() const { return called_; }
637 DISALLOW_COPY_AND_ASSIGN(AddedToRootWindowObserver);
640 TEST_F(WindowTest, WindowAddedToRootWindowShouldNotifyChildAndNotParent) {
641 AddedToRootWindowObserver parent_observer;
642 AddedToRootWindowObserver child_observer;
643 scoped_ptr<Window> parent_window(CreateTestWindowWithId(1, root_window()));
644 scoped_ptr<Window> child_window(new Window(NULL));
645 child_window->Init(aura::WINDOW_LAYER_TEXTURED);
646 child_window->Show();
648 parent_window->AddObserver(&parent_observer);
649 child_window->AddObserver(&child_observer);
651 parent_window->AddChild(child_window.get());
653 EXPECT_FALSE(parent_observer.called());
654 EXPECT_TRUE(child_observer.called());
656 parent_window->RemoveObserver(&parent_observer);
657 child_window->RemoveObserver(&child_observer);
660 // Various destruction assertions.
661 TEST_F(WindowTest, DestroyTest) {
662 DestroyTrackingDelegateImpl parent_delegate;
663 ChildWindowDelegateImpl child_delegate(&parent_delegate);
665 scoped_ptr<Window> parent(
666 CreateTestWindowWithDelegate(&parent_delegate, 0, gfx::Rect(),
668 CreateTestWindowWithDelegate(&child_delegate, 0, gfx::Rect(), parent.get());
670 // Both the parent and child should have been destroyed.
671 EXPECT_EQ(1, parent_delegate.destroying_count());
672 EXPECT_EQ(1, parent_delegate.destroyed_count());
673 EXPECT_EQ(1, child_delegate.destroying_count());
674 EXPECT_EQ(1, child_delegate.destroyed_count());
677 // Tests that a window is orphaned before OnWindowDestroyed is called.
678 TEST_F(WindowTest, OrphanedBeforeOnDestroyed) {
679 TestWindowDelegate parent_delegate;
680 DestroyOrphanDelegate child_delegate;
682 scoped_ptr<Window> parent(
683 CreateTestWindowWithDelegate(&parent_delegate, 0, gfx::Rect(),
685 scoped_ptr<Window> child(CreateTestWindowWithDelegate(&child_delegate, 0,
686 gfx::Rect(), parent.get()));
687 child_delegate.set_window(child.get());
691 // Make sure StackChildAtTop moves both the window and layer to the front.
692 TEST_F(WindowTest, StackChildAtTop) {
694 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
696 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
698 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
700 parent.AddChild(&child1);
701 parent.AddChild(&child2);
702 ASSERT_EQ(2u, parent.children().size());
703 EXPECT_EQ(&child1, parent.children()[0]);
704 EXPECT_EQ(&child2, parent.children()[1]);
705 ASSERT_EQ(2u, parent.layer()->children().size());
706 EXPECT_EQ(child1.layer(), parent.layer()->children()[0]);
707 EXPECT_EQ(child2.layer(), parent.layer()->children()[1]);
709 parent.StackChildAtTop(&child1);
710 ASSERT_EQ(2u, parent.children().size());
711 EXPECT_EQ(&child1, parent.children()[1]);
712 EXPECT_EQ(&child2, parent.children()[0]);
713 ASSERT_EQ(2u, parent.layer()->children().size());
714 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
715 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
718 // Make sure StackChildBelow works.
719 TEST_F(WindowTest, StackChildBelow) {
721 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
723 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
726 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
729 child3.Init(aura::WINDOW_LAYER_NOT_DRAWN);
732 parent.AddChild(&child1);
733 parent.AddChild(&child2);
734 parent.AddChild(&child3);
735 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent));
737 parent.StackChildBelow(&child1, &child2);
738 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent));
740 parent.StackChildBelow(&child2, &child1);
741 EXPECT_EQ("2 1 3", ChildWindowIDsAsString(&parent));
743 parent.StackChildBelow(&child3, &child2);
744 EXPECT_EQ("3 2 1", ChildWindowIDsAsString(&parent));
746 parent.StackChildBelow(&child3, &child1);
747 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(&parent));
750 // Various assertions for StackChildAbove.
751 TEST_F(WindowTest, StackChildAbove) {
753 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
755 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
757 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
759 child3.Init(aura::WINDOW_LAYER_NOT_DRAWN);
761 parent.AddChild(&child1);
762 parent.AddChild(&child2);
764 // Move 1 in front of 2.
765 parent.StackChildAbove(&child1, &child2);
766 ASSERT_EQ(2u, parent.children().size());
767 EXPECT_EQ(&child2, parent.children()[0]);
768 EXPECT_EQ(&child1, parent.children()[1]);
769 ASSERT_EQ(2u, parent.layer()->children().size());
770 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
771 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
773 // Add 3, resulting in order [2, 1, 3], then move 2 in front of 1, resulting
775 parent.AddChild(&child3);
776 parent.StackChildAbove(&child2, &child1);
777 ASSERT_EQ(3u, parent.children().size());
778 EXPECT_EQ(&child1, parent.children()[0]);
779 EXPECT_EQ(&child2, parent.children()[1]);
780 EXPECT_EQ(&child3, parent.children()[2]);
781 ASSERT_EQ(3u, parent.layer()->children().size());
782 EXPECT_EQ(child1.layer(), parent.layer()->children()[0]);
783 EXPECT_EQ(child2.layer(), parent.layer()->children()[1]);
784 EXPECT_EQ(child3.layer(), parent.layer()->children()[2]);
786 // Move 1 in front of 3, resulting in [2, 3, 1].
787 parent.StackChildAbove(&child1, &child3);
788 ASSERT_EQ(3u, parent.children().size());
789 EXPECT_EQ(&child2, parent.children()[0]);
790 EXPECT_EQ(&child3, parent.children()[1]);
791 EXPECT_EQ(&child1, parent.children()[2]);
792 ASSERT_EQ(3u, parent.layer()->children().size());
793 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
794 EXPECT_EQ(child3.layer(), parent.layer()->children()[1]);
795 EXPECT_EQ(child1.layer(), parent.layer()->children()[2]);
797 // Moving 1 in front of 2 should lower it, resulting in [2, 1, 3].
798 parent.StackChildAbove(&child1, &child2);
799 ASSERT_EQ(3u, parent.children().size());
800 EXPECT_EQ(&child2, parent.children()[0]);
801 EXPECT_EQ(&child1, parent.children()[1]);
802 EXPECT_EQ(&child3, parent.children()[2]);
803 ASSERT_EQ(3u, parent.layer()->children().size());
804 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
805 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
806 EXPECT_EQ(child3.layer(), parent.layer()->children()[2]);
809 // Various capture assertions.
810 TEST_F(WindowTest, CaptureTests) {
811 CaptureWindowDelegateImpl delegate;
812 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
813 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
814 EXPECT_FALSE(window->HasCapture());
816 delegate.ResetCounts();
819 window->SetCapture();
820 EXPECT_TRUE(window->HasCapture());
821 EXPECT_EQ(0, delegate.capture_lost_count());
822 EXPECT_EQ(0, delegate.capture_changed_event_count());
823 EventGenerator generator(root_window(), gfx::Point(50, 50));
824 generator.PressLeftButton();
825 EXPECT_EQ(1, delegate.mouse_event_count());
826 generator.ReleaseLeftButton();
828 EXPECT_EQ(2, delegate.mouse_event_count());
829 delegate.ResetCounts();
831 ui::TouchEvent touchev(
832 ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), 0, getTime());
833 DispatchEventUsingWindowDispatcher(&touchev);
834 EXPECT_EQ(1, delegate.touch_event_count());
835 delegate.ResetCounts();
837 window->ReleaseCapture();
838 EXPECT_FALSE(window->HasCapture());
839 EXPECT_EQ(1, delegate.capture_lost_count());
840 EXPECT_EQ(1, delegate.capture_changed_event_count());
841 EXPECT_EQ(1, delegate.mouse_event_count());
842 EXPECT_EQ(0, delegate.touch_event_count());
844 generator.PressLeftButton();
845 EXPECT_EQ(1, delegate.mouse_event_count());
847 ui::TouchEvent touchev2(
848 ui::ET_TOUCH_PRESSED, gfx::Point(250, 250), 1, getTime());
849 DispatchEventUsingWindowDispatcher(&touchev2);
850 EXPECT_EQ(0, delegate.touch_event_count());
852 // Removing the capture window from parent should reset the capture window
853 // in the root window.
854 window->SetCapture();
855 EXPECT_EQ(window.get(), aura::client::GetCaptureWindow(root_window()));
856 window->parent()->RemoveChild(window.get());
857 EXPECT_FALSE(window->HasCapture());
858 EXPECT_EQ(NULL, aura::client::GetCaptureWindow(root_window()));
861 TEST_F(WindowTest, TouchCaptureCancelsOtherTouches) {
862 CaptureWindowDelegateImpl delegate1;
863 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
864 &delegate1, 0, gfx::Rect(0, 0, 50, 50), root_window()));
865 CaptureWindowDelegateImpl delegate2;
866 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
867 &delegate2, 0, gfx::Rect(50, 50, 50, 50), root_window()));
870 ui::TouchEvent press(
871 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
872 DispatchEventUsingWindowDispatcher(&press);
873 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
874 EXPECT_EQ(2, delegate1.gesture_event_count());
875 delegate1.ResetCounts();
877 // Capturing to w2 should cause the touch to be canceled.
879 EXPECT_EQ(1, delegate1.touch_event_count());
880 EXPECT_EQ(0, delegate2.touch_event_count());
881 delegate1.ResetCounts();
882 delegate2.ResetCounts();
884 // Events now go to w2.
885 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, getTime());
886 DispatchEventUsingWindowDispatcher(&move);
887 EXPECT_EQ(0, delegate1.gesture_event_count());
888 EXPECT_EQ(0, delegate1.touch_event_count());
889 EXPECT_EQ(0, delegate2.gesture_event_count());
890 EXPECT_EQ(1, delegate2.touch_event_count());
892 ui::TouchEvent release(
893 ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, getTime());
894 DispatchEventUsingWindowDispatcher(&release);
895 EXPECT_EQ(0, delegate1.gesture_event_count());
896 EXPECT_EQ(0, delegate2.gesture_event_count());
898 // A new press is captured by w2.
899 ui::TouchEvent press2(
900 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
901 DispatchEventUsingWindowDispatcher(&press2);
902 EXPECT_EQ(0, delegate1.gesture_event_count());
903 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
904 EXPECT_EQ(2, delegate2.gesture_event_count());
905 delegate1.ResetCounts();
906 delegate2.ResetCounts();
908 // And releasing capture changes nothing.
909 w2->ReleaseCapture();
910 EXPECT_EQ(0, delegate1.gesture_event_count());
911 EXPECT_EQ(0, delegate1.touch_event_count());
912 EXPECT_EQ(0, delegate2.gesture_event_count());
913 EXPECT_EQ(0, delegate2.touch_event_count());
916 TEST_F(WindowTest, TouchCaptureDoesntCancelCapturedTouches) {
917 CaptureWindowDelegateImpl delegate;
918 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
919 &delegate, 0, gfx::Rect(0, 0, 50, 50), root_window()));
921 ui::TouchEvent press(
922 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
923 DispatchEventUsingWindowDispatcher(&press);
925 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
926 EXPECT_EQ(2, delegate.gesture_event_count());
927 EXPECT_EQ(1, delegate.touch_event_count());
928 delegate.ResetCounts();
930 window->SetCapture();
931 EXPECT_EQ(0, delegate.gesture_event_count());
932 EXPECT_EQ(0, delegate.touch_event_count());
933 delegate.ResetCounts();
935 // On move We will get TOUCH_MOVED, GESTURE_TAP_CANCEL,
936 // GESTURE_SCROLL_START and GESTURE_SCROLL_UPDATE.
937 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, getTime());
938 DispatchEventUsingWindowDispatcher(&move);
939 EXPECT_EQ(1, delegate.touch_event_count());
940 EXPECT_EQ(3, delegate.gesture_event_count());
941 delegate.ResetCounts();
943 // Release capture shouldn't change anything.
944 window->ReleaseCapture();
945 EXPECT_EQ(0, delegate.touch_event_count());
946 EXPECT_EQ(0, delegate.gesture_event_count());
947 delegate.ResetCounts();
949 // On move we still get TOUCH_MOVED and GESTURE_SCROLL_UPDATE.
950 ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(10, 30), 0, getTime());
951 DispatchEventUsingWindowDispatcher(&move2);
952 EXPECT_EQ(1, delegate.touch_event_count());
953 EXPECT_EQ(1, delegate.gesture_event_count());
954 delegate.ResetCounts();
956 // And on release we get TOUCH_RELEASED, GESTURE_SCROLL_END, GESTURE_END
957 ui::TouchEvent release(
958 ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, getTime());
959 DispatchEventUsingWindowDispatcher(&release);
960 EXPECT_EQ(1, delegate.touch_event_count());
961 EXPECT_EQ(2, delegate.gesture_event_count());
965 // Assertions around SetCapture() and touch/gestures.
966 TEST_F(WindowTest, TransferCaptureTouchEvents) {
968 CaptureWindowDelegateImpl d1;
969 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
970 &d1, 0, gfx::Rect(0, 0, 20, 20), root_window()));
971 ui::TouchEvent p1(ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
972 DispatchEventUsingWindowDispatcher(&p1);
973 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
974 EXPECT_EQ(1, d1.touch_event_count());
975 EXPECT_EQ(2, d1.gesture_event_count());
978 // Touch on |w2| with a different id.
979 CaptureWindowDelegateImpl d2;
980 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
981 &d2, 0, gfx::Rect(40, 0, 40, 20), root_window()));
982 ui::TouchEvent p2(ui::ET_TOUCH_PRESSED, gfx::Point(41, 10), 1, getTime());
983 DispatchEventUsingWindowDispatcher(&p2);
984 EXPECT_EQ(0, d1.touch_event_count());
985 EXPECT_EQ(0, d1.gesture_event_count());
986 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN for new target window.
987 EXPECT_EQ(1, d2.touch_event_count());
988 EXPECT_EQ(2, d2.gesture_event_count());
992 // Set capture on |w2|, this should send a cancel (TAP_CANCEL, END) to |w1|
995 EXPECT_EQ(1, d1.touch_event_count());
996 EXPECT_EQ(2, d1.gesture_event_count());
997 EXPECT_EQ(0, d2.touch_event_count());
998 EXPECT_EQ(0, d2.gesture_event_count());
1002 CaptureWindowDelegateImpl d3;
1003 scoped_ptr<Window> w3(CreateTestWindowWithDelegate(
1004 &d3, 0, gfx::Rect(0, 0, 100, 101), root_window()));
1005 // Set capture on w3. No new events should be received.
1006 // Note this difference in behavior between the first and second capture
1007 // is confusing and error prone. http://crbug.com/236930
1009 EXPECT_EQ(0, d1.touch_event_count());
1010 EXPECT_EQ(0, d1.gesture_event_count());
1011 EXPECT_EQ(0, d2.touch_event_count());
1012 EXPECT_EQ(0, d2.gesture_event_count());
1013 EXPECT_EQ(0, d3.touch_event_count());
1014 EXPECT_EQ(0, d3.gesture_event_count());
1016 // Move touch id originally associated with |w2|. Since capture was transfered
1017 // from 2 to 3 only |w3| should get the event.
1018 ui::TouchEvent m3(ui::ET_TOUCH_MOVED, gfx::Point(110, 105), 1, getTime());
1019 DispatchEventUsingWindowDispatcher(&m3);
1020 EXPECT_EQ(0, d1.touch_event_count());
1021 EXPECT_EQ(0, d1.gesture_event_count());
1022 EXPECT_EQ(0, d2.touch_event_count());
1023 EXPECT_EQ(0, d2.gesture_event_count());
1024 // |w3| gets a TOUCH_MOVE, TAP_CANCEL and two scroll related events.
1025 EXPECT_EQ(1, d3.touch_event_count());
1026 EXPECT_EQ(3, d3.gesture_event_count());
1031 // When we release capture, no touches are canceled.
1032 w3->ReleaseCapture();
1033 EXPECT_EQ(0, d1.touch_event_count());
1034 EXPECT_EQ(0, d1.gesture_event_count());
1035 EXPECT_EQ(0, d2.touch_event_count());
1036 EXPECT_EQ(0, d2.gesture_event_count());
1037 EXPECT_EQ(0, d3.touch_event_count());
1038 EXPECT_EQ(0, d3.gesture_event_count());
1040 // And when we move the touch again, |w3| still gets the events.
1041 ui::TouchEvent m4(ui::ET_TOUCH_MOVED, gfx::Point(120, 105), 1, getTime());
1042 DispatchEventUsingWindowDispatcher(&m4);
1043 EXPECT_EQ(0, d1.touch_event_count());
1044 EXPECT_EQ(0, d1.gesture_event_count());
1045 EXPECT_EQ(0, d2.touch_event_count());
1046 EXPECT_EQ(0, d2.gesture_event_count());
1047 EXPECT_EQ(1, d3.touch_event_count());
1048 EXPECT_EQ(1, d3.gesture_event_count());
1054 // Changes capture while capture is already ongoing.
1055 TEST_F(WindowTest, ChangeCaptureWhileMouseDown) {
1056 CaptureWindowDelegateImpl delegate;
1057 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
1058 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1059 CaptureWindowDelegateImpl delegate2;
1060 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
1061 &delegate2, 0, gfx::Rect(20, 20, 20, 20), root_window()));
1063 // Execute the scheduled draws so that mouse events are not
1065 RunAllPendingInMessageLoop();
1067 EXPECT_FALSE(window->HasCapture());
1070 delegate.ResetCounts();
1071 window->SetCapture();
1072 EXPECT_TRUE(window->HasCapture());
1073 EXPECT_EQ(0, delegate.capture_lost_count());
1074 EXPECT_EQ(0, delegate.capture_changed_event_count());
1075 EventGenerator generator(root_window(), gfx::Point(50, 50));
1076 generator.PressLeftButton();
1077 EXPECT_EQ(0, delegate.capture_lost_count());
1078 EXPECT_EQ(0, delegate.capture_changed_event_count());
1079 EXPECT_EQ(1, delegate.mouse_event_count());
1081 // Set capture to |w2|, should implicitly unset capture for |window|.
1082 delegate.ResetCounts();
1083 delegate2.ResetCounts();
1086 generator.MoveMouseTo(gfx::Point(40, 40), 2);
1087 EXPECT_EQ(1, delegate.capture_lost_count());
1088 EXPECT_EQ(1, delegate.capture_changed_event_count());
1089 EXPECT_EQ(1, delegate.mouse_event_count());
1090 EXPECT_EQ(2, delegate2.mouse_event_count());
1093 // Verifies capture is reset when a window is destroyed.
1094 TEST_F(WindowTest, ReleaseCaptureOnDestroy) {
1095 CaptureWindowDelegateImpl delegate;
1096 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
1097 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1098 EXPECT_FALSE(window->HasCapture());
1101 window->SetCapture();
1102 EXPECT_TRUE(window->HasCapture());
1104 // Destroy the window.
1107 // Make sure the root window doesn't reference the window anymore.
1108 EXPECT_EQ(NULL, dispatcher()->mouse_pressed_handler());
1109 EXPECT_EQ(NULL, aura::client::GetCaptureWindow(root_window()));
1112 TEST_F(WindowTest, GetBoundsInRootWindow) {
1113 scoped_ptr<Window> viewport(CreateTestWindowWithBounds(
1114 gfx::Rect(0, 0, 300, 300), root_window()));
1115 scoped_ptr<Window> child(CreateTestWindowWithBounds(
1116 gfx::Rect(0, 0, 100, 100), viewport.get()));
1118 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1120 // The |child| window's screen bounds should move along with the |viewport|.
1121 viewport->SetBounds(gfx::Rect(-100, -100, 300, 300));
1122 EXPECT_EQ("-100,-100 100x100", child->GetBoundsInRootWindow().ToString());
1124 // The |child| window is moved to the 0,0 in screen coordinates.
1125 // |GetBoundsInRootWindow()| should return 0,0.
1126 child->SetBounds(gfx::Rect(100, 100, 100, 100));
1127 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1130 class MouseEnterExitWindowDelegate : public TestWindowDelegate {
1132 MouseEnterExitWindowDelegate() : entered_(false), exited_(false) {}
1134 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
1135 switch (event->type()) {
1136 case ui::ET_MOUSE_ENTERED:
1137 EXPECT_TRUE(event->flags() & ui::EF_IS_SYNTHESIZED);
1140 case ui::ET_MOUSE_EXITED:
1141 EXPECT_TRUE(event->flags() & ui::EF_IS_SYNTHESIZED);
1149 bool entered() const { return entered_; }
1150 bool exited() const { return exited_; }
1152 // Clear the entered / exited states.
1153 void ResetExpectations() {
1162 DISALLOW_COPY_AND_ASSIGN(MouseEnterExitWindowDelegate);
1166 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1167 // mouse transitions from window to window.
1168 TEST_F(WindowTest, MouseEnterExit) {
1169 MouseEnterExitWindowDelegate d1;
1170 scoped_ptr<Window> w1(
1171 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1173 MouseEnterExitWindowDelegate d2;
1174 scoped_ptr<Window> w2(
1175 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50),
1178 test::EventGenerator generator(root_window());
1179 generator.MoveMouseToCenterOf(w1.get());
1180 EXPECT_TRUE(d1.entered());
1181 EXPECT_FALSE(d1.exited());
1182 EXPECT_FALSE(d2.entered());
1183 EXPECT_FALSE(d2.exited());
1185 generator.MoveMouseToCenterOf(w2.get());
1186 EXPECT_TRUE(d1.entered());
1187 EXPECT_TRUE(d1.exited());
1188 EXPECT_TRUE(d2.entered());
1189 EXPECT_FALSE(d2.exited());
1192 // Verifies that the WindowDelegate receives MouseExit from ET_MOUSE_EXITED.
1193 TEST_F(WindowTest, WindowTreeHostExit) {
1194 MouseEnterExitWindowDelegate d1;
1195 scoped_ptr<Window> w1(
1196 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1199 test::EventGenerator generator(root_window());
1200 generator.MoveMouseToCenterOf(w1.get());
1201 EXPECT_TRUE(d1.entered());
1202 EXPECT_FALSE(d1.exited());
1203 d1.ResetExpectations();
1205 ui::MouseEvent exit_event(
1206 ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(), 0, 0);
1207 DispatchEventUsingWindowDispatcher(&exit_event);
1208 EXPECT_FALSE(d1.entered());
1209 EXPECT_TRUE(d1.exited());
1212 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1213 // mouse transitions from window to window, even if the entered window sets
1214 // and releases capture.
1215 TEST_F(WindowTest, MouseEnterExitWithClick) {
1216 MouseEnterExitWindowDelegate d1;
1217 scoped_ptr<Window> w1(
1218 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1220 MouseEnterExitWindowDelegate d2;
1221 scoped_ptr<Window> w2(
1222 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50),
1225 test::EventGenerator generator(root_window());
1226 generator.MoveMouseToCenterOf(w1.get());
1227 EXPECT_TRUE(d1.entered());
1228 EXPECT_FALSE(d1.exited());
1229 EXPECT_FALSE(d2.entered());
1230 EXPECT_FALSE(d2.exited());
1232 // Emmulate what Views does on a click by grabbing and releasing capture.
1233 generator.PressLeftButton();
1235 w1->ReleaseCapture();
1236 generator.ReleaseLeftButton();
1238 generator.MoveMouseToCenterOf(w2.get());
1239 EXPECT_TRUE(d1.entered());
1240 EXPECT_TRUE(d1.exited());
1241 EXPECT_TRUE(d2.entered());
1242 EXPECT_FALSE(d2.exited());
1245 TEST_F(WindowTest, MouseEnterExitWhenDeleteWithCapture) {
1246 MouseEnterExitWindowDelegate delegate;
1247 scoped_ptr<Window> window(
1248 CreateTestWindowWithDelegate(&delegate, 1, gfx::Rect(10, 10, 50, 50),
1251 test::EventGenerator generator(root_window());
1252 generator.MoveMouseToCenterOf(window.get());
1253 EXPECT_TRUE(delegate.entered());
1254 EXPECT_FALSE(delegate.exited());
1256 // Emmulate what Views does on a click by grabbing and releasing capture.
1257 generator.PressLeftButton();
1258 window->SetCapture();
1260 delegate.ResetExpectations();
1261 generator.MoveMouseTo(0, 0);
1262 EXPECT_FALSE(delegate.entered());
1263 EXPECT_FALSE(delegate.exited());
1265 delegate.ResetExpectations();
1267 EXPECT_FALSE(delegate.entered());
1268 EXPECT_FALSE(delegate.exited());
1271 // Verifies that enter / exits are sent if windows appear and are deleted
1272 // under the current mouse position..
1273 TEST_F(WindowTest, MouseEnterExitWithDelete) {
1274 MouseEnterExitWindowDelegate d1;
1275 scoped_ptr<Window> w1(
1276 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1279 test::EventGenerator generator(root_window());
1280 generator.MoveMouseToCenterOf(w1.get());
1281 EXPECT_TRUE(d1.entered());
1282 EXPECT_FALSE(d1.exited());
1283 d1.ResetExpectations();
1285 MouseEnterExitWindowDelegate d2;
1287 scoped_ptr<Window> w2(
1288 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1290 // Enters / exits can be sent asynchronously.
1291 RunAllPendingInMessageLoop();
1292 EXPECT_FALSE(d1.entered());
1293 EXPECT_TRUE(d1.exited());
1294 EXPECT_TRUE(d2.entered());
1295 EXPECT_FALSE(d2.exited());
1296 d1.ResetExpectations();
1297 d2.ResetExpectations();
1299 // Enters / exits can be sent asynchronously.
1300 RunAllPendingInMessageLoop();
1301 EXPECT_TRUE(d2.exited());
1302 EXPECT_TRUE(d1.entered());
1305 // Verifies that enter / exits are sent if windows appear and are hidden
1306 // under the current mouse position..
1307 TEST_F(WindowTest, MouseEnterExitWithHide) {
1308 MouseEnterExitWindowDelegate d1;
1309 scoped_ptr<Window> w1(
1310 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1313 test::EventGenerator generator(root_window());
1314 generator.MoveMouseToCenterOf(w1.get());
1315 EXPECT_TRUE(d1.entered());
1316 EXPECT_FALSE(d1.exited());
1318 MouseEnterExitWindowDelegate d2;
1319 scoped_ptr<Window> w2(
1320 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1322 // Enters / exits can be send asynchronously.
1323 RunAllPendingInMessageLoop();
1324 EXPECT_TRUE(d1.entered());
1325 EXPECT_TRUE(d1.exited());
1326 EXPECT_TRUE(d2.entered());
1327 EXPECT_FALSE(d2.exited());
1329 d1.ResetExpectations();
1331 // Enters / exits can be send asynchronously.
1332 RunAllPendingInMessageLoop();
1333 EXPECT_TRUE(d2.exited());
1334 EXPECT_TRUE(d1.entered());
1337 TEST_F(WindowTest, MouseEnterExitWithParentHide) {
1338 MouseEnterExitWindowDelegate d1;
1339 scoped_ptr<Window> w1(
1340 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1342 MouseEnterExitWindowDelegate d2;
1343 Window* w2 = CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1345 test::EventGenerator generator(root_window());
1346 generator.MoveMouseToCenterOf(w2);
1347 // Enters / exits can be send asynchronously.
1348 RunAllPendingInMessageLoop();
1349 EXPECT_TRUE(d2.entered());
1350 EXPECT_FALSE(d2.exited());
1352 d2.ResetExpectations();
1354 RunAllPendingInMessageLoop();
1355 EXPECT_FALSE(d2.entered());
1356 EXPECT_TRUE(d2.exited());
1361 TEST_F(WindowTest, MouseEnterExitWithParentDelete) {
1362 MouseEnterExitWindowDelegate d1;
1363 scoped_ptr<Window> w1(
1364 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1366 MouseEnterExitWindowDelegate d2;
1367 Window* w2 = CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1369 test::EventGenerator generator(root_window());
1370 generator.MoveMouseToCenterOf(w2);
1372 // Enters / exits can be send asynchronously.
1373 RunAllPendingInMessageLoop();
1374 EXPECT_TRUE(d2.entered());
1375 EXPECT_FALSE(d2.exited());
1377 d2.ResetExpectations();
1379 RunAllPendingInMessageLoop();
1380 EXPECT_FALSE(d2.entered());
1381 EXPECT_TRUE(d2.exited());
1384 // Creates a window with a delegate (w111) that can handle events at a lower
1385 // z-index than a window without a delegate (w12). w12 is sized to fill the
1386 // entire bounds of the container. This test verifies that
1387 // GetEventHandlerForPoint() skips w12 even though its bounds contain the event,
1388 // because it has no children that can handle the event and it has no delegate
1389 // allowing it to handle the event itself.
1390 TEST_F(WindowTest, GetEventHandlerForPoint_NoDelegate) {
1391 TestWindowDelegate d111;
1392 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(NULL, 1,
1393 gfx::Rect(0, 0, 500, 500), root_window()));
1394 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(NULL, 11,
1395 gfx::Rect(0, 0, 500, 500), w1.get()));
1396 scoped_ptr<Window> w111(CreateTestWindowWithDelegate(&d111, 111,
1397 gfx::Rect(50, 50, 450, 450), w11.get()));
1398 scoped_ptr<Window> w12(CreateTestWindowWithDelegate(NULL, 12,
1399 gfx::Rect(0, 0, 500, 500), w1.get()));
1401 gfx::Point target_point = w111->bounds().CenterPoint();
1402 EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(target_point));
1405 class VisibilityWindowDelegate : public TestWindowDelegate {
1407 VisibilityWindowDelegate()
1412 int shown() const { return shown_; }
1413 int hidden() const { return hidden_; }
1419 virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {
1430 DISALLOW_COPY_AND_ASSIGN(VisibilityWindowDelegate);
1433 // Verifies show/hide propagate correctly to children and the layer.
1434 TEST_F(WindowTest, Visibility) {
1435 VisibilityWindowDelegate d;
1436 VisibilityWindowDelegate d2;
1437 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(&d, 1, gfx::Rect(),
1439 scoped_ptr<Window> w2(
1440 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(), w1.get()));
1441 scoped_ptr<Window> w3(CreateTestWindowWithId(3, w2.get()));
1443 // Create shows all the windows.
1444 EXPECT_TRUE(w1->IsVisible());
1445 EXPECT_TRUE(w2->IsVisible());
1446 EXPECT_TRUE(w3->IsVisible());
1447 EXPECT_EQ(1, d.shown());
1451 EXPECT_FALSE(w1->IsVisible());
1452 EXPECT_FALSE(w2->IsVisible());
1453 EXPECT_FALSE(w3->IsVisible());
1454 EXPECT_EQ(1, d.hidden());
1455 EXPECT_EQ(0, d.shown());
1458 EXPECT_FALSE(w1->IsVisible());
1459 EXPECT_FALSE(w2->IsVisible());
1460 EXPECT_FALSE(w3->IsVisible());
1463 EXPECT_FALSE(w1->IsVisible());
1464 EXPECT_FALSE(w2->IsVisible());
1465 EXPECT_FALSE(w3->IsVisible());
1469 EXPECT_TRUE(w1->IsVisible());
1470 EXPECT_TRUE(w2->IsVisible());
1471 EXPECT_FALSE(w3->IsVisible());
1472 EXPECT_EQ(0, d.hidden());
1473 EXPECT_EQ(1, d.shown());
1476 EXPECT_TRUE(w1->IsVisible());
1477 EXPECT_TRUE(w2->IsVisible());
1478 EXPECT_TRUE(w3->IsVisible());
1480 // Verify that if an ancestor isn't visible and we change the visibility of a
1481 // child window that OnChildWindowVisibilityChanged() is still invoked.
1485 EXPECT_EQ(1, d2.hidden());
1486 EXPECT_EQ(0, d2.shown());
1489 EXPECT_EQ(0, d2.hidden());
1490 EXPECT_EQ(1, d2.shown());
1493 TEST_F(WindowTest, IgnoreEventsTest) {
1494 TestWindowDelegate d11;
1495 TestWindowDelegate d12;
1496 TestWindowDelegate d111;
1497 TestWindowDelegate d121;
1498 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(NULL, 1,
1499 gfx::Rect(0, 0, 500, 500), root_window()));
1500 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(&d11, 11,
1501 gfx::Rect(0, 0, 500, 500), w1.get()));
1502 scoped_ptr<Window> w111(CreateTestWindowWithDelegate(&d111, 111,
1503 gfx::Rect(50, 50, 450, 450), w11.get()));
1504 scoped_ptr<Window> w12(CreateTestWindowWithDelegate(&d12, 12,
1505 gfx::Rect(0, 0, 500, 500), w1.get()));
1506 scoped_ptr<Window> w121(CreateTestWindowWithDelegate(&d121, 121,
1507 gfx::Rect(150, 150, 50, 50), w12.get()));
1509 EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10)));
1510 w12->set_ignore_events(true);
1511 EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10)));
1512 w12->set_ignore_events(false);
1514 EXPECT_EQ(w121.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1515 w121->set_ignore_events(true);
1516 EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1517 w12->set_ignore_events(true);
1518 EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1519 w111->set_ignore_events(true);
1520 EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1523 // Tests transformation on the root window.
1524 TEST_F(WindowTest, Transform) {
1525 gfx::Size size = dispatcher()->host()->GetBounds().size();
1526 EXPECT_EQ(gfx::Rect(size),
1527 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1528 gfx::Point()).bounds());
1530 // Rotate it clock-wise 90 degrees.
1531 gfx::Transform transform;
1532 transform.Translate(size.height(), 0);
1533 transform.Rotate(90.0);
1534 dispatcher()->host()->SetTransform(transform);
1536 // The size should be the transformed size.
1537 gfx::Size transformed_size(size.height(), size.width());
1538 EXPECT_EQ(transformed_size.ToString(),
1539 root_window()->bounds().size().ToString());
1541 gfx::Rect(transformed_size).ToString(),
1542 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1543 gfx::Point()).bounds().ToString());
1545 // Host size shouldn't change.
1546 EXPECT_EQ(size.ToString(),
1547 dispatcher()->host()->GetBounds().size().ToString());
1550 TEST_F(WindowTest, TransformGesture) {
1551 gfx::Size size = dispatcher()->host()->GetBounds().size();
1553 scoped_ptr<GestureTrackPositionDelegate> delegate(
1554 new GestureTrackPositionDelegate);
1555 scoped_ptr<Window> window(CreateTestWindowWithDelegate(delegate.get(), -1234,
1556 gfx::Rect(0, 0, 20, 20), root_window()));
1558 // Rotate the root-window clock-wise 90 degrees.
1559 gfx::Transform transform;
1560 transform.Translate(size.height(), 0.0);
1561 transform.Rotate(90.0);
1562 dispatcher()->host()->SetTransform(transform);
1564 ui::TouchEvent press(
1565 ui::ET_TOUCH_PRESSED, gfx::Point(size.height() - 10, 10), 0, getTime());
1566 DispatchEventUsingWindowDispatcher(&press);
1567 EXPECT_EQ(gfx::Point(10, 10).ToString(), delegate->position().ToString());
1571 DEFINE_WINDOW_PROPERTY_KEY(int, kIntKey, -2);
1572 DEFINE_WINDOW_PROPERTY_KEY(const char*, kStringKey, "squeamish");
1575 TEST_F(WindowTest, Property) {
1576 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window()));
1578 static const char native_prop_key[] = "fnord";
1580 // Non-existent properties should return the default values.
1581 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1582 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1583 EXPECT_EQ(NULL, w->GetNativeWindowProperty(native_prop_key));
1585 // A set property value should be returned again (even if it's the default
1587 w->SetProperty(kIntKey, INT_MAX);
1588 EXPECT_EQ(INT_MAX, w->GetProperty(kIntKey));
1589 w->SetProperty(kIntKey, -2);
1590 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1591 w->SetProperty(kIntKey, INT_MIN);
1592 EXPECT_EQ(INT_MIN, w->GetProperty(kIntKey));
1594 w->SetProperty(kStringKey, static_cast<const char*>(NULL));
1595 EXPECT_EQ(NULL, w->GetProperty(kStringKey));
1596 w->SetProperty(kStringKey, "squeamish");
1597 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1598 w->SetProperty(kStringKey, "ossifrage");
1599 EXPECT_EQ(std::string("ossifrage"), w->GetProperty(kStringKey));
1601 w->SetNativeWindowProperty(native_prop_key, &*w);
1602 EXPECT_EQ(&*w, w->GetNativeWindowProperty(native_prop_key));
1603 w->SetNativeWindowProperty(native_prop_key, NULL);
1604 EXPECT_EQ(NULL, w->GetNativeWindowProperty(native_prop_key));
1606 // ClearProperty should restore the default value.
1607 w->ClearProperty(kIntKey);
1608 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1609 w->ClearProperty(kStringKey);
1610 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1615 class TestProperty {
1618 virtual ~TestProperty() {
1619 last_deleted_ = this;
1621 static TestProperty* last_deleted() { return last_deleted_; }
1624 static TestProperty* last_deleted_;
1625 DISALLOW_COPY_AND_ASSIGN(TestProperty);
1628 TestProperty* TestProperty::last_deleted_ = NULL;
1630 DEFINE_OWNED_WINDOW_PROPERTY_KEY(TestProperty, kOwnedKey, NULL);
1634 TEST_F(WindowTest, OwnedProperty) {
1635 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window()));
1636 EXPECT_EQ(NULL, w->GetProperty(kOwnedKey));
1637 TestProperty* p1 = new TestProperty();
1638 w->SetProperty(kOwnedKey, p1);
1639 EXPECT_EQ(p1, w->GetProperty(kOwnedKey));
1640 EXPECT_EQ(NULL, TestProperty::last_deleted());
1642 TestProperty* p2 = new TestProperty();
1643 w->SetProperty(kOwnedKey, p2);
1644 EXPECT_EQ(p2, w->GetProperty(kOwnedKey));
1645 EXPECT_EQ(p1, TestProperty::last_deleted());
1647 w->ClearProperty(kOwnedKey);
1648 EXPECT_EQ(NULL, w->GetProperty(kOwnedKey));
1649 EXPECT_EQ(p2, TestProperty::last_deleted());
1651 TestProperty* p3 = new TestProperty();
1652 w->SetProperty(kOwnedKey, p3);
1653 EXPECT_EQ(p3, w->GetProperty(kOwnedKey));
1654 EXPECT_EQ(p2, TestProperty::last_deleted());
1656 EXPECT_EQ(p3, TestProperty::last_deleted());
1659 TEST_F(WindowTest, SetBoundsInternalShouldCheckTargetBounds) {
1660 // We cannot short-circuit animations in this test.
1661 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
1662 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
1664 scoped_ptr<Window> w1(
1665 CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), root_window()));
1667 EXPECT_FALSE(!w1->layer());
1668 w1->layer()->GetAnimator()->set_disable_timer_for_test(true);
1669 gfx::AnimationContainerElement* element = w1->layer()->GetAnimator();
1671 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1672 EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString());
1674 // Animate to a different position.
1676 ui::ScopedLayerAnimationSettings settings(w1->layer()->GetAnimator());
1677 w1->SetBounds(gfx::Rect(100, 100, 100, 100));
1680 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1681 EXPECT_EQ("100,100 100x100", w1->layer()->GetTargetBounds().ToString());
1683 // Animate back to the first position. The animation hasn't started yet, so
1684 // the current bounds are still (0, 0, 100, 100), but the target bounds are
1685 // (100, 100, 100, 100). If we step the animator ahead, we should find that
1686 // we're at (0, 0, 100, 100). That is, the second animation should be applied.
1688 ui::ScopedLayerAnimationSettings settings(w1->layer()->GetAnimator());
1689 w1->SetBounds(gfx::Rect(0, 0, 100, 100));
1692 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1693 EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString());
1695 // Confirm that the target bounds are reached.
1696 base::TimeTicks start_time =
1697 w1->layer()->GetAnimator()->last_step_time();
1699 element->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
1701 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1705 typedef std::pair<const void*, intptr_t> PropertyChangeInfo;
1707 class WindowObserverTest : public WindowTest,
1708 public WindowObserver {
1710 struct VisibilityInfo {
1711 bool window_visible;
1715 WindowObserverTest()
1718 destroyed_count_(0),
1719 old_property_value_(-3) {
1722 virtual ~WindowObserverTest() {}
1724 const VisibilityInfo* GetVisibilityInfo() const {
1725 return visibility_info_.get();
1728 void ResetVisibilityInfo() {
1729 visibility_info_.reset();
1732 // Returns a description of the WindowObserver methods that have been invoked.
1733 std::string WindowObserverCountStateAndClear() {
1735 base::StringPrintf("added=%d removed=%d",
1736 added_count_, removed_count_));
1737 added_count_ = removed_count_ = 0;
1741 int DestroyedCountAndClear() {
1742 int result = destroyed_count_;
1743 destroyed_count_ = 0;
1747 // Return a tuple of the arguments passed in OnPropertyChanged callback.
1748 PropertyChangeInfo PropertyChangeInfoAndClear() {
1749 PropertyChangeInfo result(property_key_, old_property_value_);
1750 property_key_ = NULL;
1751 old_property_value_ = -3;
1756 virtual void OnWindowAdded(Window* new_window) OVERRIDE {
1760 virtual void OnWillRemoveWindow(Window* window) OVERRIDE {
1764 virtual void OnWindowVisibilityChanged(Window* window,
1765 bool visible) OVERRIDE {
1766 visibility_info_.reset(new VisibilityInfo);
1767 visibility_info_->window_visible = window->IsVisible();
1768 visibility_info_->visible_param = visible;
1771 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
1772 EXPECT_FALSE(window->parent());
1776 virtual void OnWindowPropertyChanged(Window* window,
1778 intptr_t old) OVERRIDE {
1779 property_key_ = key;
1780 old_property_value_ = old;
1785 int destroyed_count_;
1786 scoped_ptr<VisibilityInfo> visibility_info_;
1787 const void* property_key_;
1788 intptr_t old_property_value_;
1790 DISALLOW_COPY_AND_ASSIGN(WindowObserverTest);
1793 // Various assertions for WindowObserver.
1794 TEST_F(WindowObserverTest, WindowObserver) {
1795 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1796 w1->AddObserver(this);
1798 // Create a new window as a child of w1, our observer should be notified.
1799 scoped_ptr<Window> w2(CreateTestWindowWithId(2, w1.get()));
1800 EXPECT_EQ("added=1 removed=0", WindowObserverCountStateAndClear());
1802 // Delete w2, which should result in the remove notification.
1804 EXPECT_EQ("added=0 removed=1", WindowObserverCountStateAndClear());
1806 // Create a window that isn't parented to w1, we shouldn't get any
1808 scoped_ptr<Window> w3(CreateTestWindowWithId(3, root_window()));
1809 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1811 // Similarly destroying w3 shouldn't notify us either.
1813 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1814 w1->RemoveObserver(this);
1817 // Test if OnWindowVisibilityChagned is invoked with expected
1819 TEST_F(WindowObserverTest, WindowVisibility) {
1820 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1821 scoped_ptr<Window> w2(CreateTestWindowWithId(1, w1.get()));
1822 w2->AddObserver(this);
1824 // Hide should make the window invisible and the passed visible
1825 // parameter is false.
1827 EXPECT_FALSE(!GetVisibilityInfo());
1828 EXPECT_FALSE(!GetVisibilityInfo());
1829 if (!GetVisibilityInfo())
1831 EXPECT_FALSE(GetVisibilityInfo()->window_visible);
1832 EXPECT_FALSE(GetVisibilityInfo()->visible_param);
1834 // If parent isn't visible, showing window won't make the window visible, but
1835 // passed visible value must be true.
1837 ResetVisibilityInfo();
1838 EXPECT_TRUE(!GetVisibilityInfo());
1840 EXPECT_FALSE(!GetVisibilityInfo());
1841 if (!GetVisibilityInfo())
1843 EXPECT_FALSE(GetVisibilityInfo()->window_visible);
1844 EXPECT_TRUE(GetVisibilityInfo()->visible_param);
1846 // If parent is visible, showing window will make the window
1847 // visible and the passed visible value is true.
1850 ResetVisibilityInfo();
1852 EXPECT_FALSE(!GetVisibilityInfo());
1853 if (!GetVisibilityInfo())
1855 EXPECT_TRUE(GetVisibilityInfo()->window_visible);
1856 EXPECT_TRUE(GetVisibilityInfo()->visible_param);
1859 // Test if OnWindowDestroyed is invoked as expected.
1860 TEST_F(WindowObserverTest, WindowDestroyed) {
1861 // Delete a window should fire a destroyed notification.
1862 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1863 w1->AddObserver(this);
1865 EXPECT_EQ(1, DestroyedCountAndClear());
1867 // Observe on child and delete parent window should fire a notification.
1868 scoped_ptr<Window> parent(CreateTestWindowWithId(1, root_window()));
1869 Window* child = CreateTestWindowWithId(1, parent.get()); // owned by parent
1870 child->AddObserver(this);
1872 EXPECT_EQ(1, DestroyedCountAndClear());
1875 TEST_F(WindowObserverTest, PropertyChanged) {
1876 // Setting property should fire a property change notification.
1877 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1878 w1->AddObserver(this);
1880 static const WindowProperty<int> prop = {-2};
1881 static const char native_prop_key[] = "fnord";
1883 w1->SetProperty(&prop, 1);
1884 EXPECT_EQ(PropertyChangeInfo(&prop, -2), PropertyChangeInfoAndClear());
1885 w1->SetProperty(&prop, -2);
1886 EXPECT_EQ(PropertyChangeInfo(&prop, 1), PropertyChangeInfoAndClear());
1887 w1->SetProperty(&prop, 3);
1888 EXPECT_EQ(PropertyChangeInfo(&prop, -2), PropertyChangeInfoAndClear());
1889 w1->ClearProperty(&prop);
1890 EXPECT_EQ(PropertyChangeInfo(&prop, 3), PropertyChangeInfoAndClear());
1892 w1->SetNativeWindowProperty(native_prop_key, &*w1);
1893 EXPECT_EQ(PropertyChangeInfo(native_prop_key, 0),
1894 PropertyChangeInfoAndClear());
1895 w1->SetNativeWindowProperty(native_prop_key, NULL);
1896 EXPECT_EQ(PropertyChangeInfo(native_prop_key,
1897 reinterpret_cast<intptr_t>(&*w1)),
1898 PropertyChangeInfoAndClear());
1900 // Sanity check to see if |PropertyChangeInfoAndClear| really clears.
1901 EXPECT_EQ(PropertyChangeInfo(
1902 reinterpret_cast<const void*>(NULL), -3), PropertyChangeInfoAndClear());
1905 TEST_F(WindowTest, AcquireLayer) {
1906 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
1907 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
1908 ui::Layer* parent = window1->parent()->layer();
1909 EXPECT_EQ(2U, parent->children().size());
1911 WindowTestApi window1_test_api(window1.get());
1912 WindowTestApi window2_test_api(window2.get());
1914 EXPECT_TRUE(window1_test_api.OwnsLayer());
1915 EXPECT_TRUE(window2_test_api.OwnsLayer());
1917 // After acquisition, window1 should not own its layer, but it should still
1918 // be available to the window.
1919 scoped_ptr<ui::Layer> window1_layer(window1->AcquireLayer());
1920 EXPECT_FALSE(window1_test_api.OwnsLayer());
1921 EXPECT_TRUE(window1_layer.get() == window1->layer());
1923 // Upon destruction, window1's layer should still be valid, and in the layer
1924 // hierarchy, but window2's should be gone, and no longer in the hierarchy.
1928 // This should be set by the window's destructor.
1929 EXPECT_TRUE(window1_layer->delegate() == NULL);
1930 EXPECT_EQ(1U, parent->children().size());
1933 // Make sure that properties which should persist from the old layer to the new
1934 // layer actually do.
1935 TEST_F(WindowTest, RecreateLayer) {
1936 // Set properties to non default values.
1937 Window w(new ColorTestWindowDelegate(SK_ColorWHITE));
1939 w.Init(aura::WINDOW_LAYER_SOLID_COLOR);
1940 w.SetBounds(gfx::Rect(0, 0, 100, 100));
1942 ui::Layer* layer = w.layer();
1943 layer->set_scale_content(false);
1944 layer->SetVisible(false);
1945 layer->SetMasksToBounds(true);
1947 ui::Layer child_layer;
1948 layer->Add(&child_layer);
1950 scoped_ptr<ui::Layer> old_layer(w.RecreateLayer());
1952 EXPECT_EQ(ui::LAYER_SOLID_COLOR, layer->type());
1953 EXPECT_FALSE(layer->scale_content());
1954 EXPECT_FALSE(layer->visible());
1955 EXPECT_EQ(1u, layer->children().size());
1956 EXPECT_TRUE(layer->GetMasksToBounds());
1957 // On recreate it's expected the bounds of both the window and layer go to
1958 // 0. See description of Window::RecreateLayer() for details.
1959 EXPECT_EQ("0,0 0x0", w.bounds().ToString());
1960 EXPECT_EQ("0,0 0x0", layer->bounds().ToString());
1963 // Verify that RecreateLayer() stacks the old layer above the newly creatd
1965 TEST_F(WindowTest, RecreateLayerZOrder) {
1966 scoped_ptr<Window> w(
1967 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(0, 0, 100, 100),
1969 scoped_ptr<ui::Layer> old_layer(w->RecreateLayer());
1971 const std::vector<ui::Layer*>& child_layers =
1972 root_window()->layer()->children();
1973 ASSERT_EQ(2u, child_layers.size());
1974 EXPECT_EQ(w->layer(), child_layers[0]);
1975 EXPECT_EQ(old_layer.get(), child_layers[1]);
1978 // Ensure that acquiring a layer then recreating a layer does not crash
1979 // and that RecreateLayer returns null.
1980 TEST_F(WindowTest, AcquireThenRecreateLayer) {
1981 scoped_ptr<Window> w(
1982 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(0, 0, 100, 100),
1984 scoped_ptr<ui::Layer>acquired_layer(w->AcquireLayer());
1985 scoped_ptr<ui::Layer>doubly_acquired_layer(w->RecreateLayer());
1986 EXPECT_EQ(NULL, doubly_acquired_layer.get());
1988 // Destroy window before layer gets destroyed.
1992 TEST_F(WindowTest, StackWindowAtBottomBelowWindowWhoseLayerHasNoDelegate) {
1993 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
1994 window1->layer()->set_name("1");
1995 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
1996 window2->layer()->set_name("2");
1997 scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window()));
1998 window3->layer()->set_name("3");
2000 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(root_window()));
2002 ui::test::ChildLayerNamesAsString(*root_window()->layer()));
2003 window1->layer()->set_delegate(NULL);
2004 root_window()->StackChildAtBottom(window3.get());
2006 // Window 3 should have moved to the bottom.
2007 EXPECT_EQ("3 1 2", ChildWindowIDsAsString(root_window()));
2009 ui::test::ChildLayerNamesAsString(*root_window()->layer()));
2012 class TestVisibilityClient : public client::VisibilityClient {
2014 explicit TestVisibilityClient(Window* root_window)
2015 : ignore_visibility_changes_(false) {
2016 client::SetVisibilityClient(root_window, this);
2018 virtual ~TestVisibilityClient() {
2021 void set_ignore_visibility_changes(bool ignore_visibility_changes) {
2022 ignore_visibility_changes_ = ignore_visibility_changes;
2025 // Overridden from client::VisibilityClient:
2026 virtual void UpdateLayerVisibility(aura::Window* window,
2027 bool visible) OVERRIDE {
2028 if (!ignore_visibility_changes_)
2029 window->layer()->SetVisible(visible);
2033 bool ignore_visibility_changes_;
2034 DISALLOW_COPY_AND_ASSIGN(TestVisibilityClient);
2037 TEST_F(WindowTest, VisibilityClientIsVisible) {
2038 TestVisibilityClient client(root_window());
2040 scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window()));
2041 EXPECT_TRUE(window->IsVisible());
2042 EXPECT_TRUE(window->layer()->visible());
2045 EXPECT_FALSE(window->IsVisible());
2046 EXPECT_FALSE(window->layer()->visible());
2049 client.set_ignore_visibility_changes(true);
2051 EXPECT_FALSE(window->IsVisible());
2052 EXPECT_TRUE(window->layer()->visible());
2055 // Tests mouse events on window change.
2056 TEST_F(WindowTest, MouseEventsOnWindowChange) {
2057 gfx::Size size = dispatcher()->host()->GetBounds().size();
2059 EventGenerator generator(root_window());
2060 generator.MoveMouseTo(50, 50);
2062 EventCountDelegate d1;
2063 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(&d1, 1,
2064 gfx::Rect(0, 0, 100, 100), root_window()));
2065 RunAllPendingInMessageLoop();
2066 // The format of result is "Enter/Mouse/Leave".
2067 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2069 // Adding new window.
2070 EventCountDelegate d11;
2071 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(
2072 &d11, 1, gfx::Rect(0, 0, 100, 100), w1.get()));
2073 RunAllPendingInMessageLoop();
2074 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2075 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2078 w11->SetBounds(gfx::Rect(0, 0, 10, 10));
2079 RunAllPendingInMessageLoop();
2080 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2081 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2083 w11->SetBounds(gfx::Rect(0, 0, 60, 60));
2084 RunAllPendingInMessageLoop();
2085 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2086 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2088 // Detach, then re-attach.
2089 w1->RemoveChild(w11.get());
2090 RunAllPendingInMessageLoop();
2091 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2092 // Window is detached, so no event is set.
2093 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2095 w1->AddChild(w11.get());
2096 RunAllPendingInMessageLoop();
2097 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2098 // Window is detached, so no event is set.
2099 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2101 // Visibility Change
2103 RunAllPendingInMessageLoop();
2104 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2105 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2108 RunAllPendingInMessageLoop();
2109 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2110 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2112 // Transform: move d11 by 100 100.
2113 gfx::Transform transform;
2114 transform.Translate(100, 100);
2115 w11->SetTransform(transform);
2116 RunAllPendingInMessageLoop();
2117 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2118 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2120 w11->SetTransform(gfx::Transform());
2121 RunAllPendingInMessageLoop();
2122 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2123 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2125 // Closing a window.
2127 RunAllPendingInMessageLoop();
2128 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2130 // Make sure we don't synthesize events if the mouse
2131 // is outside of the root window.
2132 generator.MoveMouseTo(-10, -10);
2133 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2135 // Adding new windows.
2136 w11.reset(CreateTestWindowWithDelegate(
2137 &d11, 1, gfx::Rect(0, 0, 100, 100), w1.get()));
2138 RunAllPendingInMessageLoop();
2139 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset());
2140 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2144 RunAllPendingInMessageLoop();
2145 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset());
2146 EXPECT_EQ("0 0 0", d11.GetMouseMotionCountsAndReset());
2149 class RootWindowAttachmentObserver : public WindowObserver {
2151 RootWindowAttachmentObserver() : added_count_(0), removed_count_(0) {}
2152 virtual ~RootWindowAttachmentObserver() {}
2154 int added_count() const { return added_count_; }
2155 int removed_count() const { return removed_count_; }
2162 // Overridden from WindowObserver:
2163 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
2166 virtual void OnWindowRemovingFromRootWindow(Window* window) OVERRIDE {
2174 DISALLOW_COPY_AND_ASSIGN(RootWindowAttachmentObserver);
2177 TEST_F(WindowTest, RootWindowAttachment) {
2178 RootWindowAttachmentObserver observer;
2180 // Test a direct add/remove from the RootWindow.
2181 scoped_ptr<Window> w1(new Window(NULL));
2182 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2183 w1->AddObserver(&observer);
2185 ParentWindow(w1.get());
2186 EXPECT_EQ(1, observer.added_count());
2187 EXPECT_EQ(0, observer.removed_count());
2190 EXPECT_EQ(1, observer.added_count());
2191 EXPECT_EQ(1, observer.removed_count());
2195 // Test an indirect add/remove from the RootWindow.
2196 w1.reset(new Window(NULL));
2197 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2198 Window* w11 = new Window(NULL);
2199 w11->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2200 w11->AddObserver(&observer);
2202 EXPECT_EQ(0, observer.added_count());
2203 EXPECT_EQ(0, observer.removed_count());
2205 ParentWindow(w1.get());
2206 EXPECT_EQ(1, observer.added_count());
2207 EXPECT_EQ(0, observer.removed_count());
2209 w1.reset(); // Deletes w11.
2211 EXPECT_EQ(1, observer.added_count());
2212 EXPECT_EQ(1, observer.removed_count());
2216 // Test an indirect add/remove with nested observers.
2217 w1.reset(new Window(NULL));
2218 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2219 w11 = new Window(NULL);
2220 w11->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2221 w11->AddObserver(&observer);
2223 Window* w111 = new Window(NULL);
2224 w111->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2225 w111->AddObserver(&observer);
2226 w11->AddChild(w111);
2228 EXPECT_EQ(0, observer.added_count());
2229 EXPECT_EQ(0, observer.removed_count());
2231 ParentWindow(w1.get());
2232 EXPECT_EQ(2, observer.added_count());
2233 EXPECT_EQ(0, observer.removed_count());
2235 w1.reset(); // Deletes w11 and w111.
2238 EXPECT_EQ(2, observer.added_count());
2239 EXPECT_EQ(2, observer.removed_count());
2242 TEST_F(WindowTest, OwnedByParentFalse) {
2243 // By default, a window is owned by its parent. If this is set to false, the
2244 // window will not be destroyed when its parent is.
2246 scoped_ptr<Window> w1(new Window(NULL));
2247 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2248 scoped_ptr<Window> w2(new Window(NULL));
2249 w2->set_owned_by_parent(false);
2250 w2->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2251 w1->AddChild(w2.get());
2255 // We should be able to deref w2 still, but its parent should now be NULL.
2256 EXPECT_EQ(NULL, w2->parent());
2261 // Used By DeleteWindowFromOnWindowDestroyed. Destroys a Window from
2262 // OnWindowDestroyed().
2263 class OwningWindowDelegate : public TestWindowDelegate {
2265 OwningWindowDelegate() {}
2267 void SetOwnedWindow(Window* window) {
2268 owned_window_.reset(window);
2271 virtual void OnWindowDestroyed() OVERRIDE {
2272 owned_window_.reset(NULL);
2276 scoped_ptr<Window> owned_window_;
2278 DISALLOW_COPY_AND_ASSIGN(OwningWindowDelegate);
2283 // Creates a window with two child windows. When the first child window is
2284 // destroyed (WindowDelegate::OnWindowDestroyed) it deletes the second child.
2285 // This synthesizes BrowserView and the status bubble. Both are children of the
2286 // same parent and destroying BrowserView triggers it destroying the status
2288 TEST_F(WindowTest, DeleteWindowFromOnWindowDestroyed) {
2289 scoped_ptr<Window> parent(new Window(NULL));
2290 parent->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2291 OwningWindowDelegate delegate;
2292 Window* c1 = new Window(&delegate);
2293 c1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2294 parent->AddChild(c1);
2295 Window* c2 = new Window(NULL);
2296 c2->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2297 parent->AddChild(c2);
2298 delegate.SetOwnedWindow(c2);
2304 // Used by DelegateNotifiedAsBoundsChange to verify OnBoundsChanged() is
2306 class BoundsChangeDelegate : public TestWindowDelegate {
2308 BoundsChangeDelegate() : bounds_changed_(false) {}
2310 void clear_bounds_changed() { bounds_changed_ = false; }
2311 bool bounds_changed() const {
2312 return bounds_changed_;
2316 virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
2317 const gfx::Rect& new_bounds) OVERRIDE {
2318 bounds_changed_ = true;
2322 // Was OnBoundsChanged() invoked?
2323 bool bounds_changed_;
2325 DISALLOW_COPY_AND_ASSIGN(BoundsChangeDelegate);
2330 // Verifies the delegate is notified when the actual bounds of the layer
2332 TEST_F(WindowTest, DelegateNotifiedAsBoundsChange) {
2333 BoundsChangeDelegate delegate;
2335 // We cannot short-circuit animations in this test.
2336 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
2337 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
2339 scoped_ptr<Window> window(
2340 CreateTestWindowWithDelegate(&delegate, 1,
2341 gfx::Rect(0, 0, 100, 100), root_window()));
2342 window->layer()->GetAnimator()->set_disable_timer_for_test(true);
2344 delegate.clear_bounds_changed();
2346 // Animate to a different position.
2348 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
2349 window->SetBounds(gfx::Rect(100, 100, 100, 100));
2352 // Bounds shouldn't immediately have changed.
2353 EXPECT_EQ("0,0 100x100", window->bounds().ToString());
2354 EXPECT_FALSE(delegate.bounds_changed());
2356 // Animate to the end, which should notify of the change.
2357 base::TimeTicks start_time =
2358 window->layer()->GetAnimator()->last_step_time();
2359 gfx::AnimationContainerElement* element = window->layer()->GetAnimator();
2360 element->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
2361 EXPECT_TRUE(delegate.bounds_changed());
2362 EXPECT_NE("0,0 100x100", window->bounds().ToString());
2365 // Verifies the delegate is notified when the actual bounds of the layer
2366 // change even when the window is not the layer's delegate
2367 TEST_F(WindowTest, DelegateNotifiedAsBoundsChangeInHiddenLayer) {
2368 BoundsChangeDelegate delegate;
2370 // We cannot short-circuit animations in this test.
2371 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
2372 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
2374 scoped_ptr<Window> window(
2375 CreateTestWindowWithDelegate(&delegate, 1,
2376 gfx::Rect(0, 0, 100, 100), root_window()));
2377 window->layer()->GetAnimator()->set_disable_timer_for_test(true);
2379 delegate.clear_bounds_changed();
2381 // Suppress paint on the window since it is hidden (should reset the layer's
2382 // delegate to NULL)
2383 window->SuppressPaint();
2384 EXPECT_EQ(NULL, window->layer()->delegate());
2386 // Animate to a different position.
2388 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
2389 window->SetBounds(gfx::Rect(100, 100, 110, 100));
2392 // Layer delegate is NULL but we should still get bounds changed notification.
2393 EXPECT_EQ("100,100 110x100", window->GetTargetBounds().ToString());
2394 EXPECT_TRUE(delegate.bounds_changed());
2396 delegate.clear_bounds_changed();
2398 // Animate to the end: will *not* notify of the change since we are hidden.
2399 base::TimeTicks start_time =
2400 window->layer()->GetAnimator()->last_step_time();
2401 gfx::AnimationContainerElement* element = window->layer()->GetAnimator();
2402 element->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
2404 // No bounds changed notification at the end of animation since layer
2405 // delegate is NULL.
2406 EXPECT_FALSE(delegate.bounds_changed());
2407 EXPECT_NE("0,0 100x100", window->layer()->bounds().ToString());
2412 // Used by AddChildNotifications to track notification counts.
2413 class AddChildNotificationsObserver : public WindowObserver {
2415 AddChildNotificationsObserver() : added_count_(0), removed_count_(0) {}
2417 std::string CountStringAndReset() {
2418 std::string result = base::IntToString(added_count_) + " " +
2419 base::IntToString(removed_count_);
2420 added_count_ = removed_count_ = 0;
2424 // WindowObserver overrides:
2425 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
2428 virtual void OnWindowRemovingFromRootWindow(Window* window) OVERRIDE {
2436 DISALLOW_COPY_AND_ASSIGN(AddChildNotificationsObserver);
2441 // Assertions around when root window notifications are sent.
2442 TEST_F(WindowTest, AddChildNotifications) {
2443 AddChildNotificationsObserver observer;
2444 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
2445 scoped_ptr<Window> w2(CreateTestWindowWithId(1, root_window()));
2446 w2->AddObserver(&observer);
2448 EXPECT_TRUE(w2->HasFocus());
2450 // Move |w2| to be a child of |w1|.
2451 w1->AddChild(w2.get());
2452 // Sine we moved in the same root, observer shouldn't be notified.
2453 EXPECT_EQ("0 0", observer.CountStringAndReset());
2454 // |w2| should still have focus after moving.
2455 EXPECT_TRUE(w2->HasFocus());
2458 // Tests that a delegate that destroys itself when the window is destroyed does
2460 TEST_F(WindowTest, DelegateDestroysSelfOnWindowDestroy) {
2461 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
2462 new DestroyWindowDelegate(),
2464 gfx::Rect(10, 20, 30, 40),
2468 class HierarchyObserver : public WindowObserver {
2470 HierarchyObserver(Window* target) : target_(target) {
2471 target_->AddObserver(this);
2473 virtual ~HierarchyObserver() {
2474 target_->RemoveObserver(this);
2479 const WindowObserver::HierarchyChangeParams& params) const {
2480 ParamsMatch(params_[index], params);
2488 // Overridden from WindowObserver:
2489 virtual void OnWindowHierarchyChanging(
2490 const HierarchyChangeParams& params) OVERRIDE {
2491 params_.push_back(params);
2493 virtual void OnWindowHierarchyChanged(
2494 const HierarchyChangeParams& params) OVERRIDE {
2495 params_.push_back(params);
2498 void ParamsMatch(const WindowObserver::HierarchyChangeParams& p1,
2499 const WindowObserver::HierarchyChangeParams& p2) const {
2500 EXPECT_EQ(p1.phase, p2.phase);
2501 EXPECT_EQ(p1.target, p2.target);
2502 EXPECT_EQ(p1.new_parent, p2.new_parent);
2503 EXPECT_EQ(p1.old_parent, p2.old_parent);
2504 EXPECT_EQ(p1.receiver, p2.receiver);
2508 std::vector<WindowObserver::HierarchyChangeParams> params_;
2510 DISALLOW_COPY_AND_ASSIGN(HierarchyObserver);
2513 // Tests hierarchy change notifications.
2514 TEST_F(WindowTest, OnWindowHierarchyChange) {
2516 // Simple add & remove.
2517 HierarchyObserver oroot(root_window());
2519 scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL));
2520 HierarchyObserver o1(w1.get());
2523 root_window()->AddChild(w1.get());
2525 WindowObserver::HierarchyChangeParams params;
2526 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2527 params.target = w1.get();
2528 params.old_parent = NULL;
2529 params.new_parent = root_window();
2530 params.receiver = w1.get();
2531 o1.ValidateState(0, params);
2533 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2534 params.receiver = w1.get();
2535 o1.ValidateState(1, params);
2537 params.receiver = root_window();
2538 oroot.ValidateState(0, params);
2544 root_window()->RemoveChild(w1.get());
2546 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2547 params.old_parent = root_window();
2548 params.new_parent = NULL;
2549 params.receiver = w1.get();
2551 o1.ValidateState(0, params);
2553 params.receiver = root_window();
2554 oroot.ValidateState(0, params);
2556 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2557 params.receiver = w1.get();
2558 o1.ValidateState(1, params);
2562 // Add & remove of hierarchy. Tests notification order per documentation in
2564 HierarchyObserver o(root_window());
2565 scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL));
2566 Window* w11 = CreateTestWindowWithId(11, w1.get());
2567 w1->AddObserver(&o);
2568 w11->AddObserver(&o);
2571 root_window()->AddChild(w1.get());
2573 // Dispatched to target first.
2575 WindowObserver::HierarchyChangeParams params;
2576 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2577 params.target = w1.get();
2578 params.old_parent = NULL;
2579 params.new_parent = root_window();
2580 params.receiver = w1.get();
2581 o.ValidateState(index++, params);
2583 // Dispatched to target's children.
2584 params.receiver = w11;
2585 o.ValidateState(index++, params);
2587 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2589 // Now process the "changed" phase.
2590 params.receiver = w1.get();
2591 o.ValidateState(index++, params);
2592 params.receiver = w11;
2593 o.ValidateState(index++, params);
2594 params.receiver = root_window();
2595 o.ValidateState(index++, params);
2598 root_window()->RemoveChild(w1.get());
2599 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2600 params.old_parent = root_window();
2601 params.new_parent = NULL;
2602 params.receiver = w1.get();
2603 o.ValidateState(index++, params);
2604 params.receiver = w11;
2605 o.ValidateState(index++, params);
2606 params.receiver = root_window();
2607 o.ValidateState(index++, params);
2608 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2609 params.receiver = w1.get();
2610 o.ValidateState(index++, params);
2611 params.receiver = w11;
2612 o.ValidateState(index++, params);
2618 // Reparent. Tests notification order per documentation in WindowObserver.
2619 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
2620 Window* w11 = CreateTestWindowWithId(11, w1.get());
2621 Window* w111 = CreateTestWindowWithId(111, w11);
2622 scoped_ptr<Window> w2(CreateTestWindowWithId(2, root_window()));
2624 HierarchyObserver o(root_window());
2625 w1->AddObserver(&o);
2626 w11->AddObserver(&o);
2627 w111->AddObserver(&o);
2628 w2->AddObserver(&o);
2632 // Dispatched to target first.
2634 WindowObserver::HierarchyChangeParams params;
2635 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2636 params.target = w11;
2637 params.old_parent = w1.get();
2638 params.new_parent = w2.get();
2639 params.receiver = w11;
2640 o.ValidateState(index++, params);
2642 // Then to target's children.
2643 params.receiver = w111;
2644 o.ValidateState(index++, params);
2646 // Then to target's old parent chain.
2647 params.receiver = w1.get();
2648 o.ValidateState(index++, params);
2649 params.receiver = root_window();
2650 o.ValidateState(index++, params);
2653 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2654 params.receiver = w11;
2655 o.ValidateState(index++, params);
2656 params.receiver = w111;
2657 o.ValidateState(index++, params);
2658 params.receiver = w2.get();
2659 o.ValidateState(index++, params);
2660 params.receiver = root_window();
2661 o.ValidateState(index++, params);
2669 // Verifies SchedulePaint() on a layerless window results in damaging the right
2671 TEST_F(WindowTest, LayerlessWindowSchedulePaint) {
2673 root.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2674 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2676 Window* layerless_window = new Window(NULL); // Owned by |root|.
2677 layerless_window->Init(WINDOW_LAYER_NONE);
2678 layerless_window->SetBounds(gfx::Rect(10, 11, 12, 13));
2679 root.AddChild(layerless_window);
2681 root.layer()->SendDamagedRects();
2682 layerless_window->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4));
2683 // Note the the region is clipped by the parent hence 100 going to 11.
2684 EXPECT_EQ("11,13 11x4",
2685 gfx::SkIRectToRect(root.layer()->damaged_region().getBounds()).
2688 Window* layerless_window2 = new Window(NULL); // Owned by |layerless_window|.
2689 layerless_window2->Init(WINDOW_LAYER_NONE);
2690 layerless_window2->SetBounds(gfx::Rect(1, 2, 3, 4));
2691 layerless_window->AddChild(layerless_window2);
2693 root.layer()->SendDamagedRects();
2694 layerless_window2->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4));
2695 // Note the the region is clipped by the |layerless_window| hence 100 going to
2697 EXPECT_EQ("12,15 2x2",
2698 gfx::SkIRectToRect(root.layer()->damaged_region().getBounds()).
2702 // Verifies bounds of layerless windows are correctly updated when adding
2704 TEST_F(WindowTest, NestedLayerlessWindowsBoundsOnAddRemove) {
2705 // Creates the following structure (all children owned by root):
2713 // ll: layer less, eg no layer
2715 root.Init(WINDOW_LAYER_NOT_DRAWN);
2716 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2718 Window* w1ll = new Window(NULL);
2719 w1ll->Init(WINDOW_LAYER_NONE);
2720 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
2722 Window* w11ll = new Window(NULL);
2723 w11ll->Init(WINDOW_LAYER_NONE);
2724 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
2725 w1ll->AddChild(w11ll);
2727 Window* w111 = new Window(NULL);
2728 w111->Init(WINDOW_LAYER_NOT_DRAWN);
2729 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2730 w11ll->AddChild(w111);
2732 Window* w12 = new Window(NULL);
2733 w12->Init(WINDOW_LAYER_NOT_DRAWN);
2734 w12->SetBounds(gfx::Rect(7, 8, 100, 100));
2735 w1ll->AddChild(w12);
2737 Window* w121 = new Window(NULL);
2738 w121->Init(WINDOW_LAYER_NOT_DRAWN);
2739 w121->SetBounds(gfx::Rect(9, 10, 100, 100));
2740 w12->AddChild(w121);
2742 root.AddChild(w1ll);
2744 // All layers should be parented to the root.
2745 EXPECT_EQ(root.layer(), w111->layer()->parent());
2746 EXPECT_EQ(root.layer(), w12->layer()->parent());
2747 EXPECT_EQ(w12->layer(), w121->layer()->parent());
2749 // Ensure bounds are what we expect.
2750 EXPECT_EQ("1,2 100x100", w1ll->bounds().ToString());
2751 EXPECT_EQ("3,4 100x100", w11ll->bounds().ToString());
2752 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2753 EXPECT_EQ("7,8 100x100", w12->bounds().ToString());
2754 EXPECT_EQ("9,10 100x100", w121->bounds().ToString());
2756 // Bounds of layers are relative to the nearest ancestor with a layer.
2757 EXPECT_EQ("8,10 100x100", w12->layer()->bounds().ToString());
2758 EXPECT_EQ("9,12 100x100", w111->layer()->bounds().ToString());
2759 EXPECT_EQ("9,10 100x100", w121->layer()->bounds().ToString());
2761 // Remove and repeat.
2762 root.RemoveChild(w1ll);
2764 EXPECT_TRUE(w111->layer()->parent() == NULL);
2765 EXPECT_TRUE(w12->layer()->parent() == NULL);
2767 // Verify bounds haven't changed again.
2768 EXPECT_EQ("1,2 100x100", w1ll->bounds().ToString());
2769 EXPECT_EQ("3,4 100x100", w11ll->bounds().ToString());
2770 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2771 EXPECT_EQ("7,8 100x100", w12->bounds().ToString());
2772 EXPECT_EQ("9,10 100x100", w121->bounds().ToString());
2774 // Bounds of layers should now match that of windows.
2775 EXPECT_EQ("7,8 100x100", w12->layer()->bounds().ToString());
2776 EXPECT_EQ("5,6 100x100", w111->layer()->bounds().ToString());
2777 EXPECT_EQ("9,10 100x100", w121->layer()->bounds().ToString());
2782 // Verifies bounds of layerless windows are correctly updated when bounds
2783 // of ancestor changes.
2784 TEST_F(WindowTest, NestedLayerlessWindowsBoundsOnSetBounds) {
2785 // Creates the following structure (all children owned by root):
2793 // ll: layer less, eg no layer
2795 root.Init(WINDOW_LAYER_NOT_DRAWN);
2796 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2798 Window* w1ll = new Window(NULL);
2799 w1ll->Init(WINDOW_LAYER_NONE);
2800 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
2802 Window* w11ll = new Window(NULL);
2803 w11ll->Init(WINDOW_LAYER_NONE);
2804 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
2805 w1ll->AddChild(w11ll);
2807 Window* w111 = new Window(NULL);
2808 w111->Init(WINDOW_LAYER_NOT_DRAWN);
2809 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2810 w11ll->AddChild(w111);
2812 Window* w12 = new Window(NULL);
2813 w12->Init(WINDOW_LAYER_NOT_DRAWN);
2814 w12->SetBounds(gfx::Rect(7, 8, 100, 100));
2815 w1ll->AddChild(w12);
2817 Window* w121 = new Window(NULL);
2818 w121->Init(WINDOW_LAYER_NOT_DRAWN);
2819 w121->SetBounds(gfx::Rect(9, 10, 100, 100));
2820 w12->AddChild(w121);
2822 root.AddChild(w1ll);
2824 w111->SetBounds(gfx::Rect(7, 8, 11, 12));
2825 EXPECT_EQ("7,8 11x12", w111->bounds().ToString());
2826 EXPECT_EQ("7,8 11x12", w111->GetTargetBounds().ToString());
2827 EXPECT_EQ("11,14 11x12", w111->layer()->bounds().ToString());
2830 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2831 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2832 EXPECT_EQ("5,6 100x100", w111->GetTargetBounds().ToString());
2833 EXPECT_EQ("9,12 100x100", w111->layer()->bounds().ToString());
2835 // Setting the bounds of a layerless window needs to adjust the bounds of
2836 // layered children.
2837 w11ll->SetBounds(gfx::Rect(5, 6, 100, 100));
2838 EXPECT_EQ("5,6 100x100", w11ll->bounds().ToString());
2839 EXPECT_EQ("5,6 100x100", w11ll->GetTargetBounds().ToString());
2840 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2841 EXPECT_EQ("5,6 100x100", w111->GetTargetBounds().ToString());
2842 EXPECT_EQ("11,14 100x100", w111->layer()->bounds().ToString());
2844 root.RemoveChild(w1ll);
2846 w111->SetBounds(gfx::Rect(7, 8, 11, 12));
2847 EXPECT_EQ("7,8 11x12", w111->bounds().ToString());
2848 EXPECT_EQ("7,8 11x12", w111->GetTargetBounds().ToString());
2849 EXPECT_EQ("7,8 11x12", w111->layer()->bounds().ToString());
2856 // Tracks the number of times paint is invoked along with what the clip and
2858 class PaintWindowDelegate : public TestWindowDelegate {
2860 PaintWindowDelegate() : paint_count_(0) {}
2861 virtual ~PaintWindowDelegate() {}
2863 const gfx::Rect& most_recent_paint_clip_bounds() const {
2864 return most_recent_paint_clip_bounds_;
2867 const gfx::Vector2d& most_recent_paint_matrix_offset() const {
2868 return most_recent_paint_matrix_offset_;
2871 void clear_paint_count() { paint_count_ = 0; }
2872 int paint_count() const { return paint_count_; }
2874 // TestWindowDelegate::
2875 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
2877 canvas->GetClipBounds(&most_recent_paint_clip_bounds_);
2878 const SkMatrix& matrix = canvas->sk_canvas()->getTotalMatrix();
2879 most_recent_paint_matrix_offset_ = gfx::Vector2d(
2880 SkScalarFloorToInt(matrix.getTranslateX()),
2881 SkScalarFloorToInt(matrix.getTranslateY()));
2886 gfx::Rect most_recent_paint_clip_bounds_;
2887 gfx::Vector2d most_recent_paint_matrix_offset_;
2889 DISALLOW_COPY_AND_ASSIGN(PaintWindowDelegate);
2894 // Assertions around layerless children being painted when non-layerless window
2896 TEST_F(WindowTest, PaintLayerless) {
2897 // Creates the following structure (all children owned by root):
2903 // ll: layer less, eg no layer
2904 PaintWindowDelegate w1ll_delegate;
2905 PaintWindowDelegate w11ll_delegate;
2906 PaintWindowDelegate w111_delegate;
2909 root.Init(WINDOW_LAYER_NOT_DRAWN);
2910 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2912 Window* w1ll = new Window(&w1ll_delegate);
2913 w1ll->Init(WINDOW_LAYER_NONE);
2914 w1ll->SetBounds(gfx::Rect(1, 2, 40, 50));
2916 root.AddChild(w1ll);
2918 Window* w11ll = new Window(&w11ll_delegate);
2919 w11ll->Init(WINDOW_LAYER_NONE);
2920 w11ll->SetBounds(gfx::Rect(3, 4, 11, 12));
2922 w1ll->AddChild(w11ll);
2924 Window* w111 = new Window(&w111_delegate);
2925 w111->Init(WINDOW_LAYER_NOT_DRAWN);
2926 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2928 w11ll->AddChild(w111);
2930 EXPECT_EQ(0, w1ll_delegate.paint_count());
2931 EXPECT_EQ(0, w11ll_delegate.paint_count());
2932 EXPECT_EQ(0, w111_delegate.paint_count());
2934 // Paint the root, this should trigger painting of the two layerless
2935 // descendants but not the layered descendant.
2936 gfx::Canvas canvas(gfx::Size(200, 200), 1.0f, true);
2937 static_cast<ui::LayerDelegate&>(root).OnPaintLayer(&canvas);
2939 // NOTE: SkCanvas::getClipBounds() extends the clip 1 pixel to the left and up
2940 // and 2 pixels down and to the right.
2941 EXPECT_EQ(1, w1ll_delegate.paint_count());
2942 EXPECT_EQ("-1,-1 42x52",
2943 w1ll_delegate.most_recent_paint_clip_bounds().ToString());
2945 w1ll_delegate.most_recent_paint_matrix_offset().ToString());
2946 EXPECT_EQ(1, w11ll_delegate.paint_count());
2947 EXPECT_EQ("-1,-1 13x14",
2948 w11ll_delegate.most_recent_paint_clip_bounds().ToString());
2950 w11ll_delegate.most_recent_paint_matrix_offset().ToString());
2951 EXPECT_EQ(0, w111_delegate.paint_count());
2956 std::string ConvertPointToTargetString(const Window* source,
2957 const Window* target) {
2958 gfx::Point location;
2959 Window::ConvertPointToTarget(source, target, &location);
2960 return location.ToString();
2965 // Assertions around Window::ConvertPointToTarget() with layerless windows.
2966 TEST_F(WindowTest, ConvertPointToTargetLayerless) {
2967 // Creates the following structure (all children owned by root):
2975 // ll: layer less, eg no layer
2977 root.Init(WINDOW_LAYER_NOT_DRAWN);
2978 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2980 Window* w1ll = new Window(NULL);
2981 w1ll->Init(WINDOW_LAYER_NONE);
2982 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
2984 Window* w11ll = new Window(NULL);
2985 w11ll->Init(WINDOW_LAYER_NONE);
2986 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
2987 w1ll->AddChild(w11ll);
2989 Window* w111 = new Window(NULL);
2990 w111->Init(WINDOW_LAYER_NOT_DRAWN);
2991 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2992 w11ll->AddChild(w111);
2994 Window* w12 = new Window(NULL);
2995 w12->Init(WINDOW_LAYER_NOT_DRAWN);
2996 w12->SetBounds(gfx::Rect(7, 8, 100, 100));
2997 w1ll->AddChild(w12);
2999 Window* w121 = new Window(NULL);
3000 w121->Init(WINDOW_LAYER_NOT_DRAWN);
3001 w121->SetBounds(gfx::Rect(9, 10, 100, 100));
3002 w12->AddChild(w121);
3004 root.AddChild(w1ll);
3007 EXPECT_EQ("5,6", ConvertPointToTargetString(w111, w11ll));
3010 EXPECT_EQ("8,10", ConvertPointToTargetString(w111, w1ll));
3013 EXPECT_EQ("9,12", ConvertPointToTargetString(w111, &root));
3016 EXPECT_EQ("1,2", ConvertPointToTargetString(w111, w12));
3019 EXPECT_EQ("-8,-8", ConvertPointToTargetString(w111, w121));
3022 EXPECT_EQ("-5,-6", ConvertPointToTargetString(w11ll, w111));
3025 EXPECT_EQ("3,4", ConvertPointToTargetString(w11ll, w1ll));
3028 EXPECT_EQ("4,6", ConvertPointToTargetString(w11ll, &root));
3031 EXPECT_EQ("-4,-4", ConvertPointToTargetString(w11ll, w12));
3034 #if !defined(NDEBUG)
3035 // Verifies PrintWindowHierarchy() doesn't crash with a layerless window.
3036 TEST_F(WindowTest, PrintWindowHierarchyNotCrashLayerless) {
3038 root.Init(WINDOW_LAYER_NONE);
3039 root.SetBounds(gfx::Rect(0, 0, 100, 100));
3040 root.PrintWindowHierarchy(0);
3046 // See AddWindowsFromString() for details.
3047 aura::Window* CreateWindowFromDescription(const std::string& description,
3048 WindowDelegate* delegate) {
3049 WindowLayerType window_type = WINDOW_LAYER_NOT_DRAWN;
3050 std::vector<std::string> tokens;
3051 Tokenize(description, ":", &tokens);
3052 DCHECK(!tokens.empty());
3053 std::string name(tokens[0]);
3054 tokens.erase(tokens.begin());
3055 if (!tokens.empty()) {
3056 if (tokens[0] == "ll") {
3057 window_type = WINDOW_LAYER_NONE;
3058 tokens.erase(tokens.begin());
3060 DCHECK(tokens.empty()) << "unknown tokens for creating window "
3063 Window* window = new Window(delegate);
3064 window->Init(window_type);
3065 window->SetName(name);
3066 // Window name is only propagated to layer in debug builds.
3067 if (window->layer())
3068 window->layer()->set_name(name);
3072 // Creates and adds a tree of windows to |parent|. |description| consists
3073 // of the following pieces:
3074 // X: Identifies a new window. Consists of a name and optionally ":ll" to
3075 // specify WINDOW_LAYER_NONE, eg "w1:ll".
3076 // []: optionally used to specify the children of the window. Contains any
3077 // number of window identifiers and their corresponding children.
3078 // For example: "[ a [ a1 a2:ll ] b c [ c1 ] ]" creates the tree:
3081 // a2 -> WINDOW_LAYER_NONE.
3085 // NOTE: you must have a space after every token.
3086 std::string::size_type AddWindowsFromString(aura::Window* parent,
3087 const std::string& description,
3088 std::string::size_type start_pos,
3089 WindowDelegate* delegate) {
3091 std::string::size_type end_pos = description.find(' ', start_pos);
3092 while (end_pos != std::string::npos) {
3093 const std::string::size_type part_length = end_pos - start_pos;
3094 const std::string window_description =
3095 description.substr(start_pos, part_length);
3096 if (window_description == "[") {
3097 start_pos = AddWindowsFromString(parent->children().back(),
3101 end_pos = description.find(' ', start_pos);
3102 if (end_pos == std::string::npos && start_pos != end_pos)
3103 end_pos = description.length();
3104 } else if (window_description == "]") {
3109 CreateWindowFromDescription(window_description, delegate);
3110 parent->AddChild(window);
3111 start_pos = ++end_pos;
3112 end_pos = description.find(' ', start_pos);
3118 // Used by BuildRootWindowTreeDescription().
3119 std::string BuildWindowTreeDescription(const aura::Window& window) {
3121 result += window.name();
3122 if (window.children().empty())
3126 for (size_t i = 0; i < window.children().size(); ++i) {
3129 result += BuildWindowTreeDescription(*(window.children()[i]));
3135 // Creates a string from |window|. See AddWindowsFromString() for details of the
3136 // returned string. This does *not* include the layer type in the description,
3138 std::string BuildRootWindowTreeDescription(const aura::Window& window) {
3140 for (size_t i = 0; i < window.children().size(); ++i) {
3143 result += BuildWindowTreeDescription(*(window.children()[i]));
3148 // Used by BuildRootWindowTreeDescription().
3149 std::string BuildLayerTreeDescription(const ui::Layer& layer) {
3151 result += layer.name();
3152 if (layer.children().empty())
3156 for (size_t i = 0; i < layer.children().size(); ++i) {
3159 result += BuildLayerTreeDescription(*(layer.children()[i]));
3165 // Builds a string for all the children of |layer|. The returned string is in
3166 // the same format as AddWindowsFromString() but only includes the name of the
3168 std::string BuildRootLayerTreeDescription(const ui::Layer& layer) {
3170 for (size_t i = 0; i < layer.children().size(); ++i) {
3173 result += BuildLayerTreeDescription(*(layer.children()[i]));
3178 // Returns the first window whose name matches |name| in |parent|.
3179 aura::Window* FindWindowByName(aura::Window* parent,
3180 const std::string& name) {
3181 if (parent->name() == name)
3183 for (size_t i = 0; i < parent->children().size(); ++i) {
3184 aura::Window* child = FindWindowByName(parent->children()[i], name);
3193 // Direction to stack.
3201 // Permutations of StackChildAt with various data.
3202 TEST_F(WindowTest, StackChildAtLayerless) {
3204 // Describes the window tree to create. See AddWindowsFromString() for
3206 const std::string initial_description;
3208 // Identifies the window to move.
3209 const std::string source_window;
3211 // Window to move |source_window| relative to. Not used for STACK_AT_BOTTOM
3213 const std::string target_window;
3215 StackType stack_type;
3217 // Expected window and layer results.
3218 const std::string expected_description;
3219 const std::string expected_layer_description;
3223 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3227 "2 [ 21 ] 1 [ 11 12 ]",
3233 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3237 "1 [ 11 12 ] 2 [ 21 ]",
3243 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3247 "2 [ 21 ] 1 [ 11 12 ]",
3253 "1:ll [ 11 12 ] 2:ll [ 21 ] 3:ll",
3257 "1 [ 11 12 ] 3 2 [ 21 ]",
3263 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3267 "2 [ 21 ] 1 [ 11 12 ]",
3273 "1:ll [ 11 12 ] 2:ll [ 21 ] 3:ll",
3277 "2 [ 21 ] 3 1 [ 11 12 ]",
3283 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3287 "2 [ 21 ] 1 [ 11 12 ]",
3291 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
3292 test::TestWindowDelegate delegate;
3294 root.Init(WINDOW_LAYER_NOT_DRAWN);
3295 root.SetBounds(gfx::Rect(0, 0, 100, 100));
3296 AddWindowsFromString(
3298 data[i].initial_description,
3299 static_cast<std::string::size_type>(0), &delegate);
3300 aura::Window* source = FindWindowByName(&root, data[i].source_window);
3301 ASSERT_TRUE(source != NULL) << "unable to find source window "
3302 << data[i].source_window << " at " << i;
3303 aura::Window* target = FindWindowByName(&root, data[i].target_window);
3304 switch (data[i].stack_type) {
3306 ASSERT_TRUE(target != NULL) << "unable to find target window "
3307 << data[i].target_window << " at " << i;
3308 source->parent()->StackChildAbove(source, target);
3311 ASSERT_TRUE(target != NULL) << "unable to find target window "
3312 << data[i].target_window << " at " << i;
3313 source->parent()->StackChildBelow(source, target);
3315 case STACK_AT_BOTTOM:
3316 source->parent()->StackChildAtBottom(source);
3319 source->parent()->StackChildAtTop(source);
3322 EXPECT_EQ(data[i].expected_layer_description,
3323 BuildRootLayerTreeDescription(*root.layer()))
3324 << "layer tree doesn't match at " << i;
3325 EXPECT_EQ(data[i].expected_description,
3326 BuildRootWindowTreeDescription(root))
3327 << "window tree doesn't match at " << i;