1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/aura/window.h"
11 #include "base/basictypes.h"
12 #include "base/compiler_specific.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "ui/aura/client/capture_client.h"
18 #include "ui/aura/client/focus_change_observer.h"
19 #include "ui/aura/client/visibility_client.h"
20 #include "ui/aura/client/window_tree_client.h"
21 #include "ui/aura/test/aura_test_base.h"
22 #include "ui/aura/test/event_generator.h"
23 #include "ui/aura/test/test_window_delegate.h"
24 #include "ui/aura/test/test_windows.h"
25 #include "ui/aura/test/window_test_api.h"
26 #include "ui/aura/window_delegate.h"
27 #include "ui/aura/window_event_dispatcher.h"
28 #include "ui/aura/window_observer.h"
29 #include "ui/aura/window_property.h"
30 #include "ui/aura/window_tree_host.h"
31 #include "ui/base/hit_test.h"
32 #include "ui/compositor/layer.h"
33 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
34 #include "ui/compositor/scoped_layer_animation_settings.h"
35 #include "ui/compositor/test/test_layers.h"
36 #include "ui/events/event.h"
37 #include "ui/events/event_utils.h"
38 #include "ui/events/gestures/gesture_configuration.h"
39 #include "ui/events/keycodes/keyboard_codes.h"
40 #include "ui/gfx/canvas.h"
41 #include "ui/gfx/screen.h"
42 #include "ui/gfx/skia_util.h"
43 #include "ui/gfx/vector2d.h"
45 DECLARE_WINDOW_PROPERTY_TYPE(const char*)
46 DECLARE_WINDOW_PROPERTY_TYPE(int)
51 class WindowTest : public AuraTestBase {
53 WindowTest() : max_separation_(0) {
56 virtual void SetUp() OVERRIDE {
57 AuraTestBase::SetUp();
58 // TODO: there needs to be an easier way to do this.
59 max_separation_ = ui::GestureConfiguration::
60 max_separation_for_gesture_touches_in_pixels();
61 ui::GestureConfiguration::
62 set_max_separation_for_gesture_touches_in_pixels(0);
65 virtual void TearDown() OVERRIDE {
66 AuraTestBase::TearDown();
67 ui::GestureConfiguration::
68 set_max_separation_for_gesture_touches_in_pixels(max_separation_);
74 DISALLOW_COPY_AND_ASSIGN(WindowTest);
79 // Used for verifying destruction methods are invoked.
80 class DestroyTrackingDelegateImpl : public TestWindowDelegate {
82 DestroyTrackingDelegateImpl()
83 : destroying_count_(0),
85 in_destroying_(false) {}
87 void clear_destroying_count() { destroying_count_ = 0; }
88 int destroying_count() const { return destroying_count_; }
90 void clear_destroyed_count() { destroyed_count_ = 0; }
91 int destroyed_count() const { return destroyed_count_; }
93 bool in_destroying() const { return in_destroying_; }
95 virtual void OnWindowDestroying(Window* window) OVERRIDE {
96 EXPECT_FALSE(in_destroying_);
97 in_destroying_ = true;
101 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
102 EXPECT_TRUE(in_destroying_);
103 in_destroying_ = false;
108 int destroying_count_;
109 int destroyed_count_;
112 DISALLOW_COPY_AND_ASSIGN(DestroyTrackingDelegateImpl);
115 // Used to verify that when OnWindowDestroying is invoked the parent is also
116 // is in the process of being destroyed.
117 class ChildWindowDelegateImpl : public DestroyTrackingDelegateImpl {
119 explicit ChildWindowDelegateImpl(
120 DestroyTrackingDelegateImpl* parent_delegate)
121 : parent_delegate_(parent_delegate) {
124 virtual void OnWindowDestroying(Window* window) OVERRIDE {
125 EXPECT_TRUE(parent_delegate_->in_destroying());
126 DestroyTrackingDelegateImpl::OnWindowDestroying(window);
130 DestroyTrackingDelegateImpl* parent_delegate_;
132 DISALLOW_COPY_AND_ASSIGN(ChildWindowDelegateImpl);
135 // Used to verify that a Window is removed from its parent when
136 // OnWindowDestroyed is called.
137 class DestroyOrphanDelegate : public TestWindowDelegate {
139 DestroyOrphanDelegate() : window_(NULL) {
142 void set_window(Window* window) { window_ = window; }
144 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
145 EXPECT_FALSE(window_->parent());
150 DISALLOW_COPY_AND_ASSIGN(DestroyOrphanDelegate);
153 // Used in verifying mouse capture.
154 class CaptureWindowDelegateImpl : public TestWindowDelegate {
156 CaptureWindowDelegateImpl() {
161 capture_changed_event_count_ = 0;
162 capture_lost_count_ = 0;
163 mouse_event_count_ = 0;
164 touch_event_count_ = 0;
165 gesture_event_count_ = 0;
168 int capture_changed_event_count() const {
169 return capture_changed_event_count_;
171 int capture_lost_count() const { return capture_lost_count_; }
172 int mouse_event_count() const { return mouse_event_count_; }
173 int touch_event_count() const { return touch_event_count_; }
174 int gesture_event_count() const { return gesture_event_count_; }
176 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
177 if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
178 capture_changed_event_count_++;
179 mouse_event_count_++;
181 virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
182 touch_event_count_++;
184 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
185 gesture_event_count_++;
187 virtual void OnCaptureLost() OVERRIDE {
188 capture_lost_count_++;
192 int capture_changed_event_count_;
193 int capture_lost_count_;
194 int mouse_event_count_;
195 int touch_event_count_;
196 int gesture_event_count_;
198 DISALLOW_COPY_AND_ASSIGN(CaptureWindowDelegateImpl);
201 // Keeps track of the location of the gesture.
202 class GestureTrackPositionDelegate : public TestWindowDelegate {
204 GestureTrackPositionDelegate() {}
206 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
207 position_ = event->location();
208 event->StopPropagation();
211 const gfx::Point& position() const { return position_; }
214 gfx::Point position_;
216 DISALLOW_COPY_AND_ASSIGN(GestureTrackPositionDelegate);
219 base::TimeDelta getTime() {
220 return ui::EventTimeForNow();
223 class SelfEventHandlingWindowDelegate : public TestWindowDelegate {
225 SelfEventHandlingWindowDelegate() {}
227 virtual bool ShouldDescendIntoChildForEventHandling(
229 const gfx::Point& location) OVERRIDE {
234 DISALLOW_COPY_AND_ASSIGN(SelfEventHandlingWindowDelegate);
237 // The delegate deletes itself when the window is being destroyed.
238 class DestroyWindowDelegate : public TestWindowDelegate {
240 DestroyWindowDelegate() {}
243 virtual ~DestroyWindowDelegate() {}
245 // Overridden from WindowDelegate.
246 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
250 DISALLOW_COPY_AND_ASSIGN(DestroyWindowDelegate);
255 TEST_F(WindowTest, GetChildById) {
256 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
257 scoped_ptr<Window> w11(CreateTestWindowWithId(11, w1.get()));
258 scoped_ptr<Window> w111(CreateTestWindowWithId(111, w11.get()));
259 scoped_ptr<Window> w12(CreateTestWindowWithId(12, w1.get()));
261 EXPECT_EQ(NULL, w1->GetChildById(57));
262 EXPECT_EQ(w12.get(), w1->GetChildById(12));
263 EXPECT_EQ(w111.get(), w1->GetChildById(111));
266 // Make sure that Window::Contains correctly handles children, grandchildren,
267 // and not containing NULL or parents.
268 TEST_F(WindowTest, Contains) {
270 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
272 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
274 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
276 parent.AddChild(&child1);
277 child1.AddChild(&child2);
279 EXPECT_TRUE(parent.Contains(&parent));
280 EXPECT_TRUE(parent.Contains(&child1));
281 EXPECT_TRUE(parent.Contains(&child2));
283 EXPECT_FALSE(parent.Contains(NULL));
284 EXPECT_FALSE(child1.Contains(&parent));
285 EXPECT_FALSE(child2.Contains(&child1));
288 TEST_F(WindowTest, ContainsPointInRoot) {
289 scoped_ptr<Window> w(
290 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 5, 5),
292 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(9, 9)));
293 EXPECT_TRUE(w->ContainsPointInRoot(gfx::Point(10, 10)));
294 EXPECT_TRUE(w->ContainsPointInRoot(gfx::Point(14, 14)));
295 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(15, 15)));
296 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(20, 20)));
299 TEST_F(WindowTest, ContainsPoint) {
300 scoped_ptr<Window> w(
301 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 5, 5),
303 EXPECT_TRUE(w->ContainsPoint(gfx::Point(0, 0)));
304 EXPECT_TRUE(w->ContainsPoint(gfx::Point(4, 4)));
305 EXPECT_FALSE(w->ContainsPoint(gfx::Point(5, 5)));
306 EXPECT_FALSE(w->ContainsPoint(gfx::Point(10, 10)));
309 TEST_F(WindowTest, ConvertPointToWindow) {
310 // Window::ConvertPointToWindow is mostly identical to
311 // Layer::ConvertPointToLayer, except NULL values for |source| are permitted,
312 // in which case the function just returns.
313 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
314 gfx::Point reference_point(100, 100);
315 gfx::Point test_point = reference_point;
316 Window::ConvertPointToTarget(NULL, w1.get(), &test_point);
317 EXPECT_EQ(reference_point, test_point);
320 TEST_F(WindowTest, MoveCursorTo) {
321 scoped_ptr<Window> w1(
322 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
324 scoped_ptr<Window> w11(
325 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
326 scoped_ptr<Window> w111(
327 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
328 scoped_ptr<Window> w1111(
329 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
331 Window* root = root_window();
332 root->MoveCursorTo(gfx::Point(10, 10));
334 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
335 w1->MoveCursorTo(gfx::Point(10, 10));
337 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
338 w11->MoveCursorTo(gfx::Point(10, 10));
340 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
341 w111->MoveCursorTo(gfx::Point(10, 10));
343 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
344 w1111->MoveCursorTo(gfx::Point(10, 10));
346 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
349 TEST_F(WindowTest, ContainsMouse) {
350 scoped_ptr<Window> w(
351 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
354 WindowTestApi w_test_api(w.get());
355 Window* root = root_window();
356 root->MoveCursorTo(gfx::Point(10, 10));
357 EXPECT_TRUE(w_test_api.ContainsMouse());
358 root->MoveCursorTo(gfx::Point(9, 10));
359 EXPECT_FALSE(w_test_api.ContainsMouse());
362 // Test Window::ConvertPointToWindow() with transform to root_window.
363 #if defined(USE_OZONE)
364 // TODO(rjkroege): Add cursor support in ozone: http://crbug.com/252315.
365 TEST_F(WindowTest, DISABLED_MoveCursorToWithTransformRootWindow) {
367 TEST_F(WindowTest, MoveCursorToWithTransformRootWindow) {
369 gfx::Transform transform;
370 transform.Translate(100.0, 100.0);
371 transform.Rotate(90.0);
372 transform.Scale(2.0, 5.0);
373 host()->SetTransform(transform);
374 host()->MoveCursorTo(gfx::Point(10, 10));
376 gfx::Point mouse_location;
377 EXPECT_TRUE(host()->QueryMouseLocation(&mouse_location));
378 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.OD
379 EXPECT_EQ("50,120", mouse_location.ToString());
381 EXPECT_EQ("10,10", gfx::Screen::GetScreenFor(
382 root_window())->GetCursorScreenPoint().ToString());
385 // Tests Window::ConvertPointToWindow() with transform to non-root windows.
386 TEST_F(WindowTest, MoveCursorToWithTransformWindow) {
387 scoped_ptr<Window> w1(
388 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
391 gfx::Transform transform1;
392 transform1.Scale(2, 2);
393 w1->SetTransform(transform1);
394 w1->MoveCursorTo(gfx::Point(10, 10));
396 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
398 gfx::Transform transform2;
399 transform2.Translate(-10, 20);
400 w1->SetTransform(transform2);
401 w1->MoveCursorTo(gfx::Point(10, 10));
403 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
405 gfx::Transform transform3;
406 transform3.Rotate(90.0);
407 w1->SetTransform(transform3);
408 w1->MoveCursorTo(gfx::Point(5, 5));
410 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
412 gfx::Transform transform4;
413 transform4.Translate(100.0, 100.0);
414 transform4.Rotate(90.0);
415 transform4.Scale(2.0, 5.0);
416 w1->SetTransform(transform4);
417 w1->MoveCursorTo(gfx::Point(10, 10));
419 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
422 // Test Window::ConvertPointToWindow() with complex transforms to both root and
424 // Test Window::ConvertPointToWindow() with transform to root_window.
425 #if defined(USE_OZONE)
426 // TODO(rjkroege): Add cursor support in ozone: http://crbug.com/252315.
427 TEST_F(WindowTest, DISABLED_MoveCursorToWithComplexTransform) {
429 TEST_F(WindowTest, MoveCursorToWithComplexTransform) {
431 scoped_ptr<Window> w1(
432 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
434 scoped_ptr<Window> w11(
435 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
436 scoped_ptr<Window> w111(
437 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
438 scoped_ptr<Window> w1111(
439 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
441 Window* root = root_window();
443 // The root window expects transforms that produce integer rects.
444 gfx::Transform root_transform;
445 root_transform.Translate(60.0, 70.0);
446 root_transform.Rotate(-90.0);
447 root_transform.Translate(-50.0, -50.0);
448 root_transform.Scale(2.0, 3.0);
450 gfx::Transform transform;
451 transform.Translate(10.0, 20.0);
452 transform.Rotate(10.0);
453 transform.Scale(0.3f, 0.5f);
454 host()->SetTransform(root_transform);
455 w1->SetTransform(transform);
456 w11->SetTransform(transform);
457 w111->SetTransform(transform);
458 w1111->SetTransform(transform);
460 w1111->MoveCursorTo(gfx::Point(10, 10));
463 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.
464 gfx::Point mouse_location;
465 EXPECT_TRUE(host()->QueryMouseLocation(&mouse_location));
466 EXPECT_EQ("169,80", mouse_location.ToString());
469 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
472 TEST_F(WindowTest, GetEventHandlerForPoint) {
473 scoped_ptr<Window> w1(
474 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
476 scoped_ptr<Window> w11(
477 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
478 scoped_ptr<Window> w111(
479 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
480 scoped_ptr<Window> w1111(
481 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
482 scoped_ptr<Window> w12(
483 CreateTestWindow(SK_ColorMAGENTA, 12, gfx::Rect(10, 420, 25, 25),
485 scoped_ptr<Window> w121(
486 CreateTestWindow(SK_ColorYELLOW, 121, gfx::Rect(5, 5, 5, 5), w12.get()));
487 scoped_ptr<Window> w13(
488 CreateTestWindow(SK_ColorGRAY, 13, gfx::Rect(5, 470, 50, 50), w1.get()));
490 Window* root = root_window();
491 w1->parent()->SetBounds(gfx::Rect(500, 500));
492 EXPECT_EQ(NULL, root->GetEventHandlerForPoint(gfx::Point(5, 5)));
493 EXPECT_EQ(w1.get(), root->GetEventHandlerForPoint(gfx::Point(11, 11)));
494 EXPECT_EQ(w11.get(), root->GetEventHandlerForPoint(gfx::Point(16, 16)));
495 EXPECT_EQ(w111.get(), root->GetEventHandlerForPoint(gfx::Point(21, 21)));
496 EXPECT_EQ(w1111.get(), root->GetEventHandlerForPoint(gfx::Point(26, 26)));
497 EXPECT_EQ(w12.get(), root->GetEventHandlerForPoint(gfx::Point(21, 431)));
498 EXPECT_EQ(w121.get(), root->GetEventHandlerForPoint(gfx::Point(26, 436)));
499 EXPECT_EQ(w13.get(), root->GetEventHandlerForPoint(gfx::Point(26, 481)));
502 TEST_F(WindowTest, GetEventHandlerForPointWithOverride) {
503 // If our child is flush to our top-left corner he gets events just inside the
505 scoped_ptr<Window> parent(
506 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 20, 400, 500),
508 scoped_ptr<Window> child(
509 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(0, 0, 60, 70), parent.get()));
510 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
511 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(1, 1)));
513 // We can override the hit test bounds of the parent to make the parent grab
514 // events along that edge.
515 parent->set_hit_test_bounds_override_inner(gfx::Insets(1, 1, 1, 1));
516 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
517 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(1, 1)));
520 TEST_F(WindowTest, GetEventHandlerForPointWithOverrideDescendingOrder) {
521 scoped_ptr<SelfEventHandlingWindowDelegate> parent_delegate(
522 new SelfEventHandlingWindowDelegate);
523 scoped_ptr<Window> parent(CreateTestWindowWithDelegate(
524 parent_delegate.get(), 1, gfx::Rect(10, 20, 400, 500), root_window()));
525 scoped_ptr<Window> child(
526 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(0, 0, 390, 480),
529 // We can override ShouldDescendIntoChildForEventHandling to make the parent
531 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
532 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(50, 50)));
535 TEST_F(WindowTest, GetTopWindowContainingPoint) {
536 Window* root = root_window();
537 root->SetBounds(gfx::Rect(0, 0, 300, 300));
539 scoped_ptr<Window> w1(
540 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 100, 100),
542 scoped_ptr<Window> w11(
543 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(0, 0, 120, 120), w1.get()));
545 scoped_ptr<Window> w2(
546 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(5, 5, 55, 55),
549 scoped_ptr<Window> w3(
550 CreateTestWindowWithDelegate(
551 NULL, 3, gfx::Rect(200, 200, 100, 100), root_window()));
552 scoped_ptr<Window> w31(
553 CreateTestWindow(SK_ColorCYAN, 31, gfx::Rect(0, 0, 50, 50), w3.get()));
554 scoped_ptr<Window> w311(
555 CreateTestWindow(SK_ColorBLUE, 311, gfx::Rect(0, 0, 10, 10), w31.get()));
557 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(0, 0)));
558 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(5, 5)));
559 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(10, 10)));
560 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(59, 59)));
561 EXPECT_EQ(w1.get(), root->GetTopWindowContainingPoint(gfx::Point(60, 60)));
562 EXPECT_EQ(w1.get(), root->GetTopWindowContainingPoint(gfx::Point(109, 109)));
563 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(110, 110)));
564 EXPECT_EQ(w31.get(), root->GetTopWindowContainingPoint(gfx::Point(200, 200)));
565 EXPECT_EQ(w31.get(), root->GetTopWindowContainingPoint(gfx::Point(220, 220)));
566 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(260, 260)));
569 TEST_F(WindowTest, GetToplevelWindow) {
570 const gfx::Rect kBounds(0, 0, 10, 10);
571 TestWindowDelegate delegate;
573 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
574 scoped_ptr<Window> w11(
575 CreateTestWindowWithDelegate(&delegate, 11, kBounds, w1.get()));
576 scoped_ptr<Window> w111(CreateTestWindowWithId(111, w11.get()));
577 scoped_ptr<Window> w1111(
578 CreateTestWindowWithDelegate(&delegate, 1111, kBounds, w111.get()));
580 EXPECT_TRUE(root_window()->GetToplevelWindow() == NULL);
581 EXPECT_TRUE(w1->GetToplevelWindow() == NULL);
582 EXPECT_EQ(w11.get(), w11->GetToplevelWindow());
583 EXPECT_EQ(w11.get(), w111->GetToplevelWindow());
584 EXPECT_EQ(w11.get(), w1111->GetToplevelWindow());
587 class AddedToRootWindowObserver : public WindowObserver {
589 AddedToRootWindowObserver() : called_(false) {}
591 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
595 bool called() const { return called_; }
600 DISALLOW_COPY_AND_ASSIGN(AddedToRootWindowObserver);
603 TEST_F(WindowTest, WindowAddedToRootWindowShouldNotifyChildAndNotParent) {
604 AddedToRootWindowObserver parent_observer;
605 AddedToRootWindowObserver child_observer;
606 scoped_ptr<Window> parent_window(CreateTestWindowWithId(1, root_window()));
607 scoped_ptr<Window> child_window(new Window(NULL));
608 child_window->Init(aura::WINDOW_LAYER_TEXTURED);
609 child_window->Show();
611 parent_window->AddObserver(&parent_observer);
612 child_window->AddObserver(&child_observer);
614 parent_window->AddChild(child_window.get());
616 EXPECT_FALSE(parent_observer.called());
617 EXPECT_TRUE(child_observer.called());
619 parent_window->RemoveObserver(&parent_observer);
620 child_window->RemoveObserver(&child_observer);
623 // Various destruction assertions.
624 TEST_F(WindowTest, DestroyTest) {
625 DestroyTrackingDelegateImpl parent_delegate;
626 ChildWindowDelegateImpl child_delegate(&parent_delegate);
628 scoped_ptr<Window> parent(
629 CreateTestWindowWithDelegate(&parent_delegate, 0, gfx::Rect(),
631 CreateTestWindowWithDelegate(&child_delegate, 0, gfx::Rect(), parent.get());
633 // Both the parent and child should have been destroyed.
634 EXPECT_EQ(1, parent_delegate.destroying_count());
635 EXPECT_EQ(1, parent_delegate.destroyed_count());
636 EXPECT_EQ(1, child_delegate.destroying_count());
637 EXPECT_EQ(1, child_delegate.destroyed_count());
640 // Tests that a window is orphaned before OnWindowDestroyed is called.
641 TEST_F(WindowTest, OrphanedBeforeOnDestroyed) {
642 TestWindowDelegate parent_delegate;
643 DestroyOrphanDelegate child_delegate;
645 scoped_ptr<Window> parent(
646 CreateTestWindowWithDelegate(&parent_delegate, 0, gfx::Rect(),
648 scoped_ptr<Window> child(CreateTestWindowWithDelegate(&child_delegate, 0,
649 gfx::Rect(), parent.get()));
650 child_delegate.set_window(child.get());
654 // Make sure StackChildAtTop moves both the window and layer to the front.
655 TEST_F(WindowTest, StackChildAtTop) {
657 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
659 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
661 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
663 parent.AddChild(&child1);
664 parent.AddChild(&child2);
665 ASSERT_EQ(2u, parent.children().size());
666 EXPECT_EQ(&child1, parent.children()[0]);
667 EXPECT_EQ(&child2, parent.children()[1]);
668 ASSERT_EQ(2u, parent.layer()->children().size());
669 EXPECT_EQ(child1.layer(), parent.layer()->children()[0]);
670 EXPECT_EQ(child2.layer(), parent.layer()->children()[1]);
672 parent.StackChildAtTop(&child1);
673 ASSERT_EQ(2u, parent.children().size());
674 EXPECT_EQ(&child1, parent.children()[1]);
675 EXPECT_EQ(&child2, parent.children()[0]);
676 ASSERT_EQ(2u, parent.layer()->children().size());
677 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
678 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
681 // Make sure StackChildBelow works.
682 TEST_F(WindowTest, StackChildBelow) {
684 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
686 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
689 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
692 child3.Init(aura::WINDOW_LAYER_NOT_DRAWN);
695 parent.AddChild(&child1);
696 parent.AddChild(&child2);
697 parent.AddChild(&child3);
698 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent));
700 parent.StackChildBelow(&child1, &child2);
701 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent));
703 parent.StackChildBelow(&child2, &child1);
704 EXPECT_EQ("2 1 3", ChildWindowIDsAsString(&parent));
706 parent.StackChildBelow(&child3, &child2);
707 EXPECT_EQ("3 2 1", ChildWindowIDsAsString(&parent));
709 parent.StackChildBelow(&child3, &child1);
710 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(&parent));
713 // Various assertions for StackChildAbove.
714 TEST_F(WindowTest, StackChildAbove) {
716 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
718 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
720 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
722 child3.Init(aura::WINDOW_LAYER_NOT_DRAWN);
724 parent.AddChild(&child1);
725 parent.AddChild(&child2);
727 // Move 1 in front of 2.
728 parent.StackChildAbove(&child1, &child2);
729 ASSERT_EQ(2u, parent.children().size());
730 EXPECT_EQ(&child2, parent.children()[0]);
731 EXPECT_EQ(&child1, parent.children()[1]);
732 ASSERT_EQ(2u, parent.layer()->children().size());
733 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
734 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
736 // Add 3, resulting in order [2, 1, 3], then move 2 in front of 1, resulting
738 parent.AddChild(&child3);
739 parent.StackChildAbove(&child2, &child1);
740 ASSERT_EQ(3u, parent.children().size());
741 EXPECT_EQ(&child1, parent.children()[0]);
742 EXPECT_EQ(&child2, parent.children()[1]);
743 EXPECT_EQ(&child3, parent.children()[2]);
744 ASSERT_EQ(3u, parent.layer()->children().size());
745 EXPECT_EQ(child1.layer(), parent.layer()->children()[0]);
746 EXPECT_EQ(child2.layer(), parent.layer()->children()[1]);
747 EXPECT_EQ(child3.layer(), parent.layer()->children()[2]);
749 // Move 1 in front of 3, resulting in [2, 3, 1].
750 parent.StackChildAbove(&child1, &child3);
751 ASSERT_EQ(3u, parent.children().size());
752 EXPECT_EQ(&child2, parent.children()[0]);
753 EXPECT_EQ(&child3, parent.children()[1]);
754 EXPECT_EQ(&child1, parent.children()[2]);
755 ASSERT_EQ(3u, parent.layer()->children().size());
756 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
757 EXPECT_EQ(child3.layer(), parent.layer()->children()[1]);
758 EXPECT_EQ(child1.layer(), parent.layer()->children()[2]);
760 // Moving 1 in front of 2 should lower it, resulting in [2, 1, 3].
761 parent.StackChildAbove(&child1, &child2);
762 ASSERT_EQ(3u, parent.children().size());
763 EXPECT_EQ(&child2, parent.children()[0]);
764 EXPECT_EQ(&child1, parent.children()[1]);
765 EXPECT_EQ(&child3, parent.children()[2]);
766 ASSERT_EQ(3u, parent.layer()->children().size());
767 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
768 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
769 EXPECT_EQ(child3.layer(), parent.layer()->children()[2]);
772 // Various capture assertions.
773 TEST_F(WindowTest, CaptureTests) {
774 CaptureWindowDelegateImpl delegate;
775 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
776 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
777 EXPECT_FALSE(window->HasCapture());
779 delegate.ResetCounts();
782 window->SetCapture();
783 EXPECT_TRUE(window->HasCapture());
784 EXPECT_EQ(0, delegate.capture_lost_count());
785 EXPECT_EQ(0, delegate.capture_changed_event_count());
786 EventGenerator generator(root_window(), gfx::Point(50, 50));
787 generator.PressLeftButton();
788 EXPECT_EQ(1, delegate.mouse_event_count());
789 generator.ReleaseLeftButton();
791 EXPECT_EQ(2, delegate.mouse_event_count());
792 delegate.ResetCounts();
794 ui::TouchEvent touchev(
795 ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), 0, getTime());
796 DispatchEventUsingWindowDispatcher(&touchev);
797 EXPECT_EQ(1, delegate.touch_event_count());
798 delegate.ResetCounts();
800 window->ReleaseCapture();
801 EXPECT_FALSE(window->HasCapture());
802 EXPECT_EQ(1, delegate.capture_lost_count());
803 EXPECT_EQ(1, delegate.capture_changed_event_count());
804 EXPECT_EQ(1, delegate.mouse_event_count());
805 EXPECT_EQ(0, delegate.touch_event_count());
807 generator.PressLeftButton();
808 EXPECT_EQ(1, delegate.mouse_event_count());
810 ui::TouchEvent touchev2(
811 ui::ET_TOUCH_PRESSED, gfx::Point(250, 250), 1, getTime());
812 DispatchEventUsingWindowDispatcher(&touchev2);
813 EXPECT_EQ(0, delegate.touch_event_count());
815 // Removing the capture window from parent should reset the capture window
816 // in the root window.
817 window->SetCapture();
818 EXPECT_EQ(window.get(), aura::client::GetCaptureWindow(root_window()));
819 window->parent()->RemoveChild(window.get());
820 EXPECT_FALSE(window->HasCapture());
821 EXPECT_EQ(NULL, aura::client::GetCaptureWindow(root_window()));
824 TEST_F(WindowTest, TouchCaptureCancelsOtherTouches) {
825 CaptureWindowDelegateImpl delegate1;
826 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
827 &delegate1, 0, gfx::Rect(0, 0, 50, 50), root_window()));
828 CaptureWindowDelegateImpl delegate2;
829 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
830 &delegate2, 0, gfx::Rect(50, 50, 50, 50), root_window()));
833 ui::TouchEvent press(
834 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
835 DispatchEventUsingWindowDispatcher(&press);
836 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
837 EXPECT_EQ(2, delegate1.gesture_event_count());
838 delegate1.ResetCounts();
840 // Capturing to w2 should cause the touch to be canceled.
842 EXPECT_EQ(1, delegate1.touch_event_count());
843 EXPECT_EQ(0, delegate2.touch_event_count());
844 delegate1.ResetCounts();
845 delegate2.ResetCounts();
847 // Events now go to w2.
848 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, getTime());
849 DispatchEventUsingWindowDispatcher(&move);
850 EXPECT_EQ(0, delegate1.gesture_event_count());
851 EXPECT_EQ(0, delegate1.touch_event_count());
852 EXPECT_EQ(0, delegate2.gesture_event_count());
853 EXPECT_EQ(1, delegate2.touch_event_count());
855 ui::TouchEvent release(
856 ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, getTime());
857 DispatchEventUsingWindowDispatcher(&release);
858 EXPECT_EQ(0, delegate1.gesture_event_count());
859 EXPECT_EQ(0, delegate2.gesture_event_count());
861 // A new press is captured by w2.
862 ui::TouchEvent press2(
863 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
864 DispatchEventUsingWindowDispatcher(&press2);
865 EXPECT_EQ(0, delegate1.gesture_event_count());
866 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
867 EXPECT_EQ(2, delegate2.gesture_event_count());
868 delegate1.ResetCounts();
869 delegate2.ResetCounts();
871 // And releasing capture changes nothing.
872 w2->ReleaseCapture();
873 EXPECT_EQ(0, delegate1.gesture_event_count());
874 EXPECT_EQ(0, delegate1.touch_event_count());
875 EXPECT_EQ(0, delegate2.gesture_event_count());
876 EXPECT_EQ(0, delegate2.touch_event_count());
879 TEST_F(WindowTest, TouchCaptureDoesntCancelCapturedTouches) {
880 CaptureWindowDelegateImpl delegate;
881 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
882 &delegate, 0, gfx::Rect(0, 0, 50, 50), root_window()));
884 ui::TouchEvent press(
885 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
886 DispatchEventUsingWindowDispatcher(&press);
888 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
889 EXPECT_EQ(2, delegate.gesture_event_count());
890 EXPECT_EQ(1, delegate.touch_event_count());
891 delegate.ResetCounts();
893 window->SetCapture();
894 EXPECT_EQ(0, delegate.gesture_event_count());
895 EXPECT_EQ(0, delegate.touch_event_count());
896 delegate.ResetCounts();
898 // On move We will get TOUCH_MOVED, GESTURE_TAP_CANCEL,
899 // GESTURE_SCROLL_START and GESTURE_SCROLL_UPDATE.
900 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, getTime());
901 DispatchEventUsingWindowDispatcher(&move);
902 EXPECT_EQ(1, delegate.touch_event_count());
903 EXPECT_EQ(3, delegate.gesture_event_count());
904 delegate.ResetCounts();
906 // Release capture shouldn't change anything.
907 window->ReleaseCapture();
908 EXPECT_EQ(0, delegate.touch_event_count());
909 EXPECT_EQ(0, delegate.gesture_event_count());
910 delegate.ResetCounts();
912 // On move we still get TOUCH_MOVED and GESTURE_SCROLL_UPDATE.
913 ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(10, 30), 0, getTime());
914 DispatchEventUsingWindowDispatcher(&move2);
915 EXPECT_EQ(1, delegate.touch_event_count());
916 EXPECT_EQ(1, delegate.gesture_event_count());
917 delegate.ResetCounts();
919 // And on release we get TOUCH_RELEASED, GESTURE_SCROLL_END, GESTURE_END
920 ui::TouchEvent release(
921 ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, getTime());
922 DispatchEventUsingWindowDispatcher(&release);
923 EXPECT_EQ(1, delegate.touch_event_count());
924 EXPECT_EQ(2, delegate.gesture_event_count());
928 // Assertions around SetCapture() and touch/gestures.
929 TEST_F(WindowTest, TransferCaptureTouchEvents) {
931 CaptureWindowDelegateImpl d1;
932 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
933 &d1, 0, gfx::Rect(0, 0, 20, 20), root_window()));
934 ui::TouchEvent p1(ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
935 DispatchEventUsingWindowDispatcher(&p1);
936 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
937 EXPECT_EQ(1, d1.touch_event_count());
938 EXPECT_EQ(2, d1.gesture_event_count());
941 // Touch on |w2| with a different id.
942 CaptureWindowDelegateImpl d2;
943 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
944 &d2, 0, gfx::Rect(40, 0, 40, 20), root_window()));
945 ui::TouchEvent p2(ui::ET_TOUCH_PRESSED, gfx::Point(41, 10), 1, getTime());
946 DispatchEventUsingWindowDispatcher(&p2);
947 EXPECT_EQ(0, d1.touch_event_count());
948 EXPECT_EQ(0, d1.gesture_event_count());
949 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN for new target window.
950 EXPECT_EQ(1, d2.touch_event_count());
951 EXPECT_EQ(2, d2.gesture_event_count());
955 // Set capture on |w2|, this should send a cancel (TAP_CANCEL, END) to |w1|
958 EXPECT_EQ(1, d1.touch_event_count());
959 EXPECT_EQ(2, d1.gesture_event_count());
960 EXPECT_EQ(0, d2.touch_event_count());
961 EXPECT_EQ(0, d2.gesture_event_count());
965 CaptureWindowDelegateImpl d3;
966 scoped_ptr<Window> w3(CreateTestWindowWithDelegate(
967 &d3, 0, gfx::Rect(0, 0, 100, 101), root_window()));
968 // Set capture on w3. No new events should be received.
969 // Note this difference in behavior between the first and second capture
970 // is confusing and error prone. http://crbug.com/236930
972 EXPECT_EQ(0, d1.touch_event_count());
973 EXPECT_EQ(0, d1.gesture_event_count());
974 EXPECT_EQ(0, d2.touch_event_count());
975 EXPECT_EQ(0, d2.gesture_event_count());
976 EXPECT_EQ(0, d3.touch_event_count());
977 EXPECT_EQ(0, d3.gesture_event_count());
979 // Move touch id originally associated with |w2|. Since capture was transfered
980 // from 2 to 3 only |w3| should get the event.
981 ui::TouchEvent m3(ui::ET_TOUCH_MOVED, gfx::Point(110, 105), 1, getTime());
982 DispatchEventUsingWindowDispatcher(&m3);
983 EXPECT_EQ(0, d1.touch_event_count());
984 EXPECT_EQ(0, d1.gesture_event_count());
985 EXPECT_EQ(0, d2.touch_event_count());
986 EXPECT_EQ(0, d2.gesture_event_count());
987 // |w3| gets a TOUCH_MOVE, TAP_CANCEL and two scroll related events.
988 EXPECT_EQ(1, d3.touch_event_count());
989 EXPECT_EQ(3, d3.gesture_event_count());
994 // When we release capture, no touches are canceled.
995 w3->ReleaseCapture();
996 EXPECT_EQ(0, d1.touch_event_count());
997 EXPECT_EQ(0, d1.gesture_event_count());
998 EXPECT_EQ(0, d2.touch_event_count());
999 EXPECT_EQ(0, d2.gesture_event_count());
1000 EXPECT_EQ(0, d3.touch_event_count());
1001 EXPECT_EQ(0, d3.gesture_event_count());
1003 // And when we move the touch again, |w3| still gets the events.
1004 ui::TouchEvent m4(ui::ET_TOUCH_MOVED, gfx::Point(120, 105), 1, getTime());
1005 DispatchEventUsingWindowDispatcher(&m4);
1006 EXPECT_EQ(0, d1.touch_event_count());
1007 EXPECT_EQ(0, d1.gesture_event_count());
1008 EXPECT_EQ(0, d2.touch_event_count());
1009 EXPECT_EQ(0, d2.gesture_event_count());
1010 EXPECT_EQ(1, d3.touch_event_count());
1011 EXPECT_EQ(1, d3.gesture_event_count());
1017 // Changes capture while capture is already ongoing.
1018 TEST_F(WindowTest, ChangeCaptureWhileMouseDown) {
1019 CaptureWindowDelegateImpl delegate;
1020 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
1021 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1022 CaptureWindowDelegateImpl delegate2;
1023 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
1024 &delegate2, 0, gfx::Rect(20, 20, 20, 20), root_window()));
1026 // Execute the scheduled draws so that mouse events are not
1028 RunAllPendingInMessageLoop();
1030 EXPECT_FALSE(window->HasCapture());
1033 delegate.ResetCounts();
1034 window->SetCapture();
1035 EXPECT_TRUE(window->HasCapture());
1036 EXPECT_EQ(0, delegate.capture_lost_count());
1037 EXPECT_EQ(0, delegate.capture_changed_event_count());
1038 EventGenerator generator(root_window(), gfx::Point(50, 50));
1039 generator.PressLeftButton();
1040 EXPECT_EQ(0, delegate.capture_lost_count());
1041 EXPECT_EQ(0, delegate.capture_changed_event_count());
1042 EXPECT_EQ(1, delegate.mouse_event_count());
1044 // Set capture to |w2|, should implicitly unset capture for |window|.
1045 delegate.ResetCounts();
1046 delegate2.ResetCounts();
1049 generator.MoveMouseTo(gfx::Point(40, 40), 2);
1050 EXPECT_EQ(1, delegate.capture_lost_count());
1051 EXPECT_EQ(1, delegate.capture_changed_event_count());
1052 EXPECT_EQ(1, delegate.mouse_event_count());
1053 EXPECT_EQ(2, delegate2.mouse_event_count());
1056 // Verifies capture is reset when a window is destroyed.
1057 TEST_F(WindowTest, ReleaseCaptureOnDestroy) {
1058 CaptureWindowDelegateImpl delegate;
1059 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
1060 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1061 EXPECT_FALSE(window->HasCapture());
1064 window->SetCapture();
1065 EXPECT_TRUE(window->HasCapture());
1067 // Destroy the window.
1070 // Make sure the root window doesn't reference the window anymore.
1071 EXPECT_EQ(NULL, host()->dispatcher()->mouse_pressed_handler());
1072 EXPECT_EQ(NULL, aura::client::GetCaptureWindow(root_window()));
1075 TEST_F(WindowTest, GetBoundsInRootWindow) {
1076 scoped_ptr<Window> viewport(CreateTestWindowWithBounds(
1077 gfx::Rect(0, 0, 300, 300), root_window()));
1078 scoped_ptr<Window> child(CreateTestWindowWithBounds(
1079 gfx::Rect(0, 0, 100, 100), viewport.get()));
1081 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1083 // The |child| window's screen bounds should move along with the |viewport|.
1084 viewport->SetBounds(gfx::Rect(-100, -100, 300, 300));
1085 EXPECT_EQ("-100,-100 100x100", child->GetBoundsInRootWindow().ToString());
1087 // The |child| window is moved to the 0,0 in screen coordinates.
1088 // |GetBoundsInRootWindow()| should return 0,0.
1089 child->SetBounds(gfx::Rect(100, 100, 100, 100));
1090 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1093 class MouseEnterExitWindowDelegate : public TestWindowDelegate {
1095 MouseEnterExitWindowDelegate() : entered_(false), exited_(false) {}
1097 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
1098 switch (event->type()) {
1099 case ui::ET_MOUSE_ENTERED:
1100 EXPECT_TRUE(event->flags() & ui::EF_IS_SYNTHESIZED);
1103 case ui::ET_MOUSE_EXITED:
1104 EXPECT_TRUE(event->flags() & ui::EF_IS_SYNTHESIZED);
1112 bool entered() const { return entered_; }
1113 bool exited() const { return exited_; }
1115 // Clear the entered / exited states.
1116 void ResetExpectations() {
1125 DISALLOW_COPY_AND_ASSIGN(MouseEnterExitWindowDelegate);
1129 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1130 // mouse transitions from window to window.
1131 TEST_F(WindowTest, MouseEnterExit) {
1132 MouseEnterExitWindowDelegate d1;
1133 scoped_ptr<Window> w1(
1134 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1136 MouseEnterExitWindowDelegate d2;
1137 scoped_ptr<Window> w2(
1138 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50),
1141 test::EventGenerator generator(root_window());
1142 generator.MoveMouseToCenterOf(w1.get());
1143 EXPECT_TRUE(d1.entered());
1144 EXPECT_FALSE(d1.exited());
1145 EXPECT_FALSE(d2.entered());
1146 EXPECT_FALSE(d2.exited());
1148 generator.MoveMouseToCenterOf(w2.get());
1149 EXPECT_TRUE(d1.entered());
1150 EXPECT_TRUE(d1.exited());
1151 EXPECT_TRUE(d2.entered());
1152 EXPECT_FALSE(d2.exited());
1155 // Verifies that the WindowDelegate receives MouseExit from ET_MOUSE_EXITED.
1156 TEST_F(WindowTest, WindowTreeHostExit) {
1157 MouseEnterExitWindowDelegate d1;
1158 scoped_ptr<Window> w1(
1159 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1162 test::EventGenerator generator(root_window());
1163 generator.MoveMouseToCenterOf(w1.get());
1164 EXPECT_TRUE(d1.entered());
1165 EXPECT_FALSE(d1.exited());
1166 d1.ResetExpectations();
1168 ui::MouseEvent exit_event(
1169 ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(), 0, 0);
1170 DispatchEventUsingWindowDispatcher(&exit_event);
1171 EXPECT_FALSE(d1.entered());
1172 EXPECT_TRUE(d1.exited());
1175 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1176 // mouse transitions from window to window, even if the entered window sets
1177 // and releases capture.
1178 TEST_F(WindowTest, MouseEnterExitWithClick) {
1179 MouseEnterExitWindowDelegate d1;
1180 scoped_ptr<Window> w1(
1181 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1183 MouseEnterExitWindowDelegate d2;
1184 scoped_ptr<Window> w2(
1185 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50),
1188 test::EventGenerator generator(root_window());
1189 generator.MoveMouseToCenterOf(w1.get());
1190 EXPECT_TRUE(d1.entered());
1191 EXPECT_FALSE(d1.exited());
1192 EXPECT_FALSE(d2.entered());
1193 EXPECT_FALSE(d2.exited());
1195 // Emmulate what Views does on a click by grabbing and releasing capture.
1196 generator.PressLeftButton();
1198 w1->ReleaseCapture();
1199 generator.ReleaseLeftButton();
1201 generator.MoveMouseToCenterOf(w2.get());
1202 EXPECT_TRUE(d1.entered());
1203 EXPECT_TRUE(d1.exited());
1204 EXPECT_TRUE(d2.entered());
1205 EXPECT_FALSE(d2.exited());
1208 TEST_F(WindowTest, MouseEnterExitWhenDeleteWithCapture) {
1209 MouseEnterExitWindowDelegate delegate;
1210 scoped_ptr<Window> window(
1211 CreateTestWindowWithDelegate(&delegate, 1, gfx::Rect(10, 10, 50, 50),
1214 test::EventGenerator generator(root_window());
1215 generator.MoveMouseToCenterOf(window.get());
1216 EXPECT_TRUE(delegate.entered());
1217 EXPECT_FALSE(delegate.exited());
1219 // Emmulate what Views does on a click by grabbing and releasing capture.
1220 generator.PressLeftButton();
1221 window->SetCapture();
1223 delegate.ResetExpectations();
1224 generator.MoveMouseTo(0, 0);
1225 EXPECT_FALSE(delegate.entered());
1226 EXPECT_FALSE(delegate.exited());
1228 delegate.ResetExpectations();
1230 EXPECT_FALSE(delegate.entered());
1231 EXPECT_FALSE(delegate.exited());
1234 // Verifies that enter / exits are sent if windows appear and are deleted
1235 // under the current mouse position..
1236 TEST_F(WindowTest, MouseEnterExitWithDelete) {
1237 MouseEnterExitWindowDelegate d1;
1238 scoped_ptr<Window> w1(
1239 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1242 test::EventGenerator generator(root_window());
1243 generator.MoveMouseToCenterOf(w1.get());
1244 EXPECT_TRUE(d1.entered());
1245 EXPECT_FALSE(d1.exited());
1246 d1.ResetExpectations();
1248 MouseEnterExitWindowDelegate d2;
1250 scoped_ptr<Window> w2(
1251 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1253 // Enters / exits can be sent asynchronously.
1254 RunAllPendingInMessageLoop();
1255 EXPECT_FALSE(d1.entered());
1256 EXPECT_TRUE(d1.exited());
1257 EXPECT_TRUE(d2.entered());
1258 EXPECT_FALSE(d2.exited());
1259 d1.ResetExpectations();
1260 d2.ResetExpectations();
1262 // Enters / exits can be sent asynchronously.
1263 RunAllPendingInMessageLoop();
1264 EXPECT_TRUE(d2.exited());
1265 EXPECT_TRUE(d1.entered());
1268 // Verifies that enter / exits are sent if windows appear and are hidden
1269 // under the current mouse position..
1270 TEST_F(WindowTest, MouseEnterExitWithHide) {
1271 MouseEnterExitWindowDelegate d1;
1272 scoped_ptr<Window> w1(
1273 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1276 test::EventGenerator generator(root_window());
1277 generator.MoveMouseToCenterOf(w1.get());
1278 EXPECT_TRUE(d1.entered());
1279 EXPECT_FALSE(d1.exited());
1281 MouseEnterExitWindowDelegate d2;
1282 scoped_ptr<Window> w2(
1283 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1285 // Enters / exits can be send asynchronously.
1286 RunAllPendingInMessageLoop();
1287 EXPECT_TRUE(d1.entered());
1288 EXPECT_TRUE(d1.exited());
1289 EXPECT_TRUE(d2.entered());
1290 EXPECT_FALSE(d2.exited());
1292 d1.ResetExpectations();
1294 // Enters / exits can be send asynchronously.
1295 RunAllPendingInMessageLoop();
1296 EXPECT_TRUE(d2.exited());
1297 EXPECT_TRUE(d1.entered());
1300 TEST_F(WindowTest, MouseEnterExitWithParentHide) {
1301 MouseEnterExitWindowDelegate d1;
1302 scoped_ptr<Window> w1(
1303 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1305 MouseEnterExitWindowDelegate d2;
1306 Window* w2 = CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1308 test::EventGenerator generator(root_window());
1309 generator.MoveMouseToCenterOf(w2);
1310 // Enters / exits can be send asynchronously.
1311 RunAllPendingInMessageLoop();
1312 EXPECT_TRUE(d2.entered());
1313 EXPECT_FALSE(d2.exited());
1315 d2.ResetExpectations();
1317 RunAllPendingInMessageLoop();
1318 EXPECT_FALSE(d2.entered());
1319 EXPECT_TRUE(d2.exited());
1324 TEST_F(WindowTest, MouseEnterExitWithParentDelete) {
1325 MouseEnterExitWindowDelegate d1;
1326 scoped_ptr<Window> w1(
1327 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1329 MouseEnterExitWindowDelegate d2;
1330 Window* w2 = CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1332 test::EventGenerator generator(root_window());
1333 generator.MoveMouseToCenterOf(w2);
1335 // Enters / exits can be send asynchronously.
1336 RunAllPendingInMessageLoop();
1337 EXPECT_TRUE(d2.entered());
1338 EXPECT_FALSE(d2.exited());
1340 d2.ResetExpectations();
1342 RunAllPendingInMessageLoop();
1343 EXPECT_FALSE(d2.entered());
1344 EXPECT_TRUE(d2.exited());
1347 // Creates a window with a delegate (w111) that can handle events at a lower
1348 // z-index than a window without a delegate (w12). w12 is sized to fill the
1349 // entire bounds of the container. This test verifies that
1350 // GetEventHandlerForPoint() skips w12 even though its bounds contain the event,
1351 // because it has no children that can handle the event and it has no delegate
1352 // allowing it to handle the event itself.
1353 TEST_F(WindowTest, GetEventHandlerForPoint_NoDelegate) {
1354 TestWindowDelegate d111;
1355 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(NULL, 1,
1356 gfx::Rect(0, 0, 500, 500), root_window()));
1357 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(NULL, 11,
1358 gfx::Rect(0, 0, 500, 500), w1.get()));
1359 scoped_ptr<Window> w111(CreateTestWindowWithDelegate(&d111, 111,
1360 gfx::Rect(50, 50, 450, 450), w11.get()));
1361 scoped_ptr<Window> w12(CreateTestWindowWithDelegate(NULL, 12,
1362 gfx::Rect(0, 0, 500, 500), w1.get()));
1364 gfx::Point target_point = w111->bounds().CenterPoint();
1365 EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(target_point));
1368 class VisibilityWindowDelegate : public TestWindowDelegate {
1370 VisibilityWindowDelegate()
1375 int shown() const { return shown_; }
1376 int hidden() const { return hidden_; }
1382 virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {
1393 DISALLOW_COPY_AND_ASSIGN(VisibilityWindowDelegate);
1396 // Verifies show/hide propagate correctly to children and the layer.
1397 TEST_F(WindowTest, Visibility) {
1398 VisibilityWindowDelegate d;
1399 VisibilityWindowDelegate d2;
1400 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(&d, 1, gfx::Rect(),
1402 scoped_ptr<Window> w2(
1403 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(), w1.get()));
1404 scoped_ptr<Window> w3(CreateTestWindowWithId(3, w2.get()));
1406 // Create shows all the windows.
1407 EXPECT_TRUE(w1->IsVisible());
1408 EXPECT_TRUE(w2->IsVisible());
1409 EXPECT_TRUE(w3->IsVisible());
1410 EXPECT_EQ(1, d.shown());
1414 EXPECT_FALSE(w1->IsVisible());
1415 EXPECT_FALSE(w2->IsVisible());
1416 EXPECT_FALSE(w3->IsVisible());
1417 EXPECT_EQ(1, d.hidden());
1418 EXPECT_EQ(0, d.shown());
1421 EXPECT_FALSE(w1->IsVisible());
1422 EXPECT_FALSE(w2->IsVisible());
1423 EXPECT_FALSE(w3->IsVisible());
1426 EXPECT_FALSE(w1->IsVisible());
1427 EXPECT_FALSE(w2->IsVisible());
1428 EXPECT_FALSE(w3->IsVisible());
1432 EXPECT_TRUE(w1->IsVisible());
1433 EXPECT_TRUE(w2->IsVisible());
1434 EXPECT_FALSE(w3->IsVisible());
1435 EXPECT_EQ(0, d.hidden());
1436 EXPECT_EQ(1, d.shown());
1439 EXPECT_TRUE(w1->IsVisible());
1440 EXPECT_TRUE(w2->IsVisible());
1441 EXPECT_TRUE(w3->IsVisible());
1443 // Verify that if an ancestor isn't visible and we change the visibility of a
1444 // child window that OnChildWindowVisibilityChanged() is still invoked.
1448 EXPECT_EQ(1, d2.hidden());
1449 EXPECT_EQ(0, d2.shown());
1452 EXPECT_EQ(0, d2.hidden());
1453 EXPECT_EQ(1, d2.shown());
1456 TEST_F(WindowTest, IgnoreEventsTest) {
1457 TestWindowDelegate d11;
1458 TestWindowDelegate d12;
1459 TestWindowDelegate d111;
1460 TestWindowDelegate d121;
1461 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(NULL, 1,
1462 gfx::Rect(0, 0, 500, 500), root_window()));
1463 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(&d11, 11,
1464 gfx::Rect(0, 0, 500, 500), w1.get()));
1465 scoped_ptr<Window> w111(CreateTestWindowWithDelegate(&d111, 111,
1466 gfx::Rect(50, 50, 450, 450), w11.get()));
1467 scoped_ptr<Window> w12(CreateTestWindowWithDelegate(&d12, 12,
1468 gfx::Rect(0, 0, 500, 500), w1.get()));
1469 scoped_ptr<Window> w121(CreateTestWindowWithDelegate(&d121, 121,
1470 gfx::Rect(150, 150, 50, 50), w12.get()));
1472 EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10)));
1473 w12->set_ignore_events(true);
1474 EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10)));
1475 w12->set_ignore_events(false);
1477 EXPECT_EQ(w121.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1478 w121->set_ignore_events(true);
1479 EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1480 w12->set_ignore_events(true);
1481 EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1482 w111->set_ignore_events(true);
1483 EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1486 // Tests transformation on the root window.
1487 TEST_F(WindowTest, Transform) {
1488 gfx::Size size = host()->GetBounds().size();
1489 EXPECT_EQ(gfx::Rect(size),
1490 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1491 gfx::Point()).bounds());
1493 // Rotate it clock-wise 90 degrees.
1494 gfx::Transform transform;
1495 transform.Translate(size.height(), 0);
1496 transform.Rotate(90.0);
1497 host()->SetTransform(transform);
1499 // The size should be the transformed size.
1500 gfx::Size transformed_size(size.height(), size.width());
1501 EXPECT_EQ(transformed_size.ToString(),
1502 root_window()->bounds().size().ToString());
1504 gfx::Rect(transformed_size).ToString(),
1505 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1506 gfx::Point()).bounds().ToString());
1508 // Host size shouldn't change.
1509 EXPECT_EQ(size.ToString(), host()->GetBounds().size().ToString());
1512 TEST_F(WindowTest, TransformGesture) {
1513 gfx::Size size = host()->GetBounds().size();
1515 scoped_ptr<GestureTrackPositionDelegate> delegate(
1516 new GestureTrackPositionDelegate);
1517 scoped_ptr<Window> window(CreateTestWindowWithDelegate(delegate.get(), -1234,
1518 gfx::Rect(0, 0, 20, 20), root_window()));
1520 // Rotate the root-window clock-wise 90 degrees.
1521 gfx::Transform transform;
1522 transform.Translate(size.height(), 0.0);
1523 transform.Rotate(90.0);
1524 host()->SetTransform(transform);
1526 ui::TouchEvent press(
1527 ui::ET_TOUCH_PRESSED, gfx::Point(size.height() - 10, 10), 0, getTime());
1528 DispatchEventUsingWindowDispatcher(&press);
1529 EXPECT_EQ(gfx::Point(10, 10).ToString(), delegate->position().ToString());
1533 DEFINE_WINDOW_PROPERTY_KEY(int, kIntKey, -2);
1534 DEFINE_WINDOW_PROPERTY_KEY(const char*, kStringKey, "squeamish");
1537 TEST_F(WindowTest, Property) {
1538 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window()));
1540 static const char native_prop_key[] = "fnord";
1542 // Non-existent properties should return the default values.
1543 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1544 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1545 EXPECT_EQ(NULL, w->GetNativeWindowProperty(native_prop_key));
1547 // A set property value should be returned again (even if it's the default
1549 w->SetProperty(kIntKey, INT_MAX);
1550 EXPECT_EQ(INT_MAX, w->GetProperty(kIntKey));
1551 w->SetProperty(kIntKey, -2);
1552 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1553 w->SetProperty(kIntKey, INT_MIN);
1554 EXPECT_EQ(INT_MIN, w->GetProperty(kIntKey));
1556 w->SetProperty(kStringKey, static_cast<const char*>(NULL));
1557 EXPECT_EQ(NULL, w->GetProperty(kStringKey));
1558 w->SetProperty(kStringKey, "squeamish");
1559 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1560 w->SetProperty(kStringKey, "ossifrage");
1561 EXPECT_EQ(std::string("ossifrage"), w->GetProperty(kStringKey));
1563 w->SetNativeWindowProperty(native_prop_key, &*w);
1564 EXPECT_EQ(&*w, w->GetNativeWindowProperty(native_prop_key));
1565 w->SetNativeWindowProperty(native_prop_key, NULL);
1566 EXPECT_EQ(NULL, w->GetNativeWindowProperty(native_prop_key));
1568 // ClearProperty should restore the default value.
1569 w->ClearProperty(kIntKey);
1570 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1571 w->ClearProperty(kStringKey);
1572 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1577 class TestProperty {
1580 virtual ~TestProperty() {
1581 last_deleted_ = this;
1583 static TestProperty* last_deleted() { return last_deleted_; }
1586 static TestProperty* last_deleted_;
1587 DISALLOW_COPY_AND_ASSIGN(TestProperty);
1590 TestProperty* TestProperty::last_deleted_ = NULL;
1592 DEFINE_OWNED_WINDOW_PROPERTY_KEY(TestProperty, kOwnedKey, NULL);
1596 TEST_F(WindowTest, OwnedProperty) {
1597 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window()));
1598 EXPECT_EQ(NULL, w->GetProperty(kOwnedKey));
1599 TestProperty* p1 = new TestProperty();
1600 w->SetProperty(kOwnedKey, p1);
1601 EXPECT_EQ(p1, w->GetProperty(kOwnedKey));
1602 EXPECT_EQ(NULL, TestProperty::last_deleted());
1604 TestProperty* p2 = new TestProperty();
1605 w->SetProperty(kOwnedKey, p2);
1606 EXPECT_EQ(p2, w->GetProperty(kOwnedKey));
1607 EXPECT_EQ(p1, TestProperty::last_deleted());
1609 w->ClearProperty(kOwnedKey);
1610 EXPECT_EQ(NULL, w->GetProperty(kOwnedKey));
1611 EXPECT_EQ(p2, TestProperty::last_deleted());
1613 TestProperty* p3 = new TestProperty();
1614 w->SetProperty(kOwnedKey, p3);
1615 EXPECT_EQ(p3, w->GetProperty(kOwnedKey));
1616 EXPECT_EQ(p2, TestProperty::last_deleted());
1618 EXPECT_EQ(p3, TestProperty::last_deleted());
1621 TEST_F(WindowTest, SetBoundsInternalShouldCheckTargetBounds) {
1622 // We cannot short-circuit animations in this test.
1623 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
1624 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
1626 scoped_ptr<Window> w1(
1627 CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), root_window()));
1629 EXPECT_FALSE(!w1->layer());
1630 w1->layer()->GetAnimator()->set_disable_timer_for_test(true);
1631 gfx::AnimationContainerElement* element = w1->layer()->GetAnimator();
1633 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1634 EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString());
1636 // Animate to a different position.
1638 ui::ScopedLayerAnimationSettings settings(w1->layer()->GetAnimator());
1639 w1->SetBounds(gfx::Rect(100, 100, 100, 100));
1642 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1643 EXPECT_EQ("100,100 100x100", w1->layer()->GetTargetBounds().ToString());
1645 // Animate back to the first position. The animation hasn't started yet, so
1646 // the current bounds are still (0, 0, 100, 100), but the target bounds are
1647 // (100, 100, 100, 100). If we step the animator ahead, we should find that
1648 // we're at (0, 0, 100, 100). That is, the second animation should be applied.
1650 ui::ScopedLayerAnimationSettings settings(w1->layer()->GetAnimator());
1651 w1->SetBounds(gfx::Rect(0, 0, 100, 100));
1654 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1655 EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString());
1657 // Confirm that the target bounds are reached.
1658 base::TimeTicks start_time =
1659 w1->layer()->GetAnimator()->last_step_time();
1661 element->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
1663 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1667 typedef std::pair<const void*, intptr_t> PropertyChangeInfo;
1669 class WindowObserverTest : public WindowTest,
1670 public WindowObserver {
1672 struct VisibilityInfo {
1673 bool window_visible;
1677 WindowObserverTest()
1680 destroyed_count_(0),
1681 old_property_value_(-3) {
1684 virtual ~WindowObserverTest() {}
1686 const VisibilityInfo* GetVisibilityInfo() const {
1687 return visibility_info_.get();
1690 void ResetVisibilityInfo() {
1691 visibility_info_.reset();
1694 // Returns a description of the WindowObserver methods that have been invoked.
1695 std::string WindowObserverCountStateAndClear() {
1697 base::StringPrintf("added=%d removed=%d",
1698 added_count_, removed_count_));
1699 added_count_ = removed_count_ = 0;
1703 int DestroyedCountAndClear() {
1704 int result = destroyed_count_;
1705 destroyed_count_ = 0;
1709 // Return a tuple of the arguments passed in OnPropertyChanged callback.
1710 PropertyChangeInfo PropertyChangeInfoAndClear() {
1711 PropertyChangeInfo result(property_key_, old_property_value_);
1712 property_key_ = NULL;
1713 old_property_value_ = -3;
1718 virtual void OnWindowAdded(Window* new_window) OVERRIDE {
1722 virtual void OnWillRemoveWindow(Window* window) OVERRIDE {
1726 virtual void OnWindowVisibilityChanged(Window* window,
1727 bool visible) OVERRIDE {
1728 visibility_info_.reset(new VisibilityInfo);
1729 visibility_info_->window_visible = window->IsVisible();
1730 visibility_info_->visible_param = visible;
1733 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
1734 EXPECT_FALSE(window->parent());
1738 virtual void OnWindowPropertyChanged(Window* window,
1740 intptr_t old) OVERRIDE {
1741 property_key_ = key;
1742 old_property_value_ = old;
1747 int destroyed_count_;
1748 scoped_ptr<VisibilityInfo> visibility_info_;
1749 const void* property_key_;
1750 intptr_t old_property_value_;
1752 DISALLOW_COPY_AND_ASSIGN(WindowObserverTest);
1755 // Various assertions for WindowObserver.
1756 TEST_F(WindowObserverTest, WindowObserver) {
1757 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1758 w1->AddObserver(this);
1760 // Create a new window as a child of w1, our observer should be notified.
1761 scoped_ptr<Window> w2(CreateTestWindowWithId(2, w1.get()));
1762 EXPECT_EQ("added=1 removed=0", WindowObserverCountStateAndClear());
1764 // Delete w2, which should result in the remove notification.
1766 EXPECT_EQ("added=0 removed=1", WindowObserverCountStateAndClear());
1768 // Create a window that isn't parented to w1, we shouldn't get any
1770 scoped_ptr<Window> w3(CreateTestWindowWithId(3, root_window()));
1771 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1773 // Similarly destroying w3 shouldn't notify us either.
1775 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1776 w1->RemoveObserver(this);
1779 // Test if OnWindowVisibilityChagned is invoked with expected
1781 TEST_F(WindowObserverTest, WindowVisibility) {
1782 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1783 scoped_ptr<Window> w2(CreateTestWindowWithId(1, w1.get()));
1784 w2->AddObserver(this);
1786 // Hide should make the window invisible and the passed visible
1787 // parameter is false.
1789 EXPECT_FALSE(!GetVisibilityInfo());
1790 EXPECT_FALSE(!GetVisibilityInfo());
1791 if (!GetVisibilityInfo())
1793 EXPECT_FALSE(GetVisibilityInfo()->window_visible);
1794 EXPECT_FALSE(GetVisibilityInfo()->visible_param);
1796 // If parent isn't visible, showing window won't make the window visible, but
1797 // passed visible value must be true.
1799 ResetVisibilityInfo();
1800 EXPECT_TRUE(!GetVisibilityInfo());
1802 EXPECT_FALSE(!GetVisibilityInfo());
1803 if (!GetVisibilityInfo())
1805 EXPECT_FALSE(GetVisibilityInfo()->window_visible);
1806 EXPECT_TRUE(GetVisibilityInfo()->visible_param);
1808 // If parent is visible, showing window will make the window
1809 // visible and the passed visible value is true.
1812 ResetVisibilityInfo();
1814 EXPECT_FALSE(!GetVisibilityInfo());
1815 if (!GetVisibilityInfo())
1817 EXPECT_TRUE(GetVisibilityInfo()->window_visible);
1818 EXPECT_TRUE(GetVisibilityInfo()->visible_param);
1821 // Test if OnWindowDestroyed is invoked as expected.
1822 TEST_F(WindowObserverTest, WindowDestroyed) {
1823 // Delete a window should fire a destroyed notification.
1824 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1825 w1->AddObserver(this);
1827 EXPECT_EQ(1, DestroyedCountAndClear());
1829 // Observe on child and delete parent window should fire a notification.
1830 scoped_ptr<Window> parent(CreateTestWindowWithId(1, root_window()));
1831 Window* child = CreateTestWindowWithId(1, parent.get()); // owned by parent
1832 child->AddObserver(this);
1834 EXPECT_EQ(1, DestroyedCountAndClear());
1837 TEST_F(WindowObserverTest, PropertyChanged) {
1838 // Setting property should fire a property change notification.
1839 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1840 w1->AddObserver(this);
1842 static const WindowProperty<int> prop = {-2};
1843 static const char native_prop_key[] = "fnord";
1845 w1->SetProperty(&prop, 1);
1846 EXPECT_EQ(PropertyChangeInfo(&prop, -2), PropertyChangeInfoAndClear());
1847 w1->SetProperty(&prop, -2);
1848 EXPECT_EQ(PropertyChangeInfo(&prop, 1), PropertyChangeInfoAndClear());
1849 w1->SetProperty(&prop, 3);
1850 EXPECT_EQ(PropertyChangeInfo(&prop, -2), PropertyChangeInfoAndClear());
1851 w1->ClearProperty(&prop);
1852 EXPECT_EQ(PropertyChangeInfo(&prop, 3), PropertyChangeInfoAndClear());
1854 w1->SetNativeWindowProperty(native_prop_key, &*w1);
1855 EXPECT_EQ(PropertyChangeInfo(native_prop_key, 0),
1856 PropertyChangeInfoAndClear());
1857 w1->SetNativeWindowProperty(native_prop_key, NULL);
1858 EXPECT_EQ(PropertyChangeInfo(native_prop_key,
1859 reinterpret_cast<intptr_t>(&*w1)),
1860 PropertyChangeInfoAndClear());
1862 // Sanity check to see if |PropertyChangeInfoAndClear| really clears.
1863 EXPECT_EQ(PropertyChangeInfo(
1864 reinterpret_cast<const void*>(NULL), -3), PropertyChangeInfoAndClear());
1867 TEST_F(WindowTest, AcquireLayer) {
1868 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
1869 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
1870 ui::Layer* parent = window1->parent()->layer();
1871 EXPECT_EQ(2U, parent->children().size());
1873 WindowTestApi window1_test_api(window1.get());
1874 WindowTestApi window2_test_api(window2.get());
1876 EXPECT_TRUE(window1_test_api.OwnsLayer());
1877 EXPECT_TRUE(window2_test_api.OwnsLayer());
1879 // After acquisition, window1 should not own its layer, but it should still
1880 // be available to the window.
1881 scoped_ptr<ui::Layer> window1_layer(window1->AcquireLayer());
1882 EXPECT_FALSE(window1_test_api.OwnsLayer());
1883 EXPECT_TRUE(window1_layer.get() == window1->layer());
1885 // The acquired layer's owner should be set NULL and re-acquring
1886 // should return NULL.
1887 EXPECT_FALSE(window1_layer->owner());
1888 scoped_ptr<ui::Layer> window1_layer_reacquired(window1->AcquireLayer());
1889 EXPECT_FALSE(window1_layer_reacquired.get());
1891 // Upon destruction, window1's layer should still be valid, and in the layer
1892 // hierarchy, but window2's should be gone, and no longer in the hierarchy.
1896 // This should be set by the window's destructor.
1897 EXPECT_TRUE(window1_layer->delegate() == NULL);
1898 EXPECT_EQ(1U, parent->children().size());
1901 // Make sure that properties which should persist from the old layer to the new
1902 // layer actually do.
1903 TEST_F(WindowTest, RecreateLayer) {
1904 // Set properties to non default values.
1905 Window w(new ColorTestWindowDelegate(SK_ColorWHITE));
1907 w.Init(aura::WINDOW_LAYER_SOLID_COLOR);
1908 w.SetBounds(gfx::Rect(0, 0, 100, 100));
1910 ui::Layer* layer = w.layer();
1911 layer->set_scale_content(false);
1912 layer->SetVisible(false);
1913 layer->SetMasksToBounds(true);
1915 ui::Layer child_layer;
1916 layer->Add(&child_layer);
1918 scoped_ptr<ui::Layer> old_layer(w.RecreateLayer());
1920 EXPECT_EQ(ui::LAYER_SOLID_COLOR, layer->type());
1921 EXPECT_FALSE(layer->scale_content());
1922 EXPECT_FALSE(layer->visible());
1923 EXPECT_EQ(1u, layer->children().size());
1924 EXPECT_TRUE(layer->GetMasksToBounds());
1925 EXPECT_EQ("0,0 100x100", w.bounds().ToString());
1926 EXPECT_EQ("0,0 100x100", layer->bounds().ToString());
1929 // Verify that RecreateLayer() stacks the old layer above the newly creatd
1931 TEST_F(WindowTest, RecreateLayerZOrder) {
1932 scoped_ptr<Window> w(
1933 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(0, 0, 100, 100),
1935 scoped_ptr<ui::Layer> old_layer(w->RecreateLayer());
1937 const std::vector<ui::Layer*>& child_layers =
1938 root_window()->layer()->children();
1939 ASSERT_EQ(2u, child_layers.size());
1940 EXPECT_EQ(w->layer(), child_layers[0]);
1941 EXPECT_EQ(old_layer.get(), child_layers[1]);
1944 // Ensure that acquiring a layer then recreating a layer does not crash
1945 // and that RecreateLayer returns null.
1946 TEST_F(WindowTest, AcquireThenRecreateLayer) {
1947 scoped_ptr<Window> w(
1948 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(0, 0, 100, 100),
1950 scoped_ptr<ui::Layer>acquired_layer(w->AcquireLayer());
1951 scoped_ptr<ui::Layer>doubly_acquired_layer(w->RecreateLayer());
1952 EXPECT_EQ(NULL, doubly_acquired_layer.get());
1954 // Destroy window before layer gets destroyed.
1958 TEST_F(WindowTest, StackWindowAtBottomBelowWindowWhoseLayerHasNoDelegate) {
1959 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
1960 window1->layer()->set_name("1");
1961 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
1962 window2->layer()->set_name("2");
1963 scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window()));
1964 window3->layer()->set_name("3");
1966 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(root_window()));
1968 ui::test::ChildLayerNamesAsString(*root_window()->layer()));
1969 window1->layer()->set_delegate(NULL);
1970 root_window()->StackChildAtBottom(window3.get());
1972 // Window 3 should have moved to the bottom.
1973 EXPECT_EQ("3 1 2", ChildWindowIDsAsString(root_window()));
1975 ui::test::ChildLayerNamesAsString(*root_window()->layer()));
1978 class TestVisibilityClient : public client::VisibilityClient {
1980 explicit TestVisibilityClient(Window* root_window)
1981 : ignore_visibility_changes_(false) {
1982 client::SetVisibilityClient(root_window, this);
1984 virtual ~TestVisibilityClient() {
1987 void set_ignore_visibility_changes(bool ignore_visibility_changes) {
1988 ignore_visibility_changes_ = ignore_visibility_changes;
1991 // Overridden from client::VisibilityClient:
1992 virtual void UpdateLayerVisibility(aura::Window* window,
1993 bool visible) OVERRIDE {
1994 if (!ignore_visibility_changes_)
1995 window->layer()->SetVisible(visible);
1999 bool ignore_visibility_changes_;
2000 DISALLOW_COPY_AND_ASSIGN(TestVisibilityClient);
2003 TEST_F(WindowTest, VisibilityClientIsVisible) {
2004 TestVisibilityClient client(root_window());
2006 scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window()));
2007 EXPECT_TRUE(window->IsVisible());
2008 EXPECT_TRUE(window->layer()->visible());
2011 EXPECT_FALSE(window->IsVisible());
2012 EXPECT_FALSE(window->layer()->visible());
2015 client.set_ignore_visibility_changes(true);
2017 EXPECT_FALSE(window->IsVisible());
2018 EXPECT_TRUE(window->layer()->visible());
2021 // Tests mouse events on window change.
2022 TEST_F(WindowTest, MouseEventsOnWindowChange) {
2023 gfx::Size size = host()->GetBounds().size();
2025 EventGenerator generator(root_window());
2026 generator.MoveMouseTo(50, 50);
2028 EventCountDelegate d1;
2029 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(&d1, 1,
2030 gfx::Rect(0, 0, 100, 100), root_window()));
2031 RunAllPendingInMessageLoop();
2032 // The format of result is "Enter/Mouse/Leave".
2033 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2035 // Adding new window.
2036 EventCountDelegate d11;
2037 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(
2038 &d11, 1, gfx::Rect(0, 0, 100, 100), w1.get()));
2039 RunAllPendingInMessageLoop();
2040 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2041 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2044 w11->SetBounds(gfx::Rect(0, 0, 10, 10));
2045 RunAllPendingInMessageLoop();
2046 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2047 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2049 w11->SetBounds(gfx::Rect(0, 0, 60, 60));
2050 RunAllPendingInMessageLoop();
2051 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2052 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2054 // Detach, then re-attach.
2055 w1->RemoveChild(w11.get());
2056 RunAllPendingInMessageLoop();
2057 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2058 // Window is detached, so no event is set.
2059 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2061 w1->AddChild(w11.get());
2062 RunAllPendingInMessageLoop();
2063 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2064 // Window is detached, so no event is set.
2065 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2067 // Visibility Change
2069 RunAllPendingInMessageLoop();
2070 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2071 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2074 RunAllPendingInMessageLoop();
2075 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2076 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2078 // Transform: move d11 by 100 100.
2079 gfx::Transform transform;
2080 transform.Translate(100, 100);
2081 w11->SetTransform(transform);
2082 RunAllPendingInMessageLoop();
2083 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2084 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2086 w11->SetTransform(gfx::Transform());
2087 RunAllPendingInMessageLoop();
2088 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2089 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2091 // Closing a window.
2093 RunAllPendingInMessageLoop();
2094 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2096 // Make sure we don't synthesize events if the mouse
2097 // is outside of the root window.
2098 generator.MoveMouseTo(-10, -10);
2099 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2101 // Adding new windows.
2102 w11.reset(CreateTestWindowWithDelegate(
2103 &d11, 1, gfx::Rect(0, 0, 100, 100), w1.get()));
2104 RunAllPendingInMessageLoop();
2105 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset());
2106 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2110 RunAllPendingInMessageLoop();
2111 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset());
2112 EXPECT_EQ("0 0 0", d11.GetMouseMotionCountsAndReset());
2115 class RootWindowAttachmentObserver : public WindowObserver {
2117 RootWindowAttachmentObserver() : added_count_(0), removed_count_(0) {}
2118 virtual ~RootWindowAttachmentObserver() {}
2120 int added_count() const { return added_count_; }
2121 int removed_count() const { return removed_count_; }
2128 // Overridden from WindowObserver:
2129 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
2132 virtual void OnWindowRemovingFromRootWindow(Window* window,
2133 Window* new_root) OVERRIDE {
2141 DISALLOW_COPY_AND_ASSIGN(RootWindowAttachmentObserver);
2144 TEST_F(WindowTest, RootWindowAttachment) {
2145 RootWindowAttachmentObserver observer;
2147 // Test a direct add/remove from the RootWindow.
2148 scoped_ptr<Window> w1(new Window(NULL));
2149 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2150 w1->AddObserver(&observer);
2152 ParentWindow(w1.get());
2153 EXPECT_EQ(1, observer.added_count());
2154 EXPECT_EQ(0, observer.removed_count());
2157 EXPECT_EQ(1, observer.added_count());
2158 EXPECT_EQ(1, observer.removed_count());
2162 // Test an indirect add/remove from the RootWindow.
2163 w1.reset(new Window(NULL));
2164 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2165 Window* w11 = new Window(NULL);
2166 w11->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2167 w11->AddObserver(&observer);
2169 EXPECT_EQ(0, observer.added_count());
2170 EXPECT_EQ(0, observer.removed_count());
2172 ParentWindow(w1.get());
2173 EXPECT_EQ(1, observer.added_count());
2174 EXPECT_EQ(0, observer.removed_count());
2176 w1.reset(); // Deletes w11.
2178 EXPECT_EQ(1, observer.added_count());
2179 EXPECT_EQ(1, observer.removed_count());
2183 // Test an indirect add/remove with nested observers.
2184 w1.reset(new Window(NULL));
2185 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2186 w11 = new Window(NULL);
2187 w11->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2188 w11->AddObserver(&observer);
2190 Window* w111 = new Window(NULL);
2191 w111->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2192 w111->AddObserver(&observer);
2193 w11->AddChild(w111);
2195 EXPECT_EQ(0, observer.added_count());
2196 EXPECT_EQ(0, observer.removed_count());
2198 ParentWindow(w1.get());
2199 EXPECT_EQ(2, observer.added_count());
2200 EXPECT_EQ(0, observer.removed_count());
2202 w1.reset(); // Deletes w11 and w111.
2205 EXPECT_EQ(2, observer.added_count());
2206 EXPECT_EQ(2, observer.removed_count());
2209 class BoundsChangedWindowObserver : public WindowObserver {
2211 BoundsChangedWindowObserver() : root_set_(false) {}
2213 virtual void OnWindowBoundsChanged(Window* window,
2214 const gfx::Rect& old_bounds,
2215 const gfx::Rect& new_bounds) OVERRIDE {
2216 root_set_ = window->GetRootWindow() != NULL;
2219 bool root_set() const { return root_set_; }
2224 DISALLOW_COPY_AND_ASSIGN(BoundsChangedWindowObserver);
2227 TEST_F(WindowTest, RootWindowSetWhenReparenting) {
2228 Window parent1(NULL);
2229 parent1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2230 Window parent2(NULL);
2231 parent2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2232 ParentWindow(&parent1);
2233 ParentWindow(&parent2);
2234 parent1.SetBounds(gfx::Rect(10, 10, 300, 300));
2235 parent2.SetBounds(gfx::Rect(20, 20, 300, 300));
2238 child.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2239 child.SetBounds(gfx::Rect(5, 5, 100, 100));
2240 parent1.AddChild(&child);
2242 // We need animations to start in order to observe the bounds changes.
2243 ui::ScopedAnimationDurationScaleMode animation_duration_mode(
2244 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
2245 ui::ScopedLayerAnimationSettings settings1(child.layer()->GetAnimator());
2246 settings1.SetTransitionDuration(base::TimeDelta::FromMilliseconds(100));
2247 child.SetBounds(gfx::Rect(35, 35, 100, 100));
2249 BoundsChangedWindowObserver observer;
2250 child.AddObserver(&observer);
2252 // Reparenting the |child| will cause it to get moved. During this move
2253 // the window should still have root window set.
2254 parent2.AddChild(&child);
2255 EXPECT_TRUE(observer.root_set());
2257 // TODO(varkha): Check that the target bounds didn't change after reparenting.
2260 TEST_F(WindowTest, OwnedByParentFalse) {
2261 // By default, a window is owned by its parent. If this is set to false, the
2262 // window will not be destroyed when its parent is.
2264 scoped_ptr<Window> w1(new Window(NULL));
2265 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2266 scoped_ptr<Window> w2(new Window(NULL));
2267 w2->set_owned_by_parent(false);
2268 w2->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2269 w1->AddChild(w2.get());
2273 // We should be able to deref w2 still, but its parent should now be NULL.
2274 EXPECT_EQ(NULL, w2->parent());
2279 // Used By DeleteWindowFromOnWindowDestroyed. Destroys a Window from
2280 // OnWindowDestroyed().
2281 class OwningWindowDelegate : public TestWindowDelegate {
2283 OwningWindowDelegate() {}
2285 void SetOwnedWindow(Window* window) {
2286 owned_window_.reset(window);
2289 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
2290 owned_window_.reset(NULL);
2294 scoped_ptr<Window> owned_window_;
2296 DISALLOW_COPY_AND_ASSIGN(OwningWindowDelegate);
2301 // Creates a window with two child windows. When the first child window is
2302 // destroyed (WindowDelegate::OnWindowDestroyed) it deletes the second child.
2303 // This synthesizes BrowserView and the status bubble. Both are children of the
2304 // same parent and destroying BrowserView triggers it destroying the status
2306 TEST_F(WindowTest, DeleteWindowFromOnWindowDestroyed) {
2307 scoped_ptr<Window> parent(new Window(NULL));
2308 parent->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2309 OwningWindowDelegate delegate;
2310 Window* c1 = new Window(&delegate);
2311 c1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2312 parent->AddChild(c1);
2313 Window* c2 = new Window(NULL);
2314 c2->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2315 parent->AddChild(c2);
2316 delegate.SetOwnedWindow(c2);
2322 // Used by DelegateNotifiedAsBoundsChange to verify OnBoundsChanged() is
2324 class BoundsChangeDelegate : public TestWindowDelegate {
2326 BoundsChangeDelegate() : bounds_changed_(false) {}
2328 void clear_bounds_changed() { bounds_changed_ = false; }
2329 bool bounds_changed() const {
2330 return bounds_changed_;
2334 virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
2335 const gfx::Rect& new_bounds) OVERRIDE {
2336 bounds_changed_ = true;
2340 // Was OnBoundsChanged() invoked?
2341 bool bounds_changed_;
2343 DISALLOW_COPY_AND_ASSIGN(BoundsChangeDelegate);
2348 // Verifies the delegate is notified when the actual bounds of the layer
2350 TEST_F(WindowTest, DelegateNotifiedAsBoundsChange) {
2351 BoundsChangeDelegate delegate;
2353 // We cannot short-circuit animations in this test.
2354 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
2355 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
2357 scoped_ptr<Window> window(
2358 CreateTestWindowWithDelegate(&delegate, 1,
2359 gfx::Rect(0, 0, 100, 100), root_window()));
2360 window->layer()->GetAnimator()->set_disable_timer_for_test(true);
2362 delegate.clear_bounds_changed();
2364 // Animate to a different position.
2366 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
2367 window->SetBounds(gfx::Rect(100, 100, 100, 100));
2370 // Bounds shouldn't immediately have changed.
2371 EXPECT_EQ("0,0 100x100", window->bounds().ToString());
2372 EXPECT_FALSE(delegate.bounds_changed());
2374 // Animate to the end, which should notify of the change.
2375 base::TimeTicks start_time =
2376 window->layer()->GetAnimator()->last_step_time();
2377 gfx::AnimationContainerElement* element = window->layer()->GetAnimator();
2378 element->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
2379 EXPECT_TRUE(delegate.bounds_changed());
2380 EXPECT_NE("0,0 100x100", window->bounds().ToString());
2383 // Verifies the delegate is notified when the actual bounds of the layer
2384 // change even when the window is not the layer's delegate
2385 TEST_F(WindowTest, DelegateNotifiedAsBoundsChangeInHiddenLayer) {
2386 BoundsChangeDelegate delegate;
2388 // We cannot short-circuit animations in this test.
2389 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
2390 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
2392 scoped_ptr<Window> window(
2393 CreateTestWindowWithDelegate(&delegate, 1,
2394 gfx::Rect(0, 0, 100, 100), root_window()));
2395 window->layer()->GetAnimator()->set_disable_timer_for_test(true);
2397 delegate.clear_bounds_changed();
2399 // Suppress paint on the window since it is hidden (should reset the layer's
2400 // delegate to NULL)
2401 window->SuppressPaint();
2402 EXPECT_EQ(NULL, window->layer()->delegate());
2404 // Animate to a different position.
2406 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
2407 window->SetBounds(gfx::Rect(100, 100, 110, 100));
2410 // Layer delegate is NULL but we should still get bounds changed notification.
2411 EXPECT_EQ("100,100 110x100", window->GetTargetBounds().ToString());
2412 EXPECT_TRUE(delegate.bounds_changed());
2414 delegate.clear_bounds_changed();
2416 // Animate to the end: will *not* notify of the change since we are hidden.
2417 base::TimeTicks start_time =
2418 window->layer()->GetAnimator()->last_step_time();
2419 gfx::AnimationContainerElement* element = window->layer()->GetAnimator();
2420 element->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
2422 // No bounds changed notification at the end of animation since layer
2423 // delegate is NULL.
2424 EXPECT_FALSE(delegate.bounds_changed());
2425 EXPECT_NE("0,0 100x100", window->layer()->bounds().ToString());
2430 // Used by AddChildNotifications to track notification counts.
2431 class AddChildNotificationsObserver : public WindowObserver {
2433 AddChildNotificationsObserver() : added_count_(0), removed_count_(0) {}
2435 std::string CountStringAndReset() {
2436 std::string result = base::IntToString(added_count_) + " " +
2437 base::IntToString(removed_count_);
2438 added_count_ = removed_count_ = 0;
2442 // WindowObserver overrides:
2443 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
2446 virtual void OnWindowRemovingFromRootWindow(Window* window,
2447 Window* new_root) OVERRIDE {
2455 DISALLOW_COPY_AND_ASSIGN(AddChildNotificationsObserver);
2460 // Assertions around when root window notifications are sent.
2461 TEST_F(WindowTest, AddChildNotifications) {
2462 AddChildNotificationsObserver observer;
2463 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
2464 scoped_ptr<Window> w2(CreateTestWindowWithId(1, root_window()));
2465 w2->AddObserver(&observer);
2467 EXPECT_TRUE(w2->HasFocus());
2469 // Move |w2| to be a child of |w1|.
2470 w1->AddChild(w2.get());
2471 // Sine we moved in the same root, observer shouldn't be notified.
2472 EXPECT_EQ("0 0", observer.CountStringAndReset());
2473 // |w2| should still have focus after moving.
2474 EXPECT_TRUE(w2->HasFocus());
2477 // Tests that a delegate that destroys itself when the window is destroyed does
2479 TEST_F(WindowTest, DelegateDestroysSelfOnWindowDestroy) {
2480 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
2481 new DestroyWindowDelegate(),
2483 gfx::Rect(10, 20, 30, 40),
2487 class HierarchyObserver : public WindowObserver {
2489 HierarchyObserver(Window* target) : target_(target) {
2490 target_->AddObserver(this);
2492 virtual ~HierarchyObserver() {
2493 target_->RemoveObserver(this);
2498 const WindowObserver::HierarchyChangeParams& params) const {
2499 ParamsMatch(params_[index], params);
2507 // Overridden from WindowObserver:
2508 virtual void OnWindowHierarchyChanging(
2509 const HierarchyChangeParams& params) OVERRIDE {
2510 params_.push_back(params);
2512 virtual void OnWindowHierarchyChanged(
2513 const HierarchyChangeParams& params) OVERRIDE {
2514 params_.push_back(params);
2517 void ParamsMatch(const WindowObserver::HierarchyChangeParams& p1,
2518 const WindowObserver::HierarchyChangeParams& p2) const {
2519 EXPECT_EQ(p1.phase, p2.phase);
2520 EXPECT_EQ(p1.target, p2.target);
2521 EXPECT_EQ(p1.new_parent, p2.new_parent);
2522 EXPECT_EQ(p1.old_parent, p2.old_parent);
2523 EXPECT_EQ(p1.receiver, p2.receiver);
2527 std::vector<WindowObserver::HierarchyChangeParams> params_;
2529 DISALLOW_COPY_AND_ASSIGN(HierarchyObserver);
2532 // Tests hierarchy change notifications.
2533 TEST_F(WindowTest, OnWindowHierarchyChange) {
2535 // Simple add & remove.
2536 HierarchyObserver oroot(root_window());
2538 scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL));
2539 HierarchyObserver o1(w1.get());
2542 root_window()->AddChild(w1.get());
2544 WindowObserver::HierarchyChangeParams params;
2545 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2546 params.target = w1.get();
2547 params.old_parent = NULL;
2548 params.new_parent = root_window();
2549 params.receiver = w1.get();
2550 o1.ValidateState(0, params);
2552 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2553 params.receiver = w1.get();
2554 o1.ValidateState(1, params);
2556 params.receiver = root_window();
2557 oroot.ValidateState(0, params);
2563 root_window()->RemoveChild(w1.get());
2565 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2566 params.old_parent = root_window();
2567 params.new_parent = NULL;
2568 params.receiver = w1.get();
2570 o1.ValidateState(0, params);
2572 params.receiver = root_window();
2573 oroot.ValidateState(0, params);
2575 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2576 params.receiver = w1.get();
2577 o1.ValidateState(1, params);
2581 // Add & remove of hierarchy. Tests notification order per documentation in
2583 HierarchyObserver o(root_window());
2584 scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL));
2585 Window* w11 = CreateTestWindowWithId(11, w1.get());
2586 w1->AddObserver(&o);
2587 w11->AddObserver(&o);
2590 root_window()->AddChild(w1.get());
2592 // Dispatched to target first.
2594 WindowObserver::HierarchyChangeParams params;
2595 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2596 params.target = w1.get();
2597 params.old_parent = NULL;
2598 params.new_parent = root_window();
2599 params.receiver = w1.get();
2600 o.ValidateState(index++, params);
2602 // Dispatched to target's children.
2603 params.receiver = w11;
2604 o.ValidateState(index++, params);
2606 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2608 // Now process the "changed" phase.
2609 params.receiver = w1.get();
2610 o.ValidateState(index++, params);
2611 params.receiver = w11;
2612 o.ValidateState(index++, params);
2613 params.receiver = root_window();
2614 o.ValidateState(index++, params);
2617 root_window()->RemoveChild(w1.get());
2618 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2619 params.old_parent = root_window();
2620 params.new_parent = NULL;
2621 params.receiver = w1.get();
2622 o.ValidateState(index++, params);
2623 params.receiver = w11;
2624 o.ValidateState(index++, params);
2625 params.receiver = root_window();
2626 o.ValidateState(index++, params);
2627 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2628 params.receiver = w1.get();
2629 o.ValidateState(index++, params);
2630 params.receiver = w11;
2631 o.ValidateState(index++, params);
2637 // Reparent. Tests notification order per documentation in WindowObserver.
2638 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
2639 Window* w11 = CreateTestWindowWithId(11, w1.get());
2640 Window* w111 = CreateTestWindowWithId(111, w11);
2641 scoped_ptr<Window> w2(CreateTestWindowWithId(2, root_window()));
2643 HierarchyObserver o(root_window());
2644 w1->AddObserver(&o);
2645 w11->AddObserver(&o);
2646 w111->AddObserver(&o);
2647 w2->AddObserver(&o);
2651 // Dispatched to target first.
2653 WindowObserver::HierarchyChangeParams params;
2654 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2655 params.target = w11;
2656 params.old_parent = w1.get();
2657 params.new_parent = w2.get();
2658 params.receiver = w11;
2659 o.ValidateState(index++, params);
2661 // Then to target's children.
2662 params.receiver = w111;
2663 o.ValidateState(index++, params);
2665 // Then to target's old parent chain.
2666 params.receiver = w1.get();
2667 o.ValidateState(index++, params);
2668 params.receiver = root_window();
2669 o.ValidateState(index++, params);
2672 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2673 params.receiver = w11;
2674 o.ValidateState(index++, params);
2675 params.receiver = w111;
2676 o.ValidateState(index++, params);
2677 params.receiver = w2.get();
2678 o.ValidateState(index++, params);
2679 params.receiver = root_window();
2680 o.ValidateState(index++, params);
2688 // Verifies SchedulePaint() on a layerless window results in damaging the right
2690 TEST_F(WindowTest, LayerlessWindowSchedulePaint) {
2692 root.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2693 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2695 Window* layerless_window = new Window(NULL); // Owned by |root|.
2696 layerless_window->Init(WINDOW_LAYER_NONE);
2697 layerless_window->SetBounds(gfx::Rect(10, 11, 12, 13));
2698 root.AddChild(layerless_window);
2700 root.layer()->SendDamagedRects();
2701 layerless_window->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4));
2702 // Note the the region is clipped by the parent hence 100 going to 11.
2703 EXPECT_EQ("11,13 11x4",
2704 gfx::SkIRectToRect(root.layer()->damaged_region().getBounds()).
2707 Window* layerless_window2 = new Window(NULL); // Owned by |layerless_window|.
2708 layerless_window2->Init(WINDOW_LAYER_NONE);
2709 layerless_window2->SetBounds(gfx::Rect(1, 2, 3, 4));
2710 layerless_window->AddChild(layerless_window2);
2712 root.layer()->SendDamagedRects();
2713 layerless_window2->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4));
2714 // Note the the region is clipped by the |layerless_window| hence 100 going to
2716 EXPECT_EQ("12,15 2x2",
2717 gfx::SkIRectToRect(root.layer()->damaged_region().getBounds()).
2721 // Verifies bounds of layerless windows are correctly updated when adding
2723 TEST_F(WindowTest, NestedLayerlessWindowsBoundsOnAddRemove) {
2724 // Creates the following structure (all children owned by root):
2732 // ll: layer less, eg no layer
2734 root.Init(WINDOW_LAYER_NOT_DRAWN);
2735 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2737 Window* w1ll = new Window(NULL);
2738 w1ll->Init(WINDOW_LAYER_NONE);
2739 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
2741 Window* w11ll = new Window(NULL);
2742 w11ll->Init(WINDOW_LAYER_NONE);
2743 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
2744 w1ll->AddChild(w11ll);
2746 Window* w111 = new Window(NULL);
2747 w111->Init(WINDOW_LAYER_NOT_DRAWN);
2748 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2749 w11ll->AddChild(w111);
2751 Window* w12 = new Window(NULL);
2752 w12->Init(WINDOW_LAYER_NOT_DRAWN);
2753 w12->SetBounds(gfx::Rect(7, 8, 100, 100));
2754 w1ll->AddChild(w12);
2756 Window* w121 = new Window(NULL);
2757 w121->Init(WINDOW_LAYER_NOT_DRAWN);
2758 w121->SetBounds(gfx::Rect(9, 10, 100, 100));
2759 w12->AddChild(w121);
2761 root.AddChild(w1ll);
2763 // All layers should be parented to the root.
2764 EXPECT_EQ(root.layer(), w111->layer()->parent());
2765 EXPECT_EQ(root.layer(), w12->layer()->parent());
2766 EXPECT_EQ(w12->layer(), w121->layer()->parent());
2768 // Ensure bounds are what we expect.
2769 EXPECT_EQ("1,2 100x100", w1ll->bounds().ToString());
2770 EXPECT_EQ("3,4 100x100", w11ll->bounds().ToString());
2771 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2772 EXPECT_EQ("7,8 100x100", w12->bounds().ToString());
2773 EXPECT_EQ("9,10 100x100", w121->bounds().ToString());
2775 // Bounds of layers are relative to the nearest ancestor with a layer.
2776 EXPECT_EQ("8,10 100x100", w12->layer()->bounds().ToString());
2777 EXPECT_EQ("9,12 100x100", w111->layer()->bounds().ToString());
2778 EXPECT_EQ("9,10 100x100", w121->layer()->bounds().ToString());
2780 // Remove and repeat.
2781 root.RemoveChild(w1ll);
2783 EXPECT_TRUE(w111->layer()->parent() == NULL);
2784 EXPECT_TRUE(w12->layer()->parent() == NULL);
2786 // Verify bounds haven't changed again.
2787 EXPECT_EQ("1,2 100x100", w1ll->bounds().ToString());
2788 EXPECT_EQ("3,4 100x100", w11ll->bounds().ToString());
2789 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2790 EXPECT_EQ("7,8 100x100", w12->bounds().ToString());
2791 EXPECT_EQ("9,10 100x100", w121->bounds().ToString());
2793 // Bounds of layers should now match that of windows.
2794 EXPECT_EQ("7,8 100x100", w12->layer()->bounds().ToString());
2795 EXPECT_EQ("5,6 100x100", w111->layer()->bounds().ToString());
2796 EXPECT_EQ("9,10 100x100", w121->layer()->bounds().ToString());
2801 // Verifies bounds of layerless windows are correctly updated when bounds
2802 // of ancestor changes.
2803 TEST_F(WindowTest, NestedLayerlessWindowsBoundsOnSetBounds) {
2804 // Creates the following structure (all children owned by root):
2812 // ll: layer less, eg no layer
2814 root.Init(WINDOW_LAYER_NOT_DRAWN);
2815 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2817 Window* w1ll = new Window(NULL);
2818 w1ll->Init(WINDOW_LAYER_NONE);
2819 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
2821 Window* w11ll = new Window(NULL);
2822 w11ll->Init(WINDOW_LAYER_NONE);
2823 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
2824 w1ll->AddChild(w11ll);
2826 Window* w111 = new Window(NULL);
2827 w111->Init(WINDOW_LAYER_NOT_DRAWN);
2828 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2829 w11ll->AddChild(w111);
2831 Window* w12 = new Window(NULL);
2832 w12->Init(WINDOW_LAYER_NOT_DRAWN);
2833 w12->SetBounds(gfx::Rect(7, 8, 100, 100));
2834 w1ll->AddChild(w12);
2836 Window* w121 = new Window(NULL);
2837 w121->Init(WINDOW_LAYER_NOT_DRAWN);
2838 w121->SetBounds(gfx::Rect(9, 10, 100, 100));
2839 w12->AddChild(w121);
2841 root.AddChild(w1ll);
2843 w111->SetBounds(gfx::Rect(7, 8, 11, 12));
2844 EXPECT_EQ("7,8 11x12", w111->bounds().ToString());
2845 EXPECT_EQ("7,8 11x12", w111->GetTargetBounds().ToString());
2846 EXPECT_EQ("11,14 11x12", w111->layer()->bounds().ToString());
2849 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2850 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2851 EXPECT_EQ("5,6 100x100", w111->GetTargetBounds().ToString());
2852 EXPECT_EQ("9,12 100x100", w111->layer()->bounds().ToString());
2854 // Setting the bounds of a layerless window needs to adjust the bounds of
2855 // layered children.
2856 w11ll->SetBounds(gfx::Rect(5, 6, 100, 100));
2857 EXPECT_EQ("5,6 100x100", w11ll->bounds().ToString());
2858 EXPECT_EQ("5,6 100x100", w11ll->GetTargetBounds().ToString());
2859 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2860 EXPECT_EQ("5,6 100x100", w111->GetTargetBounds().ToString());
2861 EXPECT_EQ("11,14 100x100", w111->layer()->bounds().ToString());
2863 root.RemoveChild(w1ll);
2865 w111->SetBounds(gfx::Rect(7, 8, 11, 12));
2866 EXPECT_EQ("7,8 11x12", w111->bounds().ToString());
2867 EXPECT_EQ("7,8 11x12", w111->GetTargetBounds().ToString());
2868 EXPECT_EQ("7,8 11x12", w111->layer()->bounds().ToString());
2875 // Tracks the number of times paint is invoked along with what the clip and
2877 class PaintWindowDelegate : public TestWindowDelegate {
2879 PaintWindowDelegate() : paint_count_(0) {}
2880 virtual ~PaintWindowDelegate() {}
2882 const gfx::Rect& most_recent_paint_clip_bounds() const {
2883 return most_recent_paint_clip_bounds_;
2886 const gfx::Vector2d& most_recent_paint_matrix_offset() const {
2887 return most_recent_paint_matrix_offset_;
2890 void clear_paint_count() { paint_count_ = 0; }
2891 int paint_count() const { return paint_count_; }
2893 // TestWindowDelegate::
2894 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
2896 canvas->GetClipBounds(&most_recent_paint_clip_bounds_);
2897 const SkMatrix& matrix = canvas->sk_canvas()->getTotalMatrix();
2898 most_recent_paint_matrix_offset_ = gfx::Vector2d(
2899 SkScalarFloorToInt(matrix.getTranslateX()),
2900 SkScalarFloorToInt(matrix.getTranslateY()));
2905 gfx::Rect most_recent_paint_clip_bounds_;
2906 gfx::Vector2d most_recent_paint_matrix_offset_;
2908 DISALLOW_COPY_AND_ASSIGN(PaintWindowDelegate);
2913 // Assertions around layerless children being painted when non-layerless window
2915 TEST_F(WindowTest, PaintLayerless) {
2916 // Creates the following structure (all children owned by root):
2922 // ll: layer less, eg no layer
2923 PaintWindowDelegate w1ll_delegate;
2924 PaintWindowDelegate w11ll_delegate;
2925 PaintWindowDelegate w111_delegate;
2928 root.Init(WINDOW_LAYER_NOT_DRAWN);
2929 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2931 Window* w1ll = new Window(&w1ll_delegate);
2932 w1ll->Init(WINDOW_LAYER_NONE);
2933 w1ll->SetBounds(gfx::Rect(1, 2, 40, 50));
2935 root.AddChild(w1ll);
2937 Window* w11ll = new Window(&w11ll_delegate);
2938 w11ll->Init(WINDOW_LAYER_NONE);
2939 w11ll->SetBounds(gfx::Rect(3, 4, 11, 12));
2941 w1ll->AddChild(w11ll);
2943 Window* w111 = new Window(&w111_delegate);
2944 w111->Init(WINDOW_LAYER_NOT_DRAWN);
2945 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2947 w11ll->AddChild(w111);
2949 EXPECT_EQ(0, w1ll_delegate.paint_count());
2950 EXPECT_EQ(0, w11ll_delegate.paint_count());
2951 EXPECT_EQ(0, w111_delegate.paint_count());
2953 // Paint the root, this should trigger painting of the two layerless
2954 // descendants but not the layered descendant.
2955 gfx::Canvas canvas(gfx::Size(200, 200), 1.0f, true);
2956 static_cast<ui::LayerDelegate&>(root).OnPaintLayer(&canvas);
2958 // NOTE: SkCanvas::getClipBounds() extends the clip 1 pixel to the left and up
2959 // and 2 pixels down and to the right.
2960 EXPECT_EQ(1, w1ll_delegate.paint_count());
2961 EXPECT_EQ("-1,-1 42x52",
2962 w1ll_delegate.most_recent_paint_clip_bounds().ToString());
2964 w1ll_delegate.most_recent_paint_matrix_offset().ToString());
2965 EXPECT_EQ(1, w11ll_delegate.paint_count());
2966 EXPECT_EQ("-1,-1 13x14",
2967 w11ll_delegate.most_recent_paint_clip_bounds().ToString());
2969 w11ll_delegate.most_recent_paint_matrix_offset().ToString());
2970 EXPECT_EQ(0, w111_delegate.paint_count());
2975 std::string ConvertPointToTargetString(const Window* source,
2976 const Window* target) {
2977 gfx::Point location;
2978 Window::ConvertPointToTarget(source, target, &location);
2979 return location.ToString();
2984 // Assertions around Window::ConvertPointToTarget() with layerless windows.
2985 TEST_F(WindowTest, ConvertPointToTargetLayerless) {
2986 // Creates the following structure (all children owned by root):
2994 // ll: layer less, eg no layer
2996 root.Init(WINDOW_LAYER_NOT_DRAWN);
2997 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2999 Window* w1ll = new Window(NULL);
3000 w1ll->Init(WINDOW_LAYER_NONE);
3001 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
3003 Window* w11ll = new Window(NULL);
3004 w11ll->Init(WINDOW_LAYER_NONE);
3005 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
3006 w1ll->AddChild(w11ll);
3008 Window* w111 = new Window(NULL);
3009 w111->Init(WINDOW_LAYER_NOT_DRAWN);
3010 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
3011 w11ll->AddChild(w111);
3013 Window* w12 = new Window(NULL);
3014 w12->Init(WINDOW_LAYER_NOT_DRAWN);
3015 w12->SetBounds(gfx::Rect(7, 8, 100, 100));
3016 w1ll->AddChild(w12);
3018 Window* w121 = new Window(NULL);
3019 w121->Init(WINDOW_LAYER_NOT_DRAWN);
3020 w121->SetBounds(gfx::Rect(9, 10, 100, 100));
3021 w12->AddChild(w121);
3023 root.AddChild(w1ll);
3026 EXPECT_EQ("5,6", ConvertPointToTargetString(w111, w11ll));
3029 EXPECT_EQ("8,10", ConvertPointToTargetString(w111, w1ll));
3032 EXPECT_EQ("9,12", ConvertPointToTargetString(w111, &root));
3035 EXPECT_EQ("1,2", ConvertPointToTargetString(w111, w12));
3038 EXPECT_EQ("-8,-8", ConvertPointToTargetString(w111, w121));
3041 EXPECT_EQ("-5,-6", ConvertPointToTargetString(w11ll, w111));
3044 EXPECT_EQ("3,4", ConvertPointToTargetString(w11ll, w1ll));
3047 EXPECT_EQ("4,6", ConvertPointToTargetString(w11ll, &root));
3050 EXPECT_EQ("-4,-4", ConvertPointToTargetString(w11ll, w12));
3053 #if !defined(NDEBUG)
3054 // Verifies PrintWindowHierarchy() doesn't crash with a layerless window.
3055 TEST_F(WindowTest, PrintWindowHierarchyNotCrashLayerless) {
3057 root.Init(WINDOW_LAYER_NONE);
3058 root.SetBounds(gfx::Rect(0, 0, 100, 100));
3059 root.PrintWindowHierarchy(0);
3065 // See AddWindowsFromString() for details.
3066 aura::Window* CreateWindowFromDescription(const std::string& description,
3067 WindowDelegate* delegate) {
3068 WindowLayerType window_type = WINDOW_LAYER_NOT_DRAWN;
3069 std::vector<std::string> tokens;
3070 Tokenize(description, ":", &tokens);
3071 DCHECK(!tokens.empty());
3072 std::string name(tokens[0]);
3073 tokens.erase(tokens.begin());
3074 if (!tokens.empty()) {
3075 if (tokens[0] == "ll") {
3076 window_type = WINDOW_LAYER_NONE;
3077 tokens.erase(tokens.begin());
3079 DCHECK(tokens.empty()) << "unknown tokens for creating window "
3082 Window* window = new Window(delegate);
3083 window->Init(window_type);
3084 window->SetName(name);
3085 // Window name is only propagated to layer in debug builds.
3086 if (window->layer())
3087 window->layer()->set_name(name);
3091 // Creates and adds a tree of windows to |parent|. |description| consists
3092 // of the following pieces:
3093 // X: Identifies a new window. Consists of a name and optionally ":ll" to
3094 // specify WINDOW_LAYER_NONE, eg "w1:ll".
3095 // []: optionally used to specify the children of the window. Contains any
3096 // number of window identifiers and their corresponding children.
3097 // For example: "[ a [ a1 a2:ll ] b c [ c1 ] ]" creates the tree:
3100 // a2 -> WINDOW_LAYER_NONE.
3104 // NOTE: you must have a space after every token.
3105 std::string::size_type AddWindowsFromString(aura::Window* parent,
3106 const std::string& description,
3107 std::string::size_type start_pos,
3108 WindowDelegate* delegate) {
3110 std::string::size_type end_pos = description.find(' ', start_pos);
3111 while (end_pos != std::string::npos) {
3112 const std::string::size_type part_length = end_pos - start_pos;
3113 const std::string window_description =
3114 description.substr(start_pos, part_length);
3115 if (window_description == "[") {
3116 start_pos = AddWindowsFromString(parent->children().back(),
3120 end_pos = description.find(' ', start_pos);
3121 if (end_pos == std::string::npos && start_pos != end_pos)
3122 end_pos = description.length();
3123 } else if (window_description == "]") {
3128 CreateWindowFromDescription(window_description, delegate);
3129 parent->AddChild(window);
3130 start_pos = ++end_pos;
3131 end_pos = description.find(' ', start_pos);
3137 // Used by BuildRootWindowTreeDescription().
3138 std::string BuildWindowTreeDescription(const aura::Window& window) {
3140 result += window.name();
3141 if (window.children().empty())
3145 for (size_t i = 0; i < window.children().size(); ++i) {
3148 result += BuildWindowTreeDescription(*(window.children()[i]));
3154 // Creates a string from |window|. See AddWindowsFromString() for details of the
3155 // returned string. This does *not* include the layer type in the description,
3157 std::string BuildRootWindowTreeDescription(const aura::Window& window) {
3159 for (size_t i = 0; i < window.children().size(); ++i) {
3162 result += BuildWindowTreeDescription(*(window.children()[i]));
3167 // Used by BuildRootWindowTreeDescription().
3168 std::string BuildLayerTreeDescription(const ui::Layer& layer) {
3170 result += layer.name();
3171 if (layer.children().empty())
3175 for (size_t i = 0; i < layer.children().size(); ++i) {
3178 result += BuildLayerTreeDescription(*(layer.children()[i]));
3184 // Builds a string for all the children of |layer|. The returned string is in
3185 // the same format as AddWindowsFromString() but only includes the name of the
3187 std::string BuildRootLayerTreeDescription(const ui::Layer& layer) {
3189 for (size_t i = 0; i < layer.children().size(); ++i) {
3192 result += BuildLayerTreeDescription(*(layer.children()[i]));
3197 // Returns the first window whose name matches |name| in |parent|.
3198 aura::Window* FindWindowByName(aura::Window* parent,
3199 const std::string& name) {
3200 if (parent->name() == name)
3202 for (size_t i = 0; i < parent->children().size(); ++i) {
3203 aura::Window* child = FindWindowByName(parent->children()[i], name);
3212 // Direction to stack.
3220 // Permutations of StackChildAt with various data.
3221 TEST_F(WindowTest, StackChildAtLayerless) {
3223 // Describes the window tree to create. See AddWindowsFromString() for
3225 const std::string initial_description;
3227 // Identifies the window to move.
3228 const std::string source_window;
3230 // Window to move |source_window| relative to. Not used for STACK_AT_BOTTOM
3232 const std::string target_window;
3234 StackType stack_type;
3236 // Expected window and layer results.
3237 const std::string expected_description;
3238 const std::string expected_layer_description;
3242 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3246 "2 [ 21 ] 1 [ 11 12 ]",
3252 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3256 "1 [ 11 12 ] 2 [ 21 ]",
3262 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3266 "2 [ 21 ] 1 [ 11 12 ]",
3272 "1:ll [ 11 12 ] 2:ll [ 21 ] 3:ll",
3276 "1 [ 11 12 ] 3 2 [ 21 ]",
3282 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3286 "2 [ 21 ] 1 [ 11 12 ]",
3292 "1:ll [ 11 12 ] 2:ll [ 21 ] 3:ll",
3296 "2 [ 21 ] 3 1 [ 11 12 ]",
3302 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3306 "2 [ 21 ] 1 [ 11 12 ]",
3310 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
3311 test::TestWindowDelegate delegate;
3313 root.Init(WINDOW_LAYER_NOT_DRAWN);
3314 root.SetBounds(gfx::Rect(0, 0, 100, 100));
3315 AddWindowsFromString(
3317 data[i].initial_description,
3318 static_cast<std::string::size_type>(0), &delegate);
3319 aura::Window* source = FindWindowByName(&root, data[i].source_window);
3320 ASSERT_TRUE(source != NULL) << "unable to find source window "
3321 << data[i].source_window << " at " << i;
3322 aura::Window* target = FindWindowByName(&root, data[i].target_window);
3323 switch (data[i].stack_type) {
3325 ASSERT_TRUE(target != NULL) << "unable to find target window "
3326 << data[i].target_window << " at " << i;
3327 source->parent()->StackChildAbove(source, target);
3330 ASSERT_TRUE(target != NULL) << "unable to find target window "
3331 << data[i].target_window << " at " << i;
3332 source->parent()->StackChildBelow(source, target);
3334 case STACK_AT_BOTTOM:
3335 source->parent()->StackChildAtBottom(source);
3338 source->parent()->StackChildAtTop(source);
3341 EXPECT_EQ(data[i].expected_layer_description,
3342 BuildRootLayerTreeDescription(*root.layer()))
3343 << "layer tree doesn't match at " << i;
3344 EXPECT_EQ(data[i].expected_description,
3345 BuildRootWindowTreeDescription(root))
3346 << "window tree doesn't match at " << i;