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/event_generator.h"
24 #include "ui/aura/test/test_window_delegate.h"
25 #include "ui/aura/test/test_windows.h"
26 #include "ui/aura/test/window_test_api.h"
27 #include "ui/aura/window_delegate.h"
28 #include "ui/aura/window_event_dispatcher.h"
29 #include "ui/aura/window_observer.h"
30 #include "ui/aura/window_property.h"
31 #include "ui/aura/window_tree_host.h"
32 #include "ui/base/hit_test.h"
33 #include "ui/compositor/layer.h"
34 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
35 #include "ui/compositor/scoped_layer_animation_settings.h"
36 #include "ui/compositor/test/test_layers.h"
37 #include "ui/events/event.h"
38 #include "ui/events/event_utils.h"
39 #include "ui/events/gestures/gesture_configuration.h"
40 #include "ui/events/keycodes/keyboard_codes.h"
41 #include "ui/gfx/canvas.h"
42 #include "ui/gfx/screen.h"
43 #include "ui/gfx/skia_util.h"
44 #include "ui/gfx/vector2d.h"
46 DECLARE_WINDOW_PROPERTY_TYPE(const char*)
47 DECLARE_WINDOW_PROPERTY_TYPE(int)
52 class WindowTest : public AuraTestBase {
54 WindowTest() : max_separation_(0) {
57 virtual void SetUp() OVERRIDE {
58 AuraTestBase::SetUp();
59 // TODO: there needs to be an easier way to do this.
60 max_separation_ = ui::GestureConfiguration::
61 max_separation_for_gesture_touches_in_pixels();
62 ui::GestureConfiguration::
63 set_max_separation_for_gesture_touches_in_pixels(0);
66 virtual void TearDown() OVERRIDE {
67 AuraTestBase::TearDown();
68 ui::GestureConfiguration::
69 set_max_separation_for_gesture_touches_in_pixels(max_separation_);
75 DISALLOW_COPY_AND_ASSIGN(WindowTest);
80 // Used for verifying destruction methods are invoked.
81 class DestroyTrackingDelegateImpl : public TestWindowDelegate {
83 DestroyTrackingDelegateImpl()
84 : destroying_count_(0),
86 in_destroying_(false) {}
88 void clear_destroying_count() { destroying_count_ = 0; }
89 int destroying_count() const { return destroying_count_; }
91 void clear_destroyed_count() { destroyed_count_ = 0; }
92 int destroyed_count() const { return destroyed_count_; }
94 bool in_destroying() const { return in_destroying_; }
96 virtual void OnWindowDestroying(Window* window) OVERRIDE {
97 EXPECT_FALSE(in_destroying_);
98 in_destroying_ = true;
102 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
103 EXPECT_TRUE(in_destroying_);
104 in_destroying_ = false;
109 int destroying_count_;
110 int destroyed_count_;
113 DISALLOW_COPY_AND_ASSIGN(DestroyTrackingDelegateImpl);
116 // Used to verify that when OnWindowDestroying is invoked the parent is also
117 // is in the process of being destroyed.
118 class ChildWindowDelegateImpl : public DestroyTrackingDelegateImpl {
120 explicit ChildWindowDelegateImpl(
121 DestroyTrackingDelegateImpl* parent_delegate)
122 : parent_delegate_(parent_delegate) {
125 virtual void OnWindowDestroying(Window* window) OVERRIDE {
126 EXPECT_TRUE(parent_delegate_->in_destroying());
127 DestroyTrackingDelegateImpl::OnWindowDestroying(window);
131 DestroyTrackingDelegateImpl* parent_delegate_;
133 DISALLOW_COPY_AND_ASSIGN(ChildWindowDelegateImpl);
136 // Used to verify that a Window is removed from its parent when
137 // OnWindowDestroyed is called.
138 class DestroyOrphanDelegate : public TestWindowDelegate {
140 DestroyOrphanDelegate() : window_(NULL) {
143 void set_window(Window* window) { window_ = window; }
145 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
146 EXPECT_FALSE(window_->parent());
151 DISALLOW_COPY_AND_ASSIGN(DestroyOrphanDelegate);
154 // Used in verifying mouse capture.
155 class CaptureWindowDelegateImpl : public TestWindowDelegate {
157 CaptureWindowDelegateImpl() {
162 capture_changed_event_count_ = 0;
163 capture_lost_count_ = 0;
164 mouse_event_count_ = 0;
165 touch_event_count_ = 0;
166 gesture_event_count_ = 0;
169 int capture_changed_event_count() const {
170 return capture_changed_event_count_;
172 int capture_lost_count() const { return capture_lost_count_; }
173 int mouse_event_count() const { return mouse_event_count_; }
174 int touch_event_count() const { return touch_event_count_; }
175 int gesture_event_count() const { return gesture_event_count_; }
177 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
178 if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
179 capture_changed_event_count_++;
180 mouse_event_count_++;
182 virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
183 touch_event_count_++;
185 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
186 gesture_event_count_++;
188 virtual void OnCaptureLost() OVERRIDE {
189 capture_lost_count_++;
193 int capture_changed_event_count_;
194 int capture_lost_count_;
195 int mouse_event_count_;
196 int touch_event_count_;
197 int gesture_event_count_;
199 DISALLOW_COPY_AND_ASSIGN(CaptureWindowDelegateImpl);
202 // Keeps track of the location of the gesture.
203 class GestureTrackPositionDelegate : public TestWindowDelegate {
205 GestureTrackPositionDelegate() {}
207 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
208 position_ = event->location();
209 event->StopPropagation();
212 const gfx::Point& position() const { return position_; }
215 gfx::Point position_;
217 DISALLOW_COPY_AND_ASSIGN(GestureTrackPositionDelegate);
220 base::TimeDelta getTime() {
221 return ui::EventTimeForNow();
224 class SelfEventHandlingWindowDelegate : public TestWindowDelegate {
226 SelfEventHandlingWindowDelegate() {}
228 virtual bool ShouldDescendIntoChildForEventHandling(
230 const gfx::Point& location) OVERRIDE {
235 DISALLOW_COPY_AND_ASSIGN(SelfEventHandlingWindowDelegate);
238 // The delegate deletes itself when the window is being destroyed.
239 class DestroyWindowDelegate : public TestWindowDelegate {
241 DestroyWindowDelegate() {}
244 virtual ~DestroyWindowDelegate() {}
246 // Overridden from WindowDelegate.
247 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
251 DISALLOW_COPY_AND_ASSIGN(DestroyWindowDelegate);
256 TEST_F(WindowTest, GetChildById) {
257 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
258 scoped_ptr<Window> w11(CreateTestWindowWithId(11, w1.get()));
259 scoped_ptr<Window> w111(CreateTestWindowWithId(111, w11.get()));
260 scoped_ptr<Window> w12(CreateTestWindowWithId(12, w1.get()));
262 EXPECT_EQ(NULL, w1->GetChildById(57));
263 EXPECT_EQ(w12.get(), w1->GetChildById(12));
264 EXPECT_EQ(w111.get(), w1->GetChildById(111));
267 // Make sure that Window::Contains correctly handles children, grandchildren,
268 // and not containing NULL or parents.
269 TEST_F(WindowTest, Contains) {
271 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
273 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
275 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
277 parent.AddChild(&child1);
278 child1.AddChild(&child2);
280 EXPECT_TRUE(parent.Contains(&parent));
281 EXPECT_TRUE(parent.Contains(&child1));
282 EXPECT_TRUE(parent.Contains(&child2));
284 EXPECT_FALSE(parent.Contains(NULL));
285 EXPECT_FALSE(child1.Contains(&parent));
286 EXPECT_FALSE(child2.Contains(&child1));
289 TEST_F(WindowTest, ContainsPointInRoot) {
290 scoped_ptr<Window> w(
291 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 5, 5),
293 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(9, 9)));
294 EXPECT_TRUE(w->ContainsPointInRoot(gfx::Point(10, 10)));
295 EXPECT_TRUE(w->ContainsPointInRoot(gfx::Point(14, 14)));
296 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(15, 15)));
297 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(20, 20)));
300 TEST_F(WindowTest, ContainsPoint) {
301 scoped_ptr<Window> w(
302 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 5, 5),
304 EXPECT_TRUE(w->ContainsPoint(gfx::Point(0, 0)));
305 EXPECT_TRUE(w->ContainsPoint(gfx::Point(4, 4)));
306 EXPECT_FALSE(w->ContainsPoint(gfx::Point(5, 5)));
307 EXPECT_FALSE(w->ContainsPoint(gfx::Point(10, 10)));
310 TEST_F(WindowTest, ConvertPointToWindow) {
311 // Window::ConvertPointToWindow is mostly identical to
312 // Layer::ConvertPointToLayer, except NULL values for |source| are permitted,
313 // in which case the function just returns.
314 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
315 gfx::Point reference_point(100, 100);
316 gfx::Point test_point = reference_point;
317 Window::ConvertPointToTarget(NULL, w1.get(), &test_point);
318 EXPECT_EQ(reference_point, test_point);
321 TEST_F(WindowTest, MoveCursorTo) {
322 scoped_ptr<Window> w1(
323 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
325 scoped_ptr<Window> w11(
326 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
327 scoped_ptr<Window> w111(
328 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
329 scoped_ptr<Window> w1111(
330 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
332 Window* root = root_window();
333 root->MoveCursorTo(gfx::Point(10, 10));
335 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
336 w1->MoveCursorTo(gfx::Point(10, 10));
338 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
339 w11->MoveCursorTo(gfx::Point(10, 10));
341 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
342 w111->MoveCursorTo(gfx::Point(10, 10));
344 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
345 w1111->MoveCursorTo(gfx::Point(10, 10));
347 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
350 TEST_F(WindowTest, ContainsMouse) {
351 scoped_ptr<Window> w(
352 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
355 WindowTestApi w_test_api(w.get());
356 Window* root = root_window();
357 root->MoveCursorTo(gfx::Point(10, 10));
358 EXPECT_TRUE(w_test_api.ContainsMouse());
359 root->MoveCursorTo(gfx::Point(9, 10));
360 EXPECT_FALSE(w_test_api.ContainsMouse());
363 // Test Window::ConvertPointToWindow() with transform to root_window.
364 #if defined(USE_OZONE)
365 // TODO(rjkroege): Add cursor support in ozone: http://crbug.com/252315.
366 TEST_F(WindowTest, DISABLED_MoveCursorToWithTransformRootWindow) {
368 TEST_F(WindowTest, MoveCursorToWithTransformRootWindow) {
370 gfx::Transform transform;
371 transform.Translate(100.0, 100.0);
372 transform.Rotate(90.0);
373 transform.Scale(2.0, 5.0);
374 host()->SetRootTransform(transform);
375 host()->MoveCursorTo(gfx::Point(10, 10));
377 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.OD
378 EXPECT_EQ("50,120", QueryLatestMousePositionRequestInHost(host()).ToString());
380 EXPECT_EQ("10,10", gfx::Screen::GetScreenFor(
381 root_window())->GetCursorScreenPoint().ToString());
384 // Tests Window::ConvertPointToWindow() with transform to non-root windows.
385 TEST_F(WindowTest, MoveCursorToWithTransformWindow) {
386 scoped_ptr<Window> w1(
387 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
390 gfx::Transform transform1;
391 transform1.Scale(2, 2);
392 w1->SetTransform(transform1);
393 w1->MoveCursorTo(gfx::Point(10, 10));
395 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
397 gfx::Transform transform2;
398 transform2.Translate(-10, 20);
399 w1->SetTransform(transform2);
400 w1->MoveCursorTo(gfx::Point(10, 10));
402 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
404 gfx::Transform transform3;
405 transform3.Rotate(90.0);
406 w1->SetTransform(transform3);
407 w1->MoveCursorTo(gfx::Point(5, 5));
409 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
411 gfx::Transform transform4;
412 transform4.Translate(100.0, 100.0);
413 transform4.Rotate(90.0);
414 transform4.Scale(2.0, 5.0);
415 w1->SetTransform(transform4);
416 w1->MoveCursorTo(gfx::Point(10, 10));
418 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
421 // Test Window::ConvertPointToWindow() with complex transforms to both root and
423 // Test Window::ConvertPointToWindow() with transform to root_window.
424 #if defined(USE_OZONE)
425 // TODO(rjkroege): Add cursor support in ozone: http://crbug.com/252315.
426 TEST_F(WindowTest, DISABLED_MoveCursorToWithComplexTransform) {
428 TEST_F(WindowTest, MoveCursorToWithComplexTransform) {
430 scoped_ptr<Window> w1(
431 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
433 scoped_ptr<Window> w11(
434 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
435 scoped_ptr<Window> w111(
436 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
437 scoped_ptr<Window> w1111(
438 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
440 Window* root = root_window();
442 // The root window expects transforms that produce integer rects.
443 gfx::Transform root_transform;
444 root_transform.Translate(60.0, 70.0);
445 root_transform.Rotate(-90.0);
446 root_transform.Translate(-50.0, -50.0);
447 root_transform.Scale(2.0, 3.0);
449 gfx::Transform transform;
450 transform.Translate(10.0, 20.0);
451 transform.Rotate(10.0);
452 transform.Scale(0.3f, 0.5f);
453 host()->SetRootTransform(root_transform);
454 w1->SetTransform(transform);
455 w11->SetTransform(transform);
456 w111->SetTransform(transform);
457 w1111->SetTransform(transform);
459 w1111->MoveCursorTo(gfx::Point(10, 10));
462 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.
463 EXPECT_EQ("169,80", QueryLatestMousePositionRequestInHost(host()).ToString());
466 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
469 TEST_F(WindowTest, GetEventHandlerForPoint) {
470 scoped_ptr<Window> w1(
471 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
473 scoped_ptr<Window> w11(
474 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
475 scoped_ptr<Window> w111(
476 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
477 scoped_ptr<Window> w1111(
478 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
479 scoped_ptr<Window> w12(
480 CreateTestWindow(SK_ColorMAGENTA, 12, gfx::Rect(10, 420, 25, 25),
482 scoped_ptr<Window> w121(
483 CreateTestWindow(SK_ColorYELLOW, 121, gfx::Rect(5, 5, 5, 5), w12.get()));
484 scoped_ptr<Window> w13(
485 CreateTestWindow(SK_ColorGRAY, 13, gfx::Rect(5, 470, 50, 50), w1.get()));
487 Window* root = root_window();
488 w1->parent()->SetBounds(gfx::Rect(500, 500));
489 EXPECT_EQ(NULL, root->GetEventHandlerForPoint(gfx::Point(5, 5)));
490 EXPECT_EQ(w1.get(), root->GetEventHandlerForPoint(gfx::Point(11, 11)));
491 EXPECT_EQ(w11.get(), root->GetEventHandlerForPoint(gfx::Point(16, 16)));
492 EXPECT_EQ(w111.get(), root->GetEventHandlerForPoint(gfx::Point(21, 21)));
493 EXPECT_EQ(w1111.get(), root->GetEventHandlerForPoint(gfx::Point(26, 26)));
494 EXPECT_EQ(w12.get(), root->GetEventHandlerForPoint(gfx::Point(21, 431)));
495 EXPECT_EQ(w121.get(), root->GetEventHandlerForPoint(gfx::Point(26, 436)));
496 EXPECT_EQ(w13.get(), root->GetEventHandlerForPoint(gfx::Point(26, 481)));
499 TEST_F(WindowTest, GetEventHandlerForPointWithOverride) {
500 // If our child is flush to our top-left corner he gets events just inside the
502 scoped_ptr<Window> parent(
503 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 20, 400, 500),
505 scoped_ptr<Window> child(
506 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(0, 0, 60, 70), parent.get()));
507 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
508 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(1, 1)));
510 // We can override the hit test bounds of the parent to make the parent grab
511 // events along that edge.
512 parent->set_hit_test_bounds_override_inner(gfx::Insets(1, 1, 1, 1));
513 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
514 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(1, 1)));
517 TEST_F(WindowTest, GetEventHandlerForPointWithOverrideDescendingOrder) {
518 scoped_ptr<SelfEventHandlingWindowDelegate> parent_delegate(
519 new SelfEventHandlingWindowDelegate);
520 scoped_ptr<Window> parent(CreateTestWindowWithDelegate(
521 parent_delegate.get(), 1, gfx::Rect(10, 20, 400, 500), root_window()));
522 scoped_ptr<Window> child(
523 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(0, 0, 390, 480),
526 // We can override ShouldDescendIntoChildForEventHandling to make the parent
528 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
529 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(50, 50)));
532 TEST_F(WindowTest, GetTopWindowContainingPoint) {
533 Window* root = root_window();
534 root->SetBounds(gfx::Rect(0, 0, 300, 300));
536 scoped_ptr<Window> w1(
537 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 100, 100),
539 scoped_ptr<Window> w11(
540 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(0, 0, 120, 120), w1.get()));
542 scoped_ptr<Window> w2(
543 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(5, 5, 55, 55),
546 scoped_ptr<Window> w3(
547 CreateTestWindowWithDelegate(
548 NULL, 3, gfx::Rect(200, 200, 100, 100), root_window()));
549 scoped_ptr<Window> w31(
550 CreateTestWindow(SK_ColorCYAN, 31, gfx::Rect(0, 0, 50, 50), w3.get()));
551 scoped_ptr<Window> w311(
552 CreateTestWindow(SK_ColorBLUE, 311, gfx::Rect(0, 0, 10, 10), w31.get()));
554 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(0, 0)));
555 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(5, 5)));
556 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(10, 10)));
557 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(59, 59)));
558 EXPECT_EQ(w1.get(), root->GetTopWindowContainingPoint(gfx::Point(60, 60)));
559 EXPECT_EQ(w1.get(), root->GetTopWindowContainingPoint(gfx::Point(109, 109)));
560 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(110, 110)));
561 EXPECT_EQ(w31.get(), root->GetTopWindowContainingPoint(gfx::Point(200, 200)));
562 EXPECT_EQ(w31.get(), root->GetTopWindowContainingPoint(gfx::Point(220, 220)));
563 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(260, 260)));
566 TEST_F(WindowTest, GetToplevelWindow) {
567 const gfx::Rect kBounds(0, 0, 10, 10);
568 TestWindowDelegate delegate;
570 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
571 scoped_ptr<Window> w11(
572 CreateTestWindowWithDelegate(&delegate, 11, kBounds, w1.get()));
573 scoped_ptr<Window> w111(CreateTestWindowWithId(111, w11.get()));
574 scoped_ptr<Window> w1111(
575 CreateTestWindowWithDelegate(&delegate, 1111, kBounds, w111.get()));
577 EXPECT_TRUE(root_window()->GetToplevelWindow() == NULL);
578 EXPECT_TRUE(w1->GetToplevelWindow() == NULL);
579 EXPECT_EQ(w11.get(), w11->GetToplevelWindow());
580 EXPECT_EQ(w11.get(), w111->GetToplevelWindow());
581 EXPECT_EQ(w11.get(), w1111->GetToplevelWindow());
584 class AddedToRootWindowObserver : public WindowObserver {
586 AddedToRootWindowObserver() : called_(false) {}
588 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
592 bool called() const { return called_; }
597 DISALLOW_COPY_AND_ASSIGN(AddedToRootWindowObserver);
600 TEST_F(WindowTest, WindowAddedToRootWindowShouldNotifyChildAndNotParent) {
601 AddedToRootWindowObserver parent_observer;
602 AddedToRootWindowObserver child_observer;
603 scoped_ptr<Window> parent_window(CreateTestWindowWithId(1, root_window()));
604 scoped_ptr<Window> child_window(new Window(NULL));
605 child_window->Init(aura::WINDOW_LAYER_TEXTURED);
606 child_window->Show();
608 parent_window->AddObserver(&parent_observer);
609 child_window->AddObserver(&child_observer);
611 parent_window->AddChild(child_window.get());
613 EXPECT_FALSE(parent_observer.called());
614 EXPECT_TRUE(child_observer.called());
616 parent_window->RemoveObserver(&parent_observer);
617 child_window->RemoveObserver(&child_observer);
620 // Various destruction assertions.
621 TEST_F(WindowTest, DestroyTest) {
622 DestroyTrackingDelegateImpl parent_delegate;
623 ChildWindowDelegateImpl child_delegate(&parent_delegate);
625 scoped_ptr<Window> parent(
626 CreateTestWindowWithDelegate(&parent_delegate, 0, gfx::Rect(),
628 CreateTestWindowWithDelegate(&child_delegate, 0, gfx::Rect(), parent.get());
630 // Both the parent and child should have been destroyed.
631 EXPECT_EQ(1, parent_delegate.destroying_count());
632 EXPECT_EQ(1, parent_delegate.destroyed_count());
633 EXPECT_EQ(1, child_delegate.destroying_count());
634 EXPECT_EQ(1, child_delegate.destroyed_count());
637 // Tests that a window is orphaned before OnWindowDestroyed is called.
638 TEST_F(WindowTest, OrphanedBeforeOnDestroyed) {
639 TestWindowDelegate parent_delegate;
640 DestroyOrphanDelegate child_delegate;
642 scoped_ptr<Window> parent(
643 CreateTestWindowWithDelegate(&parent_delegate, 0, gfx::Rect(),
645 scoped_ptr<Window> child(CreateTestWindowWithDelegate(&child_delegate, 0,
646 gfx::Rect(), parent.get()));
647 child_delegate.set_window(child.get());
651 // Make sure StackChildAtTop moves both the window and layer to the front.
652 TEST_F(WindowTest, StackChildAtTop) {
654 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
656 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
658 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
660 parent.AddChild(&child1);
661 parent.AddChild(&child2);
662 ASSERT_EQ(2u, parent.children().size());
663 EXPECT_EQ(&child1, parent.children()[0]);
664 EXPECT_EQ(&child2, parent.children()[1]);
665 ASSERT_EQ(2u, parent.layer()->children().size());
666 EXPECT_EQ(child1.layer(), parent.layer()->children()[0]);
667 EXPECT_EQ(child2.layer(), parent.layer()->children()[1]);
669 parent.StackChildAtTop(&child1);
670 ASSERT_EQ(2u, parent.children().size());
671 EXPECT_EQ(&child1, parent.children()[1]);
672 EXPECT_EQ(&child2, parent.children()[0]);
673 ASSERT_EQ(2u, parent.layer()->children().size());
674 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
675 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
678 // Make sure StackChildBelow works.
679 TEST_F(WindowTest, StackChildBelow) {
681 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
683 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
686 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
689 child3.Init(aura::WINDOW_LAYER_NOT_DRAWN);
692 parent.AddChild(&child1);
693 parent.AddChild(&child2);
694 parent.AddChild(&child3);
695 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent));
697 parent.StackChildBelow(&child1, &child2);
698 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent));
700 parent.StackChildBelow(&child2, &child1);
701 EXPECT_EQ("2 1 3", ChildWindowIDsAsString(&parent));
703 parent.StackChildBelow(&child3, &child2);
704 EXPECT_EQ("3 2 1", ChildWindowIDsAsString(&parent));
706 parent.StackChildBelow(&child3, &child1);
707 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(&parent));
710 // Various assertions for StackChildAbove.
711 TEST_F(WindowTest, StackChildAbove) {
713 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
715 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
717 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
719 child3.Init(aura::WINDOW_LAYER_NOT_DRAWN);
721 parent.AddChild(&child1);
722 parent.AddChild(&child2);
724 // Move 1 in front of 2.
725 parent.StackChildAbove(&child1, &child2);
726 ASSERT_EQ(2u, parent.children().size());
727 EXPECT_EQ(&child2, parent.children()[0]);
728 EXPECT_EQ(&child1, parent.children()[1]);
729 ASSERT_EQ(2u, parent.layer()->children().size());
730 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
731 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
733 // Add 3, resulting in order [2, 1, 3], then move 2 in front of 1, resulting
735 parent.AddChild(&child3);
736 parent.StackChildAbove(&child2, &child1);
737 ASSERT_EQ(3u, parent.children().size());
738 EXPECT_EQ(&child1, parent.children()[0]);
739 EXPECT_EQ(&child2, parent.children()[1]);
740 EXPECT_EQ(&child3, parent.children()[2]);
741 ASSERT_EQ(3u, parent.layer()->children().size());
742 EXPECT_EQ(child1.layer(), parent.layer()->children()[0]);
743 EXPECT_EQ(child2.layer(), parent.layer()->children()[1]);
744 EXPECT_EQ(child3.layer(), parent.layer()->children()[2]);
746 // Move 1 in front of 3, resulting in [2, 3, 1].
747 parent.StackChildAbove(&child1, &child3);
748 ASSERT_EQ(3u, parent.children().size());
749 EXPECT_EQ(&child2, parent.children()[0]);
750 EXPECT_EQ(&child3, parent.children()[1]);
751 EXPECT_EQ(&child1, parent.children()[2]);
752 ASSERT_EQ(3u, parent.layer()->children().size());
753 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
754 EXPECT_EQ(child3.layer(), parent.layer()->children()[1]);
755 EXPECT_EQ(child1.layer(), parent.layer()->children()[2]);
757 // Moving 1 in front of 2 should lower it, resulting in [2, 1, 3].
758 parent.StackChildAbove(&child1, &child2);
759 ASSERT_EQ(3u, parent.children().size());
760 EXPECT_EQ(&child2, parent.children()[0]);
761 EXPECT_EQ(&child1, parent.children()[1]);
762 EXPECT_EQ(&child3, parent.children()[2]);
763 ASSERT_EQ(3u, parent.layer()->children().size());
764 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
765 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
766 EXPECT_EQ(child3.layer(), parent.layer()->children()[2]);
769 // Various capture assertions.
770 TEST_F(WindowTest, CaptureTests) {
771 CaptureWindowDelegateImpl delegate;
772 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
773 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
774 EXPECT_FALSE(window->HasCapture());
776 delegate.ResetCounts();
779 window->SetCapture();
780 EXPECT_TRUE(window->HasCapture());
781 EXPECT_EQ(0, delegate.capture_lost_count());
782 EXPECT_EQ(0, delegate.capture_changed_event_count());
783 EventGenerator generator(root_window(), gfx::Point(50, 50));
784 generator.PressLeftButton();
785 EXPECT_EQ(1, delegate.mouse_event_count());
786 generator.ReleaseLeftButton();
788 EXPECT_EQ(2, delegate.mouse_event_count());
789 delegate.ResetCounts();
791 ui::TouchEvent touchev(
792 ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), 0, getTime());
793 DispatchEventUsingWindowDispatcher(&touchev);
794 EXPECT_EQ(1, delegate.touch_event_count());
795 delegate.ResetCounts();
797 window->ReleaseCapture();
798 EXPECT_FALSE(window->HasCapture());
799 EXPECT_EQ(1, delegate.capture_lost_count());
800 EXPECT_EQ(1, delegate.capture_changed_event_count());
801 EXPECT_EQ(1, delegate.mouse_event_count());
802 EXPECT_EQ(0, delegate.touch_event_count());
804 generator.PressLeftButton();
805 EXPECT_EQ(1, delegate.mouse_event_count());
807 ui::TouchEvent touchev2(
808 ui::ET_TOUCH_PRESSED, gfx::Point(250, 250), 1, getTime());
809 DispatchEventUsingWindowDispatcher(&touchev2);
810 EXPECT_EQ(0, delegate.touch_event_count());
812 // Removing the capture window from parent should reset the capture window
813 // in the root window.
814 window->SetCapture();
815 EXPECT_EQ(window.get(), aura::client::GetCaptureWindow(root_window()));
816 window->parent()->RemoveChild(window.get());
817 EXPECT_FALSE(window->HasCapture());
818 EXPECT_EQ(NULL, aura::client::GetCaptureWindow(root_window()));
821 TEST_F(WindowTest, TouchCaptureCancelsOtherTouches) {
822 CaptureWindowDelegateImpl delegate1;
823 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
824 &delegate1, 0, gfx::Rect(0, 0, 50, 50), root_window()));
825 CaptureWindowDelegateImpl delegate2;
826 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
827 &delegate2, 0, gfx::Rect(50, 50, 50, 50), root_window()));
830 ui::TouchEvent press(
831 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
832 DispatchEventUsingWindowDispatcher(&press);
833 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
834 EXPECT_EQ(2, delegate1.gesture_event_count());
835 delegate1.ResetCounts();
837 // Capturing to w2 should cause the touch to be canceled.
839 EXPECT_EQ(1, delegate1.touch_event_count());
840 EXPECT_EQ(0, delegate2.touch_event_count());
841 delegate1.ResetCounts();
842 delegate2.ResetCounts();
844 // Events now go to w2.
845 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, getTime());
846 DispatchEventUsingWindowDispatcher(&move);
847 EXPECT_EQ(0, delegate1.gesture_event_count());
848 EXPECT_EQ(0, delegate1.touch_event_count());
849 EXPECT_EQ(0, delegate2.gesture_event_count());
850 EXPECT_EQ(1, delegate2.touch_event_count());
852 ui::TouchEvent release(
853 ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, getTime());
854 DispatchEventUsingWindowDispatcher(&release);
855 EXPECT_EQ(0, delegate1.gesture_event_count());
856 EXPECT_EQ(0, delegate2.gesture_event_count());
858 // A new press is captured by w2.
859 ui::TouchEvent press2(
860 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
861 DispatchEventUsingWindowDispatcher(&press2);
862 EXPECT_EQ(0, delegate1.gesture_event_count());
863 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
864 EXPECT_EQ(2, delegate2.gesture_event_count());
865 delegate1.ResetCounts();
866 delegate2.ResetCounts();
868 // And releasing capture changes nothing.
869 w2->ReleaseCapture();
870 EXPECT_EQ(0, delegate1.gesture_event_count());
871 EXPECT_EQ(0, delegate1.touch_event_count());
872 EXPECT_EQ(0, delegate2.gesture_event_count());
873 EXPECT_EQ(0, delegate2.touch_event_count());
876 TEST_F(WindowTest, TouchCaptureDoesntCancelCapturedTouches) {
877 CaptureWindowDelegateImpl delegate;
878 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
879 &delegate, 0, gfx::Rect(0, 0, 50, 50), root_window()));
881 ui::TouchEvent press(
882 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
883 DispatchEventUsingWindowDispatcher(&press);
885 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
886 EXPECT_EQ(2, delegate.gesture_event_count());
887 EXPECT_EQ(1, delegate.touch_event_count());
888 delegate.ResetCounts();
890 window->SetCapture();
891 EXPECT_EQ(0, delegate.gesture_event_count());
892 EXPECT_EQ(0, delegate.touch_event_count());
893 delegate.ResetCounts();
895 // On move We will get TOUCH_MOVED, GESTURE_TAP_CANCEL,
896 // GESTURE_SCROLL_START and GESTURE_SCROLL_UPDATE.
897 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, getTime());
898 DispatchEventUsingWindowDispatcher(&move);
899 EXPECT_EQ(1, delegate.touch_event_count());
900 EXPECT_EQ(3, delegate.gesture_event_count());
901 delegate.ResetCounts();
903 // Release capture shouldn't change anything.
904 window->ReleaseCapture();
905 EXPECT_EQ(0, delegate.touch_event_count());
906 EXPECT_EQ(0, delegate.gesture_event_count());
907 delegate.ResetCounts();
909 // On move we still get TOUCH_MOVED and GESTURE_SCROLL_UPDATE.
910 ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(10, 30), 0, getTime());
911 DispatchEventUsingWindowDispatcher(&move2);
912 EXPECT_EQ(1, delegate.touch_event_count());
913 EXPECT_EQ(1, delegate.gesture_event_count());
914 delegate.ResetCounts();
916 // And on release we get TOUCH_RELEASED, GESTURE_SCROLL_END, GESTURE_END
917 ui::TouchEvent release(
918 ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, getTime());
919 DispatchEventUsingWindowDispatcher(&release);
920 EXPECT_EQ(1, delegate.touch_event_count());
921 EXPECT_EQ(2, delegate.gesture_event_count());
925 // Assertions around SetCapture() and touch/gestures.
926 TEST_F(WindowTest, TransferCaptureTouchEvents) {
928 CaptureWindowDelegateImpl d1;
929 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
930 &d1, 0, gfx::Rect(0, 0, 20, 20), root_window()));
931 ui::TouchEvent p1(ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
932 DispatchEventUsingWindowDispatcher(&p1);
933 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
934 EXPECT_EQ(1, d1.touch_event_count());
935 EXPECT_EQ(2, d1.gesture_event_count());
938 // Touch on |w2| with a different id.
939 CaptureWindowDelegateImpl d2;
940 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
941 &d2, 0, gfx::Rect(40, 0, 40, 20), root_window()));
942 ui::TouchEvent p2(ui::ET_TOUCH_PRESSED, gfx::Point(41, 10), 1, getTime());
943 DispatchEventUsingWindowDispatcher(&p2);
944 EXPECT_EQ(0, d1.touch_event_count());
945 EXPECT_EQ(0, d1.gesture_event_count());
946 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN for new target window.
947 EXPECT_EQ(1, d2.touch_event_count());
948 EXPECT_EQ(2, d2.gesture_event_count());
952 // Set capture on |w2|, this should send a cancel (TAP_CANCEL, END) to |w1|
955 EXPECT_EQ(1, d1.touch_event_count());
956 EXPECT_EQ(2, d1.gesture_event_count());
957 EXPECT_EQ(0, d2.touch_event_count());
958 EXPECT_EQ(0, d2.gesture_event_count());
962 CaptureWindowDelegateImpl d3;
963 scoped_ptr<Window> w3(CreateTestWindowWithDelegate(
964 &d3, 0, gfx::Rect(0, 0, 100, 101), root_window()));
965 // Set capture on w3. No new events should be received.
966 // Note this difference in behavior between the first and second capture
967 // is confusing and error prone. http://crbug.com/236930
969 EXPECT_EQ(0, d1.touch_event_count());
970 EXPECT_EQ(0, d1.gesture_event_count());
971 EXPECT_EQ(0, d2.touch_event_count());
972 EXPECT_EQ(0, d2.gesture_event_count());
973 EXPECT_EQ(0, d3.touch_event_count());
974 EXPECT_EQ(0, d3.gesture_event_count());
976 // Move touch id originally associated with |w2|. Since capture was transfered
977 // from 2 to 3 only |w3| should get the event.
978 ui::TouchEvent m3(ui::ET_TOUCH_MOVED, gfx::Point(110, 105), 1, getTime());
979 DispatchEventUsingWindowDispatcher(&m3);
980 EXPECT_EQ(0, d1.touch_event_count());
981 EXPECT_EQ(0, d1.gesture_event_count());
982 EXPECT_EQ(0, d2.touch_event_count());
983 EXPECT_EQ(0, d2.gesture_event_count());
984 // |w3| gets a TOUCH_MOVE, TAP_CANCEL and two scroll related events.
985 EXPECT_EQ(1, d3.touch_event_count());
986 EXPECT_EQ(3, d3.gesture_event_count());
991 // When we release capture, no touches are canceled.
992 w3->ReleaseCapture();
993 EXPECT_EQ(0, d1.touch_event_count());
994 EXPECT_EQ(0, d1.gesture_event_count());
995 EXPECT_EQ(0, d2.touch_event_count());
996 EXPECT_EQ(0, d2.gesture_event_count());
997 EXPECT_EQ(0, d3.touch_event_count());
998 EXPECT_EQ(0, d3.gesture_event_count());
1000 // And when we move the touch again, |w3| still gets the events.
1001 ui::TouchEvent m4(ui::ET_TOUCH_MOVED, gfx::Point(120, 105), 1, getTime());
1002 DispatchEventUsingWindowDispatcher(&m4);
1003 EXPECT_EQ(0, d1.touch_event_count());
1004 EXPECT_EQ(0, d1.gesture_event_count());
1005 EXPECT_EQ(0, d2.touch_event_count());
1006 EXPECT_EQ(0, d2.gesture_event_count());
1007 EXPECT_EQ(1, d3.touch_event_count());
1008 EXPECT_EQ(1, d3.gesture_event_count());
1014 // Changes capture while capture is already ongoing.
1015 TEST_F(WindowTest, ChangeCaptureWhileMouseDown) {
1016 CaptureWindowDelegateImpl delegate;
1017 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
1018 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1019 CaptureWindowDelegateImpl delegate2;
1020 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
1021 &delegate2, 0, gfx::Rect(20, 20, 20, 20), root_window()));
1023 // Execute the scheduled draws so that mouse events are not
1025 RunAllPendingInMessageLoop();
1027 EXPECT_FALSE(window->HasCapture());
1030 delegate.ResetCounts();
1031 window->SetCapture();
1032 EXPECT_TRUE(window->HasCapture());
1033 EXPECT_EQ(0, delegate.capture_lost_count());
1034 EXPECT_EQ(0, delegate.capture_changed_event_count());
1035 EventGenerator generator(root_window(), gfx::Point(50, 50));
1036 generator.PressLeftButton();
1037 EXPECT_EQ(0, delegate.capture_lost_count());
1038 EXPECT_EQ(0, delegate.capture_changed_event_count());
1039 EXPECT_EQ(1, delegate.mouse_event_count());
1041 // Set capture to |w2|, should implicitly unset capture for |window|.
1042 delegate.ResetCounts();
1043 delegate2.ResetCounts();
1046 generator.MoveMouseTo(gfx::Point(40, 40), 2);
1047 EXPECT_EQ(1, delegate.capture_lost_count());
1048 EXPECT_EQ(1, delegate.capture_changed_event_count());
1049 EXPECT_EQ(1, delegate.mouse_event_count());
1050 EXPECT_EQ(2, delegate2.mouse_event_count());
1053 // Verifies capture is reset when a window is destroyed.
1054 TEST_F(WindowTest, ReleaseCaptureOnDestroy) {
1055 CaptureWindowDelegateImpl delegate;
1056 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
1057 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1058 EXPECT_FALSE(window->HasCapture());
1061 window->SetCapture();
1062 EXPECT_TRUE(window->HasCapture());
1064 // Destroy the window.
1067 // Make sure the root window doesn't reference the window anymore.
1068 EXPECT_EQ(NULL, host()->dispatcher()->mouse_pressed_handler());
1069 EXPECT_EQ(NULL, aura::client::GetCaptureWindow(root_window()));
1072 TEST_F(WindowTest, GetBoundsInRootWindow) {
1073 scoped_ptr<Window> viewport(CreateTestWindowWithBounds(
1074 gfx::Rect(0, 0, 300, 300), root_window()));
1075 scoped_ptr<Window> child(CreateTestWindowWithBounds(
1076 gfx::Rect(0, 0, 100, 100), viewport.get()));
1078 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1080 // The |child| window's screen bounds should move along with the |viewport|.
1081 viewport->SetBounds(gfx::Rect(-100, -100, 300, 300));
1082 EXPECT_EQ("-100,-100 100x100", child->GetBoundsInRootWindow().ToString());
1084 // The |child| window is moved to the 0,0 in screen coordinates.
1085 // |GetBoundsInRootWindow()| should return 0,0.
1086 child->SetBounds(gfx::Rect(100, 100, 100, 100));
1087 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1090 class MouseEnterExitWindowDelegate : public TestWindowDelegate {
1092 MouseEnterExitWindowDelegate() : entered_(false), exited_(false) {}
1094 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
1095 switch (event->type()) {
1096 case ui::ET_MOUSE_ENTERED:
1097 EXPECT_TRUE(event->flags() & ui::EF_IS_SYNTHESIZED);
1100 case ui::ET_MOUSE_EXITED:
1101 EXPECT_TRUE(event->flags() & ui::EF_IS_SYNTHESIZED);
1109 bool entered() const { return entered_; }
1110 bool exited() const { return exited_; }
1112 // Clear the entered / exited states.
1113 void ResetExpectations() {
1122 DISALLOW_COPY_AND_ASSIGN(MouseEnterExitWindowDelegate);
1126 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1127 // mouse transitions from window to window.
1128 TEST_F(WindowTest, MouseEnterExit) {
1129 MouseEnterExitWindowDelegate d1;
1130 scoped_ptr<Window> w1(
1131 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1133 MouseEnterExitWindowDelegate d2;
1134 scoped_ptr<Window> w2(
1135 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50),
1138 test::EventGenerator generator(root_window());
1139 generator.MoveMouseToCenterOf(w1.get());
1140 EXPECT_TRUE(d1.entered());
1141 EXPECT_FALSE(d1.exited());
1142 EXPECT_FALSE(d2.entered());
1143 EXPECT_FALSE(d2.exited());
1145 generator.MoveMouseToCenterOf(w2.get());
1146 EXPECT_TRUE(d1.entered());
1147 EXPECT_TRUE(d1.exited());
1148 EXPECT_TRUE(d2.entered());
1149 EXPECT_FALSE(d2.exited());
1152 // Verifies that the WindowDelegate receives MouseExit from ET_MOUSE_EXITED.
1153 TEST_F(WindowTest, WindowTreeHostExit) {
1154 MouseEnterExitWindowDelegate d1;
1155 scoped_ptr<Window> w1(
1156 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1159 test::EventGenerator generator(root_window());
1160 generator.MoveMouseToCenterOf(w1.get());
1161 EXPECT_TRUE(d1.entered());
1162 EXPECT_FALSE(d1.exited());
1163 d1.ResetExpectations();
1165 ui::MouseEvent exit_event(
1166 ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(), 0, 0);
1167 DispatchEventUsingWindowDispatcher(&exit_event);
1168 EXPECT_FALSE(d1.entered());
1169 EXPECT_TRUE(d1.exited());
1172 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1173 // mouse transitions from window to window, even if the entered window sets
1174 // and releases capture.
1175 TEST_F(WindowTest, MouseEnterExitWithClick) {
1176 MouseEnterExitWindowDelegate d1;
1177 scoped_ptr<Window> w1(
1178 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1180 MouseEnterExitWindowDelegate d2;
1181 scoped_ptr<Window> w2(
1182 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50),
1185 test::EventGenerator generator(root_window());
1186 generator.MoveMouseToCenterOf(w1.get());
1187 EXPECT_TRUE(d1.entered());
1188 EXPECT_FALSE(d1.exited());
1189 EXPECT_FALSE(d2.entered());
1190 EXPECT_FALSE(d2.exited());
1192 // Emmulate what Views does on a click by grabbing and releasing capture.
1193 generator.PressLeftButton();
1195 w1->ReleaseCapture();
1196 generator.ReleaseLeftButton();
1198 generator.MoveMouseToCenterOf(w2.get());
1199 EXPECT_TRUE(d1.entered());
1200 EXPECT_TRUE(d1.exited());
1201 EXPECT_TRUE(d2.entered());
1202 EXPECT_FALSE(d2.exited());
1205 TEST_F(WindowTest, MouseEnterExitWhenDeleteWithCapture) {
1206 MouseEnterExitWindowDelegate delegate;
1207 scoped_ptr<Window> window(
1208 CreateTestWindowWithDelegate(&delegate, 1, gfx::Rect(10, 10, 50, 50),
1211 test::EventGenerator generator(root_window());
1212 generator.MoveMouseToCenterOf(window.get());
1213 EXPECT_TRUE(delegate.entered());
1214 EXPECT_FALSE(delegate.exited());
1216 // Emmulate what Views does on a click by grabbing and releasing capture.
1217 generator.PressLeftButton();
1218 window->SetCapture();
1220 delegate.ResetExpectations();
1221 generator.MoveMouseTo(0, 0);
1222 EXPECT_FALSE(delegate.entered());
1223 EXPECT_FALSE(delegate.exited());
1225 delegate.ResetExpectations();
1227 EXPECT_FALSE(delegate.entered());
1228 EXPECT_FALSE(delegate.exited());
1231 // Verifies that enter / exits are sent if windows appear and are deleted
1232 // under the current mouse position..
1233 TEST_F(WindowTest, MouseEnterExitWithDelete) {
1234 MouseEnterExitWindowDelegate d1;
1235 scoped_ptr<Window> w1(
1236 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1239 test::EventGenerator generator(root_window());
1240 generator.MoveMouseToCenterOf(w1.get());
1241 EXPECT_TRUE(d1.entered());
1242 EXPECT_FALSE(d1.exited());
1243 d1.ResetExpectations();
1245 MouseEnterExitWindowDelegate d2;
1247 scoped_ptr<Window> w2(
1248 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1250 // Enters / exits can be sent asynchronously.
1251 RunAllPendingInMessageLoop();
1252 EXPECT_FALSE(d1.entered());
1253 EXPECT_TRUE(d1.exited());
1254 EXPECT_TRUE(d2.entered());
1255 EXPECT_FALSE(d2.exited());
1256 d1.ResetExpectations();
1257 d2.ResetExpectations();
1259 // Enters / exits can be sent asynchronously.
1260 RunAllPendingInMessageLoop();
1261 EXPECT_TRUE(d2.exited());
1262 EXPECT_TRUE(d1.entered());
1265 // Verifies that enter / exits are sent if windows appear and are hidden
1266 // under the current mouse position..
1267 TEST_F(WindowTest, MouseEnterExitWithHide) {
1268 MouseEnterExitWindowDelegate d1;
1269 scoped_ptr<Window> w1(
1270 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1273 test::EventGenerator generator(root_window());
1274 generator.MoveMouseToCenterOf(w1.get());
1275 EXPECT_TRUE(d1.entered());
1276 EXPECT_FALSE(d1.exited());
1278 MouseEnterExitWindowDelegate d2;
1279 scoped_ptr<Window> w2(
1280 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1282 // Enters / exits can be send asynchronously.
1283 RunAllPendingInMessageLoop();
1284 EXPECT_TRUE(d1.entered());
1285 EXPECT_TRUE(d1.exited());
1286 EXPECT_TRUE(d2.entered());
1287 EXPECT_FALSE(d2.exited());
1289 d1.ResetExpectations();
1291 // Enters / exits can be send asynchronously.
1292 RunAllPendingInMessageLoop();
1293 EXPECT_TRUE(d2.exited());
1294 EXPECT_TRUE(d1.entered());
1297 TEST_F(WindowTest, MouseEnterExitWithParentHide) {
1298 MouseEnterExitWindowDelegate d1;
1299 scoped_ptr<Window> w1(
1300 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1302 MouseEnterExitWindowDelegate d2;
1303 Window* w2 = CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1305 test::EventGenerator generator(root_window());
1306 generator.MoveMouseToCenterOf(w2);
1307 // Enters / exits can be send asynchronously.
1308 RunAllPendingInMessageLoop();
1309 EXPECT_TRUE(d2.entered());
1310 EXPECT_FALSE(d2.exited());
1312 d2.ResetExpectations();
1314 RunAllPendingInMessageLoop();
1315 EXPECT_FALSE(d2.entered());
1316 EXPECT_TRUE(d2.exited());
1321 TEST_F(WindowTest, MouseEnterExitWithParentDelete) {
1322 MouseEnterExitWindowDelegate d1;
1323 scoped_ptr<Window> w1(
1324 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1326 MouseEnterExitWindowDelegate d2;
1327 Window* w2 = CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1329 test::EventGenerator generator(root_window());
1330 generator.MoveMouseToCenterOf(w2);
1332 // Enters / exits can be send asynchronously.
1333 RunAllPendingInMessageLoop();
1334 EXPECT_TRUE(d2.entered());
1335 EXPECT_FALSE(d2.exited());
1337 d2.ResetExpectations();
1339 RunAllPendingInMessageLoop();
1340 EXPECT_FALSE(d2.entered());
1341 EXPECT_TRUE(d2.exited());
1344 // Creates a window with a delegate (w111) that can handle events at a lower
1345 // z-index than a window without a delegate (w12). w12 is sized to fill the
1346 // entire bounds of the container. This test verifies that
1347 // GetEventHandlerForPoint() skips w12 even though its bounds contain the event,
1348 // because it has no children that can handle the event and it has no delegate
1349 // allowing it to handle the event itself.
1350 TEST_F(WindowTest, GetEventHandlerForPoint_NoDelegate) {
1351 TestWindowDelegate d111;
1352 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(NULL, 1,
1353 gfx::Rect(0, 0, 500, 500), root_window()));
1354 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(NULL, 11,
1355 gfx::Rect(0, 0, 500, 500), w1.get()));
1356 scoped_ptr<Window> w111(CreateTestWindowWithDelegate(&d111, 111,
1357 gfx::Rect(50, 50, 450, 450), w11.get()));
1358 scoped_ptr<Window> w12(CreateTestWindowWithDelegate(NULL, 12,
1359 gfx::Rect(0, 0, 500, 500), w1.get()));
1361 gfx::Point target_point = w111->bounds().CenterPoint();
1362 EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(target_point));
1365 class VisibilityWindowDelegate : public TestWindowDelegate {
1367 VisibilityWindowDelegate()
1372 int shown() const { return shown_; }
1373 int hidden() const { return hidden_; }
1379 virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {
1390 DISALLOW_COPY_AND_ASSIGN(VisibilityWindowDelegate);
1393 // Verifies show/hide propagate correctly to children and the layer.
1394 TEST_F(WindowTest, Visibility) {
1395 VisibilityWindowDelegate d;
1396 VisibilityWindowDelegate d2;
1397 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(&d, 1, gfx::Rect(),
1399 scoped_ptr<Window> w2(
1400 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(), w1.get()));
1401 scoped_ptr<Window> w3(CreateTestWindowWithId(3, w2.get()));
1403 // Create shows all the windows.
1404 EXPECT_TRUE(w1->IsVisible());
1405 EXPECT_TRUE(w2->IsVisible());
1406 EXPECT_TRUE(w3->IsVisible());
1407 EXPECT_EQ(1, d.shown());
1411 EXPECT_FALSE(w1->IsVisible());
1412 EXPECT_FALSE(w2->IsVisible());
1413 EXPECT_FALSE(w3->IsVisible());
1414 EXPECT_EQ(1, d.hidden());
1415 EXPECT_EQ(0, d.shown());
1418 EXPECT_FALSE(w1->IsVisible());
1419 EXPECT_FALSE(w2->IsVisible());
1420 EXPECT_FALSE(w3->IsVisible());
1423 EXPECT_FALSE(w1->IsVisible());
1424 EXPECT_FALSE(w2->IsVisible());
1425 EXPECT_FALSE(w3->IsVisible());
1429 EXPECT_TRUE(w1->IsVisible());
1430 EXPECT_TRUE(w2->IsVisible());
1431 EXPECT_FALSE(w3->IsVisible());
1432 EXPECT_EQ(0, d.hidden());
1433 EXPECT_EQ(1, d.shown());
1436 EXPECT_TRUE(w1->IsVisible());
1437 EXPECT_TRUE(w2->IsVisible());
1438 EXPECT_TRUE(w3->IsVisible());
1440 // Verify that if an ancestor isn't visible and we change the visibility of a
1441 // child window that OnChildWindowVisibilityChanged() is still invoked.
1445 EXPECT_EQ(1, d2.hidden());
1446 EXPECT_EQ(0, d2.shown());
1449 EXPECT_EQ(0, d2.hidden());
1450 EXPECT_EQ(1, d2.shown());
1453 TEST_F(WindowTest, IgnoreEventsTest) {
1454 TestWindowDelegate d11;
1455 TestWindowDelegate d12;
1456 TestWindowDelegate d111;
1457 TestWindowDelegate d121;
1458 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(NULL, 1,
1459 gfx::Rect(0, 0, 500, 500), root_window()));
1460 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(&d11, 11,
1461 gfx::Rect(0, 0, 500, 500), w1.get()));
1462 scoped_ptr<Window> w111(CreateTestWindowWithDelegate(&d111, 111,
1463 gfx::Rect(50, 50, 450, 450), w11.get()));
1464 scoped_ptr<Window> w12(CreateTestWindowWithDelegate(&d12, 12,
1465 gfx::Rect(0, 0, 500, 500), w1.get()));
1466 scoped_ptr<Window> w121(CreateTestWindowWithDelegate(&d121, 121,
1467 gfx::Rect(150, 150, 50, 50), w12.get()));
1469 EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10)));
1470 w12->set_ignore_events(true);
1471 EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10)));
1472 w12->set_ignore_events(false);
1474 EXPECT_EQ(w121.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1475 w121->set_ignore_events(true);
1476 EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1477 w12->set_ignore_events(true);
1478 EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1479 w111->set_ignore_events(true);
1480 EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1483 // Tests transformation on the root window.
1484 TEST_F(WindowTest, Transform) {
1485 gfx::Size size = host()->GetBounds().size();
1486 EXPECT_EQ(gfx::Rect(size),
1487 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1488 gfx::Point()).bounds());
1490 // Rotate it clock-wise 90 degrees.
1491 gfx::Transform transform;
1492 transform.Translate(size.height(), 0);
1493 transform.Rotate(90.0);
1494 host()->SetRootTransform(transform);
1496 // The size should be the transformed size.
1497 gfx::Size transformed_size(size.height(), size.width());
1498 EXPECT_EQ(transformed_size.ToString(),
1499 root_window()->bounds().size().ToString());
1501 gfx::Rect(transformed_size).ToString(),
1502 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1503 gfx::Point()).bounds().ToString());
1505 // Host size shouldn't change.
1506 EXPECT_EQ(size.ToString(), host()->GetBounds().size().ToString());
1509 TEST_F(WindowTest, TransformGesture) {
1510 gfx::Size size = host()->GetBounds().size();
1512 scoped_ptr<GestureTrackPositionDelegate> delegate(
1513 new GestureTrackPositionDelegate);
1514 scoped_ptr<Window> window(CreateTestWindowWithDelegate(delegate.get(), -1234,
1515 gfx::Rect(0, 0, 20, 20), root_window()));
1517 // Rotate the root-window clock-wise 90 degrees.
1518 gfx::Transform transform;
1519 transform.Translate(size.height(), 0.0);
1520 transform.Rotate(90.0);
1521 host()->SetRootTransform(transform);
1523 ui::TouchEvent press(
1524 ui::ET_TOUCH_PRESSED, gfx::Point(size.height() - 10, 10), 0, getTime());
1525 DispatchEventUsingWindowDispatcher(&press);
1526 EXPECT_EQ(gfx::Point(10, 10).ToString(), delegate->position().ToString());
1530 DEFINE_WINDOW_PROPERTY_KEY(int, kIntKey, -2);
1531 DEFINE_WINDOW_PROPERTY_KEY(const char*, kStringKey, "squeamish");
1534 TEST_F(WindowTest, Property) {
1535 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window()));
1537 static const char native_prop_key[] = "fnord";
1539 // Non-existent properties should return the default values.
1540 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1541 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1542 EXPECT_EQ(NULL, w->GetNativeWindowProperty(native_prop_key));
1544 // A set property value should be returned again (even if it's the default
1546 w->SetProperty(kIntKey, INT_MAX);
1547 EXPECT_EQ(INT_MAX, w->GetProperty(kIntKey));
1548 w->SetProperty(kIntKey, -2);
1549 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1550 w->SetProperty(kIntKey, INT_MIN);
1551 EXPECT_EQ(INT_MIN, w->GetProperty(kIntKey));
1553 w->SetProperty(kStringKey, static_cast<const char*>(NULL));
1554 EXPECT_EQ(NULL, w->GetProperty(kStringKey));
1555 w->SetProperty(kStringKey, "squeamish");
1556 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1557 w->SetProperty(kStringKey, "ossifrage");
1558 EXPECT_EQ(std::string("ossifrage"), w->GetProperty(kStringKey));
1560 w->SetNativeWindowProperty(native_prop_key, &*w);
1561 EXPECT_EQ(&*w, w->GetNativeWindowProperty(native_prop_key));
1562 w->SetNativeWindowProperty(native_prop_key, NULL);
1563 EXPECT_EQ(NULL, w->GetNativeWindowProperty(native_prop_key));
1565 // ClearProperty should restore the default value.
1566 w->ClearProperty(kIntKey);
1567 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1568 w->ClearProperty(kStringKey);
1569 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1574 class TestProperty {
1577 virtual ~TestProperty() {
1578 last_deleted_ = this;
1580 static TestProperty* last_deleted() { return last_deleted_; }
1583 static TestProperty* last_deleted_;
1584 DISALLOW_COPY_AND_ASSIGN(TestProperty);
1587 TestProperty* TestProperty::last_deleted_ = NULL;
1589 DEFINE_OWNED_WINDOW_PROPERTY_KEY(TestProperty, kOwnedKey, NULL);
1593 TEST_F(WindowTest, OwnedProperty) {
1594 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window()));
1595 EXPECT_EQ(NULL, w->GetProperty(kOwnedKey));
1596 TestProperty* p1 = new TestProperty();
1597 w->SetProperty(kOwnedKey, p1);
1598 EXPECT_EQ(p1, w->GetProperty(kOwnedKey));
1599 EXPECT_EQ(NULL, TestProperty::last_deleted());
1601 TestProperty* p2 = new TestProperty();
1602 w->SetProperty(kOwnedKey, p2);
1603 EXPECT_EQ(p2, w->GetProperty(kOwnedKey));
1604 EXPECT_EQ(p1, TestProperty::last_deleted());
1606 w->ClearProperty(kOwnedKey);
1607 EXPECT_EQ(NULL, w->GetProperty(kOwnedKey));
1608 EXPECT_EQ(p2, TestProperty::last_deleted());
1610 TestProperty* p3 = new TestProperty();
1611 w->SetProperty(kOwnedKey, p3);
1612 EXPECT_EQ(p3, w->GetProperty(kOwnedKey));
1613 EXPECT_EQ(p2, TestProperty::last_deleted());
1615 EXPECT_EQ(p3, TestProperty::last_deleted());
1618 TEST_F(WindowTest, SetBoundsInternalShouldCheckTargetBounds) {
1619 // We cannot short-circuit animations in this test.
1620 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
1621 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
1623 scoped_ptr<Window> w1(
1624 CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), root_window()));
1626 EXPECT_FALSE(!w1->layer());
1627 w1->layer()->GetAnimator()->set_disable_timer_for_test(true);
1628 gfx::AnimationContainerElement* element = w1->layer()->GetAnimator();
1630 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1631 EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString());
1633 // Animate to a different position.
1635 ui::ScopedLayerAnimationSettings settings(w1->layer()->GetAnimator());
1636 w1->SetBounds(gfx::Rect(100, 100, 100, 100));
1639 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1640 EXPECT_EQ("100,100 100x100", w1->layer()->GetTargetBounds().ToString());
1642 // Animate back to the first position. The animation hasn't started yet, so
1643 // the current bounds are still (0, 0, 100, 100), but the target bounds are
1644 // (100, 100, 100, 100). If we step the animator ahead, we should find that
1645 // we're at (0, 0, 100, 100). That is, the second animation should be applied.
1647 ui::ScopedLayerAnimationSettings settings(w1->layer()->GetAnimator());
1648 w1->SetBounds(gfx::Rect(0, 0, 100, 100));
1651 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1652 EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString());
1654 // Confirm that the target bounds are reached.
1655 base::TimeTicks start_time =
1656 w1->layer()->GetAnimator()->last_step_time();
1658 element->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
1660 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1664 typedef std::pair<const void*, intptr_t> PropertyChangeInfo;
1666 class WindowObserverTest : public WindowTest,
1667 public WindowObserver {
1669 struct VisibilityInfo {
1670 bool window_visible;
1674 WindowObserverTest()
1677 destroyed_count_(0),
1678 old_property_value_(-3) {
1681 virtual ~WindowObserverTest() {}
1683 const VisibilityInfo* GetVisibilityInfo() const {
1684 return visibility_info_.get();
1687 void ResetVisibilityInfo() {
1688 visibility_info_.reset();
1691 // Returns a description of the WindowObserver methods that have been invoked.
1692 std::string WindowObserverCountStateAndClear() {
1694 base::StringPrintf("added=%d removed=%d",
1695 added_count_, removed_count_));
1696 added_count_ = removed_count_ = 0;
1700 int DestroyedCountAndClear() {
1701 int result = destroyed_count_;
1702 destroyed_count_ = 0;
1706 // Return a tuple of the arguments passed in OnPropertyChanged callback.
1707 PropertyChangeInfo PropertyChangeInfoAndClear() {
1708 PropertyChangeInfo result(property_key_, old_property_value_);
1709 property_key_ = NULL;
1710 old_property_value_ = -3;
1715 virtual void OnWindowAdded(Window* new_window) OVERRIDE {
1719 virtual void OnWillRemoveWindow(Window* window) OVERRIDE {
1723 virtual void OnWindowVisibilityChanged(Window* window,
1724 bool visible) OVERRIDE {
1725 visibility_info_.reset(new VisibilityInfo);
1726 visibility_info_->window_visible = window->IsVisible();
1727 visibility_info_->visible_param = visible;
1730 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
1731 EXPECT_FALSE(window->parent());
1735 virtual void OnWindowPropertyChanged(Window* window,
1737 intptr_t old) OVERRIDE {
1738 property_key_ = key;
1739 old_property_value_ = old;
1744 int destroyed_count_;
1745 scoped_ptr<VisibilityInfo> visibility_info_;
1746 const void* property_key_;
1747 intptr_t old_property_value_;
1749 DISALLOW_COPY_AND_ASSIGN(WindowObserverTest);
1752 // Various assertions for WindowObserver.
1753 TEST_F(WindowObserverTest, WindowObserver) {
1754 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1755 w1->AddObserver(this);
1757 // Create a new window as a child of w1, our observer should be notified.
1758 scoped_ptr<Window> w2(CreateTestWindowWithId(2, w1.get()));
1759 EXPECT_EQ("added=1 removed=0", WindowObserverCountStateAndClear());
1761 // Delete w2, which should result in the remove notification.
1763 EXPECT_EQ("added=0 removed=1", WindowObserverCountStateAndClear());
1765 // Create a window that isn't parented to w1, we shouldn't get any
1767 scoped_ptr<Window> w3(CreateTestWindowWithId(3, root_window()));
1768 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1770 // Similarly destroying w3 shouldn't notify us either.
1772 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1773 w1->RemoveObserver(this);
1776 // Test if OnWindowVisibilityChagned is invoked with expected
1778 TEST_F(WindowObserverTest, WindowVisibility) {
1779 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1780 scoped_ptr<Window> w2(CreateTestWindowWithId(1, w1.get()));
1781 w2->AddObserver(this);
1783 // Hide should make the window invisible and the passed visible
1784 // parameter is false.
1786 EXPECT_FALSE(!GetVisibilityInfo());
1787 EXPECT_FALSE(!GetVisibilityInfo());
1788 if (!GetVisibilityInfo())
1790 EXPECT_FALSE(GetVisibilityInfo()->window_visible);
1791 EXPECT_FALSE(GetVisibilityInfo()->visible_param);
1793 // If parent isn't visible, showing window won't make the window visible, but
1794 // passed visible value must be true.
1796 ResetVisibilityInfo();
1797 EXPECT_TRUE(!GetVisibilityInfo());
1799 EXPECT_FALSE(!GetVisibilityInfo());
1800 if (!GetVisibilityInfo())
1802 EXPECT_FALSE(GetVisibilityInfo()->window_visible);
1803 EXPECT_TRUE(GetVisibilityInfo()->visible_param);
1805 // If parent is visible, showing window will make the window
1806 // visible and the passed visible value is true.
1809 ResetVisibilityInfo();
1811 EXPECT_FALSE(!GetVisibilityInfo());
1812 if (!GetVisibilityInfo())
1814 EXPECT_TRUE(GetVisibilityInfo()->window_visible);
1815 EXPECT_TRUE(GetVisibilityInfo()->visible_param);
1818 // Test if OnWindowDestroyed is invoked as expected.
1819 TEST_F(WindowObserverTest, WindowDestroyed) {
1820 // Delete a window should fire a destroyed notification.
1821 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1822 w1->AddObserver(this);
1824 EXPECT_EQ(1, DestroyedCountAndClear());
1826 // Observe on child and delete parent window should fire a notification.
1827 scoped_ptr<Window> parent(CreateTestWindowWithId(1, root_window()));
1828 Window* child = CreateTestWindowWithId(1, parent.get()); // owned by parent
1829 child->AddObserver(this);
1831 EXPECT_EQ(1, DestroyedCountAndClear());
1834 TEST_F(WindowObserverTest, PropertyChanged) {
1835 // Setting property should fire a property change notification.
1836 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1837 w1->AddObserver(this);
1839 static const WindowProperty<int> prop = {-2};
1840 static const char native_prop_key[] = "fnord";
1842 w1->SetProperty(&prop, 1);
1843 EXPECT_EQ(PropertyChangeInfo(&prop, -2), PropertyChangeInfoAndClear());
1844 w1->SetProperty(&prop, -2);
1845 EXPECT_EQ(PropertyChangeInfo(&prop, 1), PropertyChangeInfoAndClear());
1846 w1->SetProperty(&prop, 3);
1847 EXPECT_EQ(PropertyChangeInfo(&prop, -2), PropertyChangeInfoAndClear());
1848 w1->ClearProperty(&prop);
1849 EXPECT_EQ(PropertyChangeInfo(&prop, 3), PropertyChangeInfoAndClear());
1851 w1->SetNativeWindowProperty(native_prop_key, &*w1);
1852 EXPECT_EQ(PropertyChangeInfo(native_prop_key, 0),
1853 PropertyChangeInfoAndClear());
1854 w1->SetNativeWindowProperty(native_prop_key, NULL);
1855 EXPECT_EQ(PropertyChangeInfo(native_prop_key,
1856 reinterpret_cast<intptr_t>(&*w1)),
1857 PropertyChangeInfoAndClear());
1859 // Sanity check to see if |PropertyChangeInfoAndClear| really clears.
1860 EXPECT_EQ(PropertyChangeInfo(
1861 reinterpret_cast<const void*>(NULL), -3), PropertyChangeInfoAndClear());
1864 TEST_F(WindowTest, AcquireLayer) {
1865 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
1866 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
1867 ui::Layer* parent = window1->parent()->layer();
1868 EXPECT_EQ(2U, parent->children().size());
1870 WindowTestApi window1_test_api(window1.get());
1871 WindowTestApi window2_test_api(window2.get());
1873 EXPECT_TRUE(window1_test_api.OwnsLayer());
1874 EXPECT_TRUE(window2_test_api.OwnsLayer());
1876 // After acquisition, window1 should not own its layer, but it should still
1877 // be available to the window.
1878 scoped_ptr<ui::Layer> window1_layer(window1->AcquireLayer());
1879 EXPECT_FALSE(window1_test_api.OwnsLayer());
1880 EXPECT_TRUE(window1_layer.get() == window1->layer());
1882 // The acquired layer's owner should be set NULL and re-acquring
1883 // should return NULL.
1884 EXPECT_FALSE(window1_layer->owner());
1885 scoped_ptr<ui::Layer> window1_layer_reacquired(window1->AcquireLayer());
1886 EXPECT_FALSE(window1_layer_reacquired.get());
1888 // Upon destruction, window1's layer should still be valid, and in the layer
1889 // hierarchy, but window2's should be gone, and no longer in the hierarchy.
1893 // This should be set by the window's destructor.
1894 EXPECT_TRUE(window1_layer->delegate() == NULL);
1895 EXPECT_EQ(1U, parent->children().size());
1898 // Make sure that properties which should persist from the old layer to the new
1899 // layer actually do.
1900 TEST_F(WindowTest, RecreateLayer) {
1901 // Set properties to non default values.
1902 Window w(new ColorTestWindowDelegate(SK_ColorWHITE));
1904 w.Init(aura::WINDOW_LAYER_SOLID_COLOR);
1905 w.SetBounds(gfx::Rect(0, 0, 100, 100));
1907 ui::Layer* layer = w.layer();
1908 layer->set_scale_content(false);
1909 layer->SetVisible(false);
1910 layer->SetMasksToBounds(true);
1912 ui::Layer child_layer;
1913 layer->Add(&child_layer);
1915 scoped_ptr<ui::Layer> old_layer(w.RecreateLayer());
1917 EXPECT_EQ(ui::LAYER_SOLID_COLOR, layer->type());
1918 EXPECT_FALSE(layer->scale_content());
1919 EXPECT_FALSE(layer->visible());
1920 EXPECT_EQ(1u, layer->children().size());
1921 EXPECT_TRUE(layer->GetMasksToBounds());
1922 EXPECT_EQ("0,0 100x100", w.bounds().ToString());
1923 EXPECT_EQ("0,0 100x100", layer->bounds().ToString());
1926 // Verify that RecreateLayer() stacks the old layer above the newly creatd
1928 TEST_F(WindowTest, RecreateLayerZOrder) {
1929 scoped_ptr<Window> w(
1930 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(0, 0, 100, 100),
1932 scoped_ptr<ui::Layer> old_layer(w->RecreateLayer());
1934 const std::vector<ui::Layer*>& child_layers =
1935 root_window()->layer()->children();
1936 ASSERT_EQ(2u, child_layers.size());
1937 EXPECT_EQ(w->layer(), child_layers[0]);
1938 EXPECT_EQ(old_layer.get(), child_layers[1]);
1941 // Ensure that acquiring a layer then recreating a layer does not crash
1942 // and that RecreateLayer returns null.
1943 TEST_F(WindowTest, AcquireThenRecreateLayer) {
1944 scoped_ptr<Window> w(
1945 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(0, 0, 100, 100),
1947 scoped_ptr<ui::Layer> acquired_layer(w->AcquireLayer());
1948 scoped_ptr<ui::Layer> doubly_acquired_layer(w->RecreateLayer());
1949 EXPECT_EQ(NULL, doubly_acquired_layer.get());
1951 // Destroy window before layer gets destroyed.
1955 TEST_F(WindowTest, StackWindowAtBottomBelowWindowWhoseLayerHasNoDelegate) {
1956 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
1957 window1->layer()->set_name("1");
1958 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
1959 window2->layer()->set_name("2");
1960 scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window()));
1961 window3->layer()->set_name("3");
1963 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(root_window()));
1965 ui::test::ChildLayerNamesAsString(*root_window()->layer()));
1966 window1->layer()->set_delegate(NULL);
1967 root_window()->StackChildAtBottom(window3.get());
1969 // Window 3 should have moved to the bottom.
1970 EXPECT_EQ("3 1 2", ChildWindowIDsAsString(root_window()));
1972 ui::test::ChildLayerNamesAsString(*root_window()->layer()));
1975 class TestVisibilityClient : public client::VisibilityClient {
1977 explicit TestVisibilityClient(Window* root_window)
1978 : ignore_visibility_changes_(false) {
1979 client::SetVisibilityClient(root_window, this);
1981 virtual ~TestVisibilityClient() {
1984 void set_ignore_visibility_changes(bool ignore_visibility_changes) {
1985 ignore_visibility_changes_ = ignore_visibility_changes;
1988 // Overridden from client::VisibilityClient:
1989 virtual void UpdateLayerVisibility(aura::Window* window,
1990 bool visible) OVERRIDE {
1991 if (!ignore_visibility_changes_)
1992 window->layer()->SetVisible(visible);
1996 bool ignore_visibility_changes_;
1997 DISALLOW_COPY_AND_ASSIGN(TestVisibilityClient);
2000 TEST_F(WindowTest, VisibilityClientIsVisible) {
2001 TestVisibilityClient client(root_window());
2003 scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window()));
2004 EXPECT_TRUE(window->IsVisible());
2005 EXPECT_TRUE(window->layer()->visible());
2008 EXPECT_FALSE(window->IsVisible());
2009 EXPECT_FALSE(window->layer()->visible());
2012 client.set_ignore_visibility_changes(true);
2014 EXPECT_FALSE(window->IsVisible());
2015 EXPECT_TRUE(window->layer()->visible());
2018 // Tests mouse events on window change.
2019 TEST_F(WindowTest, MouseEventsOnWindowChange) {
2020 gfx::Size size = host()->GetBounds().size();
2022 EventGenerator generator(root_window());
2023 generator.MoveMouseTo(50, 50);
2025 EventCountDelegate d1;
2026 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(&d1, 1,
2027 gfx::Rect(0, 0, 100, 100), root_window()));
2028 RunAllPendingInMessageLoop();
2029 // The format of result is "Enter/Mouse/Leave".
2030 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2032 // Adding new window.
2033 EventCountDelegate d11;
2034 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(
2035 &d11, 1, gfx::Rect(0, 0, 100, 100), w1.get()));
2036 RunAllPendingInMessageLoop();
2037 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2038 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2041 w11->SetBounds(gfx::Rect(0, 0, 10, 10));
2042 RunAllPendingInMessageLoop();
2043 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2044 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2046 w11->SetBounds(gfx::Rect(0, 0, 60, 60));
2047 RunAllPendingInMessageLoop();
2048 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2049 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2051 // Detach, then re-attach.
2052 w1->RemoveChild(w11.get());
2053 RunAllPendingInMessageLoop();
2054 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2055 // Window is detached, so no event is set.
2056 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2058 w1->AddChild(w11.get());
2059 RunAllPendingInMessageLoop();
2060 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2061 // Window is detached, so no event is set.
2062 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2064 // Visibility Change
2066 RunAllPendingInMessageLoop();
2067 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2068 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2071 RunAllPendingInMessageLoop();
2072 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2073 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2075 // Transform: move d11 by 100 100.
2076 gfx::Transform transform;
2077 transform.Translate(100, 100);
2078 w11->SetTransform(transform);
2079 RunAllPendingInMessageLoop();
2080 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2081 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2083 w11->SetTransform(gfx::Transform());
2084 RunAllPendingInMessageLoop();
2085 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2086 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2088 // Closing a window.
2090 RunAllPendingInMessageLoop();
2091 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2093 // Make sure we don't synthesize events if the mouse
2094 // is outside of the root window.
2095 generator.MoveMouseTo(-10, -10);
2096 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2098 // Adding new windows.
2099 w11.reset(CreateTestWindowWithDelegate(
2100 &d11, 1, gfx::Rect(0, 0, 100, 100), w1.get()));
2101 RunAllPendingInMessageLoop();
2102 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset());
2103 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2107 RunAllPendingInMessageLoop();
2108 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset());
2109 EXPECT_EQ("0 0 0", d11.GetMouseMotionCountsAndReset());
2112 class RootWindowAttachmentObserver : public WindowObserver {
2114 RootWindowAttachmentObserver() : added_count_(0), removed_count_(0) {}
2115 virtual ~RootWindowAttachmentObserver() {}
2117 int added_count() const { return added_count_; }
2118 int removed_count() const { return removed_count_; }
2125 // Overridden from WindowObserver:
2126 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
2129 virtual void OnWindowRemovingFromRootWindow(Window* window,
2130 Window* new_root) OVERRIDE {
2138 DISALLOW_COPY_AND_ASSIGN(RootWindowAttachmentObserver);
2141 TEST_F(WindowTest, RootWindowAttachment) {
2142 RootWindowAttachmentObserver observer;
2144 // Test a direct add/remove from the RootWindow.
2145 scoped_ptr<Window> w1(new Window(NULL));
2146 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2147 w1->AddObserver(&observer);
2149 ParentWindow(w1.get());
2150 EXPECT_EQ(1, observer.added_count());
2151 EXPECT_EQ(0, observer.removed_count());
2154 EXPECT_EQ(1, observer.added_count());
2155 EXPECT_EQ(1, observer.removed_count());
2159 // Test an indirect add/remove from the RootWindow.
2160 w1.reset(new Window(NULL));
2161 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2162 Window* w11 = new Window(NULL);
2163 w11->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2164 w11->AddObserver(&observer);
2166 EXPECT_EQ(0, observer.added_count());
2167 EXPECT_EQ(0, observer.removed_count());
2169 ParentWindow(w1.get());
2170 EXPECT_EQ(1, observer.added_count());
2171 EXPECT_EQ(0, observer.removed_count());
2173 w1.reset(); // Deletes w11.
2175 EXPECT_EQ(1, observer.added_count());
2176 EXPECT_EQ(1, observer.removed_count());
2180 // Test an indirect add/remove with nested observers.
2181 w1.reset(new Window(NULL));
2182 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2183 w11 = new Window(NULL);
2184 w11->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2185 w11->AddObserver(&observer);
2187 Window* w111 = new Window(NULL);
2188 w111->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2189 w111->AddObserver(&observer);
2190 w11->AddChild(w111);
2192 EXPECT_EQ(0, observer.added_count());
2193 EXPECT_EQ(0, observer.removed_count());
2195 ParentWindow(w1.get());
2196 EXPECT_EQ(2, observer.added_count());
2197 EXPECT_EQ(0, observer.removed_count());
2199 w1.reset(); // Deletes w11 and w111.
2202 EXPECT_EQ(2, observer.added_count());
2203 EXPECT_EQ(2, observer.removed_count());
2206 class BoundsChangedWindowObserver : public WindowObserver {
2208 BoundsChangedWindowObserver() : root_set_(false) {}
2210 virtual void OnWindowBoundsChanged(Window* window,
2211 const gfx::Rect& old_bounds,
2212 const gfx::Rect& new_bounds) OVERRIDE {
2213 root_set_ = window->GetRootWindow() != NULL;
2216 bool root_set() const { return root_set_; }
2221 DISALLOW_COPY_AND_ASSIGN(BoundsChangedWindowObserver);
2224 TEST_F(WindowTest, RootWindowSetWhenReparenting) {
2225 Window parent1(NULL);
2226 parent1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2227 Window parent2(NULL);
2228 parent2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2229 ParentWindow(&parent1);
2230 ParentWindow(&parent2);
2231 parent1.SetBounds(gfx::Rect(10, 10, 300, 300));
2232 parent2.SetBounds(gfx::Rect(20, 20, 300, 300));
2235 child.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2236 child.SetBounds(gfx::Rect(5, 5, 100, 100));
2237 parent1.AddChild(&child);
2239 // We need animations to start in order to observe the bounds changes.
2240 ui::ScopedAnimationDurationScaleMode animation_duration_mode(
2241 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
2242 ui::ScopedLayerAnimationSettings settings1(child.layer()->GetAnimator());
2243 settings1.SetTransitionDuration(base::TimeDelta::FromMilliseconds(100));
2244 gfx::Rect new_bounds(gfx::Rect(35, 35, 50, 50));
2245 child.SetBounds(new_bounds);
2247 BoundsChangedWindowObserver observer;
2248 child.AddObserver(&observer);
2250 // Reparenting the |child| will cause it to get moved. During this move
2251 // the window should still have root window set.
2252 parent2.AddChild(&child);
2253 EXPECT_TRUE(observer.root_set());
2255 // Animations should stop and the bounds should be as set before the |child|
2257 EXPECT_EQ(new_bounds.ToString(), child.GetTargetBounds().ToString());
2258 EXPECT_EQ(new_bounds.ToString(), child.bounds().ToString());
2259 EXPECT_EQ("55,55 50x50", child.GetBoundsInRootWindow().ToString());
2262 TEST_F(WindowTest, OwnedByParentFalse) {
2263 // By default, a window is owned by its parent. If this is set to false, the
2264 // window will not be destroyed when its parent is.
2266 scoped_ptr<Window> w1(new Window(NULL));
2267 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2268 scoped_ptr<Window> w2(new Window(NULL));
2269 w2->set_owned_by_parent(false);
2270 w2->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2271 w1->AddChild(w2.get());
2275 // We should be able to deref w2 still, but its parent should now be NULL.
2276 EXPECT_EQ(NULL, w2->parent());
2281 // Used By DeleteWindowFromOnWindowDestroyed. Destroys a Window from
2282 // OnWindowDestroyed().
2283 class OwningWindowDelegate : public TestWindowDelegate {
2285 OwningWindowDelegate() {}
2287 void SetOwnedWindow(Window* window) {
2288 owned_window_.reset(window);
2291 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
2292 owned_window_.reset(NULL);
2296 scoped_ptr<Window> owned_window_;
2298 DISALLOW_COPY_AND_ASSIGN(OwningWindowDelegate);
2303 // Creates a window with two child windows. When the first child window is
2304 // destroyed (WindowDelegate::OnWindowDestroyed) it deletes the second child.
2305 // This synthesizes BrowserView and the status bubble. Both are children of the
2306 // same parent and destroying BrowserView triggers it destroying the status
2308 TEST_F(WindowTest, DeleteWindowFromOnWindowDestroyed) {
2309 scoped_ptr<Window> parent(new Window(NULL));
2310 parent->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2311 OwningWindowDelegate delegate;
2312 Window* c1 = new Window(&delegate);
2313 c1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2314 parent->AddChild(c1);
2315 Window* c2 = new Window(NULL);
2316 c2->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2317 parent->AddChild(c2);
2318 delegate.SetOwnedWindow(c2);
2324 // Used by DelegateNotifiedAsBoundsChange to verify OnBoundsChanged() is
2326 class BoundsChangeDelegate : public TestWindowDelegate {
2328 BoundsChangeDelegate() : bounds_changed_(false) {}
2330 void clear_bounds_changed() { bounds_changed_ = false; }
2331 bool bounds_changed() const {
2332 return bounds_changed_;
2336 virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
2337 const gfx::Rect& new_bounds) OVERRIDE {
2338 bounds_changed_ = true;
2342 // Was OnBoundsChanged() invoked?
2343 bool bounds_changed_;
2345 DISALLOW_COPY_AND_ASSIGN(BoundsChangeDelegate);
2350 // Verifies the delegate is notified when the actual bounds of the layer
2352 TEST_F(WindowTest, DelegateNotifiedAsBoundsChange) {
2353 BoundsChangeDelegate delegate;
2355 // We cannot short-circuit animations in this test.
2356 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
2357 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
2359 scoped_ptr<Window> window(
2360 CreateTestWindowWithDelegate(&delegate, 1,
2361 gfx::Rect(0, 0, 100, 100), root_window()));
2362 window->layer()->GetAnimator()->set_disable_timer_for_test(true);
2364 delegate.clear_bounds_changed();
2366 // Animate to a different position.
2368 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
2369 window->SetBounds(gfx::Rect(100, 100, 100, 100));
2372 // Bounds shouldn't immediately have changed.
2373 EXPECT_EQ("0,0 100x100", window->bounds().ToString());
2374 EXPECT_FALSE(delegate.bounds_changed());
2376 // Animate to the end, which should notify of the change.
2377 base::TimeTicks start_time =
2378 window->layer()->GetAnimator()->last_step_time();
2379 gfx::AnimationContainerElement* element = window->layer()->GetAnimator();
2380 element->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
2381 EXPECT_TRUE(delegate.bounds_changed());
2382 EXPECT_NE("0,0 100x100", window->bounds().ToString());
2385 // Verifies the delegate is notified when the actual bounds of the layer
2386 // change even when the window is not the layer's delegate
2387 TEST_F(WindowTest, DelegateNotifiedAsBoundsChangeInHiddenLayer) {
2388 BoundsChangeDelegate delegate;
2390 // We cannot short-circuit animations in this test.
2391 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
2392 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
2394 scoped_ptr<Window> window(
2395 CreateTestWindowWithDelegate(&delegate, 1,
2396 gfx::Rect(0, 0, 100, 100), root_window()));
2397 window->layer()->GetAnimator()->set_disable_timer_for_test(true);
2399 delegate.clear_bounds_changed();
2401 // Suppress paint on the window since it is hidden (should reset the layer's
2402 // delegate to NULL)
2403 window->SuppressPaint();
2404 EXPECT_EQ(NULL, window->layer()->delegate());
2406 // Animate to a different position.
2408 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
2409 window->SetBounds(gfx::Rect(100, 100, 110, 100));
2412 // Layer delegate is NULL but we should still get bounds changed notification.
2413 EXPECT_EQ("100,100 110x100", window->GetTargetBounds().ToString());
2414 EXPECT_TRUE(delegate.bounds_changed());
2416 delegate.clear_bounds_changed();
2418 // Animate to the end: will *not* notify of the change since we are hidden.
2419 base::TimeTicks start_time =
2420 window->layer()->GetAnimator()->last_step_time();
2421 gfx::AnimationContainerElement* element = window->layer()->GetAnimator();
2422 element->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
2424 // No bounds changed notification at the end of animation since layer
2425 // delegate is NULL.
2426 EXPECT_FALSE(delegate.bounds_changed());
2427 EXPECT_NE("0,0 100x100", window->layer()->bounds().ToString());
2432 // Used by AddChildNotifications to track notification counts.
2433 class AddChildNotificationsObserver : public WindowObserver {
2435 AddChildNotificationsObserver() : added_count_(0), removed_count_(0) {}
2437 std::string CountStringAndReset() {
2438 std::string result = base::IntToString(added_count_) + " " +
2439 base::IntToString(removed_count_);
2440 added_count_ = removed_count_ = 0;
2444 // WindowObserver overrides:
2445 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
2448 virtual void OnWindowRemovingFromRootWindow(Window* window,
2449 Window* new_root) OVERRIDE {
2457 DISALLOW_COPY_AND_ASSIGN(AddChildNotificationsObserver);
2462 // Assertions around when root window notifications are sent.
2463 TEST_F(WindowTest, AddChildNotifications) {
2464 AddChildNotificationsObserver observer;
2465 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
2466 scoped_ptr<Window> w2(CreateTestWindowWithId(1, root_window()));
2467 w2->AddObserver(&observer);
2469 EXPECT_TRUE(w2->HasFocus());
2471 // Move |w2| to be a child of |w1|.
2472 w1->AddChild(w2.get());
2473 // Sine we moved in the same root, observer shouldn't be notified.
2474 EXPECT_EQ("0 0", observer.CountStringAndReset());
2475 // |w2| should still have focus after moving.
2476 EXPECT_TRUE(w2->HasFocus());
2479 // Tests that a delegate that destroys itself when the window is destroyed does
2481 TEST_F(WindowTest, DelegateDestroysSelfOnWindowDestroy) {
2482 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
2483 new DestroyWindowDelegate(),
2485 gfx::Rect(10, 20, 30, 40),
2489 class HierarchyObserver : public WindowObserver {
2491 HierarchyObserver(Window* target) : target_(target) {
2492 target_->AddObserver(this);
2494 virtual ~HierarchyObserver() {
2495 target_->RemoveObserver(this);
2500 const WindowObserver::HierarchyChangeParams& params) const {
2501 ParamsMatch(params_[index], params);
2509 // Overridden from WindowObserver:
2510 virtual void OnWindowHierarchyChanging(
2511 const HierarchyChangeParams& params) OVERRIDE {
2512 params_.push_back(params);
2514 virtual void OnWindowHierarchyChanged(
2515 const HierarchyChangeParams& params) OVERRIDE {
2516 params_.push_back(params);
2519 void ParamsMatch(const WindowObserver::HierarchyChangeParams& p1,
2520 const WindowObserver::HierarchyChangeParams& p2) const {
2521 EXPECT_EQ(p1.phase, p2.phase);
2522 EXPECT_EQ(p1.target, p2.target);
2523 EXPECT_EQ(p1.new_parent, p2.new_parent);
2524 EXPECT_EQ(p1.old_parent, p2.old_parent);
2525 EXPECT_EQ(p1.receiver, p2.receiver);
2529 std::vector<WindowObserver::HierarchyChangeParams> params_;
2531 DISALLOW_COPY_AND_ASSIGN(HierarchyObserver);
2534 // Tests hierarchy change notifications.
2535 TEST_F(WindowTest, OnWindowHierarchyChange) {
2537 // Simple add & remove.
2538 HierarchyObserver oroot(root_window());
2540 scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL));
2541 HierarchyObserver o1(w1.get());
2544 root_window()->AddChild(w1.get());
2546 WindowObserver::HierarchyChangeParams params;
2547 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2548 params.target = w1.get();
2549 params.old_parent = NULL;
2550 params.new_parent = root_window();
2551 params.receiver = w1.get();
2552 o1.ValidateState(0, params);
2554 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2555 params.receiver = w1.get();
2556 o1.ValidateState(1, params);
2558 params.receiver = root_window();
2559 oroot.ValidateState(0, params);
2565 root_window()->RemoveChild(w1.get());
2567 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2568 params.old_parent = root_window();
2569 params.new_parent = NULL;
2570 params.receiver = w1.get();
2572 o1.ValidateState(0, params);
2574 params.receiver = root_window();
2575 oroot.ValidateState(0, params);
2577 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2578 params.receiver = w1.get();
2579 o1.ValidateState(1, params);
2583 // Add & remove of hierarchy. Tests notification order per documentation in
2585 HierarchyObserver o(root_window());
2586 scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL));
2587 Window* w11 = CreateTestWindowWithId(11, w1.get());
2588 w1->AddObserver(&o);
2589 w11->AddObserver(&o);
2592 root_window()->AddChild(w1.get());
2594 // Dispatched to target first.
2596 WindowObserver::HierarchyChangeParams params;
2597 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2598 params.target = w1.get();
2599 params.old_parent = NULL;
2600 params.new_parent = root_window();
2601 params.receiver = w1.get();
2602 o.ValidateState(index++, params);
2604 // Dispatched to target's children.
2605 params.receiver = w11;
2606 o.ValidateState(index++, params);
2608 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2610 // Now process the "changed" phase.
2611 params.receiver = w1.get();
2612 o.ValidateState(index++, params);
2613 params.receiver = w11;
2614 o.ValidateState(index++, params);
2615 params.receiver = root_window();
2616 o.ValidateState(index++, params);
2619 root_window()->RemoveChild(w1.get());
2620 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2621 params.old_parent = root_window();
2622 params.new_parent = NULL;
2623 params.receiver = w1.get();
2624 o.ValidateState(index++, params);
2625 params.receiver = w11;
2626 o.ValidateState(index++, params);
2627 params.receiver = root_window();
2628 o.ValidateState(index++, params);
2629 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2630 params.receiver = w1.get();
2631 o.ValidateState(index++, params);
2632 params.receiver = w11;
2633 o.ValidateState(index++, params);
2639 // Reparent. Tests notification order per documentation in WindowObserver.
2640 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
2641 Window* w11 = CreateTestWindowWithId(11, w1.get());
2642 Window* w111 = CreateTestWindowWithId(111, w11);
2643 scoped_ptr<Window> w2(CreateTestWindowWithId(2, root_window()));
2645 HierarchyObserver o(root_window());
2646 w1->AddObserver(&o);
2647 w11->AddObserver(&o);
2648 w111->AddObserver(&o);
2649 w2->AddObserver(&o);
2653 // Dispatched to target first.
2655 WindowObserver::HierarchyChangeParams params;
2656 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2657 params.target = w11;
2658 params.old_parent = w1.get();
2659 params.new_parent = w2.get();
2660 params.receiver = w11;
2661 o.ValidateState(index++, params);
2663 // Then to target's children.
2664 params.receiver = w111;
2665 o.ValidateState(index++, params);
2667 // Then to target's old parent chain.
2668 params.receiver = w1.get();
2669 o.ValidateState(index++, params);
2670 params.receiver = root_window();
2671 o.ValidateState(index++, params);
2674 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2675 params.receiver = w11;
2676 o.ValidateState(index++, params);
2677 params.receiver = w111;
2678 o.ValidateState(index++, params);
2679 params.receiver = w2.get();
2680 o.ValidateState(index++, params);
2681 params.receiver = root_window();
2682 o.ValidateState(index++, params);
2690 // Verifies SchedulePaint() on a layerless window results in damaging the right
2692 TEST_F(WindowTest, LayerlessWindowSchedulePaint) {
2694 root.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2695 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2697 Window* layerless_window = new Window(NULL); // Owned by |root|.
2698 layerless_window->Init(WINDOW_LAYER_NONE);
2699 layerless_window->SetBounds(gfx::Rect(10, 11, 12, 13));
2700 root.AddChild(layerless_window);
2702 root.layer()->SendDamagedRects();
2703 layerless_window->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4));
2704 // Note the the region is clipped by the parent hence 100 going to 11.
2705 EXPECT_EQ("11,13 11x4",
2706 gfx::SkIRectToRect(root.layer()->damaged_region().getBounds()).
2709 Window* layerless_window2 = new Window(NULL); // Owned by |layerless_window|.
2710 layerless_window2->Init(WINDOW_LAYER_NONE);
2711 layerless_window2->SetBounds(gfx::Rect(1, 2, 3, 4));
2712 layerless_window->AddChild(layerless_window2);
2714 root.layer()->SendDamagedRects();
2715 layerless_window2->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4));
2716 // Note the the region is clipped by the |layerless_window| hence 100 going to
2718 EXPECT_EQ("12,15 2x2",
2719 gfx::SkIRectToRect(root.layer()->damaged_region().getBounds()).
2723 // Verifies bounds of layerless windows are correctly updated when adding
2725 TEST_F(WindowTest, NestedLayerlessWindowsBoundsOnAddRemove) {
2726 // Creates the following structure (all children owned by root):
2734 // ll: layer less, eg no layer
2736 root.Init(WINDOW_LAYER_NOT_DRAWN);
2737 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2739 Window* w1ll = new Window(NULL);
2740 w1ll->Init(WINDOW_LAYER_NONE);
2741 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
2743 Window* w11ll = new Window(NULL);
2744 w11ll->Init(WINDOW_LAYER_NONE);
2745 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
2746 w1ll->AddChild(w11ll);
2748 Window* w111 = new Window(NULL);
2749 w111->Init(WINDOW_LAYER_NOT_DRAWN);
2750 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2751 w11ll->AddChild(w111);
2753 Window* w12 = new Window(NULL);
2754 w12->Init(WINDOW_LAYER_NOT_DRAWN);
2755 w12->SetBounds(gfx::Rect(7, 8, 100, 100));
2756 w1ll->AddChild(w12);
2758 Window* w121 = new Window(NULL);
2759 w121->Init(WINDOW_LAYER_NOT_DRAWN);
2760 w121->SetBounds(gfx::Rect(9, 10, 100, 100));
2761 w12->AddChild(w121);
2763 root.AddChild(w1ll);
2765 // All layers should be parented to the root.
2766 EXPECT_EQ(root.layer(), w111->layer()->parent());
2767 EXPECT_EQ(root.layer(), w12->layer()->parent());
2768 EXPECT_EQ(w12->layer(), w121->layer()->parent());
2770 // Ensure bounds are what we expect.
2771 EXPECT_EQ("1,2 100x100", w1ll->bounds().ToString());
2772 EXPECT_EQ("3,4 100x100", w11ll->bounds().ToString());
2773 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2774 EXPECT_EQ("7,8 100x100", w12->bounds().ToString());
2775 EXPECT_EQ("9,10 100x100", w121->bounds().ToString());
2777 // Bounds of layers are relative to the nearest ancestor with a layer.
2778 EXPECT_EQ("8,10 100x100", w12->layer()->bounds().ToString());
2779 EXPECT_EQ("9,12 100x100", w111->layer()->bounds().ToString());
2780 EXPECT_EQ("9,10 100x100", w121->layer()->bounds().ToString());
2782 // Remove and repeat.
2783 root.RemoveChild(w1ll);
2785 EXPECT_TRUE(w111->layer()->parent() == NULL);
2786 EXPECT_TRUE(w12->layer()->parent() == NULL);
2788 // Verify bounds haven't changed again.
2789 EXPECT_EQ("1,2 100x100", w1ll->bounds().ToString());
2790 EXPECT_EQ("3,4 100x100", w11ll->bounds().ToString());
2791 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2792 EXPECT_EQ("7,8 100x100", w12->bounds().ToString());
2793 EXPECT_EQ("9,10 100x100", w121->bounds().ToString());
2795 // Bounds of layers should now match that of windows.
2796 EXPECT_EQ("7,8 100x100", w12->layer()->bounds().ToString());
2797 EXPECT_EQ("5,6 100x100", w111->layer()->bounds().ToString());
2798 EXPECT_EQ("9,10 100x100", w121->layer()->bounds().ToString());
2803 // Verifies bounds of layerless windows are correctly updated when bounds
2804 // of ancestor changes.
2805 TEST_F(WindowTest, NestedLayerlessWindowsBoundsOnSetBounds) {
2806 // Creates the following structure (all children owned by root):
2814 // ll: layer less, eg no layer
2816 root.Init(WINDOW_LAYER_NOT_DRAWN);
2817 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2819 Window* w1ll = new Window(NULL);
2820 w1ll->Init(WINDOW_LAYER_NONE);
2821 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
2823 Window* w11ll = new Window(NULL);
2824 w11ll->Init(WINDOW_LAYER_NONE);
2825 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
2826 w1ll->AddChild(w11ll);
2828 Window* w111 = new Window(NULL);
2829 w111->Init(WINDOW_LAYER_NOT_DRAWN);
2830 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2831 w11ll->AddChild(w111);
2833 Window* w12 = new Window(NULL);
2834 w12->Init(WINDOW_LAYER_NOT_DRAWN);
2835 w12->SetBounds(gfx::Rect(7, 8, 100, 100));
2836 w1ll->AddChild(w12);
2838 Window* w121 = new Window(NULL);
2839 w121->Init(WINDOW_LAYER_NOT_DRAWN);
2840 w121->SetBounds(gfx::Rect(9, 10, 100, 100));
2841 w12->AddChild(w121);
2843 root.AddChild(w1ll);
2845 w111->SetBounds(gfx::Rect(7, 8, 11, 12));
2846 EXPECT_EQ("7,8 11x12", w111->bounds().ToString());
2847 EXPECT_EQ("7,8 11x12", w111->GetTargetBounds().ToString());
2848 EXPECT_EQ("11,14 11x12", w111->layer()->bounds().ToString());
2851 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2852 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2853 EXPECT_EQ("5,6 100x100", w111->GetTargetBounds().ToString());
2854 EXPECT_EQ("9,12 100x100", w111->layer()->bounds().ToString());
2856 // Setting the bounds of a layerless window needs to adjust the bounds of
2857 // layered children.
2858 w11ll->SetBounds(gfx::Rect(5, 6, 100, 100));
2859 EXPECT_EQ("5,6 100x100", w11ll->bounds().ToString());
2860 EXPECT_EQ("5,6 100x100", w11ll->GetTargetBounds().ToString());
2861 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2862 EXPECT_EQ("5,6 100x100", w111->GetTargetBounds().ToString());
2863 EXPECT_EQ("11,14 100x100", w111->layer()->bounds().ToString());
2865 root.RemoveChild(w1ll);
2867 w111->SetBounds(gfx::Rect(7, 8, 11, 12));
2868 EXPECT_EQ("7,8 11x12", w111->bounds().ToString());
2869 EXPECT_EQ("7,8 11x12", w111->GetTargetBounds().ToString());
2870 EXPECT_EQ("7,8 11x12", w111->layer()->bounds().ToString());
2877 // Tracks the number of times paint is invoked along with what the clip and
2879 class PaintWindowDelegate : public TestWindowDelegate {
2881 PaintWindowDelegate() : paint_count_(0) {}
2882 virtual ~PaintWindowDelegate() {}
2884 const gfx::Rect& most_recent_paint_clip_bounds() const {
2885 return most_recent_paint_clip_bounds_;
2888 const gfx::Vector2d& most_recent_paint_matrix_offset() const {
2889 return most_recent_paint_matrix_offset_;
2892 void clear_paint_count() { paint_count_ = 0; }
2893 int paint_count() const { return paint_count_; }
2895 // TestWindowDelegate::
2896 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
2898 canvas->GetClipBounds(&most_recent_paint_clip_bounds_);
2899 const SkMatrix& matrix = canvas->sk_canvas()->getTotalMatrix();
2900 most_recent_paint_matrix_offset_ = gfx::Vector2d(
2901 SkScalarFloorToInt(matrix.getTranslateX()),
2902 SkScalarFloorToInt(matrix.getTranslateY()));
2907 gfx::Rect most_recent_paint_clip_bounds_;
2908 gfx::Vector2d most_recent_paint_matrix_offset_;
2910 DISALLOW_COPY_AND_ASSIGN(PaintWindowDelegate);
2915 // Assertions around layerless children being painted when non-layerless window
2917 TEST_F(WindowTest, PaintLayerless) {
2918 // Creates the following structure (all children owned by root):
2924 // ll: layer less, eg no layer
2925 PaintWindowDelegate w1ll_delegate;
2926 PaintWindowDelegate w11ll_delegate;
2927 PaintWindowDelegate w111_delegate;
2930 root.Init(WINDOW_LAYER_NOT_DRAWN);
2931 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2933 Window* w1ll = new Window(&w1ll_delegate);
2934 w1ll->Init(WINDOW_LAYER_NONE);
2935 w1ll->SetBounds(gfx::Rect(1, 2, 40, 50));
2937 root.AddChild(w1ll);
2939 Window* w11ll = new Window(&w11ll_delegate);
2940 w11ll->Init(WINDOW_LAYER_NONE);
2941 w11ll->SetBounds(gfx::Rect(3, 4, 11, 12));
2943 w1ll->AddChild(w11ll);
2945 Window* w111 = new Window(&w111_delegate);
2946 w111->Init(WINDOW_LAYER_NOT_DRAWN);
2947 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2949 w11ll->AddChild(w111);
2951 EXPECT_EQ(0, w1ll_delegate.paint_count());
2952 EXPECT_EQ(0, w11ll_delegate.paint_count());
2953 EXPECT_EQ(0, w111_delegate.paint_count());
2955 // Paint the root, this should trigger painting of the two layerless
2956 // descendants but not the layered descendant.
2957 gfx::Canvas canvas(gfx::Size(200, 200), 1.0f, true);
2958 static_cast<ui::LayerDelegate&>(root).OnPaintLayer(&canvas);
2960 // NOTE: SkCanvas::getClipBounds() extends the clip 1 pixel to the left and up
2961 // and 2 pixels down and to the right.
2962 EXPECT_EQ(1, w1ll_delegate.paint_count());
2963 EXPECT_EQ("-1,-1 42x52",
2964 w1ll_delegate.most_recent_paint_clip_bounds().ToString());
2966 w1ll_delegate.most_recent_paint_matrix_offset().ToString());
2967 EXPECT_EQ(1, w11ll_delegate.paint_count());
2968 EXPECT_EQ("-1,-1 13x14",
2969 w11ll_delegate.most_recent_paint_clip_bounds().ToString());
2971 w11ll_delegate.most_recent_paint_matrix_offset().ToString());
2972 EXPECT_EQ(0, w111_delegate.paint_count());
2977 std::string ConvertPointToTargetString(const Window* source,
2978 const Window* target) {
2979 gfx::Point location;
2980 Window::ConvertPointToTarget(source, target, &location);
2981 return location.ToString();
2986 // Assertions around Window::ConvertPointToTarget() with layerless windows.
2987 TEST_F(WindowTest, ConvertPointToTargetLayerless) {
2988 // Creates the following structure (all children owned by root):
2996 // ll: layer less, eg no layer
2998 root.Init(WINDOW_LAYER_NOT_DRAWN);
2999 root.SetBounds(gfx::Rect(0, 0, 100, 100));
3001 Window* w1ll = new Window(NULL);
3002 w1ll->Init(WINDOW_LAYER_NONE);
3003 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
3005 Window* w11ll = new Window(NULL);
3006 w11ll->Init(WINDOW_LAYER_NONE);
3007 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
3008 w1ll->AddChild(w11ll);
3010 Window* w111 = new Window(NULL);
3011 w111->Init(WINDOW_LAYER_NOT_DRAWN);
3012 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
3013 w11ll->AddChild(w111);
3015 Window* w12 = new Window(NULL);
3016 w12->Init(WINDOW_LAYER_NOT_DRAWN);
3017 w12->SetBounds(gfx::Rect(7, 8, 100, 100));
3018 w1ll->AddChild(w12);
3020 Window* w121 = new Window(NULL);
3021 w121->Init(WINDOW_LAYER_NOT_DRAWN);
3022 w121->SetBounds(gfx::Rect(9, 10, 100, 100));
3023 w12->AddChild(w121);
3025 root.AddChild(w1ll);
3028 EXPECT_EQ("5,6", ConvertPointToTargetString(w111, w11ll));
3031 EXPECT_EQ("8,10", ConvertPointToTargetString(w111, w1ll));
3034 EXPECT_EQ("9,12", ConvertPointToTargetString(w111, &root));
3037 EXPECT_EQ("1,2", ConvertPointToTargetString(w111, w12));
3040 EXPECT_EQ("-8,-8", ConvertPointToTargetString(w111, w121));
3043 EXPECT_EQ("-5,-6", ConvertPointToTargetString(w11ll, w111));
3046 EXPECT_EQ("3,4", ConvertPointToTargetString(w11ll, w1ll));
3049 EXPECT_EQ("4,6", ConvertPointToTargetString(w11ll, &root));
3052 EXPECT_EQ("-4,-4", ConvertPointToTargetString(w11ll, w12));
3055 #if !defined(NDEBUG)
3056 // Verifies PrintWindowHierarchy() doesn't crash with a layerless window.
3057 TEST_F(WindowTest, PrintWindowHierarchyNotCrashLayerless) {
3059 root.Init(WINDOW_LAYER_NONE);
3060 root.SetBounds(gfx::Rect(0, 0, 100, 100));
3061 root.PrintWindowHierarchy(0);
3067 // See AddWindowsFromString() for details.
3068 aura::Window* CreateWindowFromDescription(const std::string& description,
3069 WindowDelegate* delegate) {
3070 WindowLayerType window_type = WINDOW_LAYER_NOT_DRAWN;
3071 std::vector<std::string> tokens;
3072 Tokenize(description, ":", &tokens);
3073 DCHECK(!tokens.empty());
3074 std::string name(tokens[0]);
3075 tokens.erase(tokens.begin());
3076 if (!tokens.empty()) {
3077 if (tokens[0] == "ll") {
3078 window_type = WINDOW_LAYER_NONE;
3079 tokens.erase(tokens.begin());
3081 DCHECK(tokens.empty()) << "unknown tokens for creating window "
3084 Window* window = new Window(delegate);
3085 window->Init(window_type);
3086 window->SetName(name);
3087 // Window name is only propagated to layer in debug builds.
3088 if (window->layer())
3089 window->layer()->set_name(name);
3093 // Creates and adds a tree of windows to |parent|. |description| consists
3094 // of the following pieces:
3095 // X: Identifies a new window. Consists of a name and optionally ":ll" to
3096 // specify WINDOW_LAYER_NONE, eg "w1:ll".
3097 // []: optionally used to specify the children of the window. Contains any
3098 // number of window identifiers and their corresponding children.
3099 // For example: "[ a [ a1 a2:ll ] b c [ c1 ] ]" creates the tree:
3102 // a2 -> WINDOW_LAYER_NONE.
3106 // NOTE: you must have a space after every token.
3107 std::string::size_type AddWindowsFromString(aura::Window* parent,
3108 const std::string& description,
3109 std::string::size_type start_pos,
3110 WindowDelegate* delegate) {
3112 std::string::size_type end_pos = description.find(' ', start_pos);
3113 while (end_pos != std::string::npos) {
3114 const std::string::size_type part_length = end_pos - start_pos;
3115 const std::string window_description =
3116 description.substr(start_pos, part_length);
3117 if (window_description == "[") {
3118 start_pos = AddWindowsFromString(parent->children().back(),
3122 end_pos = description.find(' ', start_pos);
3123 if (end_pos == std::string::npos && start_pos != end_pos)
3124 end_pos = description.length();
3125 } else if (window_description == "]") {
3130 CreateWindowFromDescription(window_description, delegate);
3131 parent->AddChild(window);
3132 start_pos = ++end_pos;
3133 end_pos = description.find(' ', start_pos);
3139 // Used by BuildRootWindowTreeDescription().
3140 std::string BuildWindowTreeDescription(const aura::Window& window) {
3142 result += window.name();
3143 if (window.children().empty())
3147 for (size_t i = 0; i < window.children().size(); ++i) {
3150 result += BuildWindowTreeDescription(*(window.children()[i]));
3156 // Creates a string from |window|. See AddWindowsFromString() for details of the
3157 // returned string. This does *not* include the layer type in the description,
3159 std::string BuildRootWindowTreeDescription(const aura::Window& window) {
3161 for (size_t i = 0; i < window.children().size(); ++i) {
3164 result += BuildWindowTreeDescription(*(window.children()[i]));
3169 // Used by BuildRootWindowTreeDescription().
3170 std::string BuildLayerTreeDescription(const ui::Layer& layer) {
3172 result += layer.name();
3173 if (layer.children().empty())
3177 for (size_t i = 0; i < layer.children().size(); ++i) {
3180 result += BuildLayerTreeDescription(*(layer.children()[i]));
3186 // Builds a string for all the children of |layer|. The returned string is in
3187 // the same format as AddWindowsFromString() but only includes the name of the
3189 std::string BuildRootLayerTreeDescription(const ui::Layer& layer) {
3191 for (size_t i = 0; i < layer.children().size(); ++i) {
3194 result += BuildLayerTreeDescription(*(layer.children()[i]));
3199 // Returns the first window whose name matches |name| in |parent|.
3200 aura::Window* FindWindowByName(aura::Window* parent,
3201 const std::string& name) {
3202 if (parent->name() == name)
3204 for (size_t i = 0; i < parent->children().size(); ++i) {
3205 aura::Window* child = FindWindowByName(parent->children()[i], name);
3214 // Direction to stack.
3222 // Permutations of StackChildAt with various data.
3223 TEST_F(WindowTest, StackChildAtLayerless) {
3225 // Describes the window tree to create. See AddWindowsFromString() for
3227 const std::string initial_description;
3229 // Identifies the window to move.
3230 const std::string source_window;
3232 // Window to move |source_window| relative to. Not used for STACK_AT_BOTTOM
3234 const std::string target_window;
3236 StackType stack_type;
3238 // Expected window and layer results.
3239 const std::string expected_description;
3240 const std::string expected_layer_description;
3244 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3248 "2 [ 21 ] 1 [ 11 12 ]",
3254 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3258 "1 [ 11 12 ] 2 [ 21 ]",
3264 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3268 "2 [ 21 ] 1 [ 11 12 ]",
3274 "1:ll [ 11 12 ] 2:ll [ 21 ] 3:ll",
3278 "1 [ 11 12 ] 3 2 [ 21 ]",
3284 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3288 "2 [ 21 ] 1 [ 11 12 ]",
3294 "1:ll [ 11 12 ] 2:ll [ 21 ] 3:ll",
3298 "2 [ 21 ] 3 1 [ 11 12 ]",
3304 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3308 "2 [ 21 ] 1 [ 11 12 ]",
3312 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
3313 test::TestWindowDelegate delegate;
3315 root.Init(WINDOW_LAYER_NOT_DRAWN);
3316 root.SetBounds(gfx::Rect(0, 0, 100, 100));
3317 AddWindowsFromString(
3319 data[i].initial_description,
3320 static_cast<std::string::size_type>(0), &delegate);
3321 aura::Window* source = FindWindowByName(&root, data[i].source_window);
3322 ASSERT_TRUE(source != NULL) << "unable to find source window "
3323 << data[i].source_window << " at " << i;
3324 aura::Window* target = FindWindowByName(&root, data[i].target_window);
3325 switch (data[i].stack_type) {
3327 ASSERT_TRUE(target != NULL) << "unable to find target window "
3328 << data[i].target_window << " at " << i;
3329 source->parent()->StackChildAbove(source, target);
3332 ASSERT_TRUE(target != NULL) << "unable to find target window "
3333 << data[i].target_window << " at " << i;
3334 source->parent()->StackChildBelow(source, target);
3336 case STACK_AT_BOTTOM:
3337 source->parent()->StackChildAtBottom(source);
3340 source->parent()->StackChildAtTop(source);
3343 EXPECT_EQ(data[i].expected_layer_description,
3344 BuildRootLayerTreeDescription(*root.layer()))
3345 << "layer tree doesn't match at " << i;
3346 EXPECT_EQ(data[i].expected_description,
3347 BuildRootWindowTreeDescription(root))
3348 << "window tree doesn't match at " << i;