Add persisted preference for projection touch HUD
[chromium-blink-merge.git] / ui / aura / window_unittest.cc
blob320d1a61f7b052bc61c95eaa2ebe159bf019f1af
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"
7 #include <utility>
9 #include "base/basictypes.h"
10 #include "base/compiler_specific.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/stringprintf.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "ui/aura/client/capture_client.h"
15 #include "ui/aura/client/focus_change_observer.h"
16 #include "ui/aura/client/stacking_client.h"
17 #include "ui/aura/client/visibility_client.h"
18 #include "ui/aura/layout_manager.h"
19 #include "ui/aura/root_window.h"
20 #include "ui/aura/root_window_host.h"
21 #include "ui/aura/root_window_observer.h"
22 #include "ui/aura/test/aura_test_base.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_observer.h"
29 #include "ui/aura/window_property.h"
30 #include "ui/base/events/event.h"
31 #include "ui/base/events/event_utils.h"
32 #include "ui/base/gestures/gesture_configuration.h"
33 #include "ui/base/hit_test.h"
34 #include "ui/base/keycodes/keyboard_codes.h"
35 #include "ui/compositor/layer.h"
36 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
37 #include "ui/compositor/scoped_layer_animation_settings.h"
38 #include "ui/compositor/test/test_layers.h"
39 #include "ui/gfx/canvas.h"
40 #include "ui/gfx/screen.h"
42 DECLARE_WINDOW_PROPERTY_TYPE(const char*)
43 DECLARE_WINDOW_PROPERTY_TYPE(int)
45 namespace aura {
46 namespace test {
48 class WindowTest : public AuraTestBase {
49 public:
50 WindowTest() : max_separation_(0) {
53 virtual void SetUp() OVERRIDE {
54 AuraTestBase::SetUp();
55 // TODO: there needs to be an easier way to do this.
56 max_separation_ = ui::GestureConfiguration::
57 max_separation_for_gesture_touches_in_pixels();
58 ui::GestureConfiguration::
59 set_max_separation_for_gesture_touches_in_pixels(0);
62 virtual void TearDown() OVERRIDE {
63 AuraTestBase::TearDown();
64 ui::GestureConfiguration::
65 set_max_separation_for_gesture_touches_in_pixels(max_separation_);
68 // Adds |window| to |root_window_|, through the StackingClient.
69 void SetDefaultParentByPrimaryRootWindow(aura::Window* window) {
70 window->SetDefaultParentByRootWindow(root_window(), gfx::Rect());
73 private:
74 int max_separation_;
76 DISALLOW_COPY_AND_ASSIGN(WindowTest);
79 namespace {
81 // Used for verifying destruction methods are invoked.
82 class DestroyTrackingDelegateImpl : public TestWindowDelegate {
83 public:
84 DestroyTrackingDelegateImpl()
85 : destroying_count_(0),
86 destroyed_count_(0),
87 in_destroying_(false) {}
89 void clear_destroying_count() { destroying_count_ = 0; }
90 int destroying_count() const { return destroying_count_; }
92 void clear_destroyed_count() { destroyed_count_ = 0; }
93 int destroyed_count() const { return destroyed_count_; }
95 bool in_destroying() const { return in_destroying_; }
97 virtual void OnWindowDestroying() OVERRIDE {
98 EXPECT_FALSE(in_destroying_);
99 in_destroying_ = true;
100 destroying_count_++;
103 virtual void OnWindowDestroyed() OVERRIDE {
104 EXPECT_TRUE(in_destroying_);
105 in_destroying_ = false;
106 destroyed_count_++;
109 private:
110 int destroying_count_;
111 int destroyed_count_;
112 bool in_destroying_;
114 DISALLOW_COPY_AND_ASSIGN(DestroyTrackingDelegateImpl);
117 // Used to verify that when OnWindowDestroying is invoked the parent is also
118 // is in the process of being destroyed.
119 class ChildWindowDelegateImpl : public DestroyTrackingDelegateImpl {
120 public:
121 explicit ChildWindowDelegateImpl(
122 DestroyTrackingDelegateImpl* parent_delegate)
123 : parent_delegate_(parent_delegate) {
126 virtual void OnWindowDestroying() OVERRIDE {
127 EXPECT_TRUE(parent_delegate_->in_destroying());
128 DestroyTrackingDelegateImpl::OnWindowDestroying();
131 private:
132 DestroyTrackingDelegateImpl* parent_delegate_;
134 DISALLOW_COPY_AND_ASSIGN(ChildWindowDelegateImpl);
137 // Used to verify that a Window is removed from its parent when
138 // OnWindowDestroyed is called.
139 class DestroyOrphanDelegate : public TestWindowDelegate {
140 public:
141 DestroyOrphanDelegate() : window_(NULL) {
144 void set_window(Window* window) { window_ = window; }
146 virtual void OnWindowDestroyed() OVERRIDE {
147 EXPECT_FALSE(window_->parent());
150 private:
151 Window* window_;
152 DISALLOW_COPY_AND_ASSIGN(DestroyOrphanDelegate);
155 // Used in verifying mouse capture.
156 class CaptureWindowDelegateImpl : public TestWindowDelegate {
157 public:
158 CaptureWindowDelegateImpl() {
159 ResetCounts();
162 void ResetCounts() {
163 capture_changed_event_count_ = 0;
164 capture_lost_count_ = 0;
165 mouse_event_count_ = 0;
166 touch_event_count_ = 0;
167 gesture_event_count_ = 0;
170 int capture_changed_event_count() const {
171 return capture_changed_event_count_;
173 int capture_lost_count() const { return capture_lost_count_; }
174 int mouse_event_count() const { return mouse_event_count_; }
175 int touch_event_count() const { return touch_event_count_; }
176 int gesture_event_count() const { return gesture_event_count_; }
178 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
179 if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
180 capture_changed_event_count_++;
181 mouse_event_count_++;
183 virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE {
184 touch_event_count_++;
186 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
187 gesture_event_count_++;
189 virtual void OnCaptureLost() OVERRIDE {
190 capture_lost_count_++;
193 private:
194 int capture_changed_event_count_;
195 int capture_lost_count_;
196 int mouse_event_count_;
197 int touch_event_count_;
198 int gesture_event_count_;
200 DISALLOW_COPY_AND_ASSIGN(CaptureWindowDelegateImpl);
203 // aura::WindowDelegate that tracks the window that was reported as having the
204 // focus before us.
205 class FocusDelegate : public TestWindowDelegate,
206 public aura::client::FocusChangeObserver {
207 public:
208 FocusDelegate() : previous_focused_window_(NULL) {
211 aura::Window* previous_focused_window() const {
212 return previous_focused_window_;
215 // Overridden from client::FocusChangeObserver:
216 virtual void OnWindowFocused(Window* gained_focus,
217 Window* lost_focus) OVERRIDE {
218 previous_focused_window_ = lost_focus;
221 private:
222 aura::Window* previous_focused_window_;
224 DISALLOW_COPY_AND_ASSIGN(FocusDelegate);
227 // Keeps track of the location of the gesture.
228 class GestureTrackPositionDelegate : public TestWindowDelegate {
229 public:
230 GestureTrackPositionDelegate() {}
232 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
233 position_ = event->location();
234 event->StopPropagation();
237 const gfx::Point& position() const { return position_; }
239 private:
240 gfx::Point position_;
242 DISALLOW_COPY_AND_ASSIGN(GestureTrackPositionDelegate);
245 base::TimeDelta getTime() {
246 return ui::EventTimeForNow();
249 class SelfEventHandlingWindowDelegate : public TestWindowDelegate {
250 public:
251 SelfEventHandlingWindowDelegate() {}
253 virtual bool ShouldDescendIntoChildForEventHandling(
254 Window* child,
255 const gfx::Point& location) OVERRIDE {
256 return false;
259 private:
260 DISALLOW_COPY_AND_ASSIGN(SelfEventHandlingWindowDelegate);
263 // The delegate deletes itself when the window is being destroyed.
264 class DestroyWindowDelegate : public TestWindowDelegate {
265 public:
266 DestroyWindowDelegate() {}
268 private:
269 virtual ~DestroyWindowDelegate() {}
271 // Overridden from WindowDelegate.
272 virtual void OnWindowDestroyed() OVERRIDE {
273 delete this;
276 DISALLOW_COPY_AND_ASSIGN(DestroyWindowDelegate);
279 } // namespace
281 TEST_F(WindowTest, GetChildById) {
282 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
283 scoped_ptr<Window> w11(CreateTestWindowWithId(11, w1.get()));
284 scoped_ptr<Window> w111(CreateTestWindowWithId(111, w11.get()));
285 scoped_ptr<Window> w12(CreateTestWindowWithId(12, w1.get()));
287 EXPECT_EQ(NULL, w1->GetChildById(57));
288 EXPECT_EQ(w12.get(), w1->GetChildById(12));
289 EXPECT_EQ(w111.get(), w1->GetChildById(111));
292 // Make sure that Window::Contains correctly handles children, grandchildren,
293 // and not containing NULL or parents.
294 TEST_F(WindowTest, Contains) {
295 Window parent(NULL);
296 parent.Init(ui::LAYER_NOT_DRAWN);
297 Window child1(NULL);
298 child1.Init(ui::LAYER_NOT_DRAWN);
299 Window child2(NULL);
300 child2.Init(ui::LAYER_NOT_DRAWN);
302 parent.AddChild(&child1);
303 child1.AddChild(&child2);
305 EXPECT_TRUE(parent.Contains(&parent));
306 EXPECT_TRUE(parent.Contains(&child1));
307 EXPECT_TRUE(parent.Contains(&child2));
309 EXPECT_FALSE(parent.Contains(NULL));
310 EXPECT_FALSE(child1.Contains(&parent));
311 EXPECT_FALSE(child2.Contains(&child1));
314 TEST_F(WindowTest, ContainsPointInRoot) {
315 scoped_ptr<Window> w(
316 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 5, 5),
317 root_window()));
318 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(9, 9)));
319 EXPECT_TRUE(w->ContainsPointInRoot(gfx::Point(10, 10)));
320 EXPECT_TRUE(w->ContainsPointInRoot(gfx::Point(14, 14)));
321 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(15, 15)));
322 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(20, 20)));
325 TEST_F(WindowTest, ContainsPoint) {
326 scoped_ptr<Window> w(
327 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 5, 5),
328 root_window()));
329 EXPECT_TRUE(w->ContainsPoint(gfx::Point(0, 0)));
330 EXPECT_TRUE(w->ContainsPoint(gfx::Point(4, 4)));
331 EXPECT_FALSE(w->ContainsPoint(gfx::Point(5, 5)));
332 EXPECT_FALSE(w->ContainsPoint(gfx::Point(10, 10)));
335 TEST_F(WindowTest, ConvertPointToWindow) {
336 // Window::ConvertPointToWindow is mostly identical to
337 // Layer::ConvertPointToLayer, except NULL values for |source| are permitted,
338 // in which case the function just returns.
339 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
340 gfx::Point reference_point(100, 100);
341 gfx::Point test_point = reference_point;
342 Window::ConvertPointToTarget(NULL, w1.get(), &test_point);
343 EXPECT_EQ(reference_point, test_point);
346 TEST_F(WindowTest, MoveCursorTo) {
347 scoped_ptr<Window> w1(
348 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
349 root_window()));
350 scoped_ptr<Window> w11(
351 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
352 scoped_ptr<Window> w111(
353 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
354 scoped_ptr<Window> w1111(
355 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
357 RootWindow* root = root_window();
358 root->MoveCursorTo(gfx::Point(10, 10));
359 EXPECT_EQ("10,10",
360 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
361 w1->MoveCursorTo(gfx::Point(10, 10));
362 EXPECT_EQ("20,20",
363 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
364 w11->MoveCursorTo(gfx::Point(10, 10));
365 EXPECT_EQ("25,25",
366 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
367 w111->MoveCursorTo(gfx::Point(10, 10));
368 EXPECT_EQ("30,30",
369 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
370 w1111->MoveCursorTo(gfx::Point(10, 10));
371 EXPECT_EQ("35,35",
372 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
375 TEST_F(WindowTest, ContainsMouse) {
376 scoped_ptr<Window> w(
377 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
378 root_window()));
379 w->Show();
380 WindowTestApi w_test_api(w.get());
381 RootWindow* root = root_window();
382 root->MoveCursorTo(gfx::Point(10, 10));
383 EXPECT_TRUE(w_test_api.ContainsMouse());
384 root->MoveCursorTo(gfx::Point(9, 10));
385 EXPECT_FALSE(w_test_api.ContainsMouse());
388 // Test Window::ConvertPointToWindow() with transform to root_window.
389 #if defined(USE_OZONE)
390 // TODO(rjkroege): Add cursor support in ozone: http://crbug.com/252315.
391 TEST_F(WindowTest, DISABLED_MoveCursorToWithTransformRootWindow) {
392 #else
393 TEST_F(WindowTest, MoveCursorToWithTransformRootWindow) {
394 #endif
395 RootWindow* root = root_window();
396 gfx::Transform transform;
397 transform.Translate(100.0, 100.0);
398 transform.Rotate(90.0);
399 transform.Scale(2.0, 5.0);
400 root->SetTransform(transform);
401 root->MoveCursorTo(gfx::Point(10, 10));
402 #if !defined(OS_WIN)
403 gfx::Point mouse_location;
404 EXPECT_TRUE(root->QueryMouseLocationForTest(&mouse_location));
405 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.OD
406 EXPECT_EQ("50,120", mouse_location.ToString());
407 #endif
408 EXPECT_EQ("10,10",
409 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
412 // Tests Window::ConvertPointToWindow() with transform to non-root windows.
413 TEST_F(WindowTest, MoveCursorToWithTransformWindow) {
414 scoped_ptr<Window> w1(
415 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
416 root_window()));
418 gfx::Transform transform1;
419 transform1.Scale(2, 2);
420 w1->SetTransform(transform1);
421 w1->MoveCursorTo(gfx::Point(10, 10));
422 EXPECT_EQ("30,30",
423 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
425 gfx::Transform transform2;
426 transform2.Translate(-10, 20);
427 w1->SetTransform(transform2);
428 w1->MoveCursorTo(gfx::Point(10, 10));
429 EXPECT_EQ("10,40",
430 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
432 gfx::Transform transform3;
433 transform3.Rotate(90.0);
434 w1->SetTransform(transform3);
435 w1->MoveCursorTo(gfx::Point(5, 5));
436 EXPECT_EQ("5,15",
437 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
439 gfx::Transform transform4;
440 transform4.Translate(100.0, 100.0);
441 transform4.Rotate(90.0);
442 transform4.Scale(2.0, 5.0);
443 w1->SetTransform(transform4);
444 w1->MoveCursorTo(gfx::Point(10, 10));
445 EXPECT_EQ("60,130",
446 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
449 // Test Window::ConvertPointToWindow() with complex transforms to both root and
450 // non-root windows.
451 // Test Window::ConvertPointToWindow() with transform to root_window.
452 #if defined(USE_OZONE)
453 // TODO(rjkroege): Add cursor support in ozone: http://crbug.com/252315.
454 TEST_F(WindowTest, DISABLED_MoveCursorToWithComplexTransform) {
455 #else
456 TEST_F(WindowTest, MoveCursorToWithComplexTransform) {
457 #endif
458 scoped_ptr<Window> w1(
459 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
460 root_window()));
461 scoped_ptr<Window> w11(
462 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
463 scoped_ptr<Window> w111(
464 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
465 scoped_ptr<Window> w1111(
466 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
468 RootWindow* root = root_window();
470 // The root window expects transforms that produce integer rects.
471 gfx::Transform root_transform;
472 root_transform.Translate(60.0, 70.0);
473 root_transform.Rotate(-90.0);
474 root_transform.Translate(-50.0, -50.0);
475 root_transform.Scale(2.0, 3.0);
477 gfx::Transform transform;
478 transform.Translate(10.0, 20.0);
479 transform.Rotate(10.0);
480 transform.Scale(0.3, 0.5);
481 root->SetTransform(root_transform);
482 w1->SetTransform(transform);
483 w11->SetTransform(transform);
484 w111->SetTransform(transform);
485 w1111->SetTransform(transform);
487 w1111->MoveCursorTo(gfx::Point(10, 10));
489 #if !defined(OS_WIN)
490 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.
491 gfx::Point mouse_location;
492 EXPECT_TRUE(root->QueryMouseLocationForTest(&mouse_location));
493 EXPECT_EQ("169,80", mouse_location.ToString());
494 #endif
495 EXPECT_EQ("20,53",
496 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
499 TEST_F(WindowTest, HitTest) {
500 Window w1(new ColorTestWindowDelegate(SK_ColorWHITE));
501 w1.set_id(1);
502 w1.Init(ui::LAYER_TEXTURED);
503 w1.SetBounds(gfx::Rect(10, 20, 50, 60));
504 w1.Show();
505 SetDefaultParentByPrimaryRootWindow(&w1);
507 // Points are in the Window's coordinates.
508 EXPECT_TRUE(w1.HitTest(gfx::Point(1, 1)));
509 EXPECT_FALSE(w1.HitTest(gfx::Point(-1, -1)));
511 // We can expand the bounds slightly to track events outside our border.
512 w1.SetHitTestBoundsOverrideOuter(gfx::Insets(-1, -1, -1, -1),
513 gfx::Insets(-5, -5, -5, -5));
514 EXPECT_TRUE(w1.HitTest(gfx::Point(-1, -1)));
515 EXPECT_FALSE(w1.HitTest(gfx::Point(-2, -2)));
517 ui::TouchEvent pressed(
518 ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), 0, getTime());
519 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&pressed);
520 EXPECT_TRUE(w1.HitTest(gfx::Point(-2, -2)));
521 EXPECT_TRUE(w1.HitTest(gfx::Point(-5, -5)));
522 EXPECT_FALSE(w1.HitTest(gfx::Point(-5, -6)));
523 ui::TouchEvent released(
524 ui::ET_TOUCH_RELEASED, gfx::Point(50, 50), 0, getTime());
525 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&released);
526 EXPECT_FALSE(w1.HitTest(gfx::Point(-2, -2)));
528 // TODO(beng): clip Window to parent.
531 TEST_F(WindowTest, HitTestMask) {
532 MaskedWindowDelegate d1(gfx::Rect(5, 6, 20, 30));
533 Window w1(&d1);
534 w1.Init(ui::LAYER_NOT_DRAWN);
535 w1.SetBounds(gfx::Rect(10, 20, 50, 60));
536 w1.Show();
537 SetDefaultParentByPrimaryRootWindow(&w1);
539 // Points inside the mask.
540 EXPECT_TRUE(w1.HitTest(gfx::Point(5, 6))); // top-left
541 EXPECT_TRUE(w1.HitTest(gfx::Point(15, 21))); // center
542 EXPECT_TRUE(w1.HitTest(gfx::Point(24, 35))); // bottom-right
544 // Points outside the mask.
545 EXPECT_FALSE(w1.HitTest(gfx::Point(0, 0)));
546 EXPECT_FALSE(w1.HitTest(gfx::Point(60, 80)));
547 EXPECT_FALSE(w1.HitTest(gfx::Point(4, 6)));
548 EXPECT_FALSE(w1.HitTest(gfx::Point(5, 5)));
549 EXPECT_FALSE(w1.HitTest(gfx::Point(25, 36)));
552 TEST_F(WindowTest, GetEventHandlerForPoint) {
553 scoped_ptr<Window> w1(
554 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
555 root_window()));
556 scoped_ptr<Window> w11(
557 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
558 scoped_ptr<Window> w111(
559 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
560 scoped_ptr<Window> w1111(
561 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
562 scoped_ptr<Window> w12(
563 CreateTestWindow(SK_ColorMAGENTA, 12, gfx::Rect(10, 420, 25, 25),
564 w1.get()));
565 scoped_ptr<Window> w121(
566 CreateTestWindow(SK_ColorYELLOW, 121, gfx::Rect(5, 5, 5, 5), w12.get()));
567 scoped_ptr<Window> w13(
568 CreateTestWindow(SK_ColorGRAY, 13, gfx::Rect(5, 470, 50, 50), w1.get()));
570 Window* root = root_window();
571 w1->parent()->SetBounds(gfx::Rect(500, 500));
572 EXPECT_EQ(NULL, root->GetEventHandlerForPoint(gfx::Point(5, 5)));
573 EXPECT_EQ(w1.get(), root->GetEventHandlerForPoint(gfx::Point(11, 11)));
574 EXPECT_EQ(w11.get(), root->GetEventHandlerForPoint(gfx::Point(16, 16)));
575 EXPECT_EQ(w111.get(), root->GetEventHandlerForPoint(gfx::Point(21, 21)));
576 EXPECT_EQ(w1111.get(), root->GetEventHandlerForPoint(gfx::Point(26, 26)));
577 EXPECT_EQ(w12.get(), root->GetEventHandlerForPoint(gfx::Point(21, 431)));
578 EXPECT_EQ(w121.get(), root->GetEventHandlerForPoint(gfx::Point(26, 436)));
579 EXPECT_EQ(w13.get(), root->GetEventHandlerForPoint(gfx::Point(26, 481)));
582 TEST_F(WindowTest, GetEventHandlerForPointWithOverride) {
583 // If our child is flush to our top-left corner he gets events just inside the
584 // window edges.
585 scoped_ptr<Window> parent(
586 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 20, 400, 500),
587 root_window()));
588 scoped_ptr<Window> child(
589 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(0, 0, 60, 70), parent.get()));
590 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
591 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(1, 1)));
593 // We can override the hit test bounds of the parent to make the parent grab
594 // events along that edge.
595 parent->set_hit_test_bounds_override_inner(gfx::Insets(1, 1, 1, 1));
596 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
597 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(1, 1)));
600 TEST_F(WindowTest, GetEventHandlerForPointWithOverrideDescendingOrder) {
601 scoped_ptr<SelfEventHandlingWindowDelegate> parent_delegate(
602 new SelfEventHandlingWindowDelegate);
603 scoped_ptr<Window> parent(CreateTestWindowWithDelegate(
604 parent_delegate.get(), 1, gfx::Rect(10, 20, 400, 500), root_window()));
605 scoped_ptr<Window> child(
606 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(0, 0, 390, 480),
607 parent.get()));
609 // We can override ShouldDescendIntoChildForEventHandling to make the parent
610 // grab all events.
611 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
612 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(50, 50)));
615 TEST_F(WindowTest, GetTopWindowContainingPoint) {
616 Window* root = root_window();
617 root->SetBounds(gfx::Rect(0, 0, 300, 300));
619 scoped_ptr<Window> w1(
620 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 100, 100),
621 root_window()));
622 scoped_ptr<Window> w11(
623 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(0, 0, 120, 120), w1.get()));
625 scoped_ptr<Window> w2(
626 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(5, 5, 55, 55),
627 root_window()));
629 scoped_ptr<Window> w3(
630 CreateTestWindowWithDelegate(
631 NULL, 3, gfx::Rect(200, 200, 100, 100), root_window()));
632 scoped_ptr<Window> w31(
633 CreateTestWindow(SK_ColorCYAN, 31, gfx::Rect(0, 0, 50, 50), w3.get()));
634 scoped_ptr<Window> w311(
635 CreateTestWindow(SK_ColorBLUE, 311, gfx::Rect(0, 0, 10, 10), w31.get()));
637 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(0, 0)));
638 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(5, 5)));
639 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(10, 10)));
640 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(59, 59)));
641 EXPECT_EQ(w1.get(), root->GetTopWindowContainingPoint(gfx::Point(60, 60)));
642 EXPECT_EQ(w1.get(), root->GetTopWindowContainingPoint(gfx::Point(109, 109)));
643 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(110, 110)));
644 EXPECT_EQ(w31.get(), root->GetTopWindowContainingPoint(gfx::Point(200, 200)));
645 EXPECT_EQ(w31.get(), root->GetTopWindowContainingPoint(gfx::Point(220, 220)));
646 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(260, 260)));
649 TEST_F(WindowTest, GetToplevelWindow) {
650 const gfx::Rect kBounds(0, 0, 10, 10);
651 TestWindowDelegate delegate;
653 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
654 scoped_ptr<Window> w11(
655 CreateTestWindowWithDelegate(&delegate, 11, kBounds, w1.get()));
656 scoped_ptr<Window> w111(CreateTestWindowWithId(111, w11.get()));
657 scoped_ptr<Window> w1111(
658 CreateTestWindowWithDelegate(&delegate, 1111, kBounds, w111.get()));
660 EXPECT_TRUE(root_window()->GetToplevelWindow() == NULL);
661 EXPECT_TRUE(w1->GetToplevelWindow() == NULL);
662 EXPECT_EQ(w11.get(), w11->GetToplevelWindow());
663 EXPECT_EQ(w11.get(), w111->GetToplevelWindow());
664 EXPECT_EQ(w11.get(), w1111->GetToplevelWindow());
667 class AddedToRootWindowObserver : public WindowObserver {
668 public:
669 AddedToRootWindowObserver() : called_(false) {}
671 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
672 called_ = true;
675 bool called() const { return called_; }
677 private:
678 bool called_;
680 DISALLOW_COPY_AND_ASSIGN(AddedToRootWindowObserver);
683 TEST_F(WindowTest, WindowAddedToRootWindowShouldNotifyChildAndNotParent) {
684 AddedToRootWindowObserver parent_observer;
685 AddedToRootWindowObserver child_observer;
686 scoped_ptr<Window> parent_window(CreateTestWindowWithId(1, root_window()));
687 scoped_ptr<Window> child_window(new Window(NULL));
688 child_window->Init(ui::LAYER_TEXTURED);
689 child_window->Show();
691 parent_window->AddObserver(&parent_observer);
692 child_window->AddObserver(&child_observer);
694 parent_window->AddChild(child_window.get());
696 EXPECT_FALSE(parent_observer.called());
697 EXPECT_TRUE(child_observer.called());
699 parent_window->RemoveObserver(&parent_observer);
700 child_window->RemoveObserver(&child_observer);
703 // Various destruction assertions.
704 TEST_F(WindowTest, DestroyTest) {
705 DestroyTrackingDelegateImpl parent_delegate;
706 ChildWindowDelegateImpl child_delegate(&parent_delegate);
708 scoped_ptr<Window> parent(
709 CreateTestWindowWithDelegate(&parent_delegate, 0, gfx::Rect(),
710 root_window()));
711 CreateTestWindowWithDelegate(&child_delegate, 0, gfx::Rect(), parent.get());
713 // Both the parent and child should have been destroyed.
714 EXPECT_EQ(1, parent_delegate.destroying_count());
715 EXPECT_EQ(1, parent_delegate.destroyed_count());
716 EXPECT_EQ(1, child_delegate.destroying_count());
717 EXPECT_EQ(1, child_delegate.destroyed_count());
720 // Tests that a window is orphaned before OnWindowDestroyed is called.
721 TEST_F(WindowTest, OrphanedBeforeOnDestroyed) {
722 TestWindowDelegate parent_delegate;
723 DestroyOrphanDelegate child_delegate;
725 scoped_ptr<Window> parent(
726 CreateTestWindowWithDelegate(&parent_delegate, 0, gfx::Rect(),
727 root_window()));
728 scoped_ptr<Window> child(CreateTestWindowWithDelegate(&child_delegate, 0,
729 gfx::Rect(), parent.get()));
730 child_delegate.set_window(child.get());
734 // Make sure StackChildAtTop moves both the window and layer to the front.
735 TEST_F(WindowTest, StackChildAtTop) {
736 Window parent(NULL);
737 parent.Init(ui::LAYER_NOT_DRAWN);
738 Window child1(NULL);
739 child1.Init(ui::LAYER_NOT_DRAWN);
740 Window child2(NULL);
741 child2.Init(ui::LAYER_NOT_DRAWN);
743 parent.AddChild(&child1);
744 parent.AddChild(&child2);
745 ASSERT_EQ(2u, parent.children().size());
746 EXPECT_EQ(&child1, parent.children()[0]);
747 EXPECT_EQ(&child2, parent.children()[1]);
748 ASSERT_EQ(2u, parent.layer()->children().size());
749 EXPECT_EQ(child1.layer(), parent.layer()->children()[0]);
750 EXPECT_EQ(child2.layer(), parent.layer()->children()[1]);
752 parent.StackChildAtTop(&child1);
753 ASSERT_EQ(2u, parent.children().size());
754 EXPECT_EQ(&child1, parent.children()[1]);
755 EXPECT_EQ(&child2, parent.children()[0]);
756 ASSERT_EQ(2u, parent.layer()->children().size());
757 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
758 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
761 // Make sure StackChildBelow works.
762 TEST_F(WindowTest, StackChildBelow) {
763 Window parent(NULL);
764 parent.Init(ui::LAYER_NOT_DRAWN);
765 Window child1(NULL);
766 child1.Init(ui::LAYER_NOT_DRAWN);
767 child1.set_id(1);
768 Window child2(NULL);
769 child2.Init(ui::LAYER_NOT_DRAWN);
770 child2.set_id(2);
771 Window child3(NULL);
772 child3.Init(ui::LAYER_NOT_DRAWN);
773 child3.set_id(3);
775 parent.AddChild(&child1);
776 parent.AddChild(&child2);
777 parent.AddChild(&child3);
778 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent));
780 parent.StackChildBelow(&child1, &child2);
781 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent));
783 parent.StackChildBelow(&child2, &child1);
784 EXPECT_EQ("2 1 3", ChildWindowIDsAsString(&parent));
786 parent.StackChildBelow(&child3, &child2);
787 EXPECT_EQ("3 2 1", ChildWindowIDsAsString(&parent));
789 parent.StackChildBelow(&child3, &child1);
790 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(&parent));
793 // Various assertions for StackChildAbove.
794 TEST_F(WindowTest, StackChildAbove) {
795 Window parent(NULL);
796 parent.Init(ui::LAYER_NOT_DRAWN);
797 Window child1(NULL);
798 child1.Init(ui::LAYER_NOT_DRAWN);
799 Window child2(NULL);
800 child2.Init(ui::LAYER_NOT_DRAWN);
801 Window child3(NULL);
802 child3.Init(ui::LAYER_NOT_DRAWN);
804 parent.AddChild(&child1);
805 parent.AddChild(&child2);
807 // Move 1 in front of 2.
808 parent.StackChildAbove(&child1, &child2);
809 ASSERT_EQ(2u, parent.children().size());
810 EXPECT_EQ(&child2, parent.children()[0]);
811 EXPECT_EQ(&child1, parent.children()[1]);
812 ASSERT_EQ(2u, parent.layer()->children().size());
813 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
814 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
816 // Add 3, resulting in order [2, 1, 3], then move 2 in front of 1, resulting
817 // in [1, 2, 3].
818 parent.AddChild(&child3);
819 parent.StackChildAbove(&child2, &child1);
820 ASSERT_EQ(3u, parent.children().size());
821 EXPECT_EQ(&child1, parent.children()[0]);
822 EXPECT_EQ(&child2, parent.children()[1]);
823 EXPECT_EQ(&child3, parent.children()[2]);
824 ASSERT_EQ(3u, parent.layer()->children().size());
825 EXPECT_EQ(child1.layer(), parent.layer()->children()[0]);
826 EXPECT_EQ(child2.layer(), parent.layer()->children()[1]);
827 EXPECT_EQ(child3.layer(), parent.layer()->children()[2]);
829 // Move 1 in front of 3, resulting in [2, 3, 1].
830 parent.StackChildAbove(&child1, &child3);
831 ASSERT_EQ(3u, parent.children().size());
832 EXPECT_EQ(&child2, parent.children()[0]);
833 EXPECT_EQ(&child3, parent.children()[1]);
834 EXPECT_EQ(&child1, parent.children()[2]);
835 ASSERT_EQ(3u, parent.layer()->children().size());
836 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
837 EXPECT_EQ(child3.layer(), parent.layer()->children()[1]);
838 EXPECT_EQ(child1.layer(), parent.layer()->children()[2]);
840 // Moving 1 in front of 2 should lower it, resulting in [2, 1, 3].
841 parent.StackChildAbove(&child1, &child2);
842 ASSERT_EQ(3u, parent.children().size());
843 EXPECT_EQ(&child2, parent.children()[0]);
844 EXPECT_EQ(&child1, parent.children()[1]);
845 EXPECT_EQ(&child3, parent.children()[2]);
846 ASSERT_EQ(3u, parent.layer()->children().size());
847 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
848 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
849 EXPECT_EQ(child3.layer(), parent.layer()->children()[2]);
852 // Various capture assertions.
853 TEST_F(WindowTest, CaptureTests) {
854 CaptureWindowDelegateImpl delegate;
855 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
856 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
857 EXPECT_FALSE(window->HasCapture());
859 delegate.ResetCounts();
861 // Do a capture.
862 window->SetCapture();
863 EXPECT_TRUE(window->HasCapture());
864 EXPECT_EQ(0, delegate.capture_lost_count());
865 EXPECT_EQ(0, delegate.capture_changed_event_count());
866 EventGenerator generator(root_window(), gfx::Point(50, 50));
867 generator.PressLeftButton();
868 EXPECT_EQ(1, delegate.mouse_event_count());
869 generator.ReleaseLeftButton();
871 EXPECT_EQ(2, delegate.mouse_event_count());
872 delegate.ResetCounts();
874 ui::TouchEvent touchev(
875 ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), 0, getTime());
876 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&touchev);
877 EXPECT_EQ(1, delegate.touch_event_count());
878 delegate.ResetCounts();
880 window->ReleaseCapture();
881 EXPECT_FALSE(window->HasCapture());
882 EXPECT_EQ(1, delegate.capture_lost_count());
883 EXPECT_EQ(1, delegate.capture_changed_event_count());
884 EXPECT_EQ(1, delegate.mouse_event_count());
885 EXPECT_EQ(0, delegate.touch_event_count());
887 generator.PressLeftButton();
888 EXPECT_EQ(1, delegate.mouse_event_count());
890 ui::TouchEvent touchev2(
891 ui::ET_TOUCH_PRESSED, gfx::Point(250, 250), 1, getTime());
892 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&touchev2);
893 EXPECT_EQ(0, delegate.touch_event_count());
895 // Removing the capture window from parent should reset the capture window
896 // in the root window.
897 window->SetCapture();
898 EXPECT_EQ(window.get(), aura::client::GetCaptureWindow(root_window()));
899 window->parent()->RemoveChild(window.get());
900 EXPECT_FALSE(window->HasCapture());
901 EXPECT_EQ(NULL, aura::client::GetCaptureWindow(root_window()));
904 TEST_F(WindowTest, TouchCaptureCancelsOtherTouches) {
905 CaptureWindowDelegateImpl delegate1;
906 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
907 &delegate1, 0, gfx::Rect(0, 0, 50, 50), root_window()));
908 CaptureWindowDelegateImpl delegate2;
909 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
910 &delegate2, 0, gfx::Rect(50, 50, 50, 50), root_window()));
912 // Press on w1.
913 ui::TouchEvent press(
914 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
915 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
916 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
917 EXPECT_EQ(2, delegate1.gesture_event_count());
918 delegate1.ResetCounts();
920 // Capturing to w2 should cause the touch to be canceled.
921 w2->SetCapture();
922 EXPECT_EQ(1, delegate1.touch_event_count());
923 EXPECT_EQ(0, delegate2.touch_event_count());
924 delegate1.ResetCounts();
925 delegate2.ResetCounts();
927 // Events now go to w2.
928 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, getTime());
929 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move);
930 EXPECT_EQ(0, delegate1.gesture_event_count());
931 EXPECT_EQ(0, delegate1.touch_event_count());
932 EXPECT_EQ(0, delegate2.gesture_event_count());
933 EXPECT_EQ(1, delegate2.touch_event_count());
935 ui::TouchEvent release(
936 ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, getTime());
937 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
938 EXPECT_EQ(0, delegate1.gesture_event_count());
939 EXPECT_EQ(0, delegate2.gesture_event_count());
941 // A new press is captured by w2.
942 ui::TouchEvent press2(
943 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
944 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press2);
945 EXPECT_EQ(0, delegate1.gesture_event_count());
946 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
947 EXPECT_EQ(2, delegate2.gesture_event_count());
948 delegate1.ResetCounts();
949 delegate2.ResetCounts();
951 // And releasing capture changes nothing.
952 w2->ReleaseCapture();
953 EXPECT_EQ(0, delegate1.gesture_event_count());
954 EXPECT_EQ(0, delegate1.touch_event_count());
955 EXPECT_EQ(0, delegate2.gesture_event_count());
956 EXPECT_EQ(0, delegate2.touch_event_count());
959 TEST_F(WindowTest, TouchCaptureDoesntCancelCapturedTouches) {
960 CaptureWindowDelegateImpl delegate;
961 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
962 &delegate, 0, gfx::Rect(0, 0, 50, 50), root_window()));
964 ui::TouchEvent press(
965 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
966 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
968 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
969 EXPECT_EQ(2, delegate.gesture_event_count());
970 EXPECT_EQ(1, delegate.touch_event_count());
971 delegate.ResetCounts();
973 window->SetCapture();
974 EXPECT_EQ(0, delegate.gesture_event_count());
975 EXPECT_EQ(0, delegate.touch_event_count());
976 delegate.ResetCounts();
978 // On move We will get TOUCH_MOVED, GESTURE_TAP_CANCEL,
979 // GESTURE_SCROLL_START and GESTURE_SCROLL_UPDATE.
980 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, getTime());
981 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move);
982 EXPECT_EQ(1, delegate.touch_event_count());
983 EXPECT_EQ(3, delegate.gesture_event_count());
984 delegate.ResetCounts();
986 // Release capture shouldn't change anything.
987 window->ReleaseCapture();
988 EXPECT_EQ(0, delegate.touch_event_count());
989 EXPECT_EQ(0, delegate.gesture_event_count());
990 delegate.ResetCounts();
992 // On move we still get TOUCH_MOVED and GESTURE_SCROLL_UPDATE.
993 ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(10, 30), 0, getTime());
994 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&move2);
995 EXPECT_EQ(1, delegate.touch_event_count());
996 EXPECT_EQ(1, delegate.gesture_event_count());
997 delegate.ResetCounts();
999 // And on release we get TOUCH_RELEASED, GESTURE_SCROLL_END, GESTURE_END
1000 ui::TouchEvent release(
1001 ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, getTime());
1002 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&release);
1003 EXPECT_EQ(1, delegate.touch_event_count());
1004 EXPECT_EQ(2, delegate.gesture_event_count());
1008 // Assertions around SetCapture() and touch/gestures.
1009 TEST_F(WindowTest, TransferCaptureTouchEvents) {
1010 // Touch on |w1|.
1011 CaptureWindowDelegateImpl d1;
1012 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
1013 &d1, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1014 ui::TouchEvent p1(ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
1015 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&p1);
1016 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
1017 EXPECT_EQ(1, d1.touch_event_count());
1018 EXPECT_EQ(2, d1.gesture_event_count());
1019 d1.ResetCounts();
1021 // Touch on |w2| with a different id.
1022 CaptureWindowDelegateImpl d2;
1023 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
1024 &d2, 0, gfx::Rect(40, 0, 40, 20), root_window()));
1025 ui::TouchEvent p2(ui::ET_TOUCH_PRESSED, gfx::Point(41, 10), 1, getTime());
1026 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&p2);
1027 EXPECT_EQ(0, d1.touch_event_count());
1028 EXPECT_EQ(0, d1.gesture_event_count());
1029 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN for new target window.
1030 EXPECT_EQ(1, d2.touch_event_count());
1031 EXPECT_EQ(2, d2.gesture_event_count());
1032 d1.ResetCounts();
1033 d2.ResetCounts();
1035 // Set capture on |w2|, this should send a cancel (TAP_CANCEL, END) to |w1|
1036 // but not |w2|.
1037 w2->SetCapture();
1038 EXPECT_EQ(1, d1.touch_event_count());
1039 EXPECT_EQ(2, d1.gesture_event_count());
1040 EXPECT_EQ(0, d2.touch_event_count());
1041 EXPECT_EQ(0, d2.gesture_event_count());
1042 d1.ResetCounts();
1043 d2.ResetCounts();
1045 CaptureWindowDelegateImpl d3;
1046 scoped_ptr<Window> w3(CreateTestWindowWithDelegate(
1047 &d3, 0, gfx::Rect(0, 0, 100, 101), root_window()));
1048 // Set capture on w3. No new events should be received.
1049 // Note this difference in behavior between the first and second capture
1050 // is confusing and error prone. http://crbug.com/236930
1051 w3->SetCapture();
1052 EXPECT_EQ(0, d1.touch_event_count());
1053 EXPECT_EQ(0, d1.gesture_event_count());
1054 EXPECT_EQ(0, d2.touch_event_count());
1055 EXPECT_EQ(0, d2.gesture_event_count());
1056 EXPECT_EQ(0, d3.touch_event_count());
1057 EXPECT_EQ(0, d3.gesture_event_count());
1059 // Move touch id originally associated with |w2|. Since capture was transfered
1060 // from 2 to 3 only |w3| should get the event.
1061 ui::TouchEvent m3(ui::ET_TOUCH_MOVED, gfx::Point(110, 105), 1, getTime());
1062 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&m3);
1063 EXPECT_EQ(0, d1.touch_event_count());
1064 EXPECT_EQ(0, d1.gesture_event_count());
1065 EXPECT_EQ(0, d2.touch_event_count());
1066 EXPECT_EQ(0, d2.gesture_event_count());
1067 // |w3| gets a TOUCH_MOVE, TAP_CANCEL and two scroll related events.
1068 EXPECT_EQ(1, d3.touch_event_count());
1069 EXPECT_EQ(3, d3.gesture_event_count());
1070 d1.ResetCounts();
1071 d2.ResetCounts();
1072 d3.ResetCounts();
1074 // When we release capture, no touches are canceled.
1075 w3->ReleaseCapture();
1076 EXPECT_EQ(0, d1.touch_event_count());
1077 EXPECT_EQ(0, d1.gesture_event_count());
1078 EXPECT_EQ(0, d2.touch_event_count());
1079 EXPECT_EQ(0, d2.gesture_event_count());
1080 EXPECT_EQ(0, d3.touch_event_count());
1081 EXPECT_EQ(0, d3.gesture_event_count());
1083 // And when we move the touch again, |w3| still gets the events.
1084 ui::TouchEvent m4(ui::ET_TOUCH_MOVED, gfx::Point(120, 105), 1, getTime());
1085 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&m4);
1086 EXPECT_EQ(0, d1.touch_event_count());
1087 EXPECT_EQ(0, d1.gesture_event_count());
1088 EXPECT_EQ(0, d2.touch_event_count());
1089 EXPECT_EQ(0, d2.gesture_event_count());
1090 EXPECT_EQ(1, d3.touch_event_count());
1091 EXPECT_EQ(1, d3.gesture_event_count());
1092 d1.ResetCounts();
1093 d2.ResetCounts();
1094 d3.ResetCounts();
1097 // Changes capture while capture is already ongoing.
1098 TEST_F(WindowTest, ChangeCaptureWhileMouseDown) {
1099 CaptureWindowDelegateImpl delegate;
1100 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
1101 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1102 CaptureWindowDelegateImpl delegate2;
1103 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
1104 &delegate2, 0, gfx::Rect(20, 20, 20, 20), root_window()));
1106 // Execute the scheduled draws so that mouse events are not
1107 // aggregated.
1108 RunAllPendingInMessageLoop();
1110 EXPECT_FALSE(window->HasCapture());
1112 // Do a capture.
1113 delegate.ResetCounts();
1114 window->SetCapture();
1115 EXPECT_TRUE(window->HasCapture());
1116 EXPECT_EQ(0, delegate.capture_lost_count());
1117 EXPECT_EQ(0, delegate.capture_changed_event_count());
1118 EventGenerator generator(root_window(), gfx::Point(50, 50));
1119 generator.PressLeftButton();
1120 EXPECT_EQ(0, delegate.capture_lost_count());
1121 EXPECT_EQ(0, delegate.capture_changed_event_count());
1122 EXPECT_EQ(1, delegate.mouse_event_count());
1124 // Set capture to |w2|, should implicitly unset capture for |window|.
1125 delegate.ResetCounts();
1126 delegate2.ResetCounts();
1127 w2->SetCapture();
1129 generator.MoveMouseTo(gfx::Point(40, 40), 2);
1130 EXPECT_EQ(1, delegate.capture_lost_count());
1131 EXPECT_EQ(1, delegate.capture_changed_event_count());
1132 EXPECT_EQ(1, delegate.mouse_event_count());
1133 EXPECT_EQ(2, delegate2.mouse_event_count());
1136 // Verifies capture is reset when a window is destroyed.
1137 TEST_F(WindowTest, ReleaseCaptureOnDestroy) {
1138 CaptureWindowDelegateImpl delegate;
1139 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
1140 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1141 EXPECT_FALSE(window->HasCapture());
1143 // Do a capture.
1144 window->SetCapture();
1145 EXPECT_TRUE(window->HasCapture());
1147 // Destroy the window.
1148 window.reset();
1150 // Make sure the root window doesn't reference the window anymore.
1151 EXPECT_EQ(NULL, root_window()->mouse_pressed_handler());
1152 EXPECT_EQ(NULL, aura::client::GetCaptureWindow(root_window()));
1155 TEST_F(WindowTest, GetBoundsInRootWindow) {
1156 scoped_ptr<Window> viewport(CreateTestWindowWithBounds(
1157 gfx::Rect(0, 0, 300, 300), root_window()));
1158 scoped_ptr<Window> child(CreateTestWindowWithBounds(
1159 gfx::Rect(0, 0, 100, 100), viewport.get()));
1160 // Sanity check.
1161 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1163 // The |child| window's screen bounds should move along with the |viewport|.
1164 viewport->SetBounds(gfx::Rect(-100, -100, 300, 300));
1165 EXPECT_EQ("-100,-100 100x100", child->GetBoundsInRootWindow().ToString());
1167 // The |child| window is moved to the 0,0 in screen coordinates.
1168 // |GetBoundsInRootWindow()| should return 0,0.
1169 child->SetBounds(gfx::Rect(100, 100, 100, 100));
1170 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1173 class MouseEnterExitWindowDelegate : public TestWindowDelegate {
1174 public:
1175 MouseEnterExitWindowDelegate() : entered_(false), exited_(false) {}
1177 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
1178 switch (event->type()) {
1179 case ui::ET_MOUSE_ENTERED:
1180 EXPECT_TRUE(event->flags() & ui::EF_IS_SYNTHESIZED);
1181 entered_ = true;
1182 break;
1183 case ui::ET_MOUSE_EXITED:
1184 EXPECT_TRUE(event->flags() & ui::EF_IS_SYNTHESIZED);
1185 exited_ = true;
1186 break;
1187 default:
1188 break;
1192 bool entered() const { return entered_; }
1193 bool exited() const { return exited_; }
1195 // Clear the entered / exited states.
1196 void ResetExpectations() {
1197 entered_ = false;
1198 exited_ = false;
1201 private:
1202 bool entered_;
1203 bool exited_;
1205 DISALLOW_COPY_AND_ASSIGN(MouseEnterExitWindowDelegate);
1209 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1210 // mouse transitions from window to window.
1211 TEST_F(WindowTest, MouseEnterExit) {
1212 MouseEnterExitWindowDelegate d1;
1213 scoped_ptr<Window> w1(
1214 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1215 root_window()));
1216 MouseEnterExitWindowDelegate d2;
1217 scoped_ptr<Window> w2(
1218 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50),
1219 root_window()));
1221 test::EventGenerator generator(root_window());
1222 generator.MoveMouseToCenterOf(w1.get());
1223 EXPECT_TRUE(d1.entered());
1224 EXPECT_FALSE(d1.exited());
1225 EXPECT_FALSE(d2.entered());
1226 EXPECT_FALSE(d2.exited());
1228 generator.MoveMouseToCenterOf(w2.get());
1229 EXPECT_TRUE(d1.entered());
1230 EXPECT_TRUE(d1.exited());
1231 EXPECT_TRUE(d2.entered());
1232 EXPECT_FALSE(d2.exited());
1235 // Verifies that the WindowDelegate receives MouseExit from ET_MOUSE_EXITED.
1236 TEST_F(WindowTest, RootWindowHostExit) {
1237 MouseEnterExitWindowDelegate d1;
1238 scoped_ptr<Window> w1(
1239 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1240 root_window()));
1242 test::EventGenerator generator(root_window());
1243 generator.MoveMouseToCenterOf(w1.get());
1244 EXPECT_TRUE(d1.entered());
1245 EXPECT_FALSE(d1.exited());
1246 d1.ResetExpectations();
1248 ui::MouseEvent exit_event(
1249 ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(), 0);
1250 root_window()->AsRootWindowHostDelegate()->OnHostMouseEvent(&exit_event);
1251 EXPECT_FALSE(d1.entered());
1252 EXPECT_TRUE(d1.exited());
1255 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1256 // mouse transitions from window to window, even if the entered window sets
1257 // and releases capture.
1258 TEST_F(WindowTest, MouseEnterExitWithClick) {
1259 MouseEnterExitWindowDelegate d1;
1260 scoped_ptr<Window> w1(
1261 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1262 root_window()));
1263 MouseEnterExitWindowDelegate d2;
1264 scoped_ptr<Window> w2(
1265 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50),
1266 root_window()));
1268 test::EventGenerator generator(root_window());
1269 generator.MoveMouseToCenterOf(w1.get());
1270 EXPECT_TRUE(d1.entered());
1271 EXPECT_FALSE(d1.exited());
1272 EXPECT_FALSE(d2.entered());
1273 EXPECT_FALSE(d2.exited());
1275 // Emmulate what Views does on a click by grabbing and releasing capture.
1276 generator.PressLeftButton();
1277 w1->SetCapture();
1278 w1->ReleaseCapture();
1279 generator.ReleaseLeftButton();
1281 generator.MoveMouseToCenterOf(w2.get());
1282 EXPECT_TRUE(d1.entered());
1283 EXPECT_TRUE(d1.exited());
1284 EXPECT_TRUE(d2.entered());
1285 EXPECT_FALSE(d2.exited());
1288 TEST_F(WindowTest, MouseEnterExitWhenDeleteWithCapture) {
1289 MouseEnterExitWindowDelegate delegate;
1290 scoped_ptr<Window> window(
1291 CreateTestWindowWithDelegate(&delegate, 1, gfx::Rect(10, 10, 50, 50),
1292 root_window()));
1294 test::EventGenerator generator(root_window());
1295 generator.MoveMouseToCenterOf(window.get());
1296 EXPECT_TRUE(delegate.entered());
1297 EXPECT_FALSE(delegate.exited());
1299 // Emmulate what Views does on a click by grabbing and releasing capture.
1300 generator.PressLeftButton();
1301 window->SetCapture();
1303 delegate.ResetExpectations();
1304 generator.MoveMouseTo(0, 0);
1305 EXPECT_FALSE(delegate.entered());
1306 EXPECT_FALSE(delegate.exited());
1308 delegate.ResetExpectations();
1309 window.reset();
1310 EXPECT_FALSE(delegate.entered());
1311 EXPECT_FALSE(delegate.exited());
1314 // Verifies that enter / exits are sent if windows appear and are deleted
1315 // under the current mouse position..
1316 TEST_F(WindowTest, MouseEnterExitWithDelete) {
1317 MouseEnterExitWindowDelegate d1;
1318 scoped_ptr<Window> w1(
1319 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1320 root_window()));
1322 test::EventGenerator generator(root_window());
1323 generator.MoveMouseToCenterOf(w1.get());
1324 EXPECT_TRUE(d1.entered());
1325 EXPECT_FALSE(d1.exited());
1327 MouseEnterExitWindowDelegate d2;
1329 scoped_ptr<Window> w2(
1330 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1331 root_window()));
1332 // Enters / exits can be send asynchronously.
1333 RunAllPendingInMessageLoop();
1334 EXPECT_TRUE(d1.entered());
1335 EXPECT_TRUE(d1.exited());
1336 EXPECT_TRUE(d2.entered());
1337 EXPECT_FALSE(d2.exited());
1338 d1.ResetExpectations();
1340 // Enters / exits can be send asynchronously.
1341 RunAllPendingInMessageLoop();
1342 EXPECT_TRUE(d2.exited());
1343 EXPECT_TRUE(d1.entered());
1346 // Verifies that enter / exits are sent if windows appear and are hidden
1347 // under the current mouse position..
1348 TEST_F(WindowTest, MouseEnterExitWithHide) {
1349 MouseEnterExitWindowDelegate d1;
1350 scoped_ptr<Window> w1(
1351 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1352 root_window()));
1354 test::EventGenerator generator(root_window());
1355 generator.MoveMouseToCenterOf(w1.get());
1356 EXPECT_TRUE(d1.entered());
1357 EXPECT_FALSE(d1.exited());
1359 MouseEnterExitWindowDelegate d2;
1360 scoped_ptr<Window> w2(
1361 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1362 root_window()));
1363 // Enters / exits can be send asynchronously.
1364 RunAllPendingInMessageLoop();
1365 EXPECT_TRUE(d1.entered());
1366 EXPECT_TRUE(d1.exited());
1367 EXPECT_TRUE(d2.entered());
1368 EXPECT_FALSE(d2.exited());
1370 d1.ResetExpectations();
1371 w2->Hide();
1372 // Enters / exits can be send asynchronously.
1373 RunAllPendingInMessageLoop();
1374 EXPECT_TRUE(d2.exited());
1375 EXPECT_TRUE(d1.entered());
1378 TEST_F(WindowTest, MouseEnterExitWithParentHide) {
1379 MouseEnterExitWindowDelegate d1;
1380 scoped_ptr<Window> w1(
1381 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1382 root_window()));
1383 MouseEnterExitWindowDelegate d2;
1384 Window* w2 = CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1385 w1.get());
1386 test::EventGenerator generator(root_window());
1387 generator.MoveMouseToCenterOf(w2);
1388 // Enters / exits can be send asynchronously.
1389 RunAllPendingInMessageLoop();
1390 EXPECT_TRUE(d2.entered());
1391 EXPECT_FALSE(d2.exited());
1393 d2.ResetExpectations();
1394 w1->Hide();
1395 RunAllPendingInMessageLoop();
1396 EXPECT_FALSE(d2.entered());
1397 EXPECT_TRUE(d2.exited());
1399 w1.reset();
1402 TEST_F(WindowTest, MouseEnterExitWithParentDelete) {
1403 MouseEnterExitWindowDelegate d1;
1404 scoped_ptr<Window> w1(
1405 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1406 root_window()));
1407 MouseEnterExitWindowDelegate d2;
1408 Window* w2 = CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1409 w1.get());
1410 test::EventGenerator generator(root_window());
1411 generator.MoveMouseToCenterOf(w2);
1413 // Enters / exits can be send asynchronously.
1414 RunAllPendingInMessageLoop();
1415 EXPECT_TRUE(d2.entered());
1416 EXPECT_FALSE(d2.exited());
1418 d2.ResetExpectations();
1419 w1.reset();
1420 RunAllPendingInMessageLoop();
1421 EXPECT_FALSE(d2.entered());
1422 EXPECT_TRUE(d2.exited());
1425 // Creates a window with a delegate (w111) that can handle events at a lower
1426 // z-index than a window without a delegate (w12). w12 is sized to fill the
1427 // entire bounds of the container. This test verifies that
1428 // GetEventHandlerForPoint() skips w12 even though its bounds contain the event,
1429 // because it has no children that can handle the event and it has no delegate
1430 // allowing it to handle the event itself.
1431 TEST_F(WindowTest, GetEventHandlerForPoint_NoDelegate) {
1432 TestWindowDelegate d111;
1433 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(NULL, 1,
1434 gfx::Rect(0, 0, 500, 500), root_window()));
1435 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(NULL, 11,
1436 gfx::Rect(0, 0, 500, 500), w1.get()));
1437 scoped_ptr<Window> w111(CreateTestWindowWithDelegate(&d111, 111,
1438 gfx::Rect(50, 50, 450, 450), w11.get()));
1439 scoped_ptr<Window> w12(CreateTestWindowWithDelegate(NULL, 12,
1440 gfx::Rect(0, 0, 500, 500), w1.get()));
1442 gfx::Point target_point = w111->bounds().CenterPoint();
1443 EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(target_point));
1446 class VisibilityWindowDelegate : public TestWindowDelegate {
1447 public:
1448 VisibilityWindowDelegate()
1449 : shown_(0),
1450 hidden_(0) {
1453 int shown() const { return shown_; }
1454 int hidden() const { return hidden_; }
1455 void Clear() {
1456 shown_ = 0;
1457 hidden_ = 0;
1460 virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {
1461 if (visible)
1462 shown_++;
1463 else
1464 hidden_++;
1467 private:
1468 int shown_;
1469 int hidden_;
1471 DISALLOW_COPY_AND_ASSIGN(VisibilityWindowDelegate);
1474 // Verifies show/hide propagate correctly to children and the layer.
1475 TEST_F(WindowTest, Visibility) {
1476 VisibilityWindowDelegate d;
1477 VisibilityWindowDelegate d2;
1478 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(&d, 1, gfx::Rect(),
1479 root_window()));
1480 scoped_ptr<Window> w2(
1481 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(), w1.get()));
1482 scoped_ptr<Window> w3(CreateTestWindowWithId(3, w2.get()));
1484 // Create shows all the windows.
1485 EXPECT_TRUE(w1->IsVisible());
1486 EXPECT_TRUE(w2->IsVisible());
1487 EXPECT_TRUE(w3->IsVisible());
1488 EXPECT_EQ(1, d.shown());
1490 d.Clear();
1491 w1->Hide();
1492 EXPECT_FALSE(w1->IsVisible());
1493 EXPECT_FALSE(w2->IsVisible());
1494 EXPECT_FALSE(w3->IsVisible());
1495 EXPECT_EQ(1, d.hidden());
1496 EXPECT_EQ(0, d.shown());
1498 w2->Show();
1499 EXPECT_FALSE(w1->IsVisible());
1500 EXPECT_FALSE(w2->IsVisible());
1501 EXPECT_FALSE(w3->IsVisible());
1503 w3->Hide();
1504 EXPECT_FALSE(w1->IsVisible());
1505 EXPECT_FALSE(w2->IsVisible());
1506 EXPECT_FALSE(w3->IsVisible());
1508 d.Clear();
1509 w1->Show();
1510 EXPECT_TRUE(w1->IsVisible());
1511 EXPECT_TRUE(w2->IsVisible());
1512 EXPECT_FALSE(w3->IsVisible());
1513 EXPECT_EQ(0, d.hidden());
1514 EXPECT_EQ(1, d.shown());
1516 w3->Show();
1517 EXPECT_TRUE(w1->IsVisible());
1518 EXPECT_TRUE(w2->IsVisible());
1519 EXPECT_TRUE(w3->IsVisible());
1521 // Verify that if an ancestor isn't visible and we change the visibility of a
1522 // child window that OnChildWindowVisibilityChanged() is still invoked.
1523 w1->Hide();
1524 d2.Clear();
1525 w2->Hide();
1526 EXPECT_EQ(1, d2.hidden());
1527 EXPECT_EQ(0, d2.shown());
1528 d2.Clear();
1529 w2->Show();
1530 EXPECT_EQ(0, d2.hidden());
1531 EXPECT_EQ(1, d2.shown());
1534 TEST_F(WindowTest, IgnoreEventsTest) {
1535 TestWindowDelegate d11;
1536 TestWindowDelegate d12;
1537 TestWindowDelegate d111;
1538 TestWindowDelegate d121;
1539 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(NULL, 1,
1540 gfx::Rect(0, 0, 500, 500), root_window()));
1541 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(&d11, 11,
1542 gfx::Rect(0, 0, 500, 500), w1.get()));
1543 scoped_ptr<Window> w111(CreateTestWindowWithDelegate(&d111, 111,
1544 gfx::Rect(50, 50, 450, 450), w11.get()));
1545 scoped_ptr<Window> w12(CreateTestWindowWithDelegate(&d12, 12,
1546 gfx::Rect(0, 0, 500, 500), w1.get()));
1547 scoped_ptr<Window> w121(CreateTestWindowWithDelegate(&d121, 121,
1548 gfx::Rect(150, 150, 50, 50), w12.get()));
1550 EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10)));
1551 w12->set_ignore_events(true);
1552 EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10)));
1553 w12->set_ignore_events(false);
1555 EXPECT_EQ(w121.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1556 w121->set_ignore_events(true);
1557 EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1558 w12->set_ignore_events(true);
1559 EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1560 w111->set_ignore_events(true);
1561 EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1564 // Tests transformation on the root window.
1565 TEST_F(WindowTest, Transform) {
1566 gfx::Size size = root_window()->GetHostSize();
1567 EXPECT_EQ(gfx::Rect(size),
1568 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1569 gfx::Point()).bounds());
1571 // Rotate it clock-wise 90 degrees.
1572 gfx::Transform transform;
1573 transform.Translate(size.height(), 0);
1574 transform.Rotate(90.0);
1575 root_window()->SetTransform(transform);
1577 // The size should be the transformed size.
1578 gfx::Size transformed_size(size.height(), size.width());
1579 EXPECT_EQ(transformed_size.ToString(),
1580 root_window()->bounds().size().ToString());
1581 EXPECT_EQ(
1582 gfx::Rect(transformed_size).ToString(),
1583 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1584 gfx::Point()).bounds().ToString());
1586 // Host size shouldn't change.
1587 EXPECT_EQ(size.ToString(),
1588 root_window()->GetHostSize().ToString());
1591 TEST_F(WindowTest, TransformGesture) {
1592 gfx::Size size = root_window()->GetHostSize();
1594 scoped_ptr<GestureTrackPositionDelegate> delegate(
1595 new GestureTrackPositionDelegate);
1596 scoped_ptr<Window> window(CreateTestWindowWithDelegate(delegate.get(), -1234,
1597 gfx::Rect(0, 0, 20, 20), root_window()));
1599 // Rotate the root-window clock-wise 90 degrees.
1600 gfx::Transform transform;
1601 transform.Translate(size.height(), 0.0);
1602 transform.Rotate(90.0);
1603 root_window()->SetTransform(transform);
1605 ui::TouchEvent press(
1606 ui::ET_TOUCH_PRESSED, gfx::Point(size.height() - 10, 10), 0, getTime());
1607 root_window()->AsRootWindowHostDelegate()->OnHostTouchEvent(&press);
1608 EXPECT_EQ(gfx::Point(10, 10).ToString(), delegate->position().ToString());
1611 // Various assertions for transient children.
1612 TEST_F(WindowTest, TransientChildren) {
1613 scoped_ptr<Window> parent(CreateTestWindowWithId(0, root_window()));
1614 scoped_ptr<Window> w1(CreateTestWindowWithId(1, parent.get()));
1615 scoped_ptr<Window> w3(CreateTestWindowWithId(3, parent.get()));
1616 Window* w2 = CreateTestWindowWithId(2, parent.get());
1617 w1->AddTransientChild(w2); // w2 is now owned by w1.
1618 // Stack w1 at the top (end), this should force w2 to be last (on top of w1).
1619 parent->StackChildAtTop(w1.get());
1620 ASSERT_EQ(3u, parent->children().size());
1621 EXPECT_EQ(w2, parent->children().back());
1623 // Destroy w1, which should also destroy w3 (since it's a transient child).
1624 w1.reset();
1625 w2 = NULL;
1626 ASSERT_EQ(1u, parent->children().size());
1627 EXPECT_EQ(w3.get(), parent->children()[0]);
1629 w1.reset(CreateTestWindowWithId(4, parent.get()));
1630 w2 = CreateTestWindowWithId(5, w3.get());
1631 w1->AddTransientChild(w2);
1632 parent->StackChildAtTop(w3.get());
1633 // Stack w1 at the top (end), this shouldn't affect w2 since it has a
1634 // different parent.
1635 parent->StackChildAtTop(w1.get());
1636 ASSERT_EQ(2u, parent->children().size());
1637 EXPECT_EQ(w3.get(), parent->children()[0]);
1638 EXPECT_EQ(w1.get(), parent->children()[1]);
1640 // Hiding parent should hide transient children.
1641 EXPECT_TRUE(w2->IsVisible());
1642 w1->Hide();
1643 EXPECT_FALSE(w2->IsVisible());
1646 // Tests that when a focused window is closed, its parent inherits the focus.
1647 TEST_F(WindowTest, FocusedWindowTest) {
1648 scoped_ptr<Window> parent(CreateTestWindowWithId(0, root_window()));
1649 scoped_ptr<Window> child(CreateTestWindowWithId(1, parent.get()));
1651 parent->Show();
1653 child->Focus();
1654 EXPECT_TRUE(child->HasFocus());
1655 EXPECT_FALSE(parent->HasFocus());
1657 child.reset();
1658 EXPECT_TRUE(parent->HasFocus());
1661 // Tests that the previously-focused window is passed to OnWindowFocused.
1662 // TODO(beng): Remove once the FocusController lands.
1663 TEST_F(WindowTest, OldFocusedWindowTest) {
1664 const gfx::Rect kBounds(0, 0, 100, 100);
1666 FocusDelegate delegate1;
1667 scoped_ptr<Window> window1(
1668 CreateTestWindowWithDelegate(&delegate1, 0, kBounds, root_window()));
1669 client::SetFocusChangeObserver(window1.get(), &delegate1);
1670 window1->Focus();
1671 ASSERT_TRUE(window1->HasFocus());
1672 EXPECT_TRUE(delegate1.previous_focused_window() == NULL);
1674 FocusDelegate delegate2;
1675 scoped_ptr<Window> window2(
1676 CreateTestWindowWithDelegate(&delegate2, 1, kBounds, root_window()));
1677 client::SetFocusChangeObserver(window2.get(), &delegate2);
1678 window2->Focus();
1679 ASSERT_TRUE(window2->HasFocus());
1680 EXPECT_FALSE(window1->HasFocus());
1681 EXPECT_EQ(window1.get(), delegate2.previous_focused_window());
1684 namespace {
1685 DEFINE_WINDOW_PROPERTY_KEY(int, kIntKey, -2);
1686 DEFINE_WINDOW_PROPERTY_KEY(const char*, kStringKey, "squeamish");
1689 TEST_F(WindowTest, Property) {
1690 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window()));
1692 static const char native_prop_key[] = "fnord";
1694 // Non-existent properties should return the default values.
1695 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1696 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1697 EXPECT_EQ(NULL, w->GetNativeWindowProperty(native_prop_key));
1699 // A set property value should be returned again (even if it's the default
1700 // value).
1701 w->SetProperty(kIntKey, INT_MAX);
1702 EXPECT_EQ(INT_MAX, w->GetProperty(kIntKey));
1703 w->SetProperty(kIntKey, -2);
1704 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1705 w->SetProperty(kIntKey, INT_MIN);
1706 EXPECT_EQ(INT_MIN, w->GetProperty(kIntKey));
1708 w->SetProperty(kStringKey, static_cast<const char*>(NULL));
1709 EXPECT_EQ(NULL, w->GetProperty(kStringKey));
1710 w->SetProperty(kStringKey, "squeamish");
1711 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1712 w->SetProperty(kStringKey, "ossifrage");
1713 EXPECT_EQ(std::string("ossifrage"), w->GetProperty(kStringKey));
1715 w->SetNativeWindowProperty(native_prop_key, &*w);
1716 EXPECT_EQ(&*w, w->GetNativeWindowProperty(native_prop_key));
1717 w->SetNativeWindowProperty(native_prop_key, NULL);
1718 EXPECT_EQ(NULL, w->GetNativeWindowProperty(native_prop_key));
1720 // ClearProperty should restore the default value.
1721 w->ClearProperty(kIntKey);
1722 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1723 w->ClearProperty(kStringKey);
1724 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1727 namespace {
1729 class TestProperty {
1730 public:
1731 TestProperty() {}
1732 virtual ~TestProperty() {
1733 last_deleted_ = this;
1735 static TestProperty* last_deleted() { return last_deleted_; }
1737 private:
1738 static TestProperty* last_deleted_;
1739 DISALLOW_COPY_AND_ASSIGN(TestProperty);
1742 TestProperty* TestProperty::last_deleted_ = NULL;
1744 DEFINE_OWNED_WINDOW_PROPERTY_KEY(TestProperty, kOwnedKey, NULL);
1746 } // namespace
1748 TEST_F(WindowTest, OwnedProperty) {
1749 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window()));
1750 EXPECT_EQ(NULL, w->GetProperty(kOwnedKey));
1751 TestProperty* p1 = new TestProperty();
1752 w->SetProperty(kOwnedKey, p1);
1753 EXPECT_EQ(p1, w->GetProperty(kOwnedKey));
1754 EXPECT_EQ(NULL, TestProperty::last_deleted());
1756 TestProperty* p2 = new TestProperty();
1757 w->SetProperty(kOwnedKey, p2);
1758 EXPECT_EQ(p2, w->GetProperty(kOwnedKey));
1759 EXPECT_EQ(p1, TestProperty::last_deleted());
1761 w->ClearProperty(kOwnedKey);
1762 EXPECT_EQ(NULL, w->GetProperty(kOwnedKey));
1763 EXPECT_EQ(p2, TestProperty::last_deleted());
1765 TestProperty* p3 = new TestProperty();
1766 w->SetProperty(kOwnedKey, p3);
1767 EXPECT_EQ(p3, w->GetProperty(kOwnedKey));
1768 EXPECT_EQ(p2, TestProperty::last_deleted());
1769 w.reset();
1770 EXPECT_EQ(p3, TestProperty::last_deleted());
1773 TEST_F(WindowTest, SetBoundsInternalShouldCheckTargetBounds) {
1774 // We cannot short-circuit animations in this test.
1775 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
1776 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
1778 scoped_ptr<Window> w1(
1779 CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), root_window()));
1781 EXPECT_FALSE(!w1->layer());
1782 w1->layer()->GetAnimator()->set_disable_timer_for_test(true);
1783 ui::AnimationContainerElement* element = w1->layer()->GetAnimator();
1785 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1786 EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString());
1788 // Animate to a different position.
1790 ui::ScopedLayerAnimationSettings settings(w1->layer()->GetAnimator());
1791 w1->SetBounds(gfx::Rect(100, 100, 100, 100));
1794 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1795 EXPECT_EQ("100,100 100x100", w1->layer()->GetTargetBounds().ToString());
1797 // Animate back to the first position. The animation hasn't started yet, so
1798 // the current bounds are still (0, 0, 100, 100), but the target bounds are
1799 // (100, 100, 100, 100). If we step the animator ahead, we should find that
1800 // we're at (0, 0, 100, 100). That is, the second animation should be applied.
1802 ui::ScopedLayerAnimationSettings settings(w1->layer()->GetAnimator());
1803 w1->SetBounds(gfx::Rect(0, 0, 100, 100));
1806 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1807 EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString());
1809 // Confirm that the target bounds are reached.
1810 base::TimeTicks start_time =
1811 w1->layer()->GetAnimator()->last_step_time();
1813 element->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
1815 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1819 typedef std::pair<const void*, intptr_t> PropertyChangeInfo;
1821 class WindowObserverTest : public WindowTest,
1822 public WindowObserver {
1823 public:
1824 struct VisibilityInfo {
1825 bool window_visible;
1826 bool visible_param;
1829 WindowObserverTest()
1830 : added_count_(0),
1831 removed_count_(0),
1832 destroyed_count_(0),
1833 old_property_value_(-3) {
1836 virtual ~WindowObserverTest() {}
1838 const VisibilityInfo* GetVisibilityInfo() const {
1839 return visibility_info_.get();
1842 void ResetVisibilityInfo() {
1843 visibility_info_.reset();
1846 // Returns a description of the WindowObserver methods that have been invoked.
1847 std::string WindowObserverCountStateAndClear() {
1848 std::string result(
1849 base::StringPrintf("added=%d removed=%d",
1850 added_count_, removed_count_));
1851 added_count_ = removed_count_ = 0;
1852 return result;
1855 int DestroyedCountAndClear() {
1856 int result = destroyed_count_;
1857 destroyed_count_ = 0;
1858 return result;
1861 // Return a tuple of the arguments passed in OnPropertyChanged callback.
1862 PropertyChangeInfo PropertyChangeInfoAndClear() {
1863 PropertyChangeInfo result(property_key_, old_property_value_);
1864 property_key_ = NULL;
1865 old_property_value_ = -3;
1866 return result;
1869 private:
1870 virtual void OnWindowAdded(Window* new_window) OVERRIDE {
1871 added_count_++;
1874 virtual void OnWillRemoveWindow(Window* window) OVERRIDE {
1875 removed_count_++;
1878 virtual void OnWindowVisibilityChanged(Window* window,
1879 bool visible) OVERRIDE {
1880 visibility_info_.reset(new VisibilityInfo);
1881 visibility_info_->window_visible = window->IsVisible();
1882 visibility_info_->visible_param = visible;
1885 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
1886 EXPECT_FALSE(window->parent());
1887 destroyed_count_++;
1890 virtual void OnWindowPropertyChanged(Window* window,
1891 const void* key,
1892 intptr_t old) OVERRIDE {
1893 property_key_ = key;
1894 old_property_value_ = old;
1897 int added_count_;
1898 int removed_count_;
1899 int destroyed_count_;
1900 scoped_ptr<VisibilityInfo> visibility_info_;
1901 const void* property_key_;
1902 intptr_t old_property_value_;
1904 DISALLOW_COPY_AND_ASSIGN(WindowObserverTest);
1907 // Various assertions for WindowObserver.
1908 TEST_F(WindowObserverTest, WindowObserver) {
1909 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1910 w1->AddObserver(this);
1912 // Create a new window as a child of w1, our observer should be notified.
1913 scoped_ptr<Window> w2(CreateTestWindowWithId(2, w1.get()));
1914 EXPECT_EQ("added=1 removed=0", WindowObserverCountStateAndClear());
1916 // Delete w2, which should result in the remove notification.
1917 w2.reset();
1918 EXPECT_EQ("added=0 removed=1", WindowObserverCountStateAndClear());
1920 // Create a window that isn't parented to w1, we shouldn't get any
1921 // notification.
1922 scoped_ptr<Window> w3(CreateTestWindowWithId(3, root_window()));
1923 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1925 // Similarly destroying w3 shouldn't notify us either.
1926 w3.reset();
1927 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1928 w1->RemoveObserver(this);
1931 // Test if OnWindowVisibilityChagned is invoked with expected
1932 // parameters.
1933 TEST_F(WindowObserverTest, WindowVisibility) {
1934 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1935 scoped_ptr<Window> w2(CreateTestWindowWithId(1, w1.get()));
1936 w2->AddObserver(this);
1938 // Hide should make the window invisible and the passed visible
1939 // parameter is false.
1940 w2->Hide();
1941 EXPECT_FALSE(!GetVisibilityInfo());
1942 EXPECT_FALSE(!GetVisibilityInfo());
1943 if (!GetVisibilityInfo())
1944 return;
1945 EXPECT_FALSE(GetVisibilityInfo()->window_visible);
1946 EXPECT_FALSE(GetVisibilityInfo()->visible_param);
1948 // If parent isn't visible, showing window won't make the window visible, but
1949 // passed visible value must be true.
1950 w1->Hide();
1951 ResetVisibilityInfo();
1952 EXPECT_TRUE(!GetVisibilityInfo());
1953 w2->Show();
1954 EXPECT_FALSE(!GetVisibilityInfo());
1955 if (!GetVisibilityInfo())
1956 return;
1957 EXPECT_FALSE(GetVisibilityInfo()->window_visible);
1958 EXPECT_TRUE(GetVisibilityInfo()->visible_param);
1960 // If parent is visible, showing window will make the window
1961 // visible and the passed visible value is true.
1962 w1->Show();
1963 w2->Hide();
1964 ResetVisibilityInfo();
1965 w2->Show();
1966 EXPECT_FALSE(!GetVisibilityInfo());
1967 if (!GetVisibilityInfo())
1968 return;
1969 EXPECT_TRUE(GetVisibilityInfo()->window_visible);
1970 EXPECT_TRUE(GetVisibilityInfo()->visible_param);
1973 // Test if OnWindowDestroyed is invoked as expected.
1974 TEST_F(WindowObserverTest, WindowDestroyed) {
1975 // Delete a window should fire a destroyed notification.
1976 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1977 w1->AddObserver(this);
1978 w1.reset();
1979 EXPECT_EQ(1, DestroyedCountAndClear());
1981 // Observe on child and delete parent window should fire a notification.
1982 scoped_ptr<Window> parent(CreateTestWindowWithId(1, root_window()));
1983 Window* child = CreateTestWindowWithId(1, parent.get()); // owned by parent
1984 child->AddObserver(this);
1985 parent.reset();
1986 EXPECT_EQ(1, DestroyedCountAndClear());
1989 TEST_F(WindowObserverTest, PropertyChanged) {
1990 // Setting property should fire a property change notification.
1991 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1992 w1->AddObserver(this);
1994 static const WindowProperty<int> prop = {-2};
1995 static const char native_prop_key[] = "fnord";
1997 w1->SetProperty(&prop, 1);
1998 EXPECT_EQ(PropertyChangeInfo(&prop, -2), PropertyChangeInfoAndClear());
1999 w1->SetProperty(&prop, -2);
2000 EXPECT_EQ(PropertyChangeInfo(&prop, 1), PropertyChangeInfoAndClear());
2001 w1->SetProperty(&prop, 3);
2002 EXPECT_EQ(PropertyChangeInfo(&prop, -2), PropertyChangeInfoAndClear());
2003 w1->ClearProperty(&prop);
2004 EXPECT_EQ(PropertyChangeInfo(&prop, 3), PropertyChangeInfoAndClear());
2006 w1->SetNativeWindowProperty(native_prop_key, &*w1);
2007 EXPECT_EQ(PropertyChangeInfo(native_prop_key, 0),
2008 PropertyChangeInfoAndClear());
2009 w1->SetNativeWindowProperty(native_prop_key, NULL);
2010 EXPECT_EQ(PropertyChangeInfo(native_prop_key,
2011 reinterpret_cast<intptr_t>(&*w1)),
2012 PropertyChangeInfoAndClear());
2014 // Sanity check to see if |PropertyChangeInfoAndClear| really clears.
2015 EXPECT_EQ(PropertyChangeInfo(
2016 reinterpret_cast<const void*>(NULL), -3), PropertyChangeInfoAndClear());
2019 TEST_F(WindowTest, AcquireLayer) {
2020 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
2021 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
2022 ui::Layer* parent = window1->parent()->layer();
2023 EXPECT_EQ(2U, parent->children().size());
2025 WindowTestApi window1_test_api(window1.get());
2026 WindowTestApi window2_test_api(window2.get());
2028 EXPECT_TRUE(window1_test_api.OwnsLayer());
2029 EXPECT_TRUE(window2_test_api.OwnsLayer());
2031 // After acquisition, window1 should not own its layer, but it should still
2032 // be available to the window.
2033 scoped_ptr<ui::Layer> window1_layer(window1->AcquireLayer());
2034 EXPECT_FALSE(window1_test_api.OwnsLayer());
2035 EXPECT_TRUE(window1_layer.get() == window1->layer());
2037 // Upon destruction, window1's layer should still be valid, and in the layer
2038 // hierarchy, but window2's should be gone, and no longer in the hierarchy.
2039 window1.reset();
2040 window2.reset();
2042 // This should be set by the window's destructor.
2043 EXPECT_TRUE(window1_layer->delegate() == NULL);
2044 EXPECT_EQ(1U, parent->children().size());
2047 // Make sure that properties which should persist from the old layer to the new
2048 // layer actually do.
2049 TEST_F(WindowTest, RecreateLayer) {
2050 // Set properties to non default values.
2051 Window w(new ColorTestWindowDelegate(SK_ColorWHITE));
2052 w.set_id(1);
2053 w.Init(ui::LAYER_SOLID_COLOR);
2054 w.SetBounds(gfx::Rect(0, 0, 100, 100));
2056 ui::Layer* layer = w.layer();
2057 layer->set_scale_content(false);
2058 layer->SetVisible(false);
2059 layer->SetMasksToBounds(true);
2061 ui::Layer child_layer;
2062 layer->Add(&child_layer);
2064 scoped_ptr<ui::Layer> old_layer(w.RecreateLayer());
2065 layer = w.layer();
2066 EXPECT_EQ(ui::LAYER_SOLID_COLOR, layer->type());
2067 EXPECT_FALSE(layer->scale_content());
2068 EXPECT_FALSE(layer->visible());
2069 EXPECT_EQ(1u, layer->children().size());
2070 EXPECT_TRUE(layer->GetMasksToBounds());
2073 // Verify that RecreateLayer() stacks the old layer above the newly creatd
2074 // layer.
2075 TEST_F(WindowTest, RecreateLayerZOrder) {
2076 scoped_ptr<Window> w(
2077 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(0, 0, 100, 100),
2078 root_window()));
2079 scoped_ptr<ui::Layer> old_layer(w->RecreateLayer());
2081 const std::vector<ui::Layer*>& child_layers =
2082 root_window()->layer()->children();
2083 ASSERT_EQ(2u, child_layers.size());
2084 EXPECT_EQ(w->layer(), child_layers[0]);
2085 EXPECT_EQ(old_layer.get(), child_layers[1]);
2088 // Ensure that acquiring a layer then recreating a layer does not crash
2089 // and that RecreateLayer returns null.
2090 TEST_F(WindowTest, AcquireThenRecreateLayer) {
2091 scoped_ptr<Window> w(
2092 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(0, 0, 100, 100),
2093 root_window()));
2094 scoped_ptr<ui::Layer>acquired_layer(w->AcquireLayer());
2095 scoped_ptr<ui::Layer>doubly_acquired_layer(w->RecreateLayer());
2096 EXPECT_EQ(NULL, doubly_acquired_layer.get());
2098 // Destroy window before layer gets destroyed.
2099 w.reset();
2102 TEST_F(WindowTest, StackWindowsWhoseLayersHaveNoDelegate) {
2103 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
2104 window1->layer()->set_name("1");
2105 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
2106 window2->layer()->set_name("2");
2107 scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window()));
2108 window3->layer()->set_name("3");
2110 // This brings |window1| (and its layer) to the front.
2111 root_window()->StackChildAbove(window1.get(), window3.get());
2112 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(root_window()));
2113 EXPECT_EQ("2 3 1",
2114 ui::test::ChildLayerNamesAsString(*root_window()->layer()));
2116 // Since |window1| does not have a delegate, |window2| should not move in
2117 // front of it, nor should its layer.
2118 window1->layer()->set_delegate(NULL);
2119 root_window()->StackChildAbove(window2.get(), window1.get());
2120 EXPECT_EQ("3 2 1", ChildWindowIDsAsString(root_window()));
2121 EXPECT_EQ("3 2 1",
2122 ui::test::ChildLayerNamesAsString(*root_window()->layer()));
2124 // It should still be possible to stack |window3| immediately below |window1|.
2125 root_window()->StackChildBelow(window3.get(), window1.get());
2126 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(root_window()));
2127 EXPECT_EQ("2 3 1",
2128 ui::test::ChildLayerNamesAsString(*root_window()->layer()));
2130 // Since neither |window3| nor |window1| have a delegate, |window2| should
2131 // not move in front of either.
2132 window3->layer()->set_delegate(NULL);
2133 root_window()->StackChildBelow(window2.get(), window1.get());
2134 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(root_window()));
2135 EXPECT_EQ("2 3 1",
2136 ui::test::ChildLayerNamesAsString(*root_window()->layer()));
2139 TEST_F(WindowTest, StackTransientsWhoseLayersHaveNoDelegate) {
2140 RootWindow* root = root_window();
2142 // Create a window with several transients, then a couple windows on top.
2143 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
2144 scoped_ptr<Window> window11(CreateTransientChild(11, window1.get()));
2145 scoped_ptr<Window> window12(CreateTransientChild(12, window1.get()));
2146 scoped_ptr<Window> window13(CreateTransientChild(13, window1.get()));
2147 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
2148 scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window()));
2150 EXPECT_EQ("1 11 12 13 2 3", ChildWindowIDsAsString(root));
2152 // Remove the delegates of a couple of transients, as if they are closing
2153 // and animating out.
2154 window11->layer()->set_delegate(NULL);
2155 window13->layer()->set_delegate(NULL);
2157 // Move window1 to the front. All transients should move with it, and their
2158 // order should be preserved.
2159 root->StackChildAtTop(window1.get());
2161 EXPECT_EQ("2 3 1 11 12 13", ChildWindowIDsAsString(root));
2164 class TestVisibilityClient : public client::VisibilityClient {
2165 public:
2166 explicit TestVisibilityClient(RootWindow* root_window)
2167 : ignore_visibility_changes_(false) {
2168 client::SetVisibilityClient(root_window, this);
2170 virtual ~TestVisibilityClient() {
2173 void set_ignore_visibility_changes(bool ignore_visibility_changes) {
2174 ignore_visibility_changes_ = ignore_visibility_changes;
2177 // Overridden from client::VisibilityClient:
2178 virtual void UpdateLayerVisibility(aura::Window* window,
2179 bool visible) OVERRIDE {
2180 if (!ignore_visibility_changes_)
2181 window->layer()->SetVisible(visible);
2184 private:
2185 bool ignore_visibility_changes_;
2186 DISALLOW_COPY_AND_ASSIGN(TestVisibilityClient);
2189 TEST_F(WindowTest, VisibilityClientIsVisible) {
2190 TestVisibilityClient client(root_window());
2192 scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window()));
2193 EXPECT_TRUE(window->IsVisible());
2194 EXPECT_TRUE(window->layer()->visible());
2196 window->Hide();
2197 EXPECT_FALSE(window->IsVisible());
2198 EXPECT_FALSE(window->layer()->visible());
2199 window->Show();
2201 client.set_ignore_visibility_changes(true);
2202 window->Hide();
2203 EXPECT_FALSE(window->IsVisible());
2204 EXPECT_TRUE(window->layer()->visible());
2207 // Tests mouse events on window change.
2208 TEST_F(WindowTest, MouseEventsOnWindowChange) {
2209 gfx::Size size = root_window()->GetHostSize();
2211 EventGenerator generator(root_window());
2212 generator.MoveMouseTo(50, 50);
2214 EventCountDelegate d1;
2215 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(&d1, 1,
2216 gfx::Rect(0, 0, 100, 100), root_window()));
2217 RunAllPendingInMessageLoop();
2218 // The format of result is "Enter/Mouse/Leave".
2219 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2221 // Adding new window.
2222 EventCountDelegate d11;
2223 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(
2224 &d11, 1, gfx::Rect(0, 0, 100, 100), w1.get()));
2225 RunAllPendingInMessageLoop();
2226 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2227 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2229 // Move bounds.
2230 w11->SetBounds(gfx::Rect(0, 0, 10, 10));
2231 RunAllPendingInMessageLoop();
2232 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2233 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2235 w11->SetBounds(gfx::Rect(0, 0, 60, 60));
2236 RunAllPendingInMessageLoop();
2237 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2238 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2240 // Detach, then re-attach.
2241 w1->RemoveChild(w11.get());
2242 RunAllPendingInMessageLoop();
2243 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2244 // Window is detached, so no event is set.
2245 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2247 w1->AddChild(w11.get());
2248 RunAllPendingInMessageLoop();
2249 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2250 // Window is detached, so no event is set.
2251 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2253 // Visibility Change
2254 w11->Hide();
2255 RunAllPendingInMessageLoop();
2256 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2257 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2259 w11->Show();
2260 RunAllPendingInMessageLoop();
2261 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2262 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2264 // Transform: move d11 by 100 100.
2265 gfx::Transform transform;
2266 transform.Translate(100, 100);
2267 w11->SetTransform(transform);
2268 RunAllPendingInMessageLoop();
2269 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2270 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2272 w11->SetTransform(gfx::Transform());
2273 RunAllPendingInMessageLoop();
2274 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2275 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2277 // Closing a window.
2278 w11.reset();
2279 RunAllPendingInMessageLoop();
2280 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2282 // Make sure we don't synthesize events if the mouse
2283 // is outside of the root window.
2284 generator.MoveMouseTo(-10, -10);
2285 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2287 // Adding new windows.
2288 w11.reset(CreateTestWindowWithDelegate(
2289 &d11, 1, gfx::Rect(0, 0, 100, 100), w1.get()));
2290 RunAllPendingInMessageLoop();
2291 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset());
2292 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2294 // Closing windows
2295 w11.reset();
2296 RunAllPendingInMessageLoop();
2297 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset());
2298 EXPECT_EQ("0 0 0", d11.GetMouseMotionCountsAndReset());
2301 class StackingMadrigalLayoutManager : public LayoutManager {
2302 public:
2303 explicit StackingMadrigalLayoutManager(RootWindow* root_window)
2304 : root_window_(root_window) {
2305 root_window_->SetLayoutManager(this);
2307 virtual ~StackingMadrigalLayoutManager() {
2310 private:
2311 // Overridden from LayoutManager:
2312 virtual void OnWindowResized() OVERRIDE {}
2313 virtual void OnWindowAddedToLayout(Window* child) OVERRIDE {}
2314 virtual void OnWillRemoveWindowFromLayout(Window* child) OVERRIDE {}
2315 virtual void OnWindowRemovedFromLayout(Window* child) OVERRIDE {}
2316 virtual void OnChildWindowVisibilityChanged(Window* child,
2317 bool visible) OVERRIDE {
2318 Window::Windows::const_iterator it = root_window_->children().begin();
2319 Window* last_window = NULL;
2320 for (; it != root_window_->children().end(); ++it) {
2321 if (*it == child && last_window) {
2322 if (!visible)
2323 root_window_->StackChildAbove(last_window, *it);
2324 else
2325 root_window_->StackChildAbove(*it, last_window);
2326 break;
2328 last_window = *it;
2331 virtual void SetChildBounds(Window* child,
2332 const gfx::Rect& requested_bounds) OVERRIDE {
2333 SetChildBoundsDirect(child, requested_bounds);
2336 RootWindow* root_window_;
2338 DISALLOW_COPY_AND_ASSIGN(StackingMadrigalLayoutManager);
2341 class StackingMadrigalVisibilityClient : public client::VisibilityClient {
2342 public:
2343 explicit StackingMadrigalVisibilityClient(RootWindow* root_window)
2344 : ignored_window_(NULL) {
2345 client::SetVisibilityClient(root_window, this);
2347 virtual ~StackingMadrigalVisibilityClient() {
2350 void set_ignored_window(Window* ignored_window) {
2351 ignored_window_ = ignored_window;
2354 private:
2355 // Overridden from client::VisibilityClient:
2356 virtual void UpdateLayerVisibility(Window* window, bool visible) OVERRIDE {
2357 if (!visible) {
2358 if (window == ignored_window_)
2359 window->layer()->set_delegate(NULL);
2360 else
2361 window->layer()->SetVisible(visible);
2362 } else {
2363 window->layer()->SetVisible(visible);
2367 Window* ignored_window_;
2369 DISALLOW_COPY_AND_ASSIGN(StackingMadrigalVisibilityClient);
2372 // This test attempts to reconstruct a circumstance that can happen when the
2373 // aura client attempts to manipulate the visibility and delegate of a layer
2374 // independent of window visibility.
2375 // A use case is where the client attempts to keep a window visible onscreen
2376 // even after code has called Hide() on the window. The use case for this would
2377 // be that window hides are animated (e.g. the window fades out). To prevent
2378 // spurious updating the client code may also clear window's layer's delegate,
2379 // so that the window cannot attempt to paint or update it further. The window
2380 // uses the presence of a NULL layer delegate as a signal in stacking to note
2381 // that the window is being manipulated by such a use case and its stacking
2382 // should not be adjusted.
2383 // One issue that can arise when a window opens two transient children, and the
2384 // first is hidden. Subsequent attempts to activate the transient parent can
2385 // result in the transient parent being stacked above the second transient
2386 // child. A fix is made to Window::StackAbove to prevent this, and this test
2387 // verifies this fix.
2388 TEST_F(WindowTest, StackingMadrigal) {
2389 new StackingMadrigalLayoutManager(root_window());
2390 StackingMadrigalVisibilityClient visibility_client(root_window());
2392 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
2393 scoped_ptr<Window> window11(CreateTransientChild(11, window1.get()));
2395 visibility_client.set_ignored_window(window11.get());
2397 window11->Show();
2398 window11->Hide();
2400 // As a transient, window11 should still be stacked above window1, even when
2401 // hidden.
2402 EXPECT_TRUE(WindowIsAbove(window11.get(), window1.get()));
2403 EXPECT_TRUE(LayerIsAbove(window11.get(), window1.get()));
2405 // A new transient should still be above window1. It will appear behind
2406 // window11 because we don't stack windows on top of targets with NULL
2407 // delegates.
2408 scoped_ptr<Window> window12(CreateTransientChild(12, window1.get()));
2409 window12->Show();
2411 EXPECT_TRUE(WindowIsAbove(window12.get(), window1.get()));
2412 EXPECT_TRUE(LayerIsAbove(window12.get(), window1.get()));
2414 // In earlier versions of the StackChildAbove() method, attempting to stack
2415 // window1 above window12 at this point would actually restack the layers
2416 // resulting in window12's layer being below window1's layer (though the
2417 // windows themselves would still be correctly stacked, so events would pass
2418 // through.)
2419 root_window()->StackChildAbove(window1.get(), window12.get());
2421 // Both window12 and its layer should be stacked above window1.
2422 EXPECT_TRUE(WindowIsAbove(window12.get(), window1.get()));
2423 EXPECT_TRUE(LayerIsAbove(window12.get(), window1.get()));
2426 // Test for an issue where attempting to stack a primary window on top of a
2427 // transient with a NULL layer delegate causes that primary window to be moved,
2428 // but the layer order not changed to match. http://crbug.com/112562
2429 TEST_F(WindowTest, StackOverClosingTransient) {
2430 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
2431 scoped_ptr<Window> transient1(CreateTransientChild(11, window1.get()));
2432 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
2433 scoped_ptr<Window> transient2(CreateTransientChild(21, window2.get()));
2435 // Both windows and layers are stacked in creation order.
2436 RootWindow* root = root_window();
2437 ASSERT_EQ(4u, root->children().size());
2438 EXPECT_EQ(root->children()[0], window1.get());
2439 EXPECT_EQ(root->children()[1], transient1.get());
2440 EXPECT_EQ(root->children()[2], window2.get());
2441 EXPECT_EQ(root->children()[3], transient2.get());
2442 ASSERT_EQ(4u, root->layer()->children().size());
2443 EXPECT_EQ(root->layer()->children()[0], window1->layer());
2444 EXPECT_EQ(root->layer()->children()[1], transient1->layer());
2445 EXPECT_EQ(root->layer()->children()[2], window2->layer());
2446 EXPECT_EQ(root->layer()->children()[3], transient2->layer());
2448 // This brings window1 and its transient to the front.
2449 root->StackChildAtTop(window1.get());
2451 EXPECT_EQ(root->children()[0], window2.get());
2452 EXPECT_EQ(root->children()[1], transient2.get());
2453 EXPECT_EQ(root->children()[2], window1.get());
2454 EXPECT_EQ(root->children()[3], transient1.get());
2455 EXPECT_EQ(root->layer()->children()[0], window2->layer());
2456 EXPECT_EQ(root->layer()->children()[1], transient2->layer());
2457 EXPECT_EQ(root->layer()->children()[2], window1->layer());
2458 EXPECT_EQ(root->layer()->children()[3], transient1->layer());
2460 // Pretend we're closing the top-most transient, then bring window2 to the
2461 // front. This mimics activating a browser window while the status bubble
2462 // is fading out. The transient should stay topmost.
2463 transient1->layer()->set_delegate(NULL);
2464 root->StackChildAtTop(window2.get());
2466 EXPECT_EQ(root->children()[0], window1.get());
2467 EXPECT_EQ(root->children()[1], window2.get());
2468 EXPECT_EQ(root->children()[2], transient2.get());
2469 EXPECT_EQ(root->children()[3], transient1.get());
2470 EXPECT_EQ(root->layer()->children()[0], window1->layer());
2471 EXPECT_EQ(root->layer()->children()[1], window2->layer());
2472 EXPECT_EQ(root->layer()->children()[2], transient2->layer());
2473 EXPECT_EQ(root->layer()->children()[3], transient1->layer());
2475 // Close the transient. Remaining windows are stable.
2476 transient1.reset();
2478 ASSERT_EQ(3u, root->children().size());
2479 EXPECT_EQ(root->children()[0], window1.get());
2480 EXPECT_EQ(root->children()[1], window2.get());
2481 EXPECT_EQ(root->children()[2], transient2.get());
2482 ASSERT_EQ(3u, root->layer()->children().size());
2483 EXPECT_EQ(root->layer()->children()[0], window1->layer());
2484 EXPECT_EQ(root->layer()->children()[1], window2->layer());
2485 EXPECT_EQ(root->layer()->children()[2], transient2->layer());
2487 // Open another window on top.
2488 scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window()));
2490 ASSERT_EQ(4u, root->children().size());
2491 EXPECT_EQ(root->children()[0], window1.get());
2492 EXPECT_EQ(root->children()[1], window2.get());
2493 EXPECT_EQ(root->children()[2], transient2.get());
2494 EXPECT_EQ(root->children()[3], window3.get());
2495 ASSERT_EQ(4u, root->layer()->children().size());
2496 EXPECT_EQ(root->layer()->children()[0], window1->layer());
2497 EXPECT_EQ(root->layer()->children()[1], window2->layer());
2498 EXPECT_EQ(root->layer()->children()[2], transient2->layer());
2499 EXPECT_EQ(root->layer()->children()[3], window3->layer());
2501 // Pretend we're closing the topmost non-transient window, then bring
2502 // window2 to the top. It should not move.
2503 window3->layer()->set_delegate(NULL);
2504 root->StackChildAtTop(window2.get());
2506 ASSERT_EQ(4u, root->children().size());
2507 EXPECT_EQ(root->children()[0], window1.get());
2508 EXPECT_EQ(root->children()[1], window2.get());
2509 EXPECT_EQ(root->children()[2], transient2.get());
2510 EXPECT_EQ(root->children()[3], window3.get());
2511 ASSERT_EQ(4u, root->layer()->children().size());
2512 EXPECT_EQ(root->layer()->children()[0], window1->layer());
2513 EXPECT_EQ(root->layer()->children()[1], window2->layer());
2514 EXPECT_EQ(root->layer()->children()[2], transient2->layer());
2515 EXPECT_EQ(root->layer()->children()[3], window3->layer());
2517 // Bring window1 to the top. It should move ahead of window2, but not
2518 // ahead of window3 (with NULL delegate).
2519 root->StackChildAtTop(window1.get());
2521 ASSERT_EQ(4u, root->children().size());
2522 EXPECT_EQ(root->children()[0], window2.get());
2523 EXPECT_EQ(root->children()[1], transient2.get());
2524 EXPECT_EQ(root->children()[2], window1.get());
2525 EXPECT_EQ(root->children()[3], window3.get());
2526 ASSERT_EQ(4u, root->layer()->children().size());
2527 EXPECT_EQ(root->layer()->children()[0], window2->layer());
2528 EXPECT_EQ(root->layer()->children()[1], transient2->layer());
2529 EXPECT_EQ(root->layer()->children()[2], window1->layer());
2530 EXPECT_EQ(root->layer()->children()[3], window3->layer());
2533 class RootWindowAttachmentObserver : public WindowObserver {
2534 public:
2535 RootWindowAttachmentObserver() : added_count_(0), removed_count_(0) {}
2536 virtual ~RootWindowAttachmentObserver() {}
2538 int added_count() const { return added_count_; }
2539 int removed_count() const { return removed_count_; }
2541 void Clear() {
2542 added_count_ = 0;
2543 removed_count_ = 0;
2546 // Overridden from WindowObserver:
2547 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
2548 ++added_count_;
2550 virtual void OnWindowRemovingFromRootWindow(Window* window) OVERRIDE {
2551 ++removed_count_;
2554 private:
2555 int added_count_;
2556 int removed_count_;
2558 DISALLOW_COPY_AND_ASSIGN(RootWindowAttachmentObserver);
2561 TEST_F(WindowTest, RootWindowAttachment) {
2562 RootWindowAttachmentObserver observer;
2564 // Test a direct add/remove from the RootWindow.
2565 scoped_ptr<Window> w1(new Window(NULL));
2566 w1->Init(ui::LAYER_NOT_DRAWN);
2567 w1->AddObserver(&observer);
2569 SetDefaultParentByPrimaryRootWindow(w1.get());
2570 EXPECT_EQ(1, observer.added_count());
2571 EXPECT_EQ(0, observer.removed_count());
2573 w1.reset();
2574 EXPECT_EQ(1, observer.added_count());
2575 EXPECT_EQ(1, observer.removed_count());
2577 observer.Clear();
2579 // Test an indirect add/remove from the RootWindow.
2580 w1.reset(new Window(NULL));
2581 w1->Init(ui::LAYER_NOT_DRAWN);
2582 Window* w11 = new Window(NULL);
2583 w11->Init(ui::LAYER_NOT_DRAWN);
2584 w11->AddObserver(&observer);
2585 w1->AddChild(w11);
2586 EXPECT_EQ(0, observer.added_count());
2587 EXPECT_EQ(0, observer.removed_count());
2589 SetDefaultParentByPrimaryRootWindow(w1.get());
2590 EXPECT_EQ(1, observer.added_count());
2591 EXPECT_EQ(0, observer.removed_count());
2593 w1.reset(); // Deletes w11.
2594 w11 = NULL;
2595 EXPECT_EQ(1, observer.added_count());
2596 EXPECT_EQ(1, observer.removed_count());
2598 observer.Clear();
2600 // Test an indirect add/remove with nested observers.
2601 w1.reset(new Window(NULL));
2602 w1->Init(ui::LAYER_NOT_DRAWN);
2603 w11 = new Window(NULL);
2604 w11->Init(ui::LAYER_NOT_DRAWN);
2605 w11->AddObserver(&observer);
2606 w1->AddChild(w11);
2607 Window* w111 = new Window(NULL);
2608 w111->Init(ui::LAYER_NOT_DRAWN);
2609 w111->AddObserver(&observer);
2610 w11->AddChild(w111);
2612 EXPECT_EQ(0, observer.added_count());
2613 EXPECT_EQ(0, observer.removed_count());
2615 SetDefaultParentByPrimaryRootWindow(w1.get());
2616 EXPECT_EQ(2, observer.added_count());
2617 EXPECT_EQ(0, observer.removed_count());
2619 w1.reset(); // Deletes w11 and w111.
2620 w11 = NULL;
2621 w111 = NULL;
2622 EXPECT_EQ(2, observer.added_count());
2623 EXPECT_EQ(2, observer.removed_count());
2626 TEST_F(WindowTest, OwnedByParentFalse) {
2627 // By default, a window is owned by its parent. If this is set to false, the
2628 // window will not be destroyed when its parent is.
2630 scoped_ptr<Window> w1(new Window(NULL));
2631 w1->Init(ui::LAYER_NOT_DRAWN);
2632 scoped_ptr<Window> w2(new Window(NULL));
2633 w2->set_owned_by_parent(false);
2634 w2->Init(ui::LAYER_NOT_DRAWN);
2635 w1->AddChild(w2.get());
2637 w1.reset();
2639 // We should be able to deref w2 still, but its parent should now be NULL.
2640 EXPECT_EQ(NULL, w2->parent());
2643 namespace {
2645 // Used By DeleteWindowFromOnWindowDestroyed. Destroys a Window from
2646 // OnWindowDestroyed().
2647 class OwningWindowDelegate : public TestWindowDelegate {
2648 public:
2649 OwningWindowDelegate() {}
2651 void SetOwnedWindow(Window* window) {
2652 owned_window_.reset(window);
2655 virtual void OnWindowDestroyed() OVERRIDE {
2656 owned_window_.reset(NULL);
2659 private:
2660 scoped_ptr<Window> owned_window_;
2662 DISALLOW_COPY_AND_ASSIGN(OwningWindowDelegate);
2665 } // namespace
2667 // Creates a window with two child windows. When the first child window is
2668 // destroyed (WindowDelegate::OnWindowDestroyed) it deletes the second child.
2669 // This synthesizes BrowserView and the status bubble. Both are children of the
2670 // same parent and destroying BrowserView triggers it destroying the status
2671 // bubble.
2672 TEST_F(WindowTest, DeleteWindowFromOnWindowDestroyed) {
2673 scoped_ptr<Window> parent(new Window(NULL));
2674 parent->Init(ui::LAYER_NOT_DRAWN);
2675 OwningWindowDelegate delegate;
2676 Window* c1 = new Window(&delegate);
2677 c1->Init(ui::LAYER_NOT_DRAWN);
2678 parent->AddChild(c1);
2679 Window* c2 = new Window(NULL);
2680 c2->Init(ui::LAYER_NOT_DRAWN);
2681 parent->AddChild(c2);
2682 delegate.SetOwnedWindow(c2);
2683 parent.reset();
2686 namespace {
2688 // Used by DelegateNotifiedAsBoundsChange to verify OnBoundsChanged() is
2689 // invoked.
2690 class BoundsChangeDelegate : public TestWindowDelegate {
2691 public:
2692 BoundsChangeDelegate() : bounds_changed_(false) {}
2694 void clear_bounds_changed() { bounds_changed_ = false; }
2695 bool bounds_changed() const {
2696 return bounds_changed_;
2699 // Window
2700 virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
2701 const gfx::Rect& new_bounds) OVERRIDE {
2702 bounds_changed_ = true;
2705 private:
2706 // Was OnBoundsChanged() invoked?
2707 bool bounds_changed_;
2709 DISALLOW_COPY_AND_ASSIGN(BoundsChangeDelegate);
2712 } // namespace
2714 // Verifies the delegate is notified when the actual bounds of the layer
2715 // change.
2716 TEST_F(WindowTest, DelegateNotifiedAsBoundsChange) {
2717 BoundsChangeDelegate delegate;
2719 // We cannot short-circuit animations in this test.
2720 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
2721 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
2723 scoped_ptr<Window> window(
2724 CreateTestWindowWithDelegate(&delegate, 1,
2725 gfx::Rect(0, 0, 100, 100), root_window()));
2726 window->layer()->GetAnimator()->set_disable_timer_for_test(true);
2728 delegate.clear_bounds_changed();
2730 // Animate to a different position.
2732 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
2733 window->SetBounds(gfx::Rect(100, 100, 100, 100));
2736 // Bounds shouldn't immediately have changed.
2737 EXPECT_EQ("0,0 100x100", window->bounds().ToString());
2738 EXPECT_FALSE(delegate.bounds_changed());
2740 // Animate to the end, which should notify of the change.
2741 base::TimeTicks start_time =
2742 window->layer()->GetAnimator()->last_step_time();
2743 ui::AnimationContainerElement* element = window->layer()->GetAnimator();
2744 element->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
2745 EXPECT_TRUE(delegate.bounds_changed());
2746 EXPECT_NE("0,0 100x100", window->bounds().ToString());
2749 // Verifies the delegate is notified when the actual bounds of the layer
2750 // change even when the window is not the layer's delegate
2751 TEST_F(WindowTest, DelegateNotifiedAsBoundsChangeInHiddenLayer) {
2752 BoundsChangeDelegate delegate;
2754 // We cannot short-circuit animations in this test.
2755 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
2756 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
2758 scoped_ptr<Window> window(
2759 CreateTestWindowWithDelegate(&delegate, 1,
2760 gfx::Rect(0, 0, 100, 100), root_window()));
2761 window->layer()->GetAnimator()->set_disable_timer_for_test(true);
2763 delegate.clear_bounds_changed();
2765 // Suppress paint on the window since it is hidden (should reset the layer's
2766 // delegate to NULL)
2767 window->SuppressPaint();
2768 EXPECT_EQ(NULL, window->layer()->delegate());
2770 // Animate to a different position.
2772 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
2773 window->SetBounds(gfx::Rect(100, 100, 110, 100));
2776 // Layer delegate is NULL but we should still get bounds changed notification.
2777 EXPECT_EQ("100,100 110x100", window->GetTargetBounds().ToString());
2778 EXPECT_TRUE(delegate.bounds_changed());
2780 delegate.clear_bounds_changed();
2782 // Animate to the end: will *not* notify of the change since we are hidden.
2783 base::TimeTicks start_time =
2784 window->layer()->GetAnimator()->last_step_time();
2785 ui::AnimationContainerElement* element = window->layer()->GetAnimator();
2786 element->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
2788 // No bounds changed notification at the end of animation since layer
2789 // delegate is NULL.
2790 EXPECT_FALSE(delegate.bounds_changed());
2791 EXPECT_NE("0,0 100x100", window->bounds().ToString());
2794 namespace {
2796 // Used by AddChildNotifications to track notification counts.
2797 class AddChildNotificationsObserver : public WindowObserver {
2798 public:
2799 AddChildNotificationsObserver() : added_count_(0), removed_count_(0) {}
2801 std::string CountStringAndReset() {
2802 std::string result = base::IntToString(added_count_) + " " +
2803 base::IntToString(removed_count_);
2804 added_count_ = removed_count_ = 0;
2805 return result;
2808 // WindowObserver overrides:
2809 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
2810 added_count_++;
2812 virtual void OnWindowRemovingFromRootWindow(Window* window) OVERRIDE {
2813 removed_count_++;
2816 private:
2817 int added_count_;
2818 int removed_count_;
2820 DISALLOW_COPY_AND_ASSIGN(AddChildNotificationsObserver);
2823 } // namespace
2825 // Assertions around when root window notifications are sent.
2826 TEST_F(WindowTest, AddChildNotifications) {
2827 AddChildNotificationsObserver observer;
2828 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
2829 scoped_ptr<Window> w2(CreateTestWindowWithId(1, root_window()));
2830 w2->AddObserver(&observer);
2831 w2->Focus();
2832 EXPECT_TRUE(w2->HasFocus());
2834 // Move |w2| to be a child of |w1|.
2835 w1->AddChild(w2.get());
2836 // Sine we moved in the same root, observer shouldn't be notified.
2837 EXPECT_EQ("0 0", observer.CountStringAndReset());
2838 // |w2| should still have focus after moving.
2839 EXPECT_TRUE(w2->HasFocus());
2842 // Tests that a delegate that destroys itself when the window is destroyed does
2843 // not break.
2844 TEST_F(WindowTest, DelegateDestroysSelfOnWindowDestroy) {
2845 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
2846 new DestroyWindowDelegate(),
2848 gfx::Rect(10, 20, 30, 40),
2849 root_window()));
2852 class HierarchyObserver : public WindowObserver {
2853 public:
2854 HierarchyObserver(Window* target) : target_(target) {
2855 target_->AddObserver(this);
2857 virtual ~HierarchyObserver() {
2858 target_->RemoveObserver(this);
2861 void ValidateState(
2862 int index,
2863 const WindowObserver::HierarchyChangeParams& params) const {
2864 ParamsMatch(params_[index], params);
2867 void Reset() {
2868 params_.clear();
2871 private:
2872 // Overridden from WindowObserver:
2873 virtual void OnWindowHierarchyChanging(
2874 const HierarchyChangeParams& params) OVERRIDE {
2875 params_.push_back(params);
2877 virtual void OnWindowHierarchyChanged(
2878 const HierarchyChangeParams& params) OVERRIDE {
2879 params_.push_back(params);
2882 void ParamsMatch(const WindowObserver::HierarchyChangeParams& p1,
2883 const WindowObserver::HierarchyChangeParams& p2) const {
2884 EXPECT_EQ(p1.phase, p2.phase);
2885 EXPECT_EQ(p1.target, p2.target);
2886 EXPECT_EQ(p1.new_parent, p2.new_parent);
2887 EXPECT_EQ(p1.old_parent, p2.old_parent);
2888 EXPECT_EQ(p1.receiver, p2.receiver);
2891 Window* target_;
2892 std::vector<WindowObserver::HierarchyChangeParams> params_;
2894 DISALLOW_COPY_AND_ASSIGN(HierarchyObserver);
2897 // Tests hierarchy change notifications.
2898 TEST_F(WindowTest, OnWindowHierarchyChange) {
2900 // Simple add & remove.
2901 HierarchyObserver oroot(root_window());
2903 scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL));
2904 HierarchyObserver o1(w1.get());
2906 // Add.
2907 root_window()->AddChild(w1.get());
2909 WindowObserver::HierarchyChangeParams params;
2910 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2911 params.target = w1.get();
2912 params.old_parent = NULL;
2913 params.new_parent = root_window();
2914 params.receiver = w1.get();
2915 o1.ValidateState(0, params);
2917 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2918 params.receiver = w1.get();
2919 o1.ValidateState(1, params);
2921 params.receiver = root_window();
2922 oroot.ValidateState(0, params);
2924 // Remove.
2925 o1.Reset();
2926 oroot.Reset();
2928 root_window()->RemoveChild(w1.get());
2930 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2931 params.old_parent = root_window();
2932 params.new_parent = NULL;
2933 params.receiver = w1.get();
2935 o1.ValidateState(0, params);
2937 params.receiver = root_window();
2938 oroot.ValidateState(0, params);
2940 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2941 params.receiver = w1.get();
2942 o1.ValidateState(1, params);
2946 // Add & remove of hierarchy. Tests notification order per documentation in
2947 // WindowObserver.
2948 HierarchyObserver o(root_window());
2949 scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL));
2950 Window* w11 = CreateTestWindowWithId(11, w1.get());
2951 w1->AddObserver(&o);
2952 w11->AddObserver(&o);
2954 // Add.
2955 root_window()->AddChild(w1.get());
2957 // Dispatched to target first.
2958 int index = 0;
2959 WindowObserver::HierarchyChangeParams params;
2960 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2961 params.target = w1.get();
2962 params.old_parent = NULL;
2963 params.new_parent = root_window();
2964 params.receiver = w1.get();
2965 o.ValidateState(index++, params);
2967 // Dispatched to target's children.
2968 params.receiver = w11;
2969 o.ValidateState(index++, params);
2971 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2973 // Now process the "changed" phase.
2974 params.receiver = w1.get();
2975 o.ValidateState(index++, params);
2976 params.receiver = w11;
2977 o.ValidateState(index++, params);
2978 params.receiver = root_window();
2979 o.ValidateState(index++, params);
2981 // Remove.
2982 root_window()->RemoveChild(w1.get());
2983 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2984 params.old_parent = root_window();
2985 params.new_parent = NULL;
2986 params.receiver = w1.get();
2987 o.ValidateState(index++, params);
2988 params.receiver = w11;
2989 o.ValidateState(index++, params);
2990 params.receiver = root_window();
2991 o.ValidateState(index++, params);
2992 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2993 params.receiver = w1.get();
2994 o.ValidateState(index++, params);
2995 params.receiver = w11;
2996 o.ValidateState(index++, params);
2998 w1.reset();
3002 // Reparent. Tests notification order per documentation in WindowObserver.
3003 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
3004 Window* w11 = CreateTestWindowWithId(11, w1.get());
3005 Window* w111 = CreateTestWindowWithId(111, w11);
3006 scoped_ptr<Window> w2(CreateTestWindowWithId(2, root_window()));
3008 HierarchyObserver o(root_window());
3009 w1->AddObserver(&o);
3010 w11->AddObserver(&o);
3011 w111->AddObserver(&o);
3012 w2->AddObserver(&o);
3014 w2->AddChild(w11);
3016 // Dispatched to target first.
3017 int index = 0;
3018 WindowObserver::HierarchyChangeParams params;
3019 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
3020 params.target = w11;
3021 params.old_parent = w1.get();
3022 params.new_parent = w2.get();
3023 params.receiver = w11;
3024 o.ValidateState(index++, params);
3026 // Then to target's children.
3027 params.receiver = w111;
3028 o.ValidateState(index++, params);
3030 // Then to target's old parent chain.
3031 params.receiver = w1.get();
3032 o.ValidateState(index++, params);
3033 params.receiver = root_window();
3034 o.ValidateState(index++, params);
3036 // "Changed" phase.
3037 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
3038 params.receiver = w11;
3039 o.ValidateState(index++, params);
3040 params.receiver = w111;
3041 o.ValidateState(index++, params);
3042 params.receiver = w2.get();
3043 o.ValidateState(index++, params);
3044 params.receiver = root_window();
3045 o.ValidateState(index++, params);
3047 w1.reset();
3048 w2.reset();
3053 } // namespace test
3054 } // namespace aura