1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/aura/window.h"
11 #include "base/basictypes.h"
12 #include "base/compiler_specific.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "ui/aura/client/capture_client.h"
18 #include "ui/aura/client/focus_change_observer.h"
19 #include "ui/aura/client/visibility_client.h"
20 #include "ui/aura/client/window_tree_client.h"
21 #include "ui/aura/test/aura_test_base.h"
22 #include "ui/aura/test/aura_test_utils.h"
23 #include "ui/aura/test/test_window_delegate.h"
24 #include "ui/aura/test/test_windows.h"
25 #include "ui/aura/test/window_test_api.h"
26 #include "ui/aura/window_delegate.h"
27 #include "ui/aura/window_event_dispatcher.h"
28 #include "ui/aura/window_observer.h"
29 #include "ui/aura/window_property.h"
30 #include "ui/aura/window_tree_host.h"
31 #include "ui/base/hit_test.h"
32 #include "ui/compositor/layer.h"
33 #include "ui/compositor/layer_animation_observer.h"
34 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
35 #include "ui/compositor/scoped_layer_animation_settings.h"
36 #include "ui/compositor/test/test_layers.h"
37 #include "ui/events/event.h"
38 #include "ui/events/event_utils.h"
39 #include "ui/events/gesture_detection/gesture_configuration.h"
40 #include "ui/events/keycodes/keyboard_codes.h"
41 #include "ui/events/test/event_generator.h"
42 #include "ui/gfx/canvas.h"
43 #include "ui/gfx/screen.h"
44 #include "ui/gfx/skia_util.h"
45 #include "ui/gfx/vector2d.h"
47 DECLARE_WINDOW_PROPERTY_TYPE(const char*)
48 DECLARE_WINDOW_PROPERTY_TYPE(int)
53 class WindowTest : public AuraTestBase {
55 WindowTest() : max_separation_(0) {
58 void SetUp() override {
59 AuraTestBase::SetUp();
60 // TODO: there needs to be an easier way to do this.
61 max_separation_ = ui::GestureConfiguration::GetInstance()
62 ->max_separation_for_gesture_touches_in_pixels();
63 ui::GestureConfiguration::GetInstance()
64 ->set_max_separation_for_gesture_touches_in_pixels(0);
67 void TearDown() override {
68 AuraTestBase::TearDown();
69 ui::GestureConfiguration::GetInstance()
70 ->set_max_separation_for_gesture_touches_in_pixels(max_separation_);
74 float max_separation_;
76 DISALLOW_COPY_AND_ASSIGN(WindowTest);
81 // Used for verifying destruction methods are invoked.
82 class DestroyTrackingDelegateImpl : public TestWindowDelegate {
84 DestroyTrackingDelegateImpl()
85 : destroying_count_(0),
87 in_destroying_(false) {}
89 void clear_destroying_count() { destroying_count_ = 0; }
90 int destroying_count() const { return destroying_count_; }
92 void clear_destroyed_count() { destroyed_count_ = 0; }
93 int destroyed_count() const { return destroyed_count_; }
95 bool in_destroying() const { return in_destroying_; }
97 void OnWindowDestroying(Window* window) override {
98 EXPECT_FALSE(in_destroying_);
99 in_destroying_ = true;
103 void OnWindowDestroyed(Window* window) override {
104 EXPECT_TRUE(in_destroying_);
105 in_destroying_ = false;
110 int destroying_count_;
111 int destroyed_count_;
114 DISALLOW_COPY_AND_ASSIGN(DestroyTrackingDelegateImpl);
117 // Used to verify that when OnWindowDestroying is invoked the parent is also
118 // is in the process of being destroyed.
119 class ChildWindowDelegateImpl : public DestroyTrackingDelegateImpl {
121 explicit ChildWindowDelegateImpl(
122 DestroyTrackingDelegateImpl* parent_delegate)
123 : parent_delegate_(parent_delegate) {
126 void OnWindowDestroying(Window* window) override {
127 EXPECT_TRUE(parent_delegate_->in_destroying());
128 DestroyTrackingDelegateImpl::OnWindowDestroying(window);
132 DestroyTrackingDelegateImpl* parent_delegate_;
134 DISALLOW_COPY_AND_ASSIGN(ChildWindowDelegateImpl);
137 // Used to verify that a Window is removed from its parent when
138 // OnWindowDestroyed is called.
139 class DestroyOrphanDelegate : public TestWindowDelegate {
141 DestroyOrphanDelegate() : window_(NULL) {
144 void set_window(Window* window) { window_ = window; }
146 void OnWindowDestroyed(Window* window) override {
147 EXPECT_FALSE(window_->parent());
152 DISALLOW_COPY_AND_ASSIGN(DestroyOrphanDelegate);
155 // Used in verifying mouse capture.
156 class CaptureWindowDelegateImpl : public TestWindowDelegate {
158 CaptureWindowDelegateImpl() {
163 capture_changed_event_count_ = 0;
164 capture_lost_count_ = 0;
165 mouse_event_count_ = 0;
166 touch_event_count_ = 0;
167 gesture_event_count_ = 0;
170 int capture_changed_event_count() const {
171 return capture_changed_event_count_;
173 int capture_lost_count() const { return capture_lost_count_; }
174 int mouse_event_count() const { return mouse_event_count_; }
175 int touch_event_count() const { return touch_event_count_; }
176 int gesture_event_count() const { return gesture_event_count_; }
178 void OnMouseEvent(ui::MouseEvent* event) override {
179 if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
180 capture_changed_event_count_++;
181 mouse_event_count_++;
183 void OnTouchEvent(ui::TouchEvent* event) override { touch_event_count_++; }
184 void OnGestureEvent(ui::GestureEvent* event) override {
185 gesture_event_count_++;
187 void OnCaptureLost() override { capture_lost_count_++; }
190 int capture_changed_event_count_;
191 int capture_lost_count_;
192 int mouse_event_count_;
193 int touch_event_count_;
194 int gesture_event_count_;
196 DISALLOW_COPY_AND_ASSIGN(CaptureWindowDelegateImpl);
199 // Keeps track of the location of the gesture.
200 class GestureTrackPositionDelegate : public TestWindowDelegate {
202 GestureTrackPositionDelegate() {}
204 void OnGestureEvent(ui::GestureEvent* event) override {
205 position_ = event->location();
206 event->StopPropagation();
209 const gfx::Point& position() const { return position_; }
212 gfx::Point position_;
214 DISALLOW_COPY_AND_ASSIGN(GestureTrackPositionDelegate);
217 base::TimeDelta getTime() {
218 return ui::EventTimeForNow();
221 class SelfEventHandlingWindowDelegate : public TestWindowDelegate {
223 SelfEventHandlingWindowDelegate() {}
225 bool ShouldDescendIntoChildForEventHandling(
227 const gfx::Point& location) override {
232 DISALLOW_COPY_AND_ASSIGN(SelfEventHandlingWindowDelegate);
235 // The delegate deletes itself when the window is being destroyed.
236 class DestroyWindowDelegate : public TestWindowDelegate {
238 DestroyWindowDelegate() {}
241 ~DestroyWindowDelegate() override {}
243 // Overridden from WindowDelegate.
244 void OnWindowDestroyed(Window* window) override { delete this; }
246 DISALLOW_COPY_AND_ASSIGN(DestroyWindowDelegate);
251 TEST_F(WindowTest, GetChildById) {
252 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
253 scoped_ptr<Window> w11(CreateTestWindowWithId(11, w1.get()));
254 scoped_ptr<Window> w111(CreateTestWindowWithId(111, w11.get()));
255 scoped_ptr<Window> w12(CreateTestWindowWithId(12, w1.get()));
257 EXPECT_EQ(NULL, w1->GetChildById(57));
258 EXPECT_EQ(w12.get(), w1->GetChildById(12));
259 EXPECT_EQ(w111.get(), w1->GetChildById(111));
262 // Make sure that Window::Contains correctly handles children, grandchildren,
263 // and not containing NULL or parents.
264 TEST_F(WindowTest, Contains) {
266 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
268 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
270 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
272 parent.AddChild(&child1);
273 child1.AddChild(&child2);
275 EXPECT_TRUE(parent.Contains(&parent));
276 EXPECT_TRUE(parent.Contains(&child1));
277 EXPECT_TRUE(parent.Contains(&child2));
279 EXPECT_FALSE(parent.Contains(NULL));
280 EXPECT_FALSE(child1.Contains(&parent));
281 EXPECT_FALSE(child2.Contains(&child1));
284 TEST_F(WindowTest, ContainsPointInRoot) {
285 scoped_ptr<Window> w(
286 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 5, 5),
288 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(9, 9)));
289 EXPECT_TRUE(w->ContainsPointInRoot(gfx::Point(10, 10)));
290 EXPECT_TRUE(w->ContainsPointInRoot(gfx::Point(14, 14)));
291 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(15, 15)));
292 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(20, 20)));
295 TEST_F(WindowTest, ContainsPoint) {
296 scoped_ptr<Window> w(
297 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 5, 5),
299 EXPECT_TRUE(w->ContainsPoint(gfx::Point(0, 0)));
300 EXPECT_TRUE(w->ContainsPoint(gfx::Point(4, 4)));
301 EXPECT_FALSE(w->ContainsPoint(gfx::Point(5, 5)));
302 EXPECT_FALSE(w->ContainsPoint(gfx::Point(10, 10)));
305 TEST_F(WindowTest, ConvertPointToWindow) {
306 // Window::ConvertPointToWindow is mostly identical to
307 // Layer::ConvertPointToLayer, except NULL values for |source| are permitted,
308 // in which case the function just returns.
309 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
310 gfx::Point reference_point(100, 100);
311 gfx::Point test_point = reference_point;
312 Window::ConvertPointToTarget(NULL, w1.get(), &test_point);
313 EXPECT_EQ(reference_point, test_point);
316 TEST_F(WindowTest, MoveCursorTo) {
317 scoped_ptr<Window> w1(
318 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
320 scoped_ptr<Window> w11(
321 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
322 scoped_ptr<Window> w111(
323 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
324 scoped_ptr<Window> w1111(
325 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
327 Window* root = root_window();
328 root->MoveCursorTo(gfx::Point(10, 10));
330 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
331 w1->MoveCursorTo(gfx::Point(10, 10));
333 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
334 w11->MoveCursorTo(gfx::Point(10, 10));
336 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
337 w111->MoveCursorTo(gfx::Point(10, 10));
339 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
340 w1111->MoveCursorTo(gfx::Point(10, 10));
342 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
345 TEST_F(WindowTest, ContainsMouse) {
346 scoped_ptr<Window> w(
347 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
350 WindowTestApi w_test_api(w.get());
351 Window* root = root_window();
352 root->MoveCursorTo(gfx::Point(10, 10));
353 EXPECT_TRUE(w_test_api.ContainsMouse());
354 root->MoveCursorTo(gfx::Point(9, 10));
355 EXPECT_FALSE(w_test_api.ContainsMouse());
358 // Test Window::ConvertPointToWindow() with transform to root_window.
359 TEST_F(WindowTest, MoveCursorToWithTransformRootWindow) {
360 gfx::Transform transform;
361 transform.Translate(100.0, 100.0);
362 transform.Rotate(90.0);
363 transform.Scale(2.0, 5.0);
364 host()->SetRootTransform(transform);
365 host()->MoveCursorTo(gfx::Point(10, 10));
367 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.OD
368 EXPECT_EQ("50,120", QueryLatestMousePositionRequestInHost(host()).ToString());
370 EXPECT_EQ("10,10", gfx::Screen::GetScreenFor(
371 root_window())->GetCursorScreenPoint().ToString());
374 // Tests Window::ConvertPointToWindow() with transform to non-root windows.
375 TEST_F(WindowTest, MoveCursorToWithTransformWindow) {
376 scoped_ptr<Window> w1(
377 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
380 gfx::Transform transform1;
381 transform1.Scale(2, 2);
382 w1->SetTransform(transform1);
383 w1->MoveCursorTo(gfx::Point(10, 10));
385 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
387 gfx::Transform transform2;
388 transform2.Translate(-10, 20);
389 w1->SetTransform(transform2);
390 w1->MoveCursorTo(gfx::Point(10, 10));
392 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
394 gfx::Transform transform3;
395 transform3.Rotate(90.0);
396 w1->SetTransform(transform3);
397 w1->MoveCursorTo(gfx::Point(5, 5));
399 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
401 gfx::Transform transform4;
402 transform4.Translate(100.0, 100.0);
403 transform4.Rotate(90.0);
404 transform4.Scale(2.0, 5.0);
405 w1->SetTransform(transform4);
406 w1->MoveCursorTo(gfx::Point(10, 10));
408 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
411 // Test Window::ConvertPointToWindow() with complex transforms to both root and
413 // Test Window::ConvertPointToWindow() with transform to root_window.
414 TEST_F(WindowTest, MoveCursorToWithComplexTransform) {
415 scoped_ptr<Window> w1(
416 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
418 scoped_ptr<Window> w11(
419 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
420 scoped_ptr<Window> w111(
421 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
422 scoped_ptr<Window> w1111(
423 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
425 Window* root = root_window();
427 // The root window expects transforms that produce integer rects.
428 gfx::Transform root_transform;
429 root_transform.Translate(60.0, 70.0);
430 root_transform.Rotate(-90.0);
431 root_transform.Translate(-50.0, -50.0);
432 root_transform.Scale(2.0, 3.0);
434 gfx::Transform transform;
435 transform.Translate(10.0, 20.0);
436 transform.Rotate(10.0);
437 transform.Scale(0.3f, 0.5f);
438 host()->SetRootTransform(root_transform);
439 w1->SetTransform(transform);
440 w11->SetTransform(transform);
441 w111->SetTransform(transform);
442 w1111->SetTransform(transform);
444 w1111->MoveCursorTo(gfx::Point(10, 10));
447 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.
448 EXPECT_EQ("169,80", QueryLatestMousePositionRequestInHost(host()).ToString());
451 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
454 TEST_F(WindowTest, GetEventHandlerForPoint) {
455 scoped_ptr<Window> w1(
456 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
458 scoped_ptr<Window> w11(
459 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
460 scoped_ptr<Window> w111(
461 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
462 scoped_ptr<Window> w1111(
463 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
464 scoped_ptr<Window> w12(
465 CreateTestWindow(SK_ColorMAGENTA, 12, gfx::Rect(10, 420, 25, 25),
467 scoped_ptr<Window> w121(
468 CreateTestWindow(SK_ColorYELLOW, 121, gfx::Rect(5, 5, 5, 5), w12.get()));
469 scoped_ptr<Window> w13(
470 CreateTestWindow(SK_ColorGRAY, 13, gfx::Rect(5, 470, 50, 50), w1.get()));
472 Window* root = root_window();
473 w1->parent()->SetBounds(gfx::Rect(500, 500));
474 EXPECT_EQ(NULL, root->GetEventHandlerForPoint(gfx::Point(5, 5)));
475 EXPECT_EQ(w1.get(), root->GetEventHandlerForPoint(gfx::Point(11, 11)));
476 EXPECT_EQ(w11.get(), root->GetEventHandlerForPoint(gfx::Point(16, 16)));
477 EXPECT_EQ(w111.get(), root->GetEventHandlerForPoint(gfx::Point(21, 21)));
478 EXPECT_EQ(w1111.get(), root->GetEventHandlerForPoint(gfx::Point(26, 26)));
479 EXPECT_EQ(w12.get(), root->GetEventHandlerForPoint(gfx::Point(21, 431)));
480 EXPECT_EQ(w121.get(), root->GetEventHandlerForPoint(gfx::Point(26, 436)));
481 EXPECT_EQ(w13.get(), root->GetEventHandlerForPoint(gfx::Point(26, 481)));
484 TEST_F(WindowTest, GetEventHandlerForPointWithOverride) {
485 // If our child is flush to our top-left corner he gets events just inside the
487 scoped_ptr<Window> parent(
488 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 20, 400, 500),
490 scoped_ptr<Window> child(
491 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(0, 0, 60, 70), parent.get()));
492 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
493 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(1, 1)));
495 // We can override the hit test bounds of the parent to make the parent grab
496 // events along that edge.
497 parent->set_hit_test_bounds_override_inner(gfx::Insets(1, 1, 1, 1));
498 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
499 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(1, 1)));
502 TEST_F(WindowTest, GetEventHandlerForPointWithOverrideDescendingOrder) {
503 scoped_ptr<SelfEventHandlingWindowDelegate> parent_delegate(
504 new SelfEventHandlingWindowDelegate);
505 scoped_ptr<Window> parent(CreateTestWindowWithDelegate(
506 parent_delegate.get(), 1, gfx::Rect(10, 20, 400, 500), root_window()));
507 scoped_ptr<Window> child(
508 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(0, 0, 390, 480),
511 // We can override ShouldDescendIntoChildForEventHandling to make the parent
513 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
514 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(50, 50)));
517 TEST_F(WindowTest, GetTopWindowContainingPoint) {
518 Window* root = root_window();
519 root->SetBounds(gfx::Rect(0, 0, 300, 300));
521 scoped_ptr<Window> w1(
522 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 100, 100),
524 scoped_ptr<Window> w11(
525 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(0, 0, 120, 120), w1.get()));
527 scoped_ptr<Window> w2(
528 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(5, 5, 55, 55),
531 scoped_ptr<Window> w3(
532 CreateTestWindowWithDelegate(
533 NULL, 3, gfx::Rect(200, 200, 100, 100), root_window()));
534 scoped_ptr<Window> w31(
535 CreateTestWindow(SK_ColorCYAN, 31, gfx::Rect(0, 0, 50, 50), w3.get()));
536 scoped_ptr<Window> w311(
537 CreateTestWindow(SK_ColorBLUE, 311, gfx::Rect(0, 0, 10, 10), w31.get()));
539 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(0, 0)));
540 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(5, 5)));
541 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(10, 10)));
542 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(59, 59)));
543 EXPECT_EQ(w1.get(), root->GetTopWindowContainingPoint(gfx::Point(60, 60)));
544 EXPECT_EQ(w1.get(), root->GetTopWindowContainingPoint(gfx::Point(109, 109)));
545 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(110, 110)));
546 EXPECT_EQ(w31.get(), root->GetTopWindowContainingPoint(gfx::Point(200, 200)));
547 EXPECT_EQ(w31.get(), root->GetTopWindowContainingPoint(gfx::Point(220, 220)));
548 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(260, 260)));
551 TEST_F(WindowTest, GetToplevelWindow) {
552 const gfx::Rect kBounds(0, 0, 10, 10);
553 TestWindowDelegate delegate;
555 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
556 scoped_ptr<Window> w11(
557 CreateTestWindowWithDelegate(&delegate, 11, kBounds, w1.get()));
558 scoped_ptr<Window> w111(CreateTestWindowWithId(111, w11.get()));
559 scoped_ptr<Window> w1111(
560 CreateTestWindowWithDelegate(&delegate, 1111, kBounds, w111.get()));
562 EXPECT_TRUE(root_window()->GetToplevelWindow() == NULL);
563 EXPECT_TRUE(w1->GetToplevelWindow() == NULL);
564 EXPECT_EQ(w11.get(), w11->GetToplevelWindow());
565 EXPECT_EQ(w11.get(), w111->GetToplevelWindow());
566 EXPECT_EQ(w11.get(), w1111->GetToplevelWindow());
569 class AddedToRootWindowObserver : public WindowObserver {
571 AddedToRootWindowObserver() : called_(false) {}
573 void OnWindowAddedToRootWindow(Window* window) override { called_ = true; }
575 bool called() const { return called_; }
580 DISALLOW_COPY_AND_ASSIGN(AddedToRootWindowObserver);
583 TEST_F(WindowTest, WindowAddedToRootWindowShouldNotifyChildAndNotParent) {
584 AddedToRootWindowObserver parent_observer;
585 AddedToRootWindowObserver child_observer;
586 scoped_ptr<Window> parent_window(CreateTestWindowWithId(1, root_window()));
587 scoped_ptr<Window> child_window(new Window(NULL));
588 child_window->Init(aura::WINDOW_LAYER_TEXTURED);
589 child_window->Show();
591 parent_window->AddObserver(&parent_observer);
592 child_window->AddObserver(&child_observer);
594 parent_window->AddChild(child_window.get());
596 EXPECT_FALSE(parent_observer.called());
597 EXPECT_TRUE(child_observer.called());
599 parent_window->RemoveObserver(&parent_observer);
600 child_window->RemoveObserver(&child_observer);
603 // Various destruction assertions.
604 TEST_F(WindowTest, DestroyTest) {
605 DestroyTrackingDelegateImpl parent_delegate;
606 ChildWindowDelegateImpl child_delegate(&parent_delegate);
608 scoped_ptr<Window> parent(
609 CreateTestWindowWithDelegate(&parent_delegate, 0, gfx::Rect(),
611 CreateTestWindowWithDelegate(&child_delegate, 0, gfx::Rect(), parent.get());
613 // Both the parent and child should have been destroyed.
614 EXPECT_EQ(1, parent_delegate.destroying_count());
615 EXPECT_EQ(1, parent_delegate.destroyed_count());
616 EXPECT_EQ(1, child_delegate.destroying_count());
617 EXPECT_EQ(1, child_delegate.destroyed_count());
620 // Tests that a window is orphaned before OnWindowDestroyed is called.
621 TEST_F(WindowTest, OrphanedBeforeOnDestroyed) {
622 TestWindowDelegate parent_delegate;
623 DestroyOrphanDelegate child_delegate;
625 scoped_ptr<Window> parent(
626 CreateTestWindowWithDelegate(&parent_delegate, 0, gfx::Rect(),
628 scoped_ptr<Window> child(CreateTestWindowWithDelegate(&child_delegate, 0,
629 gfx::Rect(), parent.get()));
630 child_delegate.set_window(child.get());
634 // Make sure StackChildAtTop moves both the window and layer to the front.
635 TEST_F(WindowTest, StackChildAtTop) {
637 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
639 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
641 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
643 parent.AddChild(&child1);
644 parent.AddChild(&child2);
645 ASSERT_EQ(2u, parent.children().size());
646 EXPECT_EQ(&child1, parent.children()[0]);
647 EXPECT_EQ(&child2, parent.children()[1]);
648 ASSERT_EQ(2u, parent.layer()->children().size());
649 EXPECT_EQ(child1.layer(), parent.layer()->children()[0]);
650 EXPECT_EQ(child2.layer(), parent.layer()->children()[1]);
652 parent.StackChildAtTop(&child1);
653 ASSERT_EQ(2u, parent.children().size());
654 EXPECT_EQ(&child1, parent.children()[1]);
655 EXPECT_EQ(&child2, parent.children()[0]);
656 ASSERT_EQ(2u, parent.layer()->children().size());
657 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
658 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
661 // Make sure StackChildBelow works.
662 TEST_F(WindowTest, StackChildBelow) {
664 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
666 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
669 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
672 child3.Init(aura::WINDOW_LAYER_NOT_DRAWN);
675 parent.AddChild(&child1);
676 parent.AddChild(&child2);
677 parent.AddChild(&child3);
678 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent));
680 parent.StackChildBelow(&child1, &child2);
681 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent));
683 parent.StackChildBelow(&child2, &child1);
684 EXPECT_EQ("2 1 3", ChildWindowIDsAsString(&parent));
686 parent.StackChildBelow(&child3, &child2);
687 EXPECT_EQ("3 2 1", ChildWindowIDsAsString(&parent));
689 parent.StackChildBelow(&child3, &child1);
690 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(&parent));
693 // Various assertions for StackChildAbove.
694 TEST_F(WindowTest, StackChildAbove) {
696 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
698 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
700 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
702 child3.Init(aura::WINDOW_LAYER_NOT_DRAWN);
704 parent.AddChild(&child1);
705 parent.AddChild(&child2);
707 // Move 1 in front of 2.
708 parent.StackChildAbove(&child1, &child2);
709 ASSERT_EQ(2u, parent.children().size());
710 EXPECT_EQ(&child2, parent.children()[0]);
711 EXPECT_EQ(&child1, parent.children()[1]);
712 ASSERT_EQ(2u, parent.layer()->children().size());
713 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
714 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
716 // Add 3, resulting in order [2, 1, 3], then move 2 in front of 1, resulting
718 parent.AddChild(&child3);
719 parent.StackChildAbove(&child2, &child1);
720 ASSERT_EQ(3u, parent.children().size());
721 EXPECT_EQ(&child1, parent.children()[0]);
722 EXPECT_EQ(&child2, parent.children()[1]);
723 EXPECT_EQ(&child3, parent.children()[2]);
724 ASSERT_EQ(3u, parent.layer()->children().size());
725 EXPECT_EQ(child1.layer(), parent.layer()->children()[0]);
726 EXPECT_EQ(child2.layer(), parent.layer()->children()[1]);
727 EXPECT_EQ(child3.layer(), parent.layer()->children()[2]);
729 // Move 1 in front of 3, resulting in [2, 3, 1].
730 parent.StackChildAbove(&child1, &child3);
731 ASSERT_EQ(3u, parent.children().size());
732 EXPECT_EQ(&child2, parent.children()[0]);
733 EXPECT_EQ(&child3, parent.children()[1]);
734 EXPECT_EQ(&child1, parent.children()[2]);
735 ASSERT_EQ(3u, parent.layer()->children().size());
736 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
737 EXPECT_EQ(child3.layer(), parent.layer()->children()[1]);
738 EXPECT_EQ(child1.layer(), parent.layer()->children()[2]);
740 // Moving 1 in front of 2 should lower it, resulting in [2, 1, 3].
741 parent.StackChildAbove(&child1, &child2);
742 ASSERT_EQ(3u, parent.children().size());
743 EXPECT_EQ(&child2, parent.children()[0]);
744 EXPECT_EQ(&child1, parent.children()[1]);
745 EXPECT_EQ(&child3, parent.children()[2]);
746 ASSERT_EQ(3u, parent.layer()->children().size());
747 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
748 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
749 EXPECT_EQ(child3.layer(), parent.layer()->children()[2]);
752 // Various capture assertions.
753 TEST_F(WindowTest, CaptureTests) {
754 CaptureWindowDelegateImpl delegate;
755 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
756 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
757 EXPECT_FALSE(window->HasCapture());
759 delegate.ResetCounts();
762 window->SetCapture();
763 EXPECT_TRUE(window->HasCapture());
764 EXPECT_EQ(0, delegate.capture_lost_count());
765 EXPECT_EQ(0, delegate.capture_changed_event_count());
766 ui::test::EventGenerator generator(root_window(), gfx::Point(50, 50));
767 generator.PressLeftButton();
768 EXPECT_EQ(1, delegate.mouse_event_count());
769 generator.ReleaseLeftButton();
771 EXPECT_EQ(2, delegate.mouse_event_count());
772 delegate.ResetCounts();
774 ui::TouchEvent touchev(
775 ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), 0, getTime());
776 DispatchEventUsingWindowDispatcher(&touchev);
777 EXPECT_EQ(1, delegate.touch_event_count());
778 delegate.ResetCounts();
780 window->ReleaseCapture();
781 EXPECT_FALSE(window->HasCapture());
782 EXPECT_EQ(1, delegate.capture_lost_count());
783 EXPECT_EQ(1, delegate.capture_changed_event_count());
784 EXPECT_EQ(1, delegate.mouse_event_count());
785 EXPECT_EQ(0, delegate.touch_event_count());
787 generator.PressLeftButton();
788 EXPECT_EQ(1, delegate.mouse_event_count());
790 ui::TouchEvent touchev2(
791 ui::ET_TOUCH_PRESSED, gfx::Point(250, 250), 1, getTime());
792 DispatchEventUsingWindowDispatcher(&touchev2);
793 EXPECT_EQ(0, delegate.touch_event_count());
795 // Removing the capture window from parent should reset the capture window
796 // in the root window.
797 window->SetCapture();
798 EXPECT_EQ(window.get(), aura::client::GetCaptureWindow(root_window()));
799 window->parent()->RemoveChild(window.get());
800 EXPECT_FALSE(window->HasCapture());
801 EXPECT_EQ(NULL, aura::client::GetCaptureWindow(root_window()));
804 TEST_F(WindowTest, TouchCaptureCancelsOtherTouches) {
805 CaptureWindowDelegateImpl delegate1;
806 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
807 &delegate1, 0, gfx::Rect(0, 0, 50, 50), root_window()));
808 CaptureWindowDelegateImpl delegate2;
809 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
810 &delegate2, 0, gfx::Rect(50, 50, 50, 50), root_window()));
813 ui::TouchEvent press1(
814 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
815 DispatchEventUsingWindowDispatcher(&press1);
816 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
817 EXPECT_EQ(2, delegate1.gesture_event_count());
818 delegate1.ResetCounts();
820 // Capturing to w2 should cause the touch to be canceled.
822 EXPECT_EQ(1, delegate1.touch_event_count());
823 EXPECT_EQ(0, delegate2.touch_event_count());
824 delegate1.ResetCounts();
825 delegate2.ResetCounts();
827 // Events now go to w2.
828 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, getTime());
829 DispatchEventUsingWindowDispatcher(&move);
830 EXPECT_EQ(0, delegate1.gesture_event_count());
831 EXPECT_EQ(0, delegate1.touch_event_count());
832 EXPECT_EQ(0, delegate2.gesture_event_count());
833 EXPECT_EQ(1, delegate2.touch_event_count());
835 ui::TouchEvent release(
836 ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, getTime());
837 DispatchEventUsingWindowDispatcher(&release);
838 EXPECT_EQ(0, delegate1.gesture_event_count());
839 EXPECT_EQ(0, delegate2.gesture_event_count());
841 // A new press is captured by w2.
842 ui::TouchEvent press2(
843 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
844 DispatchEventUsingWindowDispatcher(&press2);
845 EXPECT_EQ(0, delegate1.gesture_event_count());
846 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
847 EXPECT_EQ(2, delegate2.gesture_event_count());
848 delegate1.ResetCounts();
849 delegate2.ResetCounts();
851 // And releasing capture changes nothing.
852 w2->ReleaseCapture();
853 EXPECT_EQ(0, delegate1.gesture_event_count());
854 EXPECT_EQ(0, delegate1.touch_event_count());
855 EXPECT_EQ(0, delegate2.gesture_event_count());
856 EXPECT_EQ(0, delegate2.touch_event_count());
859 TEST_F(WindowTest, TouchCaptureDoesntCancelCapturedTouches) {
860 CaptureWindowDelegateImpl delegate;
861 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
862 &delegate, 0, gfx::Rect(0, 0, 50, 50), root_window()));
863 base::TimeDelta time = getTime();
864 const int kTimeDelta = 100;
866 ui::TouchEvent press(
867 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, time);
868 DispatchEventUsingWindowDispatcher(&press);
870 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
871 EXPECT_EQ(2, delegate.gesture_event_count());
872 EXPECT_EQ(1, delegate.touch_event_count());
873 delegate.ResetCounts();
875 window->SetCapture();
876 EXPECT_EQ(0, delegate.gesture_event_count());
877 EXPECT_EQ(0, delegate.touch_event_count());
878 delegate.ResetCounts();
880 // On move We will get TOUCH_MOVED, GESTURE_TAP_CANCEL,
881 // GESTURE_SCROLL_START and GESTURE_SCROLL_UPDATE.
882 time += base::TimeDelta::FromMilliseconds(kTimeDelta);
883 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, time);
884 DispatchEventUsingWindowDispatcher(&move);
885 EXPECT_EQ(1, delegate.touch_event_count());
886 EXPECT_EQ(3, delegate.gesture_event_count());
887 delegate.ResetCounts();
889 // Release capture shouldn't change anything.
890 window->ReleaseCapture();
891 EXPECT_EQ(0, delegate.touch_event_count());
892 EXPECT_EQ(0, delegate.gesture_event_count());
893 delegate.ResetCounts();
895 // On move we still get TOUCH_MOVED and GESTURE_SCROLL_UPDATE.
896 time += base::TimeDelta::FromMilliseconds(kTimeDelta);
897 ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(10, 30), 0, time);
898 DispatchEventUsingWindowDispatcher(&move2);
899 EXPECT_EQ(1, delegate.touch_event_count());
900 EXPECT_EQ(1, delegate.gesture_event_count());
901 delegate.ResetCounts();
903 // And on release we get TOUCH_RELEASED, GESTURE_SCROLL_END, GESTURE_END
904 time += base::TimeDelta::FromMilliseconds(kTimeDelta);
905 ui::TouchEvent release(
906 ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, time);
907 DispatchEventUsingWindowDispatcher(&release);
908 EXPECT_EQ(1, delegate.touch_event_count());
909 EXPECT_EQ(2, delegate.gesture_event_count());
913 // Assertions around SetCapture() and touch/gestures.
914 TEST_F(WindowTest, TransferCaptureTouchEvents) {
916 CaptureWindowDelegateImpl d1;
917 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
918 &d1, 0, gfx::Rect(0, 0, 20, 20), root_window()));
919 ui::TouchEvent p1(ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
920 DispatchEventUsingWindowDispatcher(&p1);
921 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
922 EXPECT_EQ(1, d1.touch_event_count());
923 EXPECT_EQ(2, d1.gesture_event_count());
926 // Touch on |w2| with a different id.
927 CaptureWindowDelegateImpl d2;
928 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
929 &d2, 0, gfx::Rect(40, 0, 40, 20), root_window()));
930 ui::TouchEvent p2(ui::ET_TOUCH_PRESSED, gfx::Point(41, 10), 1, getTime());
931 DispatchEventUsingWindowDispatcher(&p2);
932 EXPECT_EQ(0, d1.touch_event_count());
933 EXPECT_EQ(0, d1.gesture_event_count());
934 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN for new target window.
935 EXPECT_EQ(1, d2.touch_event_count());
936 EXPECT_EQ(2, d2.gesture_event_count());
940 // Set capture on |w2|, this should send a cancel (TAP_CANCEL, END) to |w1|
943 EXPECT_EQ(1, d1.touch_event_count());
944 EXPECT_EQ(2, d1.gesture_event_count());
945 EXPECT_EQ(0, d2.touch_event_count());
946 EXPECT_EQ(0, d2.gesture_event_count());
950 CaptureWindowDelegateImpl d3;
951 scoped_ptr<Window> w3(CreateTestWindowWithDelegate(
952 &d3, 0, gfx::Rect(0, 0, 100, 101), root_window()));
953 // Set capture on w3. No new events should be received.
954 // Note this difference in behavior between the first and second capture
955 // is confusing and error prone. http://crbug.com/236930
957 EXPECT_EQ(0, d1.touch_event_count());
958 EXPECT_EQ(0, d1.gesture_event_count());
959 EXPECT_EQ(0, d2.touch_event_count());
960 EXPECT_EQ(0, d2.gesture_event_count());
961 EXPECT_EQ(0, d3.touch_event_count());
962 EXPECT_EQ(0, d3.gesture_event_count());
964 // Move touch id originally associated with |w2|. Since capture was transfered
965 // from 2 to 3 only |w3| should get the event.
966 ui::TouchEvent m3(ui::ET_TOUCH_MOVED, gfx::Point(110, 105), 1, getTime());
967 DispatchEventUsingWindowDispatcher(&m3);
968 EXPECT_EQ(0, d1.touch_event_count());
969 EXPECT_EQ(0, d1.gesture_event_count());
970 EXPECT_EQ(0, d2.touch_event_count());
971 EXPECT_EQ(0, d2.gesture_event_count());
972 // |w3| gets a TOUCH_MOVE, TAP_CANCEL and two scroll related events.
973 EXPECT_EQ(1, d3.touch_event_count());
974 EXPECT_EQ(3, d3.gesture_event_count());
979 // When we release capture, no touches are canceled.
980 w3->ReleaseCapture();
981 EXPECT_EQ(0, d1.touch_event_count());
982 EXPECT_EQ(0, d1.gesture_event_count());
983 EXPECT_EQ(0, d2.touch_event_count());
984 EXPECT_EQ(0, d2.gesture_event_count());
985 EXPECT_EQ(0, d3.touch_event_count());
986 EXPECT_EQ(0, d3.gesture_event_count());
988 // And when we move the touch again, |w3| still gets the events.
989 ui::TouchEvent m4(ui::ET_TOUCH_MOVED, gfx::Point(120, 105), 1, getTime());
990 DispatchEventUsingWindowDispatcher(&m4);
991 EXPECT_EQ(0, d1.touch_event_count());
992 EXPECT_EQ(0, d1.gesture_event_count());
993 EXPECT_EQ(0, d2.touch_event_count());
994 EXPECT_EQ(0, d2.gesture_event_count());
995 EXPECT_EQ(1, d3.touch_event_count());
996 EXPECT_EQ(1, d3.gesture_event_count());
1002 // Changes capture while capture is already ongoing.
1003 TEST_F(WindowTest, ChangeCaptureWhileMouseDown) {
1004 CaptureWindowDelegateImpl delegate;
1005 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
1006 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1007 CaptureWindowDelegateImpl delegate2;
1008 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
1009 &delegate2, 0, gfx::Rect(20, 20, 20, 20), root_window()));
1011 // Execute the scheduled draws so that mouse events are not
1013 RunAllPendingInMessageLoop();
1015 EXPECT_FALSE(window->HasCapture());
1018 delegate.ResetCounts();
1019 window->SetCapture();
1020 EXPECT_TRUE(window->HasCapture());
1021 EXPECT_EQ(0, delegate.capture_lost_count());
1022 EXPECT_EQ(0, delegate.capture_changed_event_count());
1023 ui::test::EventGenerator generator(root_window(), gfx::Point(50, 50));
1024 generator.PressLeftButton();
1025 EXPECT_EQ(0, delegate.capture_lost_count());
1026 EXPECT_EQ(0, delegate.capture_changed_event_count());
1027 EXPECT_EQ(1, delegate.mouse_event_count());
1029 // Set capture to |w2|, should implicitly unset capture for |window|.
1030 delegate.ResetCounts();
1031 delegate2.ResetCounts();
1034 generator.MoveMouseTo(gfx::Point(40, 40), 2);
1035 EXPECT_EQ(1, delegate.capture_lost_count());
1036 EXPECT_EQ(1, delegate.capture_changed_event_count());
1037 EXPECT_EQ(1, delegate.mouse_event_count());
1038 EXPECT_EQ(2, delegate2.mouse_event_count());
1041 // Verifies capture is reset when a window is destroyed.
1042 TEST_F(WindowTest, ReleaseCaptureOnDestroy) {
1043 CaptureWindowDelegateImpl delegate;
1044 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
1045 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1046 EXPECT_FALSE(window->HasCapture());
1049 window->SetCapture();
1050 EXPECT_TRUE(window->HasCapture());
1052 // Destroy the window.
1055 // Make sure the root window doesn't reference the window anymore.
1056 EXPECT_EQ(NULL, host()->dispatcher()->mouse_pressed_handler());
1057 EXPECT_EQ(NULL, aura::client::GetCaptureWindow(root_window()));
1060 TEST_F(WindowTest, GetBoundsInRootWindow) {
1061 scoped_ptr<Window> viewport(CreateTestWindowWithBounds(
1062 gfx::Rect(0, 0, 300, 300), root_window()));
1063 scoped_ptr<Window> child(CreateTestWindowWithBounds(
1064 gfx::Rect(0, 0, 100, 100), viewport.get()));
1066 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1068 // The |child| window's screen bounds should move along with the |viewport|.
1069 viewport->SetBounds(gfx::Rect(-100, -100, 300, 300));
1070 EXPECT_EQ("-100,-100 100x100", child->GetBoundsInRootWindow().ToString());
1072 // The |child| window is moved to the 0,0 in screen coordinates.
1073 // |GetBoundsInRootWindow()| should return 0,0.
1074 child->SetBounds(gfx::Rect(100, 100, 100, 100));
1075 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1078 class MouseEnterExitWindowDelegate : public TestWindowDelegate {
1080 MouseEnterExitWindowDelegate() : entered_(false), exited_(false) {}
1082 void OnMouseEvent(ui::MouseEvent* event) override {
1083 switch (event->type()) {
1084 case ui::ET_MOUSE_ENTERED:
1085 EXPECT_TRUE(event->flags() & ui::EF_IS_SYNTHESIZED);
1088 case ui::ET_MOUSE_EXITED:
1089 EXPECT_TRUE(event->flags() & ui::EF_IS_SYNTHESIZED);
1097 bool entered() const { return entered_; }
1098 bool exited() const { return exited_; }
1100 // Clear the entered / exited states.
1101 void ResetExpectations() {
1110 DISALLOW_COPY_AND_ASSIGN(MouseEnterExitWindowDelegate);
1114 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1115 // mouse transitions from window to window.
1116 TEST_F(WindowTest, MouseEnterExit) {
1117 MouseEnterExitWindowDelegate d1;
1118 scoped_ptr<Window> w1(
1119 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1121 MouseEnterExitWindowDelegate d2;
1122 scoped_ptr<Window> w2(
1123 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50),
1126 ui::test::EventGenerator generator(root_window());
1127 generator.MoveMouseToCenterOf(w1.get());
1128 EXPECT_TRUE(d1.entered());
1129 EXPECT_FALSE(d1.exited());
1130 EXPECT_FALSE(d2.entered());
1131 EXPECT_FALSE(d2.exited());
1133 generator.MoveMouseToCenterOf(w2.get());
1134 EXPECT_TRUE(d1.entered());
1135 EXPECT_TRUE(d1.exited());
1136 EXPECT_TRUE(d2.entered());
1137 EXPECT_FALSE(d2.exited());
1140 // Verifies that the WindowDelegate receives MouseExit from ET_MOUSE_EXITED.
1141 TEST_F(WindowTest, WindowTreeHostExit) {
1142 MouseEnterExitWindowDelegate d1;
1143 scoped_ptr<Window> w1(
1144 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1147 ui::test::EventGenerator generator(root_window());
1148 generator.MoveMouseToCenterOf(w1.get());
1149 EXPECT_TRUE(d1.entered());
1150 EXPECT_FALSE(d1.exited());
1151 d1.ResetExpectations();
1153 ui::MouseEvent exit_event(
1154 ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(), 0, 0);
1155 DispatchEventUsingWindowDispatcher(&exit_event);
1156 EXPECT_FALSE(d1.entered());
1157 EXPECT_TRUE(d1.exited());
1160 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1161 // mouse transitions from window to window, even if the entered window sets
1162 // and releases capture.
1163 TEST_F(WindowTest, MouseEnterExitWithClick) {
1164 MouseEnterExitWindowDelegate d1;
1165 scoped_ptr<Window> w1(
1166 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1168 MouseEnterExitWindowDelegate d2;
1169 scoped_ptr<Window> w2(
1170 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50),
1173 ui::test::EventGenerator generator(root_window());
1174 generator.MoveMouseToCenterOf(w1.get());
1175 EXPECT_TRUE(d1.entered());
1176 EXPECT_FALSE(d1.exited());
1177 EXPECT_FALSE(d2.entered());
1178 EXPECT_FALSE(d2.exited());
1180 // Emmulate what Views does on a click by grabbing and releasing capture.
1181 generator.PressLeftButton();
1183 w1->ReleaseCapture();
1184 generator.ReleaseLeftButton();
1186 generator.MoveMouseToCenterOf(w2.get());
1187 EXPECT_TRUE(d1.entered());
1188 EXPECT_TRUE(d1.exited());
1189 EXPECT_TRUE(d2.entered());
1190 EXPECT_FALSE(d2.exited());
1193 TEST_F(WindowTest, MouseEnterExitWhenDeleteWithCapture) {
1194 MouseEnterExitWindowDelegate delegate;
1195 scoped_ptr<Window> window(
1196 CreateTestWindowWithDelegate(&delegate, 1, gfx::Rect(10, 10, 50, 50),
1199 ui::test::EventGenerator generator(root_window());
1200 generator.MoveMouseToCenterOf(window.get());
1201 EXPECT_TRUE(delegate.entered());
1202 EXPECT_FALSE(delegate.exited());
1204 // Emmulate what Views does on a click by grabbing and releasing capture.
1205 generator.PressLeftButton();
1206 window->SetCapture();
1208 delegate.ResetExpectations();
1209 generator.MoveMouseTo(0, 0);
1210 EXPECT_FALSE(delegate.entered());
1211 EXPECT_FALSE(delegate.exited());
1213 delegate.ResetExpectations();
1215 EXPECT_FALSE(delegate.entered());
1216 EXPECT_FALSE(delegate.exited());
1219 // Verifies that enter / exits are sent if windows appear and are deleted
1220 // under the current mouse position..
1221 TEST_F(WindowTest, MouseEnterExitWithDelete) {
1222 MouseEnterExitWindowDelegate d1;
1223 scoped_ptr<Window> w1(
1224 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1227 ui::test::EventGenerator generator(root_window());
1228 generator.MoveMouseToCenterOf(w1.get());
1229 EXPECT_TRUE(d1.entered());
1230 EXPECT_FALSE(d1.exited());
1231 d1.ResetExpectations();
1233 MouseEnterExitWindowDelegate d2;
1235 scoped_ptr<Window> w2(
1236 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1238 // Enters / exits can be sent asynchronously.
1239 RunAllPendingInMessageLoop();
1240 EXPECT_FALSE(d1.entered());
1241 EXPECT_TRUE(d1.exited());
1242 EXPECT_TRUE(d2.entered());
1243 EXPECT_FALSE(d2.exited());
1244 d1.ResetExpectations();
1245 d2.ResetExpectations();
1247 // Enters / exits can be sent asynchronously.
1248 RunAllPendingInMessageLoop();
1249 EXPECT_TRUE(d2.exited());
1250 EXPECT_TRUE(d1.entered());
1253 // Verifies that enter / exits are sent if windows appear and are hidden
1254 // under the current mouse position..
1255 TEST_F(WindowTest, MouseEnterExitWithHide) {
1256 MouseEnterExitWindowDelegate d1;
1257 scoped_ptr<Window> w1(
1258 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1261 ui::test::EventGenerator generator(root_window());
1262 generator.MoveMouseToCenterOf(w1.get());
1263 EXPECT_TRUE(d1.entered());
1264 EXPECT_FALSE(d1.exited());
1266 MouseEnterExitWindowDelegate d2;
1267 scoped_ptr<Window> w2(
1268 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1270 // Enters / exits can be send asynchronously.
1271 RunAllPendingInMessageLoop();
1272 EXPECT_TRUE(d1.entered());
1273 EXPECT_TRUE(d1.exited());
1274 EXPECT_TRUE(d2.entered());
1275 EXPECT_FALSE(d2.exited());
1277 d1.ResetExpectations();
1279 // Enters / exits can be send asynchronously.
1280 RunAllPendingInMessageLoop();
1281 EXPECT_TRUE(d2.exited());
1282 EXPECT_TRUE(d1.entered());
1285 TEST_F(WindowTest, MouseEnterExitWithParentHide) {
1286 MouseEnterExitWindowDelegate d1;
1287 scoped_ptr<Window> w1(
1288 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1290 MouseEnterExitWindowDelegate d2;
1291 Window* w2 = CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1293 ui::test::EventGenerator generator(root_window());
1294 generator.MoveMouseToCenterOf(w2);
1295 // Enters / exits can be send asynchronously.
1296 RunAllPendingInMessageLoop();
1297 EXPECT_TRUE(d2.entered());
1298 EXPECT_FALSE(d2.exited());
1300 d2.ResetExpectations();
1302 RunAllPendingInMessageLoop();
1303 EXPECT_FALSE(d2.entered());
1304 EXPECT_TRUE(d2.exited());
1309 TEST_F(WindowTest, MouseEnterExitWithParentDelete) {
1310 MouseEnterExitWindowDelegate d1;
1311 scoped_ptr<Window> w1(
1312 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1314 MouseEnterExitWindowDelegate d2;
1315 Window* w2 = CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1317 ui::test::EventGenerator generator(root_window());
1318 generator.MoveMouseToCenterOf(w2);
1320 // Enters / exits can be send asynchronously.
1321 RunAllPendingInMessageLoop();
1322 EXPECT_TRUE(d2.entered());
1323 EXPECT_FALSE(d2.exited());
1325 d2.ResetExpectations();
1327 RunAllPendingInMessageLoop();
1328 EXPECT_FALSE(d2.entered());
1329 EXPECT_TRUE(d2.exited());
1332 // Creates a window with a delegate (w111) that can handle events at a lower
1333 // z-index than a window without a delegate (w12). w12 is sized to fill the
1334 // entire bounds of the container. This test verifies that
1335 // GetEventHandlerForPoint() skips w12 even though its bounds contain the event,
1336 // because it has no children that can handle the event and it has no delegate
1337 // allowing it to handle the event itself.
1338 TEST_F(WindowTest, GetEventHandlerForPoint_NoDelegate) {
1339 TestWindowDelegate d111;
1340 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(NULL, 1,
1341 gfx::Rect(0, 0, 500, 500), root_window()));
1342 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(NULL, 11,
1343 gfx::Rect(0, 0, 500, 500), w1.get()));
1344 scoped_ptr<Window> w111(CreateTestWindowWithDelegate(&d111, 111,
1345 gfx::Rect(50, 50, 450, 450), w11.get()));
1346 scoped_ptr<Window> w12(CreateTestWindowWithDelegate(NULL, 12,
1347 gfx::Rect(0, 0, 500, 500), w1.get()));
1349 gfx::Point target_point = w111->bounds().CenterPoint();
1350 EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(target_point));
1353 class VisibilityWindowDelegate : public TestWindowDelegate {
1355 VisibilityWindowDelegate()
1360 int shown() const { return shown_; }
1361 int hidden() const { return hidden_; }
1367 void OnWindowTargetVisibilityChanged(bool visible) override {
1378 DISALLOW_COPY_AND_ASSIGN(VisibilityWindowDelegate);
1381 // Verifies show/hide propagate correctly to children and the layer.
1382 TEST_F(WindowTest, Visibility) {
1383 VisibilityWindowDelegate d;
1384 VisibilityWindowDelegate d2;
1385 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(&d, 1, gfx::Rect(),
1387 scoped_ptr<Window> w2(
1388 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(), w1.get()));
1389 scoped_ptr<Window> w3(CreateTestWindowWithId(3, w2.get()));
1391 // Create shows all the windows.
1392 EXPECT_TRUE(w1->IsVisible());
1393 EXPECT_TRUE(w2->IsVisible());
1394 EXPECT_TRUE(w3->IsVisible());
1395 EXPECT_EQ(1, d.shown());
1399 EXPECT_FALSE(w1->IsVisible());
1400 EXPECT_FALSE(w2->IsVisible());
1401 EXPECT_FALSE(w3->IsVisible());
1402 EXPECT_EQ(1, d.hidden());
1403 EXPECT_EQ(0, d.shown());
1406 EXPECT_FALSE(w1->IsVisible());
1407 EXPECT_FALSE(w2->IsVisible());
1408 EXPECT_FALSE(w3->IsVisible());
1411 EXPECT_FALSE(w1->IsVisible());
1412 EXPECT_FALSE(w2->IsVisible());
1413 EXPECT_FALSE(w3->IsVisible());
1417 EXPECT_TRUE(w1->IsVisible());
1418 EXPECT_TRUE(w2->IsVisible());
1419 EXPECT_FALSE(w3->IsVisible());
1420 EXPECT_EQ(0, d.hidden());
1421 EXPECT_EQ(1, d.shown());
1424 EXPECT_TRUE(w1->IsVisible());
1425 EXPECT_TRUE(w2->IsVisible());
1426 EXPECT_TRUE(w3->IsVisible());
1428 // Verify that if an ancestor isn't visible and we change the visibility of a
1429 // child window that OnChildWindowVisibilityChanged() is still invoked.
1433 EXPECT_EQ(1, d2.hidden());
1434 EXPECT_EQ(0, d2.shown());
1437 EXPECT_EQ(0, d2.hidden());
1438 EXPECT_EQ(1, d2.shown());
1441 TEST_F(WindowTest, IgnoreEventsTest) {
1442 TestWindowDelegate d11;
1443 TestWindowDelegate d12;
1444 TestWindowDelegate d111;
1445 TestWindowDelegate d121;
1446 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(NULL, 1,
1447 gfx::Rect(0, 0, 500, 500), root_window()));
1448 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(&d11, 11,
1449 gfx::Rect(0, 0, 500, 500), w1.get()));
1450 scoped_ptr<Window> w111(CreateTestWindowWithDelegate(&d111, 111,
1451 gfx::Rect(50, 50, 450, 450), w11.get()));
1452 scoped_ptr<Window> w12(CreateTestWindowWithDelegate(&d12, 12,
1453 gfx::Rect(0, 0, 500, 500), w1.get()));
1454 scoped_ptr<Window> w121(CreateTestWindowWithDelegate(&d121, 121,
1455 gfx::Rect(150, 150, 50, 50), w12.get()));
1457 EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10)));
1458 w12->set_ignore_events(true);
1459 EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10)));
1460 w12->set_ignore_events(false);
1462 EXPECT_EQ(w121.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1463 w121->set_ignore_events(true);
1464 EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1465 w12->set_ignore_events(true);
1466 EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1467 w111->set_ignore_events(true);
1468 EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1471 // Tests transformation on the root window.
1472 TEST_F(WindowTest, Transform) {
1473 gfx::Size size = host()->GetBounds().size();
1474 EXPECT_EQ(gfx::Rect(size),
1475 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1476 gfx::Point()).bounds());
1478 // Rotate it clock-wise 90 degrees.
1479 gfx::Transform transform;
1480 transform.Translate(size.height(), 0);
1481 transform.Rotate(90.0);
1482 host()->SetRootTransform(transform);
1484 // The size should be the transformed size.
1485 gfx::Size transformed_size(size.height(), size.width());
1486 EXPECT_EQ(transformed_size.ToString(),
1487 root_window()->bounds().size().ToString());
1489 gfx::Rect(transformed_size).ToString(),
1490 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1491 gfx::Point()).bounds().ToString());
1493 // Host size shouldn't change.
1494 EXPECT_EQ(size.ToString(), host()->GetBounds().size().ToString());
1497 TEST_F(WindowTest, TransformGesture) {
1498 gfx::Size size = host()->GetBounds().size();
1500 scoped_ptr<GestureTrackPositionDelegate> delegate(
1501 new GestureTrackPositionDelegate);
1502 scoped_ptr<Window> window(CreateTestWindowWithDelegate(delegate.get(), -1234,
1503 gfx::Rect(0, 0, 20, 20), root_window()));
1505 // Rotate the root-window clock-wise 90 degrees.
1506 gfx::Transform transform;
1507 transform.Translate(size.height(), 0.0);
1508 transform.Rotate(90.0);
1509 host()->SetRootTransform(transform);
1511 ui::TouchEvent press(
1512 ui::ET_TOUCH_PRESSED, gfx::Point(size.height() - 10, 10), 0, getTime());
1513 DispatchEventUsingWindowDispatcher(&press);
1514 EXPECT_EQ(gfx::Point(10, 10).ToString(), delegate->position().ToString());
1518 DEFINE_WINDOW_PROPERTY_KEY(int, kIntKey, -2);
1519 DEFINE_WINDOW_PROPERTY_KEY(const char*, kStringKey, "squeamish");
1522 TEST_F(WindowTest, Property) {
1523 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window()));
1525 static const char native_prop_key[] = "fnord";
1527 // Non-existent properties should return the default values.
1528 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1529 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1530 EXPECT_EQ(NULL, w->GetNativeWindowProperty(native_prop_key));
1532 // A set property value should be returned again (even if it's the default
1534 w->SetProperty(kIntKey, INT_MAX);
1535 EXPECT_EQ(INT_MAX, w->GetProperty(kIntKey));
1536 w->SetProperty(kIntKey, -2);
1537 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1538 w->SetProperty(kIntKey, INT_MIN);
1539 EXPECT_EQ(INT_MIN, w->GetProperty(kIntKey));
1541 w->SetProperty(kStringKey, static_cast<const char*>(NULL));
1542 EXPECT_EQ(NULL, w->GetProperty(kStringKey));
1543 w->SetProperty(kStringKey, "squeamish");
1544 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1545 w->SetProperty(kStringKey, "ossifrage");
1546 EXPECT_EQ(std::string("ossifrage"), w->GetProperty(kStringKey));
1548 w->SetNativeWindowProperty(native_prop_key, &*w);
1549 EXPECT_EQ(&*w, w->GetNativeWindowProperty(native_prop_key));
1550 w->SetNativeWindowProperty(native_prop_key, NULL);
1551 EXPECT_EQ(NULL, w->GetNativeWindowProperty(native_prop_key));
1553 // ClearProperty should restore the default value.
1554 w->ClearProperty(kIntKey);
1555 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1556 w->ClearProperty(kStringKey);
1557 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1562 class TestProperty {
1565 virtual ~TestProperty() {
1566 last_deleted_ = this;
1568 static TestProperty* last_deleted() { return last_deleted_; }
1571 static TestProperty* last_deleted_;
1572 DISALLOW_COPY_AND_ASSIGN(TestProperty);
1575 TestProperty* TestProperty::last_deleted_ = NULL;
1577 DEFINE_OWNED_WINDOW_PROPERTY_KEY(TestProperty, kOwnedKey, NULL);
1581 TEST_F(WindowTest, OwnedProperty) {
1582 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window()));
1583 EXPECT_EQ(NULL, w->GetProperty(kOwnedKey));
1584 TestProperty* p1 = new TestProperty();
1585 w->SetProperty(kOwnedKey, p1);
1586 EXPECT_EQ(p1, w->GetProperty(kOwnedKey));
1587 EXPECT_EQ(NULL, TestProperty::last_deleted());
1589 TestProperty* p2 = new TestProperty();
1590 w->SetProperty(kOwnedKey, p2);
1591 EXPECT_EQ(p2, w->GetProperty(kOwnedKey));
1592 EXPECT_EQ(p1, TestProperty::last_deleted());
1594 w->ClearProperty(kOwnedKey);
1595 EXPECT_EQ(NULL, w->GetProperty(kOwnedKey));
1596 EXPECT_EQ(p2, TestProperty::last_deleted());
1598 TestProperty* p3 = new TestProperty();
1599 w->SetProperty(kOwnedKey, p3);
1600 EXPECT_EQ(p3, w->GetProperty(kOwnedKey));
1601 EXPECT_EQ(p2, TestProperty::last_deleted());
1603 EXPECT_EQ(p3, TestProperty::last_deleted());
1606 TEST_F(WindowTest, SetBoundsInternalShouldCheckTargetBounds) {
1607 // We cannot short-circuit animations in this test.
1608 ui::ScopedAnimationDurationScaleMode test_duration_mode(
1609 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
1611 scoped_ptr<Window> w1(
1612 CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), root_window()));
1614 EXPECT_FALSE(!w1->layer());
1615 w1->layer()->GetAnimator()->set_disable_timer_for_test(true);
1616 ui::LayerAnimator* animator = w1->layer()->GetAnimator();
1618 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1619 EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString());
1621 // Animate to a different position.
1623 ui::ScopedLayerAnimationSettings settings(w1->layer()->GetAnimator());
1624 w1->SetBounds(gfx::Rect(100, 100, 100, 100));
1627 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1628 EXPECT_EQ("100,100 100x100", w1->layer()->GetTargetBounds().ToString());
1630 // Animate back to the first position. The animation hasn't started yet, so
1631 // the current bounds are still (0, 0, 100, 100), but the target bounds are
1632 // (100, 100, 100, 100). If we step the animator ahead, we should find that
1633 // we're at (0, 0, 100, 100). That is, the second animation should be applied.
1635 ui::ScopedLayerAnimationSettings settings(w1->layer()->GetAnimator());
1636 w1->SetBounds(gfx::Rect(0, 0, 100, 100));
1639 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1640 EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString());
1642 // Confirm that the target bounds are reached.
1643 base::TimeTicks start_time =
1644 w1->layer()->GetAnimator()->last_step_time();
1646 animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
1648 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1652 typedef std::pair<const void*, intptr_t> PropertyChangeInfo;
1654 class WindowObserverTest : public WindowTest,
1655 public WindowObserver {
1657 struct VisibilityInfo {
1658 bool window_visible;
1663 WindowObserverTest()
1666 destroyed_count_(0),
1667 old_property_value_(-3) {
1670 ~WindowObserverTest() override {}
1672 const VisibilityInfo* GetVisibilityInfo() const {
1673 return visibility_info_.get();
1676 void ResetVisibilityInfo() {
1677 visibility_info_.reset();
1680 // Returns a description of the WindowObserver methods that have been invoked.
1681 std::string WindowObserverCountStateAndClear() {
1683 base::StringPrintf("added=%d removed=%d",
1684 added_count_, removed_count_));
1685 added_count_ = removed_count_ = 0;
1689 int DestroyedCountAndClear() {
1690 int result = destroyed_count_;
1691 destroyed_count_ = 0;
1695 // Return a tuple of the arguments passed in OnPropertyChanged callback.
1696 PropertyChangeInfo PropertyChangeInfoAndClear() {
1697 PropertyChangeInfo result(property_key_, old_property_value_);
1698 property_key_ = NULL;
1699 old_property_value_ = -3;
1703 std::string TransformNotificationsAndClear() {
1705 for (std::vector<std::pair<int, int> >::iterator it =
1706 transform_notifications_.begin();
1707 it != transform_notifications_.end();
1709 base::StringAppendF(&result, "(%d,%d)", it->first, it->second);
1711 transform_notifications_.clear();
1716 void OnWindowAdded(Window* new_window) override { added_count_++; }
1718 void OnWillRemoveWindow(Window* window) override { removed_count_++; }
1720 void OnWindowVisibilityChanged(Window* window, bool visible) override {
1721 if (!visibility_info_) {
1722 visibility_info_.reset(new VisibilityInfo);
1723 visibility_info_->changed_count = 0;
1725 visibility_info_->window_visible = window->IsVisible();
1726 visibility_info_->visible_param = visible;
1727 visibility_info_->changed_count++;
1730 void OnWindowDestroyed(Window* window) override {
1731 EXPECT_FALSE(window->parent());
1735 void OnWindowPropertyChanged(Window* window,
1737 intptr_t old) override {
1738 property_key_ = key;
1739 old_property_value_ = old;
1742 void OnAncestorWindowTransformed(Window* source, Window* window) override {
1743 transform_notifications_.push_back(
1744 std::make_pair(source->id(), window->id()));
1749 int destroyed_count_;
1750 scoped_ptr<VisibilityInfo> visibility_info_;
1751 const void* property_key_;
1752 intptr_t old_property_value_;
1753 std::vector<std::pair<int, int> > transform_notifications_;
1755 DISALLOW_COPY_AND_ASSIGN(WindowObserverTest);
1758 // Various assertions for WindowObserver.
1759 TEST_F(WindowObserverTest, WindowObserver) {
1760 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1761 w1->AddObserver(this);
1763 // Create a new window as a child of w1, our observer should be notified.
1764 scoped_ptr<Window> w2(CreateTestWindowWithId(2, w1.get()));
1765 EXPECT_EQ("added=1 removed=0", WindowObserverCountStateAndClear());
1767 // Delete w2, which should result in the remove notification.
1769 EXPECT_EQ("added=0 removed=1", WindowObserverCountStateAndClear());
1771 // Create a window that isn't parented to w1, we shouldn't get any
1773 scoped_ptr<Window> w3(CreateTestWindowWithId(3, root_window()));
1774 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1776 // Similarly destroying w3 shouldn't notify us either.
1778 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1779 w1->RemoveObserver(this);
1782 // Test if OnWindowVisibilityChagned is invoked with expected
1784 TEST_F(WindowObserverTest, WindowVisibility) {
1785 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1786 scoped_ptr<Window> w2(CreateTestWindowWithId(1, w1.get()));
1787 w2->AddObserver(this);
1789 // Hide should make the window invisible and the passed visible
1790 // parameter is false.
1792 EXPECT_FALSE(!GetVisibilityInfo());
1793 EXPECT_FALSE(!GetVisibilityInfo());
1794 if (!GetVisibilityInfo())
1796 EXPECT_FALSE(GetVisibilityInfo()->window_visible);
1797 EXPECT_FALSE(GetVisibilityInfo()->visible_param);
1798 EXPECT_EQ(1, GetVisibilityInfo()->changed_count);
1800 // If parent isn't visible, showing window won't make the window visible, but
1801 // passed visible value must be true.
1803 ResetVisibilityInfo();
1804 EXPECT_TRUE(!GetVisibilityInfo());
1806 EXPECT_FALSE(!GetVisibilityInfo());
1807 if (!GetVisibilityInfo())
1809 EXPECT_FALSE(GetVisibilityInfo()->window_visible);
1810 EXPECT_TRUE(GetVisibilityInfo()->visible_param);
1811 EXPECT_EQ(1, GetVisibilityInfo()->changed_count);
1813 // If parent is visible, showing window will make the window
1814 // visible and the passed visible value is true.
1817 ResetVisibilityInfo();
1819 EXPECT_FALSE(!GetVisibilityInfo());
1820 if (!GetVisibilityInfo())
1822 EXPECT_TRUE(GetVisibilityInfo()->window_visible);
1823 EXPECT_TRUE(GetVisibilityInfo()->visible_param);
1824 EXPECT_EQ(1, GetVisibilityInfo()->changed_count);
1826 // Verify that the OnWindowVisibilityChanged only once
1827 // per visibility change.
1829 EXPECT_EQ(2, GetVisibilityInfo()->changed_count);
1832 EXPECT_EQ(2, GetVisibilityInfo()->changed_count);
1835 // Test if OnWindowDestroyed is invoked as expected.
1836 TEST_F(WindowObserverTest, WindowDestroyed) {
1837 // Delete a window should fire a destroyed notification.
1838 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1839 w1->AddObserver(this);
1841 EXPECT_EQ(1, DestroyedCountAndClear());
1843 // Observe on child and delete parent window should fire a notification.
1844 scoped_ptr<Window> parent(CreateTestWindowWithId(1, root_window()));
1845 Window* child = CreateTestWindowWithId(1, parent.get()); // owned by parent
1846 child->AddObserver(this);
1848 EXPECT_EQ(1, DestroyedCountAndClear());
1851 TEST_F(WindowObserverTest, PropertyChanged) {
1852 // Setting property should fire a property change notification.
1853 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1854 w1->AddObserver(this);
1856 static const WindowProperty<int> prop = {-2};
1857 static const char native_prop_key[] = "fnord";
1859 w1->SetProperty(&prop, 1);
1860 EXPECT_EQ(PropertyChangeInfo(&prop, -2), PropertyChangeInfoAndClear());
1861 w1->SetProperty(&prop, -2);
1862 EXPECT_EQ(PropertyChangeInfo(&prop, 1), PropertyChangeInfoAndClear());
1863 w1->SetProperty(&prop, 3);
1864 EXPECT_EQ(PropertyChangeInfo(&prop, -2), PropertyChangeInfoAndClear());
1865 w1->ClearProperty(&prop);
1866 EXPECT_EQ(PropertyChangeInfo(&prop, 3), PropertyChangeInfoAndClear());
1868 w1->SetNativeWindowProperty(native_prop_key, &*w1);
1869 EXPECT_EQ(PropertyChangeInfo(native_prop_key, 0),
1870 PropertyChangeInfoAndClear());
1871 w1->SetNativeWindowProperty(native_prop_key, NULL);
1872 EXPECT_EQ(PropertyChangeInfo(native_prop_key,
1873 reinterpret_cast<intptr_t>(&*w1)),
1874 PropertyChangeInfoAndClear());
1876 // Sanity check to see if |PropertyChangeInfoAndClear| really clears.
1877 EXPECT_EQ(PropertyChangeInfo(
1878 reinterpret_cast<const void*>(NULL), -3), PropertyChangeInfoAndClear());
1881 TEST_F(WindowObserverTest, AncestorTransformed) {
1882 // Create following window hierarchy:
1888 // Then, apply a transform to |w1| and ensure all its descendants are
1890 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1891 w1->AddObserver(this);
1892 scoped_ptr<Window> w2(CreateTestWindowWithId(2, w1.get()));
1893 w2->AddObserver(this);
1894 scoped_ptr<Window> w3(CreateTestWindowWithId(3, w1.get()));
1895 w3->AddObserver(this);
1896 scoped_ptr<Window> w4(CreateTestWindowWithId(4, w3.get()));
1897 w4->AddObserver(this);
1899 EXPECT_EQ(std::string(), TransformNotificationsAndClear());
1901 gfx::Transform transform;
1902 transform.Translate(10, 10);
1903 w1->SetTransform(transform);
1905 EXPECT_EQ("(1,1)(1,2)(1,3)(1,4)", TransformNotificationsAndClear());
1908 TEST_F(WindowTest, AcquireLayer) {
1909 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
1910 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
1911 ui::Layer* parent = window1->parent()->layer();
1912 EXPECT_EQ(2U, parent->children().size());
1914 WindowTestApi window1_test_api(window1.get());
1915 WindowTestApi window2_test_api(window2.get());
1917 EXPECT_TRUE(window1_test_api.OwnsLayer());
1918 EXPECT_TRUE(window2_test_api.OwnsLayer());
1920 // After acquisition, window1 should not own its layer, but it should still
1921 // be available to the window.
1922 scoped_ptr<ui::Layer> window1_layer(window1->AcquireLayer());
1923 EXPECT_FALSE(window1_test_api.OwnsLayer());
1924 EXPECT_TRUE(window1_layer.get() == window1->layer());
1926 // The acquired layer's owner should be set NULL and re-acquring
1927 // should return NULL.
1928 EXPECT_FALSE(window1_layer->owner());
1929 scoped_ptr<ui::Layer> window1_layer_reacquired(window1->AcquireLayer());
1930 EXPECT_FALSE(window1_layer_reacquired.get());
1932 // Upon destruction, window1's layer should still be valid, and in the layer
1933 // hierarchy, but window2's should be gone, and no longer in the hierarchy.
1937 // This should be set by the window's destructor.
1938 EXPECT_TRUE(window1_layer->delegate() == NULL);
1939 EXPECT_EQ(1U, parent->children().size());
1942 // Make sure that properties which should persist from the old layer to the new
1943 // layer actually do.
1944 TEST_F(WindowTest, RecreateLayer) {
1945 // Set properties to non default values.
1946 Window w(new ColorTestWindowDelegate(SK_ColorWHITE));
1948 w.Init(aura::WINDOW_LAYER_SOLID_COLOR);
1949 w.SetBounds(gfx::Rect(0, 0, 100, 100));
1951 ui::Layer* layer = w.layer();
1952 layer->SetVisible(false);
1953 layer->SetMasksToBounds(true);
1955 ui::Layer child_layer;
1956 layer->Add(&child_layer);
1958 scoped_ptr<ui::Layer> old_layer(w.RecreateLayer());
1960 EXPECT_EQ(ui::LAYER_SOLID_COLOR, layer->type());
1961 EXPECT_FALSE(layer->visible());
1962 EXPECT_EQ(1u, layer->children().size());
1963 EXPECT_TRUE(layer->GetMasksToBounds());
1964 EXPECT_EQ("0,0 100x100", w.bounds().ToString());
1965 EXPECT_EQ("0,0 100x100", layer->bounds().ToString());
1968 // Verify that RecreateLayer() stacks the old layer above the newly creatd
1970 TEST_F(WindowTest, RecreateLayerZOrder) {
1971 scoped_ptr<Window> w(
1972 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(0, 0, 100, 100),
1974 scoped_ptr<ui::Layer> old_layer(w->RecreateLayer());
1976 const std::vector<ui::Layer*>& child_layers =
1977 root_window()->layer()->children();
1978 ASSERT_EQ(2u, child_layers.size());
1979 EXPECT_EQ(w->layer(), child_layers[0]);
1980 EXPECT_EQ(old_layer.get(), child_layers[1]);
1983 // Ensure that acquiring a layer then recreating a layer does not crash
1984 // and that RecreateLayer returns null.
1985 TEST_F(WindowTest, AcquireThenRecreateLayer) {
1986 scoped_ptr<Window> w(
1987 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(0, 0, 100, 100),
1989 scoped_ptr<ui::Layer> acquired_layer(w->AcquireLayer());
1990 scoped_ptr<ui::Layer> doubly_acquired_layer(w->RecreateLayer());
1991 EXPECT_EQ(NULL, doubly_acquired_layer.get());
1993 // Destroy window before layer gets destroyed.
1997 TEST_F(WindowTest, StackWindowAtBottomBelowWindowWhoseLayerHasNoDelegate) {
1998 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
1999 window1->layer()->set_name("1");
2000 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
2001 window2->layer()->set_name("2");
2002 scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window()));
2003 window3->layer()->set_name("3");
2005 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(root_window()));
2007 ui::test::ChildLayerNamesAsString(*root_window()->layer()));
2008 window1->layer()->set_delegate(NULL);
2009 root_window()->StackChildAtBottom(window3.get());
2011 // Window 3 should have moved to the bottom.
2012 EXPECT_EQ("3 1 2", ChildWindowIDsAsString(root_window()));
2014 ui::test::ChildLayerNamesAsString(*root_window()->layer()));
2017 class TestVisibilityClient : public client::VisibilityClient {
2019 explicit TestVisibilityClient(Window* root_window)
2020 : ignore_visibility_changes_(false) {
2021 client::SetVisibilityClient(root_window, this);
2023 ~TestVisibilityClient() override {}
2025 void set_ignore_visibility_changes(bool ignore_visibility_changes) {
2026 ignore_visibility_changes_ = ignore_visibility_changes;
2029 // Overridden from client::VisibilityClient:
2030 void UpdateLayerVisibility(aura::Window* window, bool visible) override {
2031 if (!ignore_visibility_changes_)
2032 window->layer()->SetVisible(visible);
2036 bool ignore_visibility_changes_;
2037 DISALLOW_COPY_AND_ASSIGN(TestVisibilityClient);
2040 TEST_F(WindowTest, VisibilityClientIsVisible) {
2041 TestVisibilityClient client(root_window());
2043 scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window()));
2044 EXPECT_TRUE(window->IsVisible());
2045 EXPECT_TRUE(window->layer()->visible());
2048 EXPECT_FALSE(window->IsVisible());
2049 EXPECT_FALSE(window->layer()->visible());
2052 client.set_ignore_visibility_changes(true);
2054 EXPECT_FALSE(window->IsVisible());
2055 EXPECT_TRUE(window->layer()->visible());
2058 // Tests mouse events on window change.
2059 TEST_F(WindowTest, MouseEventsOnWindowChange) {
2060 gfx::Size size = host()->GetBounds().size();
2062 ui::test::EventGenerator generator(root_window());
2063 generator.MoveMouseTo(50, 50);
2065 EventCountDelegate d1;
2066 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(&d1, 1,
2067 gfx::Rect(0, 0, 100, 100), root_window()));
2068 RunAllPendingInMessageLoop();
2069 // The format of result is "Enter/Mouse/Leave".
2070 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2072 // Adding new window.
2073 EventCountDelegate d11;
2074 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(
2075 &d11, 1, gfx::Rect(0, 0, 100, 100), w1.get()));
2076 RunAllPendingInMessageLoop();
2077 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2078 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2081 w11->SetBounds(gfx::Rect(0, 0, 10, 10));
2082 RunAllPendingInMessageLoop();
2083 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2084 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2086 w11->SetBounds(gfx::Rect(0, 0, 60, 60));
2087 RunAllPendingInMessageLoop();
2088 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2089 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2091 // Detach, then re-attach.
2092 w1->RemoveChild(w11.get());
2093 RunAllPendingInMessageLoop();
2094 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2095 // Window is detached, so no event is set.
2096 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2098 w1->AddChild(w11.get());
2099 RunAllPendingInMessageLoop();
2100 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2101 // Window is detached, so no event is set.
2102 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2104 // Visibility Change
2106 RunAllPendingInMessageLoop();
2107 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2108 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2111 RunAllPendingInMessageLoop();
2112 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2113 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2115 // Transform: move d11 by 100 100.
2116 gfx::Transform transform;
2117 transform.Translate(100, 100);
2118 w11->SetTransform(transform);
2119 RunAllPendingInMessageLoop();
2120 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2121 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2123 w11->SetTransform(gfx::Transform());
2124 RunAllPendingInMessageLoop();
2125 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2126 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2128 // Closing a window.
2130 RunAllPendingInMessageLoop();
2131 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2133 // Make sure we don't synthesize events if the mouse
2134 // is outside of the root window.
2135 generator.MoveMouseTo(-10, -10);
2136 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2138 // Adding new windows.
2139 w11.reset(CreateTestWindowWithDelegate(
2140 &d11, 1, gfx::Rect(0, 0, 100, 100), w1.get()));
2141 RunAllPendingInMessageLoop();
2142 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset());
2143 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2147 RunAllPendingInMessageLoop();
2148 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset());
2149 EXPECT_EQ("0 0 0", d11.GetMouseMotionCountsAndReset());
2152 class RootWindowAttachmentObserver : public WindowObserver {
2154 RootWindowAttachmentObserver() : added_count_(0), removed_count_(0) {}
2155 ~RootWindowAttachmentObserver() override {}
2157 int added_count() const { return added_count_; }
2158 int removed_count() const { return removed_count_; }
2165 // Overridden from WindowObserver:
2166 void OnWindowAddedToRootWindow(Window* window) override { ++added_count_; }
2167 void OnWindowRemovingFromRootWindow(Window* window,
2168 Window* new_root) override {
2176 DISALLOW_COPY_AND_ASSIGN(RootWindowAttachmentObserver);
2179 TEST_F(WindowTest, RootWindowAttachment) {
2180 RootWindowAttachmentObserver observer;
2182 // Test a direct add/remove from the RootWindow.
2183 scoped_ptr<Window> w1(new Window(NULL));
2184 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2185 w1->AddObserver(&observer);
2187 ParentWindow(w1.get());
2188 EXPECT_EQ(1, observer.added_count());
2189 EXPECT_EQ(0, observer.removed_count());
2192 EXPECT_EQ(1, observer.added_count());
2193 EXPECT_EQ(1, observer.removed_count());
2197 // Test an indirect add/remove from the RootWindow.
2198 w1.reset(new Window(NULL));
2199 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2200 Window* w11 = new Window(NULL);
2201 w11->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2202 w11->AddObserver(&observer);
2204 EXPECT_EQ(0, observer.added_count());
2205 EXPECT_EQ(0, observer.removed_count());
2207 ParentWindow(w1.get());
2208 EXPECT_EQ(1, observer.added_count());
2209 EXPECT_EQ(0, observer.removed_count());
2211 w1.reset(); // Deletes w11.
2213 EXPECT_EQ(1, observer.added_count());
2214 EXPECT_EQ(1, observer.removed_count());
2218 // Test an indirect add/remove with nested observers.
2219 w1.reset(new Window(NULL));
2220 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2221 w11 = new Window(NULL);
2222 w11->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2223 w11->AddObserver(&observer);
2225 Window* w111 = new Window(NULL);
2226 w111->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2227 w111->AddObserver(&observer);
2228 w11->AddChild(w111);
2230 EXPECT_EQ(0, observer.added_count());
2231 EXPECT_EQ(0, observer.removed_count());
2233 ParentWindow(w1.get());
2234 EXPECT_EQ(2, observer.added_count());
2235 EXPECT_EQ(0, observer.removed_count());
2237 w1.reset(); // Deletes w11 and w111.
2240 EXPECT_EQ(2, observer.added_count());
2241 EXPECT_EQ(2, observer.removed_count());
2244 class BoundsChangedWindowObserver : public WindowObserver {
2246 BoundsChangedWindowObserver() : root_set_(false) {}
2248 void OnWindowBoundsChanged(Window* window,
2249 const gfx::Rect& old_bounds,
2250 const gfx::Rect& new_bounds) override {
2251 root_set_ = window->GetRootWindow() != NULL;
2254 bool root_set() const { return root_set_; }
2259 DISALLOW_COPY_AND_ASSIGN(BoundsChangedWindowObserver);
2262 TEST_F(WindowTest, RootWindowSetWhenReparenting) {
2263 Window parent1(NULL);
2264 parent1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2265 Window parent2(NULL);
2266 parent2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2267 ParentWindow(&parent1);
2268 ParentWindow(&parent2);
2269 parent1.SetBounds(gfx::Rect(10, 10, 300, 300));
2270 parent2.SetBounds(gfx::Rect(20, 20, 300, 300));
2272 BoundsChangedWindowObserver observer;
2274 child.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2275 child.SetBounds(gfx::Rect(5, 5, 100, 100));
2276 parent1.AddChild(&child);
2278 // We need animations to start in order to observe the bounds changes.
2279 ui::ScopedAnimationDurationScaleMode test_duration_mode(
2280 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2281 ui::ScopedLayerAnimationSettings settings1(child.layer()->GetAnimator());
2282 settings1.SetTransitionDuration(base::TimeDelta::FromMilliseconds(100));
2283 gfx::Rect new_bounds(gfx::Rect(35, 35, 50, 50));
2284 child.SetBounds(new_bounds);
2286 child.AddObserver(&observer);
2288 // Reparenting the |child| will cause it to get moved. During this move
2289 // the window should still have root window set.
2290 parent2.AddChild(&child);
2291 EXPECT_TRUE(observer.root_set());
2293 // Animations should stop and the bounds should be as set before the |child|
2295 EXPECT_EQ(new_bounds.ToString(), child.GetTargetBounds().ToString());
2296 EXPECT_EQ(new_bounds.ToString(), child.bounds().ToString());
2297 EXPECT_EQ("55,55 50x50", child.GetBoundsInRootWindow().ToString());
2300 TEST_F(WindowTest, OwnedByParentFalse) {
2301 // By default, a window is owned by its parent. If this is set to false, the
2302 // window will not be destroyed when its parent is.
2304 scoped_ptr<Window> w1(new Window(NULL));
2305 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2306 scoped_ptr<Window> w2(new Window(NULL));
2307 w2->set_owned_by_parent(false);
2308 w2->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2309 w1->AddChild(w2.get());
2313 // We should be able to deref w2 still, but its parent should now be NULL.
2314 EXPECT_EQ(NULL, w2->parent());
2319 // Used By DeleteWindowFromOnWindowDestroyed. Destroys a Window from
2320 // OnWindowDestroyed().
2321 class OwningWindowDelegate : public TestWindowDelegate {
2323 OwningWindowDelegate() {}
2325 void SetOwnedWindow(Window* window) {
2326 owned_window_.reset(window);
2329 void OnWindowDestroyed(Window* window) override { owned_window_.reset(NULL); }
2332 scoped_ptr<Window> owned_window_;
2334 DISALLOW_COPY_AND_ASSIGN(OwningWindowDelegate);
2339 // Creates a window with two child windows. When the first child window is
2340 // destroyed (WindowDelegate::OnWindowDestroyed) it deletes the second child.
2341 // This synthesizes BrowserView and the status bubble. Both are children of the
2342 // same parent and destroying BrowserView triggers it destroying the status
2344 TEST_F(WindowTest, DeleteWindowFromOnWindowDestroyed) {
2345 scoped_ptr<Window> parent(new Window(NULL));
2346 parent->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2347 OwningWindowDelegate delegate;
2348 Window* c1 = new Window(&delegate);
2349 c1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2350 parent->AddChild(c1);
2351 Window* c2 = new Window(NULL);
2352 c2->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2353 parent->AddChild(c2);
2354 delegate.SetOwnedWindow(c2);
2360 // Used by DelegateNotifiedAsBoundsChange to verify OnBoundsChanged() is
2362 class BoundsChangeDelegate : public TestWindowDelegate {
2364 BoundsChangeDelegate() : bounds_changed_(false) {}
2366 void clear_bounds_changed() { bounds_changed_ = false; }
2367 bool bounds_changed() const {
2368 return bounds_changed_;
2372 void OnBoundsChanged(const gfx::Rect& old_bounds,
2373 const gfx::Rect& new_bounds) override {
2374 bounds_changed_ = true;
2378 // Was OnBoundsChanged() invoked?
2379 bool bounds_changed_;
2381 DISALLOW_COPY_AND_ASSIGN(BoundsChangeDelegate);
2386 // Verifies the delegate is notified when the actual bounds of the layer
2388 TEST_F(WindowTest, DelegateNotifiedAsBoundsChange) {
2389 BoundsChangeDelegate delegate;
2391 // We cannot short-circuit animations in this test.
2392 ui::ScopedAnimationDurationScaleMode test_duration_mode(
2393 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2395 scoped_ptr<Window> window(
2396 CreateTestWindowWithDelegate(&delegate, 1,
2397 gfx::Rect(0, 0, 100, 100), root_window()));
2398 window->layer()->GetAnimator()->set_disable_timer_for_test(true);
2400 delegate.clear_bounds_changed();
2402 // Animate to a different position.
2404 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
2405 window->SetBounds(gfx::Rect(100, 100, 100, 100));
2408 // Bounds shouldn't immediately have changed.
2409 EXPECT_EQ("0,0 100x100", window->bounds().ToString());
2410 EXPECT_FALSE(delegate.bounds_changed());
2412 // Animate to the end, which should notify of the change.
2413 base::TimeTicks start_time =
2414 window->layer()->GetAnimator()->last_step_time();
2415 ui::LayerAnimator* animator = window->layer()->GetAnimator();
2416 animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
2417 EXPECT_TRUE(delegate.bounds_changed());
2418 EXPECT_NE("0,0 100x100", window->bounds().ToString());
2421 // Verifies the delegate is notified when the actual bounds of the layer
2422 // change even when the window is not the layer's delegate
2423 TEST_F(WindowTest, DelegateNotifiedAsBoundsChangeInHiddenLayer) {
2424 BoundsChangeDelegate delegate;
2426 // We cannot short-circuit animations in this test.
2427 ui::ScopedAnimationDurationScaleMode test_duration_mode(
2428 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2430 scoped_ptr<Window> window(
2431 CreateTestWindowWithDelegate(&delegate, 1,
2432 gfx::Rect(0, 0, 100, 100), root_window()));
2433 window->layer()->GetAnimator()->set_disable_timer_for_test(true);
2435 delegate.clear_bounds_changed();
2437 // Suppress paint on the window since it is hidden (should reset the layer's
2438 // delegate to NULL)
2439 window->SuppressPaint();
2440 EXPECT_EQ(NULL, window->layer()->delegate());
2442 // Animate to a different position.
2444 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
2445 window->SetBounds(gfx::Rect(100, 100, 110, 100));
2448 // Layer delegate is NULL but we should still get bounds changed notification.
2449 EXPECT_EQ("100,100 110x100", window->GetTargetBounds().ToString());
2450 EXPECT_TRUE(delegate.bounds_changed());
2452 delegate.clear_bounds_changed();
2454 // Animate to the end: will *not* notify of the change since we are hidden.
2455 base::TimeTicks start_time =
2456 window->layer()->GetAnimator()->last_step_time();
2457 ui::LayerAnimator* animator = window->layer()->GetAnimator();
2458 animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
2460 // No bounds changed notification at the end of animation since layer
2461 // delegate is NULL.
2462 EXPECT_FALSE(delegate.bounds_changed());
2463 EXPECT_NE("0,0 100x100", window->layer()->bounds().ToString());
2468 // Used by AddChildNotifications to track notification counts.
2469 class AddChildNotificationsObserver : public WindowObserver {
2471 AddChildNotificationsObserver() : added_count_(0), removed_count_(0) {}
2473 std::string CountStringAndReset() {
2474 std::string result = base::IntToString(added_count_) + " " +
2475 base::IntToString(removed_count_);
2476 added_count_ = removed_count_ = 0;
2480 // WindowObserver overrides:
2481 void OnWindowAddedToRootWindow(Window* window) override { added_count_++; }
2482 void OnWindowRemovingFromRootWindow(Window* window,
2483 Window* new_root) override {
2491 DISALLOW_COPY_AND_ASSIGN(AddChildNotificationsObserver);
2496 // Assertions around when root window notifications are sent.
2497 TEST_F(WindowTest, AddChildNotifications) {
2498 AddChildNotificationsObserver observer;
2499 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
2500 scoped_ptr<Window> w2(CreateTestWindowWithId(1, root_window()));
2501 w2->AddObserver(&observer);
2503 EXPECT_TRUE(w2->HasFocus());
2505 // Move |w2| to be a child of |w1|.
2506 w1->AddChild(w2.get());
2507 // Sine we moved in the same root, observer shouldn't be notified.
2508 EXPECT_EQ("0 0", observer.CountStringAndReset());
2509 // |w2| should still have focus after moving.
2510 EXPECT_TRUE(w2->HasFocus());
2513 // Tests that a delegate that destroys itself when the window is destroyed does
2515 TEST_F(WindowTest, DelegateDestroysSelfOnWindowDestroy) {
2516 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
2517 new DestroyWindowDelegate(),
2519 gfx::Rect(10, 20, 30, 40),
2523 class HierarchyObserver : public WindowObserver {
2525 HierarchyObserver(Window* target) : target_(target) {
2526 target_->AddObserver(this);
2528 ~HierarchyObserver() override { target_->RemoveObserver(this); }
2532 const WindowObserver::HierarchyChangeParams& params) const {
2533 ParamsMatch(params_[index], params);
2541 // Overridden from WindowObserver:
2542 void OnWindowHierarchyChanging(const HierarchyChangeParams& params) override {
2543 params_.push_back(params);
2545 void OnWindowHierarchyChanged(const HierarchyChangeParams& params) override {
2546 params_.push_back(params);
2549 void ParamsMatch(const WindowObserver::HierarchyChangeParams& p1,
2550 const WindowObserver::HierarchyChangeParams& p2) const {
2551 EXPECT_EQ(p1.phase, p2.phase);
2552 EXPECT_EQ(p1.target, p2.target);
2553 EXPECT_EQ(p1.new_parent, p2.new_parent);
2554 EXPECT_EQ(p1.old_parent, p2.old_parent);
2555 EXPECT_EQ(p1.receiver, p2.receiver);
2559 std::vector<WindowObserver::HierarchyChangeParams> params_;
2561 DISALLOW_COPY_AND_ASSIGN(HierarchyObserver);
2564 // Tests hierarchy change notifications.
2565 TEST_F(WindowTest, OnWindowHierarchyChange) {
2567 // Simple add & remove.
2568 HierarchyObserver oroot(root_window());
2570 scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL));
2571 HierarchyObserver o1(w1.get());
2574 root_window()->AddChild(w1.get());
2576 WindowObserver::HierarchyChangeParams params;
2577 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2578 params.target = w1.get();
2579 params.old_parent = NULL;
2580 params.new_parent = root_window();
2581 params.receiver = w1.get();
2582 o1.ValidateState(0, params);
2584 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2585 params.receiver = w1.get();
2586 o1.ValidateState(1, params);
2588 params.receiver = root_window();
2589 oroot.ValidateState(0, params);
2595 root_window()->RemoveChild(w1.get());
2597 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2598 params.old_parent = root_window();
2599 params.new_parent = NULL;
2600 params.receiver = w1.get();
2602 o1.ValidateState(0, params);
2604 params.receiver = root_window();
2605 oroot.ValidateState(0, params);
2607 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2608 params.receiver = w1.get();
2609 o1.ValidateState(1, params);
2613 // Add & remove of hierarchy. Tests notification order per documentation in
2615 HierarchyObserver o(root_window());
2616 scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL));
2617 Window* w11 = CreateTestWindowWithId(11, w1.get());
2618 w1->AddObserver(&o);
2619 w11->AddObserver(&o);
2622 root_window()->AddChild(w1.get());
2624 // Dispatched to target first.
2626 WindowObserver::HierarchyChangeParams params;
2627 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2628 params.target = w1.get();
2629 params.old_parent = NULL;
2630 params.new_parent = root_window();
2631 params.receiver = w1.get();
2632 o.ValidateState(index++, params);
2634 // Dispatched to target's children.
2635 params.receiver = w11;
2636 o.ValidateState(index++, params);
2638 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2640 // Now process the "changed" phase.
2641 params.receiver = w1.get();
2642 o.ValidateState(index++, params);
2643 params.receiver = w11;
2644 o.ValidateState(index++, params);
2645 params.receiver = root_window();
2646 o.ValidateState(index++, params);
2649 root_window()->RemoveChild(w1.get());
2650 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2651 params.old_parent = root_window();
2652 params.new_parent = NULL;
2653 params.receiver = w1.get();
2654 o.ValidateState(index++, params);
2655 params.receiver = w11;
2656 o.ValidateState(index++, params);
2657 params.receiver = root_window();
2658 o.ValidateState(index++, params);
2659 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2660 params.receiver = w1.get();
2661 o.ValidateState(index++, params);
2662 params.receiver = w11;
2663 o.ValidateState(index++, params);
2669 // Reparent. Tests notification order per documentation in WindowObserver.
2670 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
2671 Window* w11 = CreateTestWindowWithId(11, w1.get());
2672 Window* w111 = CreateTestWindowWithId(111, w11);
2673 scoped_ptr<Window> w2(CreateTestWindowWithId(2, root_window()));
2675 HierarchyObserver o(root_window());
2676 w1->AddObserver(&o);
2677 w11->AddObserver(&o);
2678 w111->AddObserver(&o);
2679 w2->AddObserver(&o);
2683 // Dispatched to target first.
2685 WindowObserver::HierarchyChangeParams params;
2686 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2687 params.target = w11;
2688 params.old_parent = w1.get();
2689 params.new_parent = w2.get();
2690 params.receiver = w11;
2691 o.ValidateState(index++, params);
2693 // Then to target's children.
2694 params.receiver = w111;
2695 o.ValidateState(index++, params);
2697 // Then to target's old parent chain.
2698 params.receiver = w1.get();
2699 o.ValidateState(index++, params);
2700 params.receiver = root_window();
2701 o.ValidateState(index++, params);
2704 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2705 params.receiver = w11;
2706 o.ValidateState(index++, params);
2707 params.receiver = w111;
2708 o.ValidateState(index++, params);
2709 params.receiver = w2.get();
2710 o.ValidateState(index++, params);
2711 params.receiver = root_window();
2712 o.ValidateState(index++, params);
2720 // Verifies SchedulePaint() on a layerless window results in damaging the right
2722 TEST_F(WindowTest, LayerlessWindowSchedulePaint) {
2724 root.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2725 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2727 Window* layerless_window = new Window(NULL); // Owned by |root|.
2728 layerless_window->Init(WINDOW_LAYER_NONE);
2729 layerless_window->SetBounds(gfx::Rect(10, 11, 12, 13));
2730 root.AddChild(layerless_window);
2732 root.layer()->SendDamagedRects();
2733 layerless_window->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4));
2734 // Note the the region is clipped by the parent hence 100 going to 11.
2735 EXPECT_EQ("11,13 11x4",
2736 gfx::SkIRectToRect(root.layer()->damaged_region().getBounds()).
2739 Window* layerless_window2 = new Window(NULL); // Owned by |layerless_window|.
2740 layerless_window2->Init(WINDOW_LAYER_NONE);
2741 layerless_window2->SetBounds(gfx::Rect(1, 2, 3, 4));
2742 layerless_window->AddChild(layerless_window2);
2744 root.layer()->SendDamagedRects();
2745 layerless_window2->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4));
2746 // Note the the region is clipped by the |layerless_window| hence 100 going to
2748 EXPECT_EQ("12,15 2x2",
2749 gfx::SkIRectToRect(root.layer()->damaged_region().getBounds()).
2753 // Verifies bounds of layerless windows are correctly updated when adding
2755 TEST_F(WindowTest, NestedLayerlessWindowsBoundsOnAddRemove) {
2756 // Creates the following structure (all children owned by root):
2764 // ll: layer less, eg no layer
2766 root.Init(WINDOW_LAYER_NOT_DRAWN);
2767 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2769 Window* w1ll = new Window(NULL);
2770 w1ll->Init(WINDOW_LAYER_NONE);
2771 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
2773 Window* w11ll = new Window(NULL);
2774 w11ll->Init(WINDOW_LAYER_NONE);
2775 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
2776 w1ll->AddChild(w11ll);
2778 Window* w111 = new Window(NULL);
2779 w111->Init(WINDOW_LAYER_NOT_DRAWN);
2780 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2781 w11ll->AddChild(w111);
2783 Window* w12 = new Window(NULL);
2784 w12->Init(WINDOW_LAYER_NOT_DRAWN);
2785 w12->SetBounds(gfx::Rect(7, 8, 100, 100));
2786 w1ll->AddChild(w12);
2788 Window* w121 = new Window(NULL);
2789 w121->Init(WINDOW_LAYER_NOT_DRAWN);
2790 w121->SetBounds(gfx::Rect(9, 10, 100, 100));
2791 w12->AddChild(w121);
2793 root.AddChild(w1ll);
2795 // All layers should be parented to the root.
2796 EXPECT_EQ(root.layer(), w111->layer()->parent());
2797 EXPECT_EQ(root.layer(), w12->layer()->parent());
2798 EXPECT_EQ(w12->layer(), w121->layer()->parent());
2800 // Ensure bounds are what we expect.
2801 EXPECT_EQ("1,2 100x100", w1ll->bounds().ToString());
2802 EXPECT_EQ("3,4 100x100", w11ll->bounds().ToString());
2803 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2804 EXPECT_EQ("7,8 100x100", w12->bounds().ToString());
2805 EXPECT_EQ("9,10 100x100", w121->bounds().ToString());
2807 // Bounds of layers are relative to the nearest ancestor with a layer.
2808 EXPECT_EQ("8,10 100x100", w12->layer()->bounds().ToString());
2809 EXPECT_EQ("9,12 100x100", w111->layer()->bounds().ToString());
2810 EXPECT_EQ("9,10 100x100", w121->layer()->bounds().ToString());
2812 // Remove and repeat.
2813 root.RemoveChild(w1ll);
2815 EXPECT_TRUE(w111->layer()->parent() == NULL);
2816 EXPECT_TRUE(w12->layer()->parent() == NULL);
2818 // Verify bounds haven't changed again.
2819 EXPECT_EQ("1,2 100x100", w1ll->bounds().ToString());
2820 EXPECT_EQ("3,4 100x100", w11ll->bounds().ToString());
2821 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2822 EXPECT_EQ("7,8 100x100", w12->bounds().ToString());
2823 EXPECT_EQ("9,10 100x100", w121->bounds().ToString());
2825 // Bounds of layers should now match that of windows.
2826 EXPECT_EQ("7,8 100x100", w12->layer()->bounds().ToString());
2827 EXPECT_EQ("5,6 100x100", w111->layer()->bounds().ToString());
2828 EXPECT_EQ("9,10 100x100", w121->layer()->bounds().ToString());
2833 // Verifies bounds of layerless windows are correctly updated when bounds
2834 // of ancestor changes.
2835 TEST_F(WindowTest, NestedLayerlessWindowsBoundsOnSetBounds) {
2836 // Creates the following structure (all children owned by root):
2844 // ll: layer less, eg no layer
2846 root.Init(WINDOW_LAYER_NOT_DRAWN);
2847 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2849 Window* w1ll = new Window(NULL);
2850 w1ll->Init(WINDOW_LAYER_NONE);
2851 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
2853 Window* w11ll = new Window(NULL);
2854 w11ll->Init(WINDOW_LAYER_NONE);
2855 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
2856 w1ll->AddChild(w11ll);
2858 Window* w111 = new Window(NULL);
2859 w111->Init(WINDOW_LAYER_NOT_DRAWN);
2860 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2861 w11ll->AddChild(w111);
2863 Window* w12 = new Window(NULL);
2864 w12->Init(WINDOW_LAYER_NOT_DRAWN);
2865 w12->SetBounds(gfx::Rect(7, 8, 100, 100));
2866 w1ll->AddChild(w12);
2868 Window* w121 = new Window(NULL);
2869 w121->Init(WINDOW_LAYER_NOT_DRAWN);
2870 w121->SetBounds(gfx::Rect(9, 10, 100, 100));
2871 w12->AddChild(w121);
2873 root.AddChild(w1ll);
2875 w111->SetBounds(gfx::Rect(7, 8, 11, 12));
2876 EXPECT_EQ("7,8 11x12", w111->bounds().ToString());
2877 EXPECT_EQ("7,8 11x12", w111->GetTargetBounds().ToString());
2878 EXPECT_EQ("11,14 11x12", w111->layer()->bounds().ToString());
2881 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2882 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2883 EXPECT_EQ("5,6 100x100", w111->GetTargetBounds().ToString());
2884 EXPECT_EQ("9,12 100x100", w111->layer()->bounds().ToString());
2886 // Setting the bounds of a layerless window needs to adjust the bounds of
2887 // layered children.
2888 w11ll->SetBounds(gfx::Rect(5, 6, 100, 100));
2889 EXPECT_EQ("5,6 100x100", w11ll->bounds().ToString());
2890 EXPECT_EQ("5,6 100x100", w11ll->GetTargetBounds().ToString());
2891 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2892 EXPECT_EQ("5,6 100x100", w111->GetTargetBounds().ToString());
2893 EXPECT_EQ("11,14 100x100", w111->layer()->bounds().ToString());
2895 root.RemoveChild(w1ll);
2897 w111->SetBounds(gfx::Rect(7, 8, 11, 12));
2898 EXPECT_EQ("7,8 11x12", w111->bounds().ToString());
2899 EXPECT_EQ("7,8 11x12", w111->GetTargetBounds().ToString());
2900 EXPECT_EQ("7,8 11x12", w111->layer()->bounds().ToString());
2907 // Tracks the number of times paint is invoked along with what the clip and
2909 class PaintWindowDelegate : public TestWindowDelegate {
2911 PaintWindowDelegate() : paint_count_(0) {}
2912 ~PaintWindowDelegate() override {}
2914 const gfx::Rect& most_recent_paint_clip_bounds() const {
2915 return most_recent_paint_clip_bounds_;
2918 const gfx::Vector2d& most_recent_paint_matrix_offset() const {
2919 return most_recent_paint_matrix_offset_;
2922 void clear_paint_count() { paint_count_ = 0; }
2923 int paint_count() const { return paint_count_; }
2925 // TestWindowDelegate::
2926 void OnPaint(gfx::Canvas* canvas) override {
2928 canvas->GetClipBounds(&most_recent_paint_clip_bounds_);
2929 const SkMatrix& matrix = canvas->sk_canvas()->getTotalMatrix();
2930 most_recent_paint_matrix_offset_ = gfx::Vector2d(
2931 SkScalarFloorToInt(matrix.getTranslateX()),
2932 SkScalarFloorToInt(matrix.getTranslateY()));
2937 gfx::Rect most_recent_paint_clip_bounds_;
2938 gfx::Vector2d most_recent_paint_matrix_offset_;
2940 DISALLOW_COPY_AND_ASSIGN(PaintWindowDelegate);
2945 // Assertions around layerless children being painted when non-layerless window
2947 TEST_F(WindowTest, PaintLayerless) {
2948 // Creates the following structure (all children owned by root):
2954 // ll: layer less, eg no layer
2955 PaintWindowDelegate w1ll_delegate;
2956 PaintWindowDelegate w11ll_delegate;
2957 PaintWindowDelegate w111_delegate;
2960 root.Init(WINDOW_LAYER_NOT_DRAWN);
2961 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2963 Window* w1ll = new Window(&w1ll_delegate);
2964 w1ll->Init(WINDOW_LAYER_NONE);
2965 w1ll->SetBounds(gfx::Rect(1, 2, 40, 50));
2967 root.AddChild(w1ll);
2969 Window* w11ll = new Window(&w11ll_delegate);
2970 w11ll->Init(WINDOW_LAYER_NONE);
2971 w11ll->SetBounds(gfx::Rect(3, 4, 11, 12));
2973 w1ll->AddChild(w11ll);
2975 Window* w111 = new Window(&w111_delegate);
2976 w111->Init(WINDOW_LAYER_NOT_DRAWN);
2977 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2979 w11ll->AddChild(w111);
2981 EXPECT_EQ(0, w1ll_delegate.paint_count());
2982 EXPECT_EQ(0, w11ll_delegate.paint_count());
2983 EXPECT_EQ(0, w111_delegate.paint_count());
2985 // Paint the root, this should trigger painting of the two layerless
2986 // descendants but not the layered descendant.
2987 gfx::Canvas canvas(gfx::Size(200, 200), 1.0f, true);
2988 static_cast<ui::LayerDelegate&>(root).OnPaintLayer(&canvas);
2990 // NOTE: SkCanvas::getClipBounds() extends the clip 1 pixel to the left and up
2991 // and 2 pixels down and to the right.
2992 EXPECT_EQ(1, w1ll_delegate.paint_count());
2993 EXPECT_EQ("-1,-1 42x52",
2994 w1ll_delegate.most_recent_paint_clip_bounds().ToString());
2996 w1ll_delegate.most_recent_paint_matrix_offset().ToString());
2997 EXPECT_EQ(1, w11ll_delegate.paint_count());
2998 EXPECT_EQ("-1,-1 13x14",
2999 w11ll_delegate.most_recent_paint_clip_bounds().ToString());
3001 w11ll_delegate.most_recent_paint_matrix_offset().ToString());
3002 EXPECT_EQ(0, w111_delegate.paint_count());
3007 std::string ConvertPointToTargetString(const Window* source,
3008 const Window* target) {
3009 gfx::Point location;
3010 Window::ConvertPointToTarget(source, target, &location);
3011 return location.ToString();
3016 // Assertions around Window::ConvertPointToTarget() with layerless windows.
3017 TEST_F(WindowTest, ConvertPointToTargetLayerless) {
3018 // Creates the following structure (all children owned by root):
3026 // ll: layer less, eg no layer
3028 root.Init(WINDOW_LAYER_NOT_DRAWN);
3029 root.SetBounds(gfx::Rect(0, 0, 100, 100));
3031 Window* w1ll = new Window(NULL);
3032 w1ll->Init(WINDOW_LAYER_NONE);
3033 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
3035 Window* w11ll = new Window(NULL);
3036 w11ll->Init(WINDOW_LAYER_NONE);
3037 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
3038 w1ll->AddChild(w11ll);
3040 Window* w111 = new Window(NULL);
3041 w111->Init(WINDOW_LAYER_NOT_DRAWN);
3042 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
3043 w11ll->AddChild(w111);
3045 Window* w12 = new Window(NULL);
3046 w12->Init(WINDOW_LAYER_NOT_DRAWN);
3047 w12->SetBounds(gfx::Rect(7, 8, 100, 100));
3048 w1ll->AddChild(w12);
3050 Window* w121 = new Window(NULL);
3051 w121->Init(WINDOW_LAYER_NOT_DRAWN);
3052 w121->SetBounds(gfx::Rect(9, 10, 100, 100));
3053 w12->AddChild(w121);
3055 root.AddChild(w1ll);
3058 EXPECT_EQ("5,6", ConvertPointToTargetString(w111, w11ll));
3061 EXPECT_EQ("8,10", ConvertPointToTargetString(w111, w1ll));
3064 EXPECT_EQ("9,12", ConvertPointToTargetString(w111, &root));
3067 EXPECT_EQ("1,2", ConvertPointToTargetString(w111, w12));
3070 EXPECT_EQ("-8,-8", ConvertPointToTargetString(w111, w121));
3073 EXPECT_EQ("-5,-6", ConvertPointToTargetString(w11ll, w111));
3076 EXPECT_EQ("3,4", ConvertPointToTargetString(w11ll, w1ll));
3079 EXPECT_EQ("4,6", ConvertPointToTargetString(w11ll, &root));
3082 EXPECT_EQ("-4,-4", ConvertPointToTargetString(w11ll, w12));
3085 #if !defined(NDEBUG)
3086 // Verifies PrintWindowHierarchy() doesn't crash with a layerless window.
3087 TEST_F(WindowTest, PrintWindowHierarchyNotCrashLayerless) {
3089 root.Init(WINDOW_LAYER_NONE);
3090 root.SetBounds(gfx::Rect(0, 0, 100, 100));
3091 root.PrintWindowHierarchy(0);
3097 // See AddWindowsFromString() for details.
3098 aura::Window* CreateWindowFromDescription(const std::string& description,
3099 WindowDelegate* delegate) {
3100 WindowLayerType window_type = WINDOW_LAYER_NOT_DRAWN;
3101 std::vector<std::string> tokens;
3102 Tokenize(description, ":", &tokens);
3103 DCHECK(!tokens.empty());
3104 std::string name(tokens[0]);
3105 tokens.erase(tokens.begin());
3106 if (!tokens.empty()) {
3107 if (tokens[0] == "ll") {
3108 window_type = WINDOW_LAYER_NONE;
3109 tokens.erase(tokens.begin());
3111 DCHECK(tokens.empty()) << "unknown tokens for creating window "
3114 Window* window = new Window(delegate);
3115 window->Init(window_type);
3116 window->SetName(name);
3117 // Window name is only propagated to layer in debug builds.
3118 if (window->layer())
3119 window->layer()->set_name(name);
3123 // Creates and adds a tree of windows to |parent|. |description| consists
3124 // of the following pieces:
3125 // X: Identifies a new window. Consists of a name and optionally ":ll" to
3126 // specify WINDOW_LAYER_NONE, eg "w1:ll".
3127 // []: optionally used to specify the children of the window. Contains any
3128 // number of window identifiers and their corresponding children.
3129 // For example: "[ a [ a1 a2:ll ] b c [ c1 ] ]" creates the tree:
3132 // a2 -> WINDOW_LAYER_NONE.
3136 // NOTE: you must have a space after every token.
3137 std::string::size_type AddWindowsFromString(aura::Window* parent,
3138 const std::string& description,
3139 std::string::size_type start_pos,
3140 WindowDelegate* delegate) {
3142 std::string::size_type end_pos = description.find(' ', start_pos);
3143 while (end_pos != std::string::npos) {
3144 const std::string::size_type part_length = end_pos - start_pos;
3145 const std::string window_description =
3146 description.substr(start_pos, part_length);
3147 if (window_description == "[") {
3148 start_pos = AddWindowsFromString(parent->children().back(),
3152 end_pos = description.find(' ', start_pos);
3153 if (end_pos == std::string::npos && start_pos != end_pos)
3154 end_pos = description.length();
3155 } else if (window_description == "]") {
3160 CreateWindowFromDescription(window_description, delegate);
3161 parent->AddChild(window);
3162 start_pos = ++end_pos;
3163 end_pos = description.find(' ', start_pos);
3169 // Used by BuildRootWindowTreeDescription().
3170 std::string BuildWindowTreeDescription(const aura::Window& window) {
3172 result += window.name();
3173 if (window.children().empty())
3177 for (size_t i = 0; i < window.children().size(); ++i) {
3180 result += BuildWindowTreeDescription(*(window.children()[i]));
3186 // Creates a string from |window|. See AddWindowsFromString() for details of the
3187 // returned string. This does *not* include the layer type in the description,
3189 std::string BuildRootWindowTreeDescription(const aura::Window& window) {
3191 for (size_t i = 0; i < window.children().size(); ++i) {
3194 result += BuildWindowTreeDescription(*(window.children()[i]));
3199 // Used by BuildRootWindowTreeDescription().
3200 std::string BuildLayerTreeDescription(const ui::Layer& layer) {
3202 result += layer.name();
3203 if (layer.children().empty())
3207 for (size_t i = 0; i < layer.children().size(); ++i) {
3210 result += BuildLayerTreeDescription(*(layer.children()[i]));
3216 // Builds a string for all the children of |layer|. The returned string is in
3217 // the same format as AddWindowsFromString() but only includes the name of the
3219 std::string BuildRootLayerTreeDescription(const ui::Layer& layer) {
3221 for (size_t i = 0; i < layer.children().size(); ++i) {
3224 result += BuildLayerTreeDescription(*(layer.children()[i]));
3229 // Returns the first window whose name matches |name| in |parent|.
3230 aura::Window* FindWindowByName(aura::Window* parent,
3231 const std::string& name) {
3232 if (parent->name() == name)
3234 for (size_t i = 0; i < parent->children().size(); ++i) {
3235 aura::Window* child = FindWindowByName(parent->children()[i], name);
3244 // Direction to stack.
3252 // Permutations of StackChildAt with various data.
3253 TEST_F(WindowTest, StackChildAtLayerless) {
3255 // Describes the window tree to create. See AddWindowsFromString() for
3257 const std::string initial_description;
3259 // Identifies the window to move.
3260 const std::string source_window;
3262 // Window to move |source_window| relative to. Not used for STACK_AT_BOTTOM
3264 const std::string target_window;
3266 StackType stack_type;
3268 // Expected window and layer results.
3269 const std::string expected_description;
3270 const std::string expected_layer_description;
3274 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3278 "2 [ 21 ] 1 [ 11 12 ]",
3284 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3288 "1 [ 11 12 ] 2 [ 21 ]",
3294 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3298 "2 [ 21 ] 1 [ 11 12 ]",
3304 "1:ll [ 11 12 ] 2:ll [ 21 ] 3:ll",
3308 "1 [ 11 12 ] 3 2 [ 21 ]",
3314 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3318 "2 [ 21 ] 1 [ 11 12 ]",
3324 "1:ll [ 11 12 ] 2:ll [ 21 ] 3:ll",
3328 "2 [ 21 ] 3 1 [ 11 12 ]",
3334 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3338 "2 [ 21 ] 1 [ 11 12 ]",
3342 for (size_t i = 0; i < arraysize(data); ++i) {
3343 test::TestWindowDelegate delegate;
3345 root.Init(WINDOW_LAYER_NOT_DRAWN);
3346 root.SetBounds(gfx::Rect(0, 0, 100, 100));
3347 AddWindowsFromString(
3349 data[i].initial_description,
3350 static_cast<std::string::size_type>(0), &delegate);
3351 aura::Window* source = FindWindowByName(&root, data[i].source_window);
3352 ASSERT_TRUE(source != NULL) << "unable to find source window "
3353 << data[i].source_window << " at " << i;
3354 aura::Window* target = FindWindowByName(&root, data[i].target_window);
3355 switch (data[i].stack_type) {
3357 ASSERT_TRUE(target != NULL) << "unable to find target window "
3358 << data[i].target_window << " at " << i;
3359 source->parent()->StackChildAbove(source, target);
3362 ASSERT_TRUE(target != NULL) << "unable to find target window "
3363 << data[i].target_window << " at " << i;
3364 source->parent()->StackChildBelow(source, target);
3366 case STACK_AT_BOTTOM:
3367 source->parent()->StackChildAtBottom(source);
3370 source->parent()->StackChildAtTop(source);
3373 EXPECT_EQ(data[i].expected_layer_description,
3374 BuildRootLayerTreeDescription(*root.layer()))
3375 << "layer tree doesn't match at " << i;
3376 EXPECT_EQ(data[i].expected_description,
3377 BuildRootWindowTreeDescription(root))
3378 << "window tree doesn't match at " << i;
3384 class TestLayerAnimationObserver : public ui::LayerAnimationObserver {
3386 TestLayerAnimationObserver()
3387 : animation_completed_(false),
3388 animation_aborted_(false) {}
3389 ~TestLayerAnimationObserver() override {}
3391 bool animation_completed() const { return animation_completed_; }
3392 bool animation_aborted() const { return animation_aborted_; }
3395 animation_completed_ = false;
3396 animation_aborted_ = false;
3400 // ui::LayerAnimationObserver:
3401 void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override {
3402 animation_completed_ = true;
3405 void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override {
3406 animation_aborted_ = true;
3409 void OnLayerAnimationScheduled(
3410 ui::LayerAnimationSequence* sequence) override {}
3412 bool animation_completed_;
3413 bool animation_aborted_;
3415 DISALLOW_COPY_AND_ASSIGN(TestLayerAnimationObserver);
3420 TEST_F(WindowTest, WindowDestroyCompletesAnimations) {
3421 ui::ScopedAnimationDurationScaleMode test_duration_mode(
3422 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
3423 scoped_refptr<ui::LayerAnimator> animator =
3424 ui::LayerAnimator::CreateImplicitAnimator();
3425 TestLayerAnimationObserver observer;
3426 animator->AddObserver(&observer);
3427 // Make sure destroying a Window completes the animation.
3429 scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window()));
3430 window->layer()->SetAnimator(animator.get());
3432 gfx::Transform transform;
3433 transform.Scale(0.5f, 0.5f);
3434 window->SetTransform(transform);
3436 EXPECT_TRUE(animator->is_animating());
3437 EXPECT_FALSE(observer.animation_completed());
3439 EXPECT_TRUE(animator.get());
3440 EXPECT_FALSE(animator->is_animating());
3441 EXPECT_TRUE(observer.animation_completed());
3442 EXPECT_FALSE(observer.animation_aborted());
3443 animator->RemoveObserver(&observer);
3446 animator = ui::LayerAnimator::CreateImplicitAnimator();
3447 animator->AddObserver(&observer);
3449 layer.SetAnimator(animator.get());
3451 scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window()));
3452 window->layer()->Add(&layer);
3454 gfx::Transform transform;
3455 transform.Scale(0.5f, 0.5f);
3456 layer.SetTransform(transform);
3458 EXPECT_TRUE(animator->is_animating());
3459 EXPECT_FALSE(observer.animation_completed());
3462 EXPECT_TRUE(animator.get());
3463 EXPECT_FALSE(animator->is_animating());
3464 EXPECT_TRUE(observer.animation_completed());
3465 EXPECT_FALSE(observer.animation_aborted());
3466 animator->RemoveObserver(&observer);