Roll DEPS for libelf clang compilation fix.
[chromium-blink-merge.git] / ui / aura / window_unittest.cc
blob37cf5edca783169da05c17d47ac628f9059ab54a
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 <string>
8 #include <utility>
9 #include <vector>
11 #include "base/basictypes.h"
12 #include "base/compiler_specific.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "ui/aura/client/capture_client.h"
18 #include "ui/aura/client/focus_change_observer.h"
19 #include "ui/aura/client/visibility_client.h"
20 #include "ui/aura/client/window_tree_client.h"
21 #include "ui/aura/test/aura_test_base.h"
22 #include "ui/aura/test/aura_test_utils.h"
23 #include "ui/aura/test/event_generator.h"
24 #include "ui/aura/test/test_window_delegate.h"
25 #include "ui/aura/test/test_windows.h"
26 #include "ui/aura/test/window_test_api.h"
27 #include "ui/aura/window_delegate.h"
28 #include "ui/aura/window_event_dispatcher.h"
29 #include "ui/aura/window_observer.h"
30 #include "ui/aura/window_property.h"
31 #include "ui/aura/window_tree_host.h"
32 #include "ui/base/hit_test.h"
33 #include "ui/compositor/layer.h"
34 #include "ui/compositor/layer_animation_observer.h"
35 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
36 #include "ui/compositor/scoped_layer_animation_settings.h"
37 #include "ui/compositor/test/test_layers.h"
38 #include "ui/events/event.h"
39 #include "ui/events/event_utils.h"
40 #include "ui/events/gestures/gesture_configuration.h"
41 #include "ui/events/keycodes/keyboard_codes.h"
42 #include "ui/gfx/canvas.h"
43 #include "ui/gfx/screen.h"
44 #include "ui/gfx/skia_util.h"
45 #include "ui/gfx/vector2d.h"
47 DECLARE_WINDOW_PROPERTY_TYPE(const char*)
48 DECLARE_WINDOW_PROPERTY_TYPE(int)
50 namespace aura {
51 namespace test {
53 class WindowTest : public AuraTestBase {
54 public:
55 WindowTest() : max_separation_(0) {
58 virtual void SetUp() OVERRIDE {
59 AuraTestBase::SetUp();
60 // TODO: there needs to be an easier way to do this.
61 max_separation_ = ui::GestureConfiguration::
62 max_separation_for_gesture_touches_in_pixels();
63 ui::GestureConfiguration::
64 set_max_separation_for_gesture_touches_in_pixels(0);
67 virtual void TearDown() OVERRIDE {
68 AuraTestBase::TearDown();
69 ui::GestureConfiguration::
70 set_max_separation_for_gesture_touches_in_pixels(max_separation_);
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(Window* window) OVERRIDE {
98 EXPECT_FALSE(in_destroying_);
99 in_destroying_ = true;
100 destroying_count_++;
103 virtual void OnWindowDestroyed(Window* window) 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(Window* window) OVERRIDE {
127 EXPECT_TRUE(parent_delegate_->in_destroying());
128 DestroyTrackingDelegateImpl::OnWindowDestroying(window);
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(Window* window) 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 // Keeps track of the location of the gesture.
204 class GestureTrackPositionDelegate : public TestWindowDelegate {
205 public:
206 GestureTrackPositionDelegate() {}
208 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
209 position_ = event->location();
210 event->StopPropagation();
213 const gfx::Point& position() const { return position_; }
215 private:
216 gfx::Point position_;
218 DISALLOW_COPY_AND_ASSIGN(GestureTrackPositionDelegate);
221 base::TimeDelta getTime() {
222 return ui::EventTimeForNow();
225 class SelfEventHandlingWindowDelegate : public TestWindowDelegate {
226 public:
227 SelfEventHandlingWindowDelegate() {}
229 virtual bool ShouldDescendIntoChildForEventHandling(
230 Window* child,
231 const gfx::Point& location) OVERRIDE {
232 return false;
235 private:
236 DISALLOW_COPY_AND_ASSIGN(SelfEventHandlingWindowDelegate);
239 // The delegate deletes itself when the window is being destroyed.
240 class DestroyWindowDelegate : public TestWindowDelegate {
241 public:
242 DestroyWindowDelegate() {}
244 private:
245 virtual ~DestroyWindowDelegate() {}
247 // Overridden from WindowDelegate.
248 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
249 delete this;
252 DISALLOW_COPY_AND_ASSIGN(DestroyWindowDelegate);
255 } // namespace
257 TEST_F(WindowTest, GetChildById) {
258 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
259 scoped_ptr<Window> w11(CreateTestWindowWithId(11, w1.get()));
260 scoped_ptr<Window> w111(CreateTestWindowWithId(111, w11.get()));
261 scoped_ptr<Window> w12(CreateTestWindowWithId(12, w1.get()));
263 EXPECT_EQ(NULL, w1->GetChildById(57));
264 EXPECT_EQ(w12.get(), w1->GetChildById(12));
265 EXPECT_EQ(w111.get(), w1->GetChildById(111));
268 // Make sure that Window::Contains correctly handles children, grandchildren,
269 // and not containing NULL or parents.
270 TEST_F(WindowTest, Contains) {
271 Window parent(NULL);
272 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
273 Window child1(NULL);
274 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
275 Window child2(NULL);
276 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
278 parent.AddChild(&child1);
279 child1.AddChild(&child2);
281 EXPECT_TRUE(parent.Contains(&parent));
282 EXPECT_TRUE(parent.Contains(&child1));
283 EXPECT_TRUE(parent.Contains(&child2));
285 EXPECT_FALSE(parent.Contains(NULL));
286 EXPECT_FALSE(child1.Contains(&parent));
287 EXPECT_FALSE(child2.Contains(&child1));
290 TEST_F(WindowTest, ContainsPointInRoot) {
291 scoped_ptr<Window> w(
292 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 5, 5),
293 root_window()));
294 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(9, 9)));
295 EXPECT_TRUE(w->ContainsPointInRoot(gfx::Point(10, 10)));
296 EXPECT_TRUE(w->ContainsPointInRoot(gfx::Point(14, 14)));
297 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(15, 15)));
298 EXPECT_FALSE(w->ContainsPointInRoot(gfx::Point(20, 20)));
301 TEST_F(WindowTest, ContainsPoint) {
302 scoped_ptr<Window> w(
303 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 5, 5),
304 root_window()));
305 EXPECT_TRUE(w->ContainsPoint(gfx::Point(0, 0)));
306 EXPECT_TRUE(w->ContainsPoint(gfx::Point(4, 4)));
307 EXPECT_FALSE(w->ContainsPoint(gfx::Point(5, 5)));
308 EXPECT_FALSE(w->ContainsPoint(gfx::Point(10, 10)));
311 TEST_F(WindowTest, ConvertPointToWindow) {
312 // Window::ConvertPointToWindow is mostly identical to
313 // Layer::ConvertPointToLayer, except NULL values for |source| are permitted,
314 // in which case the function just returns.
315 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
316 gfx::Point reference_point(100, 100);
317 gfx::Point test_point = reference_point;
318 Window::ConvertPointToTarget(NULL, w1.get(), &test_point);
319 EXPECT_EQ(reference_point, test_point);
322 TEST_F(WindowTest, MoveCursorTo) {
323 scoped_ptr<Window> w1(
324 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
325 root_window()));
326 scoped_ptr<Window> w11(
327 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
328 scoped_ptr<Window> w111(
329 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
330 scoped_ptr<Window> w1111(
331 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
333 Window* root = root_window();
334 root->MoveCursorTo(gfx::Point(10, 10));
335 EXPECT_EQ("10,10",
336 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
337 w1->MoveCursorTo(gfx::Point(10, 10));
338 EXPECT_EQ("20,20",
339 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
340 w11->MoveCursorTo(gfx::Point(10, 10));
341 EXPECT_EQ("25,25",
342 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
343 w111->MoveCursorTo(gfx::Point(10, 10));
344 EXPECT_EQ("30,30",
345 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
346 w1111->MoveCursorTo(gfx::Point(10, 10));
347 EXPECT_EQ("35,35",
348 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
351 TEST_F(WindowTest, ContainsMouse) {
352 scoped_ptr<Window> w(
353 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
354 root_window()));
355 w->Show();
356 WindowTestApi w_test_api(w.get());
357 Window* root = root_window();
358 root->MoveCursorTo(gfx::Point(10, 10));
359 EXPECT_TRUE(w_test_api.ContainsMouse());
360 root->MoveCursorTo(gfx::Point(9, 10));
361 EXPECT_FALSE(w_test_api.ContainsMouse());
364 // Test Window::ConvertPointToWindow() with transform to root_window.
365 #if defined(USE_OZONE)
366 // TODO(rjkroege): Add cursor support in ozone: http://crbug.com/252315.
367 TEST_F(WindowTest, DISABLED_MoveCursorToWithTransformRootWindow) {
368 #else
369 TEST_F(WindowTest, MoveCursorToWithTransformRootWindow) {
370 #endif
371 gfx::Transform transform;
372 transform.Translate(100.0, 100.0);
373 transform.Rotate(90.0);
374 transform.Scale(2.0, 5.0);
375 host()->SetRootTransform(transform);
376 host()->MoveCursorTo(gfx::Point(10, 10));
377 #if !defined(OS_WIN)
378 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.OD
379 EXPECT_EQ("50,120", QueryLatestMousePositionRequestInHost(host()).ToString());
380 #endif
381 EXPECT_EQ("10,10", gfx::Screen::GetScreenFor(
382 root_window())->GetCursorScreenPoint().ToString());
385 // Tests Window::ConvertPointToWindow() with transform to non-root windows.
386 TEST_F(WindowTest, MoveCursorToWithTransformWindow) {
387 scoped_ptr<Window> w1(
388 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
389 root_window()));
391 gfx::Transform transform1;
392 transform1.Scale(2, 2);
393 w1->SetTransform(transform1);
394 w1->MoveCursorTo(gfx::Point(10, 10));
395 EXPECT_EQ("30,30",
396 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
398 gfx::Transform transform2;
399 transform2.Translate(-10, 20);
400 w1->SetTransform(transform2);
401 w1->MoveCursorTo(gfx::Point(10, 10));
402 EXPECT_EQ("10,40",
403 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
405 gfx::Transform transform3;
406 transform3.Rotate(90.0);
407 w1->SetTransform(transform3);
408 w1->MoveCursorTo(gfx::Point(5, 5));
409 EXPECT_EQ("5,15",
410 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
412 gfx::Transform transform4;
413 transform4.Translate(100.0, 100.0);
414 transform4.Rotate(90.0);
415 transform4.Scale(2.0, 5.0);
416 w1->SetTransform(transform4);
417 w1->MoveCursorTo(gfx::Point(10, 10));
418 EXPECT_EQ("60,130",
419 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString());
422 // Test Window::ConvertPointToWindow() with complex transforms to both root and
423 // non-root windows.
424 // Test Window::ConvertPointToWindow() with transform to root_window.
425 #if defined(USE_OZONE)
426 // TODO(rjkroege): Add cursor support in ozone: http://crbug.com/252315.
427 TEST_F(WindowTest, DISABLED_MoveCursorToWithComplexTransform) {
428 #else
429 TEST_F(WindowTest, MoveCursorToWithComplexTransform) {
430 #endif
431 scoped_ptr<Window> w1(
432 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
433 root_window()));
434 scoped_ptr<Window> w11(
435 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
436 scoped_ptr<Window> w111(
437 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
438 scoped_ptr<Window> w1111(
439 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
441 Window* root = root_window();
443 // The root window expects transforms that produce integer rects.
444 gfx::Transform root_transform;
445 root_transform.Translate(60.0, 70.0);
446 root_transform.Rotate(-90.0);
447 root_transform.Translate(-50.0, -50.0);
448 root_transform.Scale(2.0, 3.0);
450 gfx::Transform transform;
451 transform.Translate(10.0, 20.0);
452 transform.Rotate(10.0);
453 transform.Scale(0.3f, 0.5f);
454 host()->SetRootTransform(root_transform);
455 w1->SetTransform(transform);
456 w11->SetTransform(transform);
457 w111->SetTransform(transform);
458 w1111->SetTransform(transform);
460 w1111->MoveCursorTo(gfx::Point(10, 10));
462 #if !defined(OS_WIN)
463 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.
464 EXPECT_EQ("169,80", QueryLatestMousePositionRequestInHost(host()).ToString());
465 #endif
466 EXPECT_EQ("20,53",
467 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString());
470 TEST_F(WindowTest, GetEventHandlerForPoint) {
471 scoped_ptr<Window> w1(
472 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500),
473 root_window()));
474 scoped_ptr<Window> w11(
475 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get()));
476 scoped_ptr<Window> w111(
477 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get()));
478 scoped_ptr<Window> w1111(
479 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get()));
480 scoped_ptr<Window> w12(
481 CreateTestWindow(SK_ColorMAGENTA, 12, gfx::Rect(10, 420, 25, 25),
482 w1.get()));
483 scoped_ptr<Window> w121(
484 CreateTestWindow(SK_ColorYELLOW, 121, gfx::Rect(5, 5, 5, 5), w12.get()));
485 scoped_ptr<Window> w13(
486 CreateTestWindow(SK_ColorGRAY, 13, gfx::Rect(5, 470, 50, 50), w1.get()));
488 Window* root = root_window();
489 w1->parent()->SetBounds(gfx::Rect(500, 500));
490 EXPECT_EQ(NULL, root->GetEventHandlerForPoint(gfx::Point(5, 5)));
491 EXPECT_EQ(w1.get(), root->GetEventHandlerForPoint(gfx::Point(11, 11)));
492 EXPECT_EQ(w11.get(), root->GetEventHandlerForPoint(gfx::Point(16, 16)));
493 EXPECT_EQ(w111.get(), root->GetEventHandlerForPoint(gfx::Point(21, 21)));
494 EXPECT_EQ(w1111.get(), root->GetEventHandlerForPoint(gfx::Point(26, 26)));
495 EXPECT_EQ(w12.get(), root->GetEventHandlerForPoint(gfx::Point(21, 431)));
496 EXPECT_EQ(w121.get(), root->GetEventHandlerForPoint(gfx::Point(26, 436)));
497 EXPECT_EQ(w13.get(), root->GetEventHandlerForPoint(gfx::Point(26, 481)));
500 TEST_F(WindowTest, GetEventHandlerForPointWithOverride) {
501 // If our child is flush to our top-left corner he gets events just inside the
502 // window edges.
503 scoped_ptr<Window> parent(
504 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 20, 400, 500),
505 root_window()));
506 scoped_ptr<Window> child(
507 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(0, 0, 60, 70), parent.get()));
508 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
509 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(1, 1)));
511 // We can override the hit test bounds of the parent to make the parent grab
512 // events along that edge.
513 parent->set_hit_test_bounds_override_inner(gfx::Insets(1, 1, 1, 1));
514 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
515 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(1, 1)));
518 TEST_F(WindowTest, GetEventHandlerForPointWithOverrideDescendingOrder) {
519 scoped_ptr<SelfEventHandlingWindowDelegate> parent_delegate(
520 new SelfEventHandlingWindowDelegate);
521 scoped_ptr<Window> parent(CreateTestWindowWithDelegate(
522 parent_delegate.get(), 1, gfx::Rect(10, 20, 400, 500), root_window()));
523 scoped_ptr<Window> child(
524 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(0, 0, 390, 480),
525 parent.get()));
527 // We can override ShouldDescendIntoChildForEventHandling to make the parent
528 // grab all events.
529 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0)));
530 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(50, 50)));
533 TEST_F(WindowTest, GetTopWindowContainingPoint) {
534 Window* root = root_window();
535 root->SetBounds(gfx::Rect(0, 0, 300, 300));
537 scoped_ptr<Window> w1(
538 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 100, 100),
539 root_window()));
540 scoped_ptr<Window> w11(
541 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(0, 0, 120, 120), w1.get()));
543 scoped_ptr<Window> w2(
544 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(5, 5, 55, 55),
545 root_window()));
547 scoped_ptr<Window> w3(
548 CreateTestWindowWithDelegate(
549 NULL, 3, gfx::Rect(200, 200, 100, 100), root_window()));
550 scoped_ptr<Window> w31(
551 CreateTestWindow(SK_ColorCYAN, 31, gfx::Rect(0, 0, 50, 50), w3.get()));
552 scoped_ptr<Window> w311(
553 CreateTestWindow(SK_ColorBLUE, 311, gfx::Rect(0, 0, 10, 10), w31.get()));
555 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(0, 0)));
556 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(5, 5)));
557 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(10, 10)));
558 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(59, 59)));
559 EXPECT_EQ(w1.get(), root->GetTopWindowContainingPoint(gfx::Point(60, 60)));
560 EXPECT_EQ(w1.get(), root->GetTopWindowContainingPoint(gfx::Point(109, 109)));
561 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(110, 110)));
562 EXPECT_EQ(w31.get(), root->GetTopWindowContainingPoint(gfx::Point(200, 200)));
563 EXPECT_EQ(w31.get(), root->GetTopWindowContainingPoint(gfx::Point(220, 220)));
564 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(260, 260)));
567 TEST_F(WindowTest, GetToplevelWindow) {
568 const gfx::Rect kBounds(0, 0, 10, 10);
569 TestWindowDelegate delegate;
571 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
572 scoped_ptr<Window> w11(
573 CreateTestWindowWithDelegate(&delegate, 11, kBounds, w1.get()));
574 scoped_ptr<Window> w111(CreateTestWindowWithId(111, w11.get()));
575 scoped_ptr<Window> w1111(
576 CreateTestWindowWithDelegate(&delegate, 1111, kBounds, w111.get()));
578 EXPECT_TRUE(root_window()->GetToplevelWindow() == NULL);
579 EXPECT_TRUE(w1->GetToplevelWindow() == NULL);
580 EXPECT_EQ(w11.get(), w11->GetToplevelWindow());
581 EXPECT_EQ(w11.get(), w111->GetToplevelWindow());
582 EXPECT_EQ(w11.get(), w1111->GetToplevelWindow());
585 class AddedToRootWindowObserver : public WindowObserver {
586 public:
587 AddedToRootWindowObserver() : called_(false) {}
589 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
590 called_ = true;
593 bool called() const { return called_; }
595 private:
596 bool called_;
598 DISALLOW_COPY_AND_ASSIGN(AddedToRootWindowObserver);
601 TEST_F(WindowTest, WindowAddedToRootWindowShouldNotifyChildAndNotParent) {
602 AddedToRootWindowObserver parent_observer;
603 AddedToRootWindowObserver child_observer;
604 scoped_ptr<Window> parent_window(CreateTestWindowWithId(1, root_window()));
605 scoped_ptr<Window> child_window(new Window(NULL));
606 child_window->Init(aura::WINDOW_LAYER_TEXTURED);
607 child_window->Show();
609 parent_window->AddObserver(&parent_observer);
610 child_window->AddObserver(&child_observer);
612 parent_window->AddChild(child_window.get());
614 EXPECT_FALSE(parent_observer.called());
615 EXPECT_TRUE(child_observer.called());
617 parent_window->RemoveObserver(&parent_observer);
618 child_window->RemoveObserver(&child_observer);
621 // Various destruction assertions.
622 TEST_F(WindowTest, DestroyTest) {
623 DestroyTrackingDelegateImpl parent_delegate;
624 ChildWindowDelegateImpl child_delegate(&parent_delegate);
626 scoped_ptr<Window> parent(
627 CreateTestWindowWithDelegate(&parent_delegate, 0, gfx::Rect(),
628 root_window()));
629 CreateTestWindowWithDelegate(&child_delegate, 0, gfx::Rect(), parent.get());
631 // Both the parent and child should have been destroyed.
632 EXPECT_EQ(1, parent_delegate.destroying_count());
633 EXPECT_EQ(1, parent_delegate.destroyed_count());
634 EXPECT_EQ(1, child_delegate.destroying_count());
635 EXPECT_EQ(1, child_delegate.destroyed_count());
638 // Tests that a window is orphaned before OnWindowDestroyed is called.
639 TEST_F(WindowTest, OrphanedBeforeOnDestroyed) {
640 TestWindowDelegate parent_delegate;
641 DestroyOrphanDelegate child_delegate;
643 scoped_ptr<Window> parent(
644 CreateTestWindowWithDelegate(&parent_delegate, 0, gfx::Rect(),
645 root_window()));
646 scoped_ptr<Window> child(CreateTestWindowWithDelegate(&child_delegate, 0,
647 gfx::Rect(), parent.get()));
648 child_delegate.set_window(child.get());
652 // Make sure StackChildAtTop moves both the window and layer to the front.
653 TEST_F(WindowTest, StackChildAtTop) {
654 Window parent(NULL);
655 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
656 Window child1(NULL);
657 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
658 Window child2(NULL);
659 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
661 parent.AddChild(&child1);
662 parent.AddChild(&child2);
663 ASSERT_EQ(2u, parent.children().size());
664 EXPECT_EQ(&child1, parent.children()[0]);
665 EXPECT_EQ(&child2, parent.children()[1]);
666 ASSERT_EQ(2u, parent.layer()->children().size());
667 EXPECT_EQ(child1.layer(), parent.layer()->children()[0]);
668 EXPECT_EQ(child2.layer(), parent.layer()->children()[1]);
670 parent.StackChildAtTop(&child1);
671 ASSERT_EQ(2u, parent.children().size());
672 EXPECT_EQ(&child1, parent.children()[1]);
673 EXPECT_EQ(&child2, parent.children()[0]);
674 ASSERT_EQ(2u, parent.layer()->children().size());
675 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
676 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
679 // Make sure StackChildBelow works.
680 TEST_F(WindowTest, StackChildBelow) {
681 Window parent(NULL);
682 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
683 Window child1(NULL);
684 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
685 child1.set_id(1);
686 Window child2(NULL);
687 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
688 child2.set_id(2);
689 Window child3(NULL);
690 child3.Init(aura::WINDOW_LAYER_NOT_DRAWN);
691 child3.set_id(3);
693 parent.AddChild(&child1);
694 parent.AddChild(&child2);
695 parent.AddChild(&child3);
696 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent));
698 parent.StackChildBelow(&child1, &child2);
699 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent));
701 parent.StackChildBelow(&child2, &child1);
702 EXPECT_EQ("2 1 3", ChildWindowIDsAsString(&parent));
704 parent.StackChildBelow(&child3, &child2);
705 EXPECT_EQ("3 2 1", ChildWindowIDsAsString(&parent));
707 parent.StackChildBelow(&child3, &child1);
708 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(&parent));
711 // Various assertions for StackChildAbove.
712 TEST_F(WindowTest, StackChildAbove) {
713 Window parent(NULL);
714 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN);
715 Window child1(NULL);
716 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
717 Window child2(NULL);
718 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
719 Window child3(NULL);
720 child3.Init(aura::WINDOW_LAYER_NOT_DRAWN);
722 parent.AddChild(&child1);
723 parent.AddChild(&child2);
725 // Move 1 in front of 2.
726 parent.StackChildAbove(&child1, &child2);
727 ASSERT_EQ(2u, parent.children().size());
728 EXPECT_EQ(&child2, parent.children()[0]);
729 EXPECT_EQ(&child1, parent.children()[1]);
730 ASSERT_EQ(2u, parent.layer()->children().size());
731 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
732 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
734 // Add 3, resulting in order [2, 1, 3], then move 2 in front of 1, resulting
735 // in [1, 2, 3].
736 parent.AddChild(&child3);
737 parent.StackChildAbove(&child2, &child1);
738 ASSERT_EQ(3u, parent.children().size());
739 EXPECT_EQ(&child1, parent.children()[0]);
740 EXPECT_EQ(&child2, parent.children()[1]);
741 EXPECT_EQ(&child3, parent.children()[2]);
742 ASSERT_EQ(3u, parent.layer()->children().size());
743 EXPECT_EQ(child1.layer(), parent.layer()->children()[0]);
744 EXPECT_EQ(child2.layer(), parent.layer()->children()[1]);
745 EXPECT_EQ(child3.layer(), parent.layer()->children()[2]);
747 // Move 1 in front of 3, resulting in [2, 3, 1].
748 parent.StackChildAbove(&child1, &child3);
749 ASSERT_EQ(3u, parent.children().size());
750 EXPECT_EQ(&child2, parent.children()[0]);
751 EXPECT_EQ(&child3, parent.children()[1]);
752 EXPECT_EQ(&child1, parent.children()[2]);
753 ASSERT_EQ(3u, parent.layer()->children().size());
754 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
755 EXPECT_EQ(child3.layer(), parent.layer()->children()[1]);
756 EXPECT_EQ(child1.layer(), parent.layer()->children()[2]);
758 // Moving 1 in front of 2 should lower it, resulting in [2, 1, 3].
759 parent.StackChildAbove(&child1, &child2);
760 ASSERT_EQ(3u, parent.children().size());
761 EXPECT_EQ(&child2, parent.children()[0]);
762 EXPECT_EQ(&child1, parent.children()[1]);
763 EXPECT_EQ(&child3, parent.children()[2]);
764 ASSERT_EQ(3u, parent.layer()->children().size());
765 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]);
766 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]);
767 EXPECT_EQ(child3.layer(), parent.layer()->children()[2]);
770 // Various capture assertions.
771 TEST_F(WindowTest, CaptureTests) {
772 CaptureWindowDelegateImpl delegate;
773 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
774 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
775 EXPECT_FALSE(window->HasCapture());
777 delegate.ResetCounts();
779 // Do a capture.
780 window->SetCapture();
781 EXPECT_TRUE(window->HasCapture());
782 EXPECT_EQ(0, delegate.capture_lost_count());
783 EXPECT_EQ(0, delegate.capture_changed_event_count());
784 EventGenerator generator(root_window(), gfx::Point(50, 50));
785 generator.PressLeftButton();
786 EXPECT_EQ(1, delegate.mouse_event_count());
787 generator.ReleaseLeftButton();
789 EXPECT_EQ(2, delegate.mouse_event_count());
790 delegate.ResetCounts();
792 ui::TouchEvent touchev(
793 ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), 0, getTime());
794 DispatchEventUsingWindowDispatcher(&touchev);
795 EXPECT_EQ(1, delegate.touch_event_count());
796 delegate.ResetCounts();
798 window->ReleaseCapture();
799 EXPECT_FALSE(window->HasCapture());
800 EXPECT_EQ(1, delegate.capture_lost_count());
801 EXPECT_EQ(1, delegate.capture_changed_event_count());
802 EXPECT_EQ(1, delegate.mouse_event_count());
803 EXPECT_EQ(0, delegate.touch_event_count());
805 generator.PressLeftButton();
806 EXPECT_EQ(1, delegate.mouse_event_count());
808 ui::TouchEvent touchev2(
809 ui::ET_TOUCH_PRESSED, gfx::Point(250, 250), 1, getTime());
810 DispatchEventUsingWindowDispatcher(&touchev2);
811 EXPECT_EQ(0, delegate.touch_event_count());
813 // Removing the capture window from parent should reset the capture window
814 // in the root window.
815 window->SetCapture();
816 EXPECT_EQ(window.get(), aura::client::GetCaptureWindow(root_window()));
817 window->parent()->RemoveChild(window.get());
818 EXPECT_FALSE(window->HasCapture());
819 EXPECT_EQ(NULL, aura::client::GetCaptureWindow(root_window()));
822 TEST_F(WindowTest, TouchCaptureCancelsOtherTouches) {
823 CaptureWindowDelegateImpl delegate1;
824 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
825 &delegate1, 0, gfx::Rect(0, 0, 50, 50), root_window()));
826 CaptureWindowDelegateImpl delegate2;
827 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
828 &delegate2, 0, gfx::Rect(50, 50, 50, 50), root_window()));
830 // Press on w1.
831 ui::TouchEvent press(
832 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
833 DispatchEventUsingWindowDispatcher(&press);
834 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
835 EXPECT_EQ(2, delegate1.gesture_event_count());
836 delegate1.ResetCounts();
838 // Capturing to w2 should cause the touch to be canceled.
839 w2->SetCapture();
840 EXPECT_EQ(1, delegate1.touch_event_count());
841 EXPECT_EQ(0, delegate2.touch_event_count());
842 delegate1.ResetCounts();
843 delegate2.ResetCounts();
845 // Events now go to w2.
846 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, getTime());
847 DispatchEventUsingWindowDispatcher(&move);
848 EXPECT_EQ(0, delegate1.gesture_event_count());
849 EXPECT_EQ(0, delegate1.touch_event_count());
850 EXPECT_EQ(0, delegate2.gesture_event_count());
851 EXPECT_EQ(1, delegate2.touch_event_count());
853 ui::TouchEvent release(
854 ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, getTime());
855 DispatchEventUsingWindowDispatcher(&release);
856 EXPECT_EQ(0, delegate1.gesture_event_count());
857 EXPECT_EQ(0, delegate2.gesture_event_count());
859 // A new press is captured by w2.
860 ui::TouchEvent press2(
861 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
862 DispatchEventUsingWindowDispatcher(&press2);
863 EXPECT_EQ(0, delegate1.gesture_event_count());
864 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
865 EXPECT_EQ(2, delegate2.gesture_event_count());
866 delegate1.ResetCounts();
867 delegate2.ResetCounts();
869 // And releasing capture changes nothing.
870 w2->ReleaseCapture();
871 EXPECT_EQ(0, delegate1.gesture_event_count());
872 EXPECT_EQ(0, delegate1.touch_event_count());
873 EXPECT_EQ(0, delegate2.gesture_event_count());
874 EXPECT_EQ(0, delegate2.touch_event_count());
877 TEST_F(WindowTest, TouchCaptureDoesntCancelCapturedTouches) {
878 CaptureWindowDelegateImpl delegate;
879 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
880 &delegate, 0, gfx::Rect(0, 0, 50, 50), root_window()));
882 ui::TouchEvent press(
883 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
884 DispatchEventUsingWindowDispatcher(&press);
886 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
887 EXPECT_EQ(2, delegate.gesture_event_count());
888 EXPECT_EQ(1, delegate.touch_event_count());
889 delegate.ResetCounts();
891 window->SetCapture();
892 EXPECT_EQ(0, delegate.gesture_event_count());
893 EXPECT_EQ(0, delegate.touch_event_count());
894 delegate.ResetCounts();
896 // On move We will get TOUCH_MOVED, GESTURE_TAP_CANCEL,
897 // GESTURE_SCROLL_START and GESTURE_SCROLL_UPDATE.
898 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, getTime());
899 DispatchEventUsingWindowDispatcher(&move);
900 EXPECT_EQ(1, delegate.touch_event_count());
901 EXPECT_EQ(3, delegate.gesture_event_count());
902 delegate.ResetCounts();
904 // Release capture shouldn't change anything.
905 window->ReleaseCapture();
906 EXPECT_EQ(0, delegate.touch_event_count());
907 EXPECT_EQ(0, delegate.gesture_event_count());
908 delegate.ResetCounts();
910 // On move we still get TOUCH_MOVED and GESTURE_SCROLL_UPDATE.
911 ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(10, 30), 0, getTime());
912 DispatchEventUsingWindowDispatcher(&move2);
913 EXPECT_EQ(1, delegate.touch_event_count());
914 EXPECT_EQ(1, delegate.gesture_event_count());
915 delegate.ResetCounts();
917 // And on release we get TOUCH_RELEASED, GESTURE_SCROLL_END, GESTURE_END
918 ui::TouchEvent release(
919 ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, getTime());
920 DispatchEventUsingWindowDispatcher(&release);
921 EXPECT_EQ(1, delegate.touch_event_count());
922 EXPECT_EQ(2, delegate.gesture_event_count());
926 // Assertions around SetCapture() and touch/gestures.
927 TEST_F(WindowTest, TransferCaptureTouchEvents) {
928 // Touch on |w1|.
929 CaptureWindowDelegateImpl d1;
930 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
931 &d1, 0, gfx::Rect(0, 0, 20, 20), root_window()));
932 ui::TouchEvent p1(ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime());
933 DispatchEventUsingWindowDispatcher(&p1);
934 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN.
935 EXPECT_EQ(1, d1.touch_event_count());
936 EXPECT_EQ(2, d1.gesture_event_count());
937 d1.ResetCounts();
939 // Touch on |w2| with a different id.
940 CaptureWindowDelegateImpl d2;
941 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
942 &d2, 0, gfx::Rect(40, 0, 40, 20), root_window()));
943 ui::TouchEvent p2(ui::ET_TOUCH_PRESSED, gfx::Point(41, 10), 1, getTime());
944 DispatchEventUsingWindowDispatcher(&p2);
945 EXPECT_EQ(0, d1.touch_event_count());
946 EXPECT_EQ(0, d1.gesture_event_count());
947 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN for new target window.
948 EXPECT_EQ(1, d2.touch_event_count());
949 EXPECT_EQ(2, d2.gesture_event_count());
950 d1.ResetCounts();
951 d2.ResetCounts();
953 // Set capture on |w2|, this should send a cancel (TAP_CANCEL, END) to |w1|
954 // but not |w2|.
955 w2->SetCapture();
956 EXPECT_EQ(1, d1.touch_event_count());
957 EXPECT_EQ(2, d1.gesture_event_count());
958 EXPECT_EQ(0, d2.touch_event_count());
959 EXPECT_EQ(0, d2.gesture_event_count());
960 d1.ResetCounts();
961 d2.ResetCounts();
963 CaptureWindowDelegateImpl d3;
964 scoped_ptr<Window> w3(CreateTestWindowWithDelegate(
965 &d3, 0, gfx::Rect(0, 0, 100, 101), root_window()));
966 // Set capture on w3. No new events should be received.
967 // Note this difference in behavior between the first and second capture
968 // is confusing and error prone. http://crbug.com/236930
969 w3->SetCapture();
970 EXPECT_EQ(0, d1.touch_event_count());
971 EXPECT_EQ(0, d1.gesture_event_count());
972 EXPECT_EQ(0, d2.touch_event_count());
973 EXPECT_EQ(0, d2.gesture_event_count());
974 EXPECT_EQ(0, d3.touch_event_count());
975 EXPECT_EQ(0, d3.gesture_event_count());
977 // Move touch id originally associated with |w2|. Since capture was transfered
978 // from 2 to 3 only |w3| should get the event.
979 ui::TouchEvent m3(ui::ET_TOUCH_MOVED, gfx::Point(110, 105), 1, getTime());
980 DispatchEventUsingWindowDispatcher(&m3);
981 EXPECT_EQ(0, d1.touch_event_count());
982 EXPECT_EQ(0, d1.gesture_event_count());
983 EXPECT_EQ(0, d2.touch_event_count());
984 EXPECT_EQ(0, d2.gesture_event_count());
985 // |w3| gets a TOUCH_MOVE, TAP_CANCEL and two scroll related events.
986 EXPECT_EQ(1, d3.touch_event_count());
987 EXPECT_EQ(3, d3.gesture_event_count());
988 d1.ResetCounts();
989 d2.ResetCounts();
990 d3.ResetCounts();
992 // When we release capture, no touches are canceled.
993 w3->ReleaseCapture();
994 EXPECT_EQ(0, d1.touch_event_count());
995 EXPECT_EQ(0, d1.gesture_event_count());
996 EXPECT_EQ(0, d2.touch_event_count());
997 EXPECT_EQ(0, d2.gesture_event_count());
998 EXPECT_EQ(0, d3.touch_event_count());
999 EXPECT_EQ(0, d3.gesture_event_count());
1001 // And when we move the touch again, |w3| still gets the events.
1002 ui::TouchEvent m4(ui::ET_TOUCH_MOVED, gfx::Point(120, 105), 1, getTime());
1003 DispatchEventUsingWindowDispatcher(&m4);
1004 EXPECT_EQ(0, d1.touch_event_count());
1005 EXPECT_EQ(0, d1.gesture_event_count());
1006 EXPECT_EQ(0, d2.touch_event_count());
1007 EXPECT_EQ(0, d2.gesture_event_count());
1008 EXPECT_EQ(1, d3.touch_event_count());
1009 EXPECT_EQ(1, d3.gesture_event_count());
1010 d1.ResetCounts();
1011 d2.ResetCounts();
1012 d3.ResetCounts();
1015 // Changes capture while capture is already ongoing.
1016 TEST_F(WindowTest, ChangeCaptureWhileMouseDown) {
1017 CaptureWindowDelegateImpl delegate;
1018 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
1019 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1020 CaptureWindowDelegateImpl delegate2;
1021 scoped_ptr<Window> w2(CreateTestWindowWithDelegate(
1022 &delegate2, 0, gfx::Rect(20, 20, 20, 20), root_window()));
1024 // Execute the scheduled draws so that mouse events are not
1025 // aggregated.
1026 RunAllPendingInMessageLoop();
1028 EXPECT_FALSE(window->HasCapture());
1030 // Do a capture.
1031 delegate.ResetCounts();
1032 window->SetCapture();
1033 EXPECT_TRUE(window->HasCapture());
1034 EXPECT_EQ(0, delegate.capture_lost_count());
1035 EXPECT_EQ(0, delegate.capture_changed_event_count());
1036 EventGenerator generator(root_window(), gfx::Point(50, 50));
1037 generator.PressLeftButton();
1038 EXPECT_EQ(0, delegate.capture_lost_count());
1039 EXPECT_EQ(0, delegate.capture_changed_event_count());
1040 EXPECT_EQ(1, delegate.mouse_event_count());
1042 // Set capture to |w2|, should implicitly unset capture for |window|.
1043 delegate.ResetCounts();
1044 delegate2.ResetCounts();
1045 w2->SetCapture();
1047 generator.MoveMouseTo(gfx::Point(40, 40), 2);
1048 EXPECT_EQ(1, delegate.capture_lost_count());
1049 EXPECT_EQ(1, delegate.capture_changed_event_count());
1050 EXPECT_EQ(1, delegate.mouse_event_count());
1051 EXPECT_EQ(2, delegate2.mouse_event_count());
1054 // Verifies capture is reset when a window is destroyed.
1055 TEST_F(WindowTest, ReleaseCaptureOnDestroy) {
1056 CaptureWindowDelegateImpl delegate;
1057 scoped_ptr<Window> window(CreateTestWindowWithDelegate(
1058 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window()));
1059 EXPECT_FALSE(window->HasCapture());
1061 // Do a capture.
1062 window->SetCapture();
1063 EXPECT_TRUE(window->HasCapture());
1065 // Destroy the window.
1066 window.reset();
1068 // Make sure the root window doesn't reference the window anymore.
1069 EXPECT_EQ(NULL, host()->dispatcher()->mouse_pressed_handler());
1070 EXPECT_EQ(NULL, aura::client::GetCaptureWindow(root_window()));
1073 TEST_F(WindowTest, GetBoundsInRootWindow) {
1074 scoped_ptr<Window> viewport(CreateTestWindowWithBounds(
1075 gfx::Rect(0, 0, 300, 300), root_window()));
1076 scoped_ptr<Window> child(CreateTestWindowWithBounds(
1077 gfx::Rect(0, 0, 100, 100), viewport.get()));
1078 // Sanity check.
1079 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1081 // The |child| window's screen bounds should move along with the |viewport|.
1082 viewport->SetBounds(gfx::Rect(-100, -100, 300, 300));
1083 EXPECT_EQ("-100,-100 100x100", child->GetBoundsInRootWindow().ToString());
1085 // The |child| window is moved to the 0,0 in screen coordinates.
1086 // |GetBoundsInRootWindow()| should return 0,0.
1087 child->SetBounds(gfx::Rect(100, 100, 100, 100));
1088 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString());
1091 class MouseEnterExitWindowDelegate : public TestWindowDelegate {
1092 public:
1093 MouseEnterExitWindowDelegate() : entered_(false), exited_(false) {}
1095 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
1096 switch (event->type()) {
1097 case ui::ET_MOUSE_ENTERED:
1098 EXPECT_TRUE(event->flags() & ui::EF_IS_SYNTHESIZED);
1099 entered_ = true;
1100 break;
1101 case ui::ET_MOUSE_EXITED:
1102 EXPECT_TRUE(event->flags() & ui::EF_IS_SYNTHESIZED);
1103 exited_ = true;
1104 break;
1105 default:
1106 break;
1110 bool entered() const { return entered_; }
1111 bool exited() const { return exited_; }
1113 // Clear the entered / exited states.
1114 void ResetExpectations() {
1115 entered_ = false;
1116 exited_ = false;
1119 private:
1120 bool entered_;
1121 bool exited_;
1123 DISALLOW_COPY_AND_ASSIGN(MouseEnterExitWindowDelegate);
1127 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1128 // mouse transitions from window to window.
1129 TEST_F(WindowTest, MouseEnterExit) {
1130 MouseEnterExitWindowDelegate d1;
1131 scoped_ptr<Window> w1(
1132 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1133 root_window()));
1134 MouseEnterExitWindowDelegate d2;
1135 scoped_ptr<Window> w2(
1136 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50),
1137 root_window()));
1139 test::EventGenerator generator(root_window());
1140 generator.MoveMouseToCenterOf(w1.get());
1141 EXPECT_TRUE(d1.entered());
1142 EXPECT_FALSE(d1.exited());
1143 EXPECT_FALSE(d2.entered());
1144 EXPECT_FALSE(d2.exited());
1146 generator.MoveMouseToCenterOf(w2.get());
1147 EXPECT_TRUE(d1.entered());
1148 EXPECT_TRUE(d1.exited());
1149 EXPECT_TRUE(d2.entered());
1150 EXPECT_FALSE(d2.exited());
1153 // Verifies that the WindowDelegate receives MouseExit from ET_MOUSE_EXITED.
1154 TEST_F(WindowTest, WindowTreeHostExit) {
1155 MouseEnterExitWindowDelegate d1;
1156 scoped_ptr<Window> w1(
1157 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1158 root_window()));
1160 test::EventGenerator generator(root_window());
1161 generator.MoveMouseToCenterOf(w1.get());
1162 EXPECT_TRUE(d1.entered());
1163 EXPECT_FALSE(d1.exited());
1164 d1.ResetExpectations();
1166 ui::MouseEvent exit_event(
1167 ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(), 0, 0);
1168 DispatchEventUsingWindowDispatcher(&exit_event);
1169 EXPECT_FALSE(d1.entered());
1170 EXPECT_TRUE(d1.exited());
1173 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for
1174 // mouse transitions from window to window, even if the entered window sets
1175 // and releases capture.
1176 TEST_F(WindowTest, MouseEnterExitWithClick) {
1177 MouseEnterExitWindowDelegate d1;
1178 scoped_ptr<Window> w1(
1179 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1180 root_window()));
1181 MouseEnterExitWindowDelegate d2;
1182 scoped_ptr<Window> w2(
1183 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50),
1184 root_window()));
1186 test::EventGenerator generator(root_window());
1187 generator.MoveMouseToCenterOf(w1.get());
1188 EXPECT_TRUE(d1.entered());
1189 EXPECT_FALSE(d1.exited());
1190 EXPECT_FALSE(d2.entered());
1191 EXPECT_FALSE(d2.exited());
1193 // Emmulate what Views does on a click by grabbing and releasing capture.
1194 generator.PressLeftButton();
1195 w1->SetCapture();
1196 w1->ReleaseCapture();
1197 generator.ReleaseLeftButton();
1199 generator.MoveMouseToCenterOf(w2.get());
1200 EXPECT_TRUE(d1.entered());
1201 EXPECT_TRUE(d1.exited());
1202 EXPECT_TRUE(d2.entered());
1203 EXPECT_FALSE(d2.exited());
1206 TEST_F(WindowTest, MouseEnterExitWhenDeleteWithCapture) {
1207 MouseEnterExitWindowDelegate delegate;
1208 scoped_ptr<Window> window(
1209 CreateTestWindowWithDelegate(&delegate, 1, gfx::Rect(10, 10, 50, 50),
1210 root_window()));
1212 test::EventGenerator generator(root_window());
1213 generator.MoveMouseToCenterOf(window.get());
1214 EXPECT_TRUE(delegate.entered());
1215 EXPECT_FALSE(delegate.exited());
1217 // Emmulate what Views does on a click by grabbing and releasing capture.
1218 generator.PressLeftButton();
1219 window->SetCapture();
1221 delegate.ResetExpectations();
1222 generator.MoveMouseTo(0, 0);
1223 EXPECT_FALSE(delegate.entered());
1224 EXPECT_FALSE(delegate.exited());
1226 delegate.ResetExpectations();
1227 window.reset();
1228 EXPECT_FALSE(delegate.entered());
1229 EXPECT_FALSE(delegate.exited());
1232 // Verifies that enter / exits are sent if windows appear and are deleted
1233 // under the current mouse position..
1234 TEST_F(WindowTest, MouseEnterExitWithDelete) {
1235 MouseEnterExitWindowDelegate d1;
1236 scoped_ptr<Window> w1(
1237 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1238 root_window()));
1240 test::EventGenerator generator(root_window());
1241 generator.MoveMouseToCenterOf(w1.get());
1242 EXPECT_TRUE(d1.entered());
1243 EXPECT_FALSE(d1.exited());
1244 d1.ResetExpectations();
1246 MouseEnterExitWindowDelegate d2;
1248 scoped_ptr<Window> w2(
1249 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1250 root_window()));
1251 // Enters / exits can be sent asynchronously.
1252 RunAllPendingInMessageLoop();
1253 EXPECT_FALSE(d1.entered());
1254 EXPECT_TRUE(d1.exited());
1255 EXPECT_TRUE(d2.entered());
1256 EXPECT_FALSE(d2.exited());
1257 d1.ResetExpectations();
1258 d2.ResetExpectations();
1260 // Enters / exits can be sent asynchronously.
1261 RunAllPendingInMessageLoop();
1262 EXPECT_TRUE(d2.exited());
1263 EXPECT_TRUE(d1.entered());
1266 // Verifies that enter / exits are sent if windows appear and are hidden
1267 // under the current mouse position..
1268 TEST_F(WindowTest, MouseEnterExitWithHide) {
1269 MouseEnterExitWindowDelegate d1;
1270 scoped_ptr<Window> w1(
1271 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1272 root_window()));
1274 test::EventGenerator generator(root_window());
1275 generator.MoveMouseToCenterOf(w1.get());
1276 EXPECT_TRUE(d1.entered());
1277 EXPECT_FALSE(d1.exited());
1279 MouseEnterExitWindowDelegate d2;
1280 scoped_ptr<Window> w2(
1281 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1282 root_window()));
1283 // Enters / exits can be send asynchronously.
1284 RunAllPendingInMessageLoop();
1285 EXPECT_TRUE(d1.entered());
1286 EXPECT_TRUE(d1.exited());
1287 EXPECT_TRUE(d2.entered());
1288 EXPECT_FALSE(d2.exited());
1290 d1.ResetExpectations();
1291 w2->Hide();
1292 // Enters / exits can be send asynchronously.
1293 RunAllPendingInMessageLoop();
1294 EXPECT_TRUE(d2.exited());
1295 EXPECT_TRUE(d1.entered());
1298 TEST_F(WindowTest, MouseEnterExitWithParentHide) {
1299 MouseEnterExitWindowDelegate d1;
1300 scoped_ptr<Window> w1(
1301 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1302 root_window()));
1303 MouseEnterExitWindowDelegate d2;
1304 Window* w2 = CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1305 w1.get());
1306 test::EventGenerator generator(root_window());
1307 generator.MoveMouseToCenterOf(w2);
1308 // Enters / exits can be send asynchronously.
1309 RunAllPendingInMessageLoop();
1310 EXPECT_TRUE(d2.entered());
1311 EXPECT_FALSE(d2.exited());
1313 d2.ResetExpectations();
1314 w1->Hide();
1315 RunAllPendingInMessageLoop();
1316 EXPECT_FALSE(d2.entered());
1317 EXPECT_TRUE(d2.exited());
1319 w1.reset();
1322 TEST_F(WindowTest, MouseEnterExitWithParentDelete) {
1323 MouseEnterExitWindowDelegate d1;
1324 scoped_ptr<Window> w1(
1325 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50),
1326 root_window()));
1327 MouseEnterExitWindowDelegate d2;
1328 Window* w2 = CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50),
1329 w1.get());
1330 test::EventGenerator generator(root_window());
1331 generator.MoveMouseToCenterOf(w2);
1333 // Enters / exits can be send asynchronously.
1334 RunAllPendingInMessageLoop();
1335 EXPECT_TRUE(d2.entered());
1336 EXPECT_FALSE(d2.exited());
1338 d2.ResetExpectations();
1339 w1.reset();
1340 RunAllPendingInMessageLoop();
1341 EXPECT_FALSE(d2.entered());
1342 EXPECT_TRUE(d2.exited());
1345 // Creates a window with a delegate (w111) that can handle events at a lower
1346 // z-index than a window without a delegate (w12). w12 is sized to fill the
1347 // entire bounds of the container. This test verifies that
1348 // GetEventHandlerForPoint() skips w12 even though its bounds contain the event,
1349 // because it has no children that can handle the event and it has no delegate
1350 // allowing it to handle the event itself.
1351 TEST_F(WindowTest, GetEventHandlerForPoint_NoDelegate) {
1352 TestWindowDelegate d111;
1353 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(NULL, 1,
1354 gfx::Rect(0, 0, 500, 500), root_window()));
1355 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(NULL, 11,
1356 gfx::Rect(0, 0, 500, 500), w1.get()));
1357 scoped_ptr<Window> w111(CreateTestWindowWithDelegate(&d111, 111,
1358 gfx::Rect(50, 50, 450, 450), w11.get()));
1359 scoped_ptr<Window> w12(CreateTestWindowWithDelegate(NULL, 12,
1360 gfx::Rect(0, 0, 500, 500), w1.get()));
1362 gfx::Point target_point = w111->bounds().CenterPoint();
1363 EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(target_point));
1366 class VisibilityWindowDelegate : public TestWindowDelegate {
1367 public:
1368 VisibilityWindowDelegate()
1369 : shown_(0),
1370 hidden_(0) {
1373 int shown() const { return shown_; }
1374 int hidden() const { return hidden_; }
1375 void Clear() {
1376 shown_ = 0;
1377 hidden_ = 0;
1380 virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE {
1381 if (visible)
1382 shown_++;
1383 else
1384 hidden_++;
1387 private:
1388 int shown_;
1389 int hidden_;
1391 DISALLOW_COPY_AND_ASSIGN(VisibilityWindowDelegate);
1394 // Verifies show/hide propagate correctly to children and the layer.
1395 TEST_F(WindowTest, Visibility) {
1396 VisibilityWindowDelegate d;
1397 VisibilityWindowDelegate d2;
1398 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(&d, 1, gfx::Rect(),
1399 root_window()));
1400 scoped_ptr<Window> w2(
1401 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(), w1.get()));
1402 scoped_ptr<Window> w3(CreateTestWindowWithId(3, w2.get()));
1404 // Create shows all the windows.
1405 EXPECT_TRUE(w1->IsVisible());
1406 EXPECT_TRUE(w2->IsVisible());
1407 EXPECT_TRUE(w3->IsVisible());
1408 EXPECT_EQ(1, d.shown());
1410 d.Clear();
1411 w1->Hide();
1412 EXPECT_FALSE(w1->IsVisible());
1413 EXPECT_FALSE(w2->IsVisible());
1414 EXPECT_FALSE(w3->IsVisible());
1415 EXPECT_EQ(1, d.hidden());
1416 EXPECT_EQ(0, d.shown());
1418 w2->Show();
1419 EXPECT_FALSE(w1->IsVisible());
1420 EXPECT_FALSE(w2->IsVisible());
1421 EXPECT_FALSE(w3->IsVisible());
1423 w3->Hide();
1424 EXPECT_FALSE(w1->IsVisible());
1425 EXPECT_FALSE(w2->IsVisible());
1426 EXPECT_FALSE(w3->IsVisible());
1428 d.Clear();
1429 w1->Show();
1430 EXPECT_TRUE(w1->IsVisible());
1431 EXPECT_TRUE(w2->IsVisible());
1432 EXPECT_FALSE(w3->IsVisible());
1433 EXPECT_EQ(0, d.hidden());
1434 EXPECT_EQ(1, d.shown());
1436 w3->Show();
1437 EXPECT_TRUE(w1->IsVisible());
1438 EXPECT_TRUE(w2->IsVisible());
1439 EXPECT_TRUE(w3->IsVisible());
1441 // Verify that if an ancestor isn't visible and we change the visibility of a
1442 // child window that OnChildWindowVisibilityChanged() is still invoked.
1443 w1->Hide();
1444 d2.Clear();
1445 w2->Hide();
1446 EXPECT_EQ(1, d2.hidden());
1447 EXPECT_EQ(0, d2.shown());
1448 d2.Clear();
1449 w2->Show();
1450 EXPECT_EQ(0, d2.hidden());
1451 EXPECT_EQ(1, d2.shown());
1454 TEST_F(WindowTest, IgnoreEventsTest) {
1455 TestWindowDelegate d11;
1456 TestWindowDelegate d12;
1457 TestWindowDelegate d111;
1458 TestWindowDelegate d121;
1459 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(NULL, 1,
1460 gfx::Rect(0, 0, 500, 500), root_window()));
1461 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(&d11, 11,
1462 gfx::Rect(0, 0, 500, 500), w1.get()));
1463 scoped_ptr<Window> w111(CreateTestWindowWithDelegate(&d111, 111,
1464 gfx::Rect(50, 50, 450, 450), w11.get()));
1465 scoped_ptr<Window> w12(CreateTestWindowWithDelegate(&d12, 12,
1466 gfx::Rect(0, 0, 500, 500), w1.get()));
1467 scoped_ptr<Window> w121(CreateTestWindowWithDelegate(&d121, 121,
1468 gfx::Rect(150, 150, 50, 50), w12.get()));
1470 EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10)));
1471 w12->set_ignore_events(true);
1472 EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10)));
1473 w12->set_ignore_events(false);
1475 EXPECT_EQ(w121.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1476 w121->set_ignore_events(true);
1477 EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1478 w12->set_ignore_events(true);
1479 EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1480 w111->set_ignore_events(true);
1481 EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
1484 // Tests transformation on the root window.
1485 TEST_F(WindowTest, Transform) {
1486 gfx::Size size = host()->GetBounds().size();
1487 EXPECT_EQ(gfx::Rect(size),
1488 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1489 gfx::Point()).bounds());
1491 // Rotate it clock-wise 90 degrees.
1492 gfx::Transform transform;
1493 transform.Translate(size.height(), 0);
1494 transform.Rotate(90.0);
1495 host()->SetRootTransform(transform);
1497 // The size should be the transformed size.
1498 gfx::Size transformed_size(size.height(), size.width());
1499 EXPECT_EQ(transformed_size.ToString(),
1500 root_window()->bounds().size().ToString());
1501 EXPECT_EQ(
1502 gfx::Rect(transformed_size).ToString(),
1503 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint(
1504 gfx::Point()).bounds().ToString());
1506 // Host size shouldn't change.
1507 EXPECT_EQ(size.ToString(), host()->GetBounds().size().ToString());
1510 TEST_F(WindowTest, TransformGesture) {
1511 gfx::Size size = host()->GetBounds().size();
1513 scoped_ptr<GestureTrackPositionDelegate> delegate(
1514 new GestureTrackPositionDelegate);
1515 scoped_ptr<Window> window(CreateTestWindowWithDelegate(delegate.get(), -1234,
1516 gfx::Rect(0, 0, 20, 20), root_window()));
1518 // Rotate the root-window clock-wise 90 degrees.
1519 gfx::Transform transform;
1520 transform.Translate(size.height(), 0.0);
1521 transform.Rotate(90.0);
1522 host()->SetRootTransform(transform);
1524 ui::TouchEvent press(
1525 ui::ET_TOUCH_PRESSED, gfx::Point(size.height() - 10, 10), 0, getTime());
1526 DispatchEventUsingWindowDispatcher(&press);
1527 EXPECT_EQ(gfx::Point(10, 10).ToString(), delegate->position().ToString());
1530 namespace {
1531 DEFINE_WINDOW_PROPERTY_KEY(int, kIntKey, -2);
1532 DEFINE_WINDOW_PROPERTY_KEY(const char*, kStringKey, "squeamish");
1535 TEST_F(WindowTest, Property) {
1536 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window()));
1538 static const char native_prop_key[] = "fnord";
1540 // Non-existent properties should return the default values.
1541 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1542 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1543 EXPECT_EQ(NULL, w->GetNativeWindowProperty(native_prop_key));
1545 // A set property value should be returned again (even if it's the default
1546 // value).
1547 w->SetProperty(kIntKey, INT_MAX);
1548 EXPECT_EQ(INT_MAX, w->GetProperty(kIntKey));
1549 w->SetProperty(kIntKey, -2);
1550 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1551 w->SetProperty(kIntKey, INT_MIN);
1552 EXPECT_EQ(INT_MIN, w->GetProperty(kIntKey));
1554 w->SetProperty(kStringKey, static_cast<const char*>(NULL));
1555 EXPECT_EQ(NULL, w->GetProperty(kStringKey));
1556 w->SetProperty(kStringKey, "squeamish");
1557 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1558 w->SetProperty(kStringKey, "ossifrage");
1559 EXPECT_EQ(std::string("ossifrage"), w->GetProperty(kStringKey));
1561 w->SetNativeWindowProperty(native_prop_key, &*w);
1562 EXPECT_EQ(&*w, w->GetNativeWindowProperty(native_prop_key));
1563 w->SetNativeWindowProperty(native_prop_key, NULL);
1564 EXPECT_EQ(NULL, w->GetNativeWindowProperty(native_prop_key));
1566 // ClearProperty should restore the default value.
1567 w->ClearProperty(kIntKey);
1568 EXPECT_EQ(-2, w->GetProperty(kIntKey));
1569 w->ClearProperty(kStringKey);
1570 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey));
1573 namespace {
1575 class TestProperty {
1576 public:
1577 TestProperty() {}
1578 virtual ~TestProperty() {
1579 last_deleted_ = this;
1581 static TestProperty* last_deleted() { return last_deleted_; }
1583 private:
1584 static TestProperty* last_deleted_;
1585 DISALLOW_COPY_AND_ASSIGN(TestProperty);
1588 TestProperty* TestProperty::last_deleted_ = NULL;
1590 DEFINE_OWNED_WINDOW_PROPERTY_KEY(TestProperty, kOwnedKey, NULL);
1592 } // namespace
1594 TEST_F(WindowTest, OwnedProperty) {
1595 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window()));
1596 EXPECT_EQ(NULL, w->GetProperty(kOwnedKey));
1597 TestProperty* p1 = new TestProperty();
1598 w->SetProperty(kOwnedKey, p1);
1599 EXPECT_EQ(p1, w->GetProperty(kOwnedKey));
1600 EXPECT_EQ(NULL, TestProperty::last_deleted());
1602 TestProperty* p2 = new TestProperty();
1603 w->SetProperty(kOwnedKey, p2);
1604 EXPECT_EQ(p2, w->GetProperty(kOwnedKey));
1605 EXPECT_EQ(p1, TestProperty::last_deleted());
1607 w->ClearProperty(kOwnedKey);
1608 EXPECT_EQ(NULL, w->GetProperty(kOwnedKey));
1609 EXPECT_EQ(p2, TestProperty::last_deleted());
1611 TestProperty* p3 = new TestProperty();
1612 w->SetProperty(kOwnedKey, p3);
1613 EXPECT_EQ(p3, w->GetProperty(kOwnedKey));
1614 EXPECT_EQ(p2, TestProperty::last_deleted());
1615 w.reset();
1616 EXPECT_EQ(p3, TestProperty::last_deleted());
1619 TEST_F(WindowTest, SetBoundsInternalShouldCheckTargetBounds) {
1620 // We cannot short-circuit animations in this test.
1621 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
1622 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
1624 scoped_ptr<Window> w1(
1625 CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), root_window()));
1627 EXPECT_FALSE(!w1->layer());
1628 w1->layer()->GetAnimator()->set_disable_timer_for_test(true);
1629 ui::LayerAnimator* animator = w1->layer()->GetAnimator();
1631 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1632 EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString());
1634 // Animate to a different position.
1636 ui::ScopedLayerAnimationSettings settings(w1->layer()->GetAnimator());
1637 w1->SetBounds(gfx::Rect(100, 100, 100, 100));
1640 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1641 EXPECT_EQ("100,100 100x100", w1->layer()->GetTargetBounds().ToString());
1643 // Animate back to the first position. The animation hasn't started yet, so
1644 // the current bounds are still (0, 0, 100, 100), but the target bounds are
1645 // (100, 100, 100, 100). If we step the animator ahead, we should find that
1646 // we're at (0, 0, 100, 100). That is, the second animation should be applied.
1648 ui::ScopedLayerAnimationSettings settings(w1->layer()->GetAnimator());
1649 w1->SetBounds(gfx::Rect(0, 0, 100, 100));
1652 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1653 EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString());
1655 // Confirm that the target bounds are reached.
1656 base::TimeTicks start_time =
1657 w1->layer()->GetAnimator()->last_step_time();
1659 animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
1661 EXPECT_EQ("0,0 100x100", w1->bounds().ToString());
1665 typedef std::pair<const void*, intptr_t> PropertyChangeInfo;
1667 class WindowObserverTest : public WindowTest,
1668 public WindowObserver {
1669 public:
1670 struct VisibilityInfo {
1671 bool window_visible;
1672 bool visible_param;
1675 WindowObserverTest()
1676 : added_count_(0),
1677 removed_count_(0),
1678 destroyed_count_(0),
1679 old_property_value_(-3) {
1682 virtual ~WindowObserverTest() {}
1684 const VisibilityInfo* GetVisibilityInfo() const {
1685 return visibility_info_.get();
1688 void ResetVisibilityInfo() {
1689 visibility_info_.reset();
1692 // Returns a description of the WindowObserver methods that have been invoked.
1693 std::string WindowObserverCountStateAndClear() {
1694 std::string result(
1695 base::StringPrintf("added=%d removed=%d",
1696 added_count_, removed_count_));
1697 added_count_ = removed_count_ = 0;
1698 return result;
1701 int DestroyedCountAndClear() {
1702 int result = destroyed_count_;
1703 destroyed_count_ = 0;
1704 return result;
1707 // Return a tuple of the arguments passed in OnPropertyChanged callback.
1708 PropertyChangeInfo PropertyChangeInfoAndClear() {
1709 PropertyChangeInfo result(property_key_, old_property_value_);
1710 property_key_ = NULL;
1711 old_property_value_ = -3;
1712 return result;
1715 private:
1716 virtual void OnWindowAdded(Window* new_window) OVERRIDE {
1717 added_count_++;
1720 virtual void OnWillRemoveWindow(Window* window) OVERRIDE {
1721 removed_count_++;
1724 virtual void OnWindowVisibilityChanged(Window* window,
1725 bool visible) OVERRIDE {
1726 visibility_info_.reset(new VisibilityInfo);
1727 visibility_info_->window_visible = window->IsVisible();
1728 visibility_info_->visible_param = visible;
1731 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
1732 EXPECT_FALSE(window->parent());
1733 destroyed_count_++;
1736 virtual void OnWindowPropertyChanged(Window* window,
1737 const void* key,
1738 intptr_t old) OVERRIDE {
1739 property_key_ = key;
1740 old_property_value_ = old;
1743 int added_count_;
1744 int removed_count_;
1745 int destroyed_count_;
1746 scoped_ptr<VisibilityInfo> visibility_info_;
1747 const void* property_key_;
1748 intptr_t old_property_value_;
1750 DISALLOW_COPY_AND_ASSIGN(WindowObserverTest);
1753 // Various assertions for WindowObserver.
1754 TEST_F(WindowObserverTest, WindowObserver) {
1755 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1756 w1->AddObserver(this);
1758 // Create a new window as a child of w1, our observer should be notified.
1759 scoped_ptr<Window> w2(CreateTestWindowWithId(2, w1.get()));
1760 EXPECT_EQ("added=1 removed=0", WindowObserverCountStateAndClear());
1762 // Delete w2, which should result in the remove notification.
1763 w2.reset();
1764 EXPECT_EQ("added=0 removed=1", WindowObserverCountStateAndClear());
1766 // Create a window that isn't parented to w1, we shouldn't get any
1767 // notification.
1768 scoped_ptr<Window> w3(CreateTestWindowWithId(3, root_window()));
1769 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1771 // Similarly destroying w3 shouldn't notify us either.
1772 w3.reset();
1773 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear());
1774 w1->RemoveObserver(this);
1777 // Test if OnWindowVisibilityChagned is invoked with expected
1778 // parameters.
1779 TEST_F(WindowObserverTest, WindowVisibility) {
1780 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1781 scoped_ptr<Window> w2(CreateTestWindowWithId(1, w1.get()));
1782 w2->AddObserver(this);
1784 // Hide should make the window invisible and the passed visible
1785 // parameter is false.
1786 w2->Hide();
1787 EXPECT_FALSE(!GetVisibilityInfo());
1788 EXPECT_FALSE(!GetVisibilityInfo());
1789 if (!GetVisibilityInfo())
1790 return;
1791 EXPECT_FALSE(GetVisibilityInfo()->window_visible);
1792 EXPECT_FALSE(GetVisibilityInfo()->visible_param);
1794 // If parent isn't visible, showing window won't make the window visible, but
1795 // passed visible value must be true.
1796 w1->Hide();
1797 ResetVisibilityInfo();
1798 EXPECT_TRUE(!GetVisibilityInfo());
1799 w2->Show();
1800 EXPECT_FALSE(!GetVisibilityInfo());
1801 if (!GetVisibilityInfo())
1802 return;
1803 EXPECT_FALSE(GetVisibilityInfo()->window_visible);
1804 EXPECT_TRUE(GetVisibilityInfo()->visible_param);
1806 // If parent is visible, showing window will make the window
1807 // visible and the passed visible value is true.
1808 w1->Show();
1809 w2->Hide();
1810 ResetVisibilityInfo();
1811 w2->Show();
1812 EXPECT_FALSE(!GetVisibilityInfo());
1813 if (!GetVisibilityInfo())
1814 return;
1815 EXPECT_TRUE(GetVisibilityInfo()->window_visible);
1816 EXPECT_TRUE(GetVisibilityInfo()->visible_param);
1819 // Test if OnWindowDestroyed is invoked as expected.
1820 TEST_F(WindowObserverTest, WindowDestroyed) {
1821 // Delete a window should fire a destroyed notification.
1822 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1823 w1->AddObserver(this);
1824 w1.reset();
1825 EXPECT_EQ(1, DestroyedCountAndClear());
1827 // Observe on child and delete parent window should fire a notification.
1828 scoped_ptr<Window> parent(CreateTestWindowWithId(1, root_window()));
1829 Window* child = CreateTestWindowWithId(1, parent.get()); // owned by parent
1830 child->AddObserver(this);
1831 parent.reset();
1832 EXPECT_EQ(1, DestroyedCountAndClear());
1835 TEST_F(WindowObserverTest, PropertyChanged) {
1836 // Setting property should fire a property change notification.
1837 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
1838 w1->AddObserver(this);
1840 static const WindowProperty<int> prop = {-2};
1841 static const char native_prop_key[] = "fnord";
1843 w1->SetProperty(&prop, 1);
1844 EXPECT_EQ(PropertyChangeInfo(&prop, -2), PropertyChangeInfoAndClear());
1845 w1->SetProperty(&prop, -2);
1846 EXPECT_EQ(PropertyChangeInfo(&prop, 1), PropertyChangeInfoAndClear());
1847 w1->SetProperty(&prop, 3);
1848 EXPECT_EQ(PropertyChangeInfo(&prop, -2), PropertyChangeInfoAndClear());
1849 w1->ClearProperty(&prop);
1850 EXPECT_EQ(PropertyChangeInfo(&prop, 3), PropertyChangeInfoAndClear());
1852 w1->SetNativeWindowProperty(native_prop_key, &*w1);
1853 EXPECT_EQ(PropertyChangeInfo(native_prop_key, 0),
1854 PropertyChangeInfoAndClear());
1855 w1->SetNativeWindowProperty(native_prop_key, NULL);
1856 EXPECT_EQ(PropertyChangeInfo(native_prop_key,
1857 reinterpret_cast<intptr_t>(&*w1)),
1858 PropertyChangeInfoAndClear());
1860 // Sanity check to see if |PropertyChangeInfoAndClear| really clears.
1861 EXPECT_EQ(PropertyChangeInfo(
1862 reinterpret_cast<const void*>(NULL), -3), PropertyChangeInfoAndClear());
1865 TEST_F(WindowTest, AcquireLayer) {
1866 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
1867 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
1868 ui::Layer* parent = window1->parent()->layer();
1869 EXPECT_EQ(2U, parent->children().size());
1871 WindowTestApi window1_test_api(window1.get());
1872 WindowTestApi window2_test_api(window2.get());
1874 EXPECT_TRUE(window1_test_api.OwnsLayer());
1875 EXPECT_TRUE(window2_test_api.OwnsLayer());
1877 // After acquisition, window1 should not own its layer, but it should still
1878 // be available to the window.
1879 scoped_ptr<ui::Layer> window1_layer(window1->AcquireLayer());
1880 EXPECT_FALSE(window1_test_api.OwnsLayer());
1881 EXPECT_TRUE(window1_layer.get() == window1->layer());
1883 // The acquired layer's owner should be set NULL and re-acquring
1884 // should return NULL.
1885 EXPECT_FALSE(window1_layer->owner());
1886 scoped_ptr<ui::Layer> window1_layer_reacquired(window1->AcquireLayer());
1887 EXPECT_FALSE(window1_layer_reacquired.get());
1889 // Upon destruction, window1's layer should still be valid, and in the layer
1890 // hierarchy, but window2's should be gone, and no longer in the hierarchy.
1891 window1.reset();
1892 window2.reset();
1894 // This should be set by the window's destructor.
1895 EXPECT_TRUE(window1_layer->delegate() == NULL);
1896 EXPECT_EQ(1U, parent->children().size());
1899 // Make sure that properties which should persist from the old layer to the new
1900 // layer actually do.
1901 TEST_F(WindowTest, RecreateLayer) {
1902 // Set properties to non default values.
1903 Window w(new ColorTestWindowDelegate(SK_ColorWHITE));
1904 w.set_id(1);
1905 w.Init(aura::WINDOW_LAYER_SOLID_COLOR);
1906 w.SetBounds(gfx::Rect(0, 0, 100, 100));
1908 ui::Layer* layer = w.layer();
1909 layer->SetVisible(false);
1910 layer->SetMasksToBounds(true);
1912 ui::Layer child_layer;
1913 layer->Add(&child_layer);
1915 scoped_ptr<ui::Layer> old_layer(w.RecreateLayer());
1916 layer = w.layer();
1917 EXPECT_EQ(ui::LAYER_SOLID_COLOR, layer->type());
1918 EXPECT_FALSE(layer->visible());
1919 EXPECT_EQ(1u, layer->children().size());
1920 EXPECT_TRUE(layer->GetMasksToBounds());
1921 EXPECT_EQ("0,0 100x100", w.bounds().ToString());
1922 EXPECT_EQ("0,0 100x100", layer->bounds().ToString());
1925 // Verify that RecreateLayer() stacks the old layer above the newly creatd
1926 // layer.
1927 TEST_F(WindowTest, RecreateLayerZOrder) {
1928 scoped_ptr<Window> w(
1929 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(0, 0, 100, 100),
1930 root_window()));
1931 scoped_ptr<ui::Layer> old_layer(w->RecreateLayer());
1933 const std::vector<ui::Layer*>& child_layers =
1934 root_window()->layer()->children();
1935 ASSERT_EQ(2u, child_layers.size());
1936 EXPECT_EQ(w->layer(), child_layers[0]);
1937 EXPECT_EQ(old_layer.get(), child_layers[1]);
1940 // Ensure that acquiring a layer then recreating a layer does not crash
1941 // and that RecreateLayer returns null.
1942 TEST_F(WindowTest, AcquireThenRecreateLayer) {
1943 scoped_ptr<Window> w(
1944 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(0, 0, 100, 100),
1945 root_window()));
1946 scoped_ptr<ui::Layer> acquired_layer(w->AcquireLayer());
1947 scoped_ptr<ui::Layer> doubly_acquired_layer(w->RecreateLayer());
1948 EXPECT_EQ(NULL, doubly_acquired_layer.get());
1950 // Destroy window before layer gets destroyed.
1951 w.reset();
1954 TEST_F(WindowTest, StackWindowAtBottomBelowWindowWhoseLayerHasNoDelegate) {
1955 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window()));
1956 window1->layer()->set_name("1");
1957 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window()));
1958 window2->layer()->set_name("2");
1959 scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window()));
1960 window3->layer()->set_name("3");
1962 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(root_window()));
1963 EXPECT_EQ("1 2 3",
1964 ui::test::ChildLayerNamesAsString(*root_window()->layer()));
1965 window1->layer()->set_delegate(NULL);
1966 root_window()->StackChildAtBottom(window3.get());
1968 // Window 3 should have moved to the bottom.
1969 EXPECT_EQ("3 1 2", ChildWindowIDsAsString(root_window()));
1970 EXPECT_EQ("3 1 2",
1971 ui::test::ChildLayerNamesAsString(*root_window()->layer()));
1974 class TestVisibilityClient : public client::VisibilityClient {
1975 public:
1976 explicit TestVisibilityClient(Window* root_window)
1977 : ignore_visibility_changes_(false) {
1978 client::SetVisibilityClient(root_window, this);
1980 virtual ~TestVisibilityClient() {
1983 void set_ignore_visibility_changes(bool ignore_visibility_changes) {
1984 ignore_visibility_changes_ = ignore_visibility_changes;
1987 // Overridden from client::VisibilityClient:
1988 virtual void UpdateLayerVisibility(aura::Window* window,
1989 bool visible) OVERRIDE {
1990 if (!ignore_visibility_changes_)
1991 window->layer()->SetVisible(visible);
1994 private:
1995 bool ignore_visibility_changes_;
1996 DISALLOW_COPY_AND_ASSIGN(TestVisibilityClient);
1999 TEST_F(WindowTest, VisibilityClientIsVisible) {
2000 TestVisibilityClient client(root_window());
2002 scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window()));
2003 EXPECT_TRUE(window->IsVisible());
2004 EXPECT_TRUE(window->layer()->visible());
2006 window->Hide();
2007 EXPECT_FALSE(window->IsVisible());
2008 EXPECT_FALSE(window->layer()->visible());
2009 window->Show();
2011 client.set_ignore_visibility_changes(true);
2012 window->Hide();
2013 EXPECT_FALSE(window->IsVisible());
2014 EXPECT_TRUE(window->layer()->visible());
2017 // Tests mouse events on window change.
2018 TEST_F(WindowTest, MouseEventsOnWindowChange) {
2019 gfx::Size size = host()->GetBounds().size();
2021 EventGenerator generator(root_window());
2022 generator.MoveMouseTo(50, 50);
2024 EventCountDelegate d1;
2025 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(&d1, 1,
2026 gfx::Rect(0, 0, 100, 100), root_window()));
2027 RunAllPendingInMessageLoop();
2028 // The format of result is "Enter/Mouse/Leave".
2029 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2031 // Adding new window.
2032 EventCountDelegate d11;
2033 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(
2034 &d11, 1, gfx::Rect(0, 0, 100, 100), w1.get()));
2035 RunAllPendingInMessageLoop();
2036 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2037 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2039 // Move bounds.
2040 w11->SetBounds(gfx::Rect(0, 0, 10, 10));
2041 RunAllPendingInMessageLoop();
2042 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2043 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2045 w11->SetBounds(gfx::Rect(0, 0, 60, 60));
2046 RunAllPendingInMessageLoop();
2047 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2048 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2050 // Detach, then re-attach.
2051 w1->RemoveChild(w11.get());
2052 RunAllPendingInMessageLoop();
2053 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2054 // Window is detached, so no event is set.
2055 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2057 w1->AddChild(w11.get());
2058 RunAllPendingInMessageLoop();
2059 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2060 // Window is detached, so no event is set.
2061 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2063 // Visibility Change
2064 w11->Hide();
2065 RunAllPendingInMessageLoop();
2066 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2067 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2069 w11->Show();
2070 RunAllPendingInMessageLoop();
2071 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2072 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2074 // Transform: move d11 by 100 100.
2075 gfx::Transform transform;
2076 transform.Translate(100, 100);
2077 w11->SetTransform(transform);
2078 RunAllPendingInMessageLoop();
2079 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2080 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2082 w11->SetTransform(gfx::Transform());
2083 RunAllPendingInMessageLoop();
2084 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2085 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset());
2087 // Closing a window.
2088 w11.reset();
2089 RunAllPendingInMessageLoop();
2090 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset());
2092 // Make sure we don't synthesize events if the mouse
2093 // is outside of the root window.
2094 generator.MoveMouseTo(-10, -10);
2095 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset());
2097 // Adding new windows.
2098 w11.reset(CreateTestWindowWithDelegate(
2099 &d11, 1, gfx::Rect(0, 0, 100, 100), w1.get()));
2100 RunAllPendingInMessageLoop();
2101 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset());
2102 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset());
2104 // Closing windows
2105 w11.reset();
2106 RunAllPendingInMessageLoop();
2107 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset());
2108 EXPECT_EQ("0 0 0", d11.GetMouseMotionCountsAndReset());
2111 class RootWindowAttachmentObserver : public WindowObserver {
2112 public:
2113 RootWindowAttachmentObserver() : added_count_(0), removed_count_(0) {}
2114 virtual ~RootWindowAttachmentObserver() {}
2116 int added_count() const { return added_count_; }
2117 int removed_count() const { return removed_count_; }
2119 void Clear() {
2120 added_count_ = 0;
2121 removed_count_ = 0;
2124 // Overridden from WindowObserver:
2125 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
2126 ++added_count_;
2128 virtual void OnWindowRemovingFromRootWindow(Window* window,
2129 Window* new_root) OVERRIDE {
2130 ++removed_count_;
2133 private:
2134 int added_count_;
2135 int removed_count_;
2137 DISALLOW_COPY_AND_ASSIGN(RootWindowAttachmentObserver);
2140 TEST_F(WindowTest, RootWindowAttachment) {
2141 RootWindowAttachmentObserver observer;
2143 // Test a direct add/remove from the RootWindow.
2144 scoped_ptr<Window> w1(new Window(NULL));
2145 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2146 w1->AddObserver(&observer);
2148 ParentWindow(w1.get());
2149 EXPECT_EQ(1, observer.added_count());
2150 EXPECT_EQ(0, observer.removed_count());
2152 w1.reset();
2153 EXPECT_EQ(1, observer.added_count());
2154 EXPECT_EQ(1, observer.removed_count());
2156 observer.Clear();
2158 // Test an indirect add/remove from the RootWindow.
2159 w1.reset(new Window(NULL));
2160 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2161 Window* w11 = new Window(NULL);
2162 w11->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2163 w11->AddObserver(&observer);
2164 w1->AddChild(w11);
2165 EXPECT_EQ(0, observer.added_count());
2166 EXPECT_EQ(0, observer.removed_count());
2168 ParentWindow(w1.get());
2169 EXPECT_EQ(1, observer.added_count());
2170 EXPECT_EQ(0, observer.removed_count());
2172 w1.reset(); // Deletes w11.
2173 w11 = NULL;
2174 EXPECT_EQ(1, observer.added_count());
2175 EXPECT_EQ(1, observer.removed_count());
2177 observer.Clear();
2179 // Test an indirect add/remove with nested observers.
2180 w1.reset(new Window(NULL));
2181 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2182 w11 = new Window(NULL);
2183 w11->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2184 w11->AddObserver(&observer);
2185 w1->AddChild(w11);
2186 Window* w111 = new Window(NULL);
2187 w111->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2188 w111->AddObserver(&observer);
2189 w11->AddChild(w111);
2191 EXPECT_EQ(0, observer.added_count());
2192 EXPECT_EQ(0, observer.removed_count());
2194 ParentWindow(w1.get());
2195 EXPECT_EQ(2, observer.added_count());
2196 EXPECT_EQ(0, observer.removed_count());
2198 w1.reset(); // Deletes w11 and w111.
2199 w11 = NULL;
2200 w111 = NULL;
2201 EXPECT_EQ(2, observer.added_count());
2202 EXPECT_EQ(2, observer.removed_count());
2205 class BoundsChangedWindowObserver : public WindowObserver {
2206 public:
2207 BoundsChangedWindowObserver() : root_set_(false) {}
2209 virtual void OnWindowBoundsChanged(Window* window,
2210 const gfx::Rect& old_bounds,
2211 const gfx::Rect& new_bounds) OVERRIDE {
2212 root_set_ = window->GetRootWindow() != NULL;
2215 bool root_set() const { return root_set_; }
2217 private:
2218 bool root_set_;
2220 DISALLOW_COPY_AND_ASSIGN(BoundsChangedWindowObserver);
2223 TEST_F(WindowTest, RootWindowSetWhenReparenting) {
2224 Window parent1(NULL);
2225 parent1.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2226 Window parent2(NULL);
2227 parent2.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2228 ParentWindow(&parent1);
2229 ParentWindow(&parent2);
2230 parent1.SetBounds(gfx::Rect(10, 10, 300, 300));
2231 parent2.SetBounds(gfx::Rect(20, 20, 300, 300));
2233 BoundsChangedWindowObserver observer;
2234 Window child(NULL);
2235 child.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2236 child.SetBounds(gfx::Rect(5, 5, 100, 100));
2237 parent1.AddChild(&child);
2239 // We need animations to start in order to observe the bounds changes.
2240 ui::ScopedAnimationDurationScaleMode animation_duration_mode(
2241 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
2242 ui::ScopedLayerAnimationSettings settings1(child.layer()->GetAnimator());
2243 settings1.SetTransitionDuration(base::TimeDelta::FromMilliseconds(100));
2244 gfx::Rect new_bounds(gfx::Rect(35, 35, 50, 50));
2245 child.SetBounds(new_bounds);
2247 child.AddObserver(&observer);
2249 // Reparenting the |child| will cause it to get moved. During this move
2250 // the window should still have root window set.
2251 parent2.AddChild(&child);
2252 EXPECT_TRUE(observer.root_set());
2254 // Animations should stop and the bounds should be as set before the |child|
2255 // got reparented.
2256 EXPECT_EQ(new_bounds.ToString(), child.GetTargetBounds().ToString());
2257 EXPECT_EQ(new_bounds.ToString(), child.bounds().ToString());
2258 EXPECT_EQ("55,55 50x50", child.GetBoundsInRootWindow().ToString());
2261 TEST_F(WindowTest, OwnedByParentFalse) {
2262 // By default, a window is owned by its parent. If this is set to false, the
2263 // window will not be destroyed when its parent is.
2265 scoped_ptr<Window> w1(new Window(NULL));
2266 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2267 scoped_ptr<Window> w2(new Window(NULL));
2268 w2->set_owned_by_parent(false);
2269 w2->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2270 w1->AddChild(w2.get());
2272 w1.reset();
2274 // We should be able to deref w2 still, but its parent should now be NULL.
2275 EXPECT_EQ(NULL, w2->parent());
2278 namespace {
2280 // Used By DeleteWindowFromOnWindowDestroyed. Destroys a Window from
2281 // OnWindowDestroyed().
2282 class OwningWindowDelegate : public TestWindowDelegate {
2283 public:
2284 OwningWindowDelegate() {}
2286 void SetOwnedWindow(Window* window) {
2287 owned_window_.reset(window);
2290 virtual void OnWindowDestroyed(Window* window) OVERRIDE {
2291 owned_window_.reset(NULL);
2294 private:
2295 scoped_ptr<Window> owned_window_;
2297 DISALLOW_COPY_AND_ASSIGN(OwningWindowDelegate);
2300 } // namespace
2302 // Creates a window with two child windows. When the first child window is
2303 // destroyed (WindowDelegate::OnWindowDestroyed) it deletes the second child.
2304 // This synthesizes BrowserView and the status bubble. Both are children of the
2305 // same parent and destroying BrowserView triggers it destroying the status
2306 // bubble.
2307 TEST_F(WindowTest, DeleteWindowFromOnWindowDestroyed) {
2308 scoped_ptr<Window> parent(new Window(NULL));
2309 parent->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2310 OwningWindowDelegate delegate;
2311 Window* c1 = new Window(&delegate);
2312 c1->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2313 parent->AddChild(c1);
2314 Window* c2 = new Window(NULL);
2315 c2->Init(aura::WINDOW_LAYER_NOT_DRAWN);
2316 parent->AddChild(c2);
2317 delegate.SetOwnedWindow(c2);
2318 parent.reset();
2321 namespace {
2323 // Used by DelegateNotifiedAsBoundsChange to verify OnBoundsChanged() is
2324 // invoked.
2325 class BoundsChangeDelegate : public TestWindowDelegate {
2326 public:
2327 BoundsChangeDelegate() : bounds_changed_(false) {}
2329 void clear_bounds_changed() { bounds_changed_ = false; }
2330 bool bounds_changed() const {
2331 return bounds_changed_;
2334 // Window
2335 virtual void OnBoundsChanged(const gfx::Rect& old_bounds,
2336 const gfx::Rect& new_bounds) OVERRIDE {
2337 bounds_changed_ = true;
2340 private:
2341 // Was OnBoundsChanged() invoked?
2342 bool bounds_changed_;
2344 DISALLOW_COPY_AND_ASSIGN(BoundsChangeDelegate);
2347 } // namespace
2349 // Verifies the delegate is notified when the actual bounds of the layer
2350 // change.
2351 TEST_F(WindowTest, DelegateNotifiedAsBoundsChange) {
2352 BoundsChangeDelegate delegate;
2354 // We cannot short-circuit animations in this test.
2355 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
2356 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
2358 scoped_ptr<Window> window(
2359 CreateTestWindowWithDelegate(&delegate, 1,
2360 gfx::Rect(0, 0, 100, 100), root_window()));
2361 window->layer()->GetAnimator()->set_disable_timer_for_test(true);
2363 delegate.clear_bounds_changed();
2365 // Animate to a different position.
2367 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
2368 window->SetBounds(gfx::Rect(100, 100, 100, 100));
2371 // Bounds shouldn't immediately have changed.
2372 EXPECT_EQ("0,0 100x100", window->bounds().ToString());
2373 EXPECT_FALSE(delegate.bounds_changed());
2375 // Animate to the end, which should notify of the change.
2376 base::TimeTicks start_time =
2377 window->layer()->GetAnimator()->last_step_time();
2378 ui::LayerAnimator* animator = window->layer()->GetAnimator();
2379 animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
2380 EXPECT_TRUE(delegate.bounds_changed());
2381 EXPECT_NE("0,0 100x100", window->bounds().ToString());
2384 // Verifies the delegate is notified when the actual bounds of the layer
2385 // change even when the window is not the layer's delegate
2386 TEST_F(WindowTest, DelegateNotifiedAsBoundsChangeInHiddenLayer) {
2387 BoundsChangeDelegate delegate;
2389 // We cannot short-circuit animations in this test.
2390 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
2391 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
2393 scoped_ptr<Window> window(
2394 CreateTestWindowWithDelegate(&delegate, 1,
2395 gfx::Rect(0, 0, 100, 100), root_window()));
2396 window->layer()->GetAnimator()->set_disable_timer_for_test(true);
2398 delegate.clear_bounds_changed();
2400 // Suppress paint on the window since it is hidden (should reset the layer's
2401 // delegate to NULL)
2402 window->SuppressPaint();
2403 EXPECT_EQ(NULL, window->layer()->delegate());
2405 // Animate to a different position.
2407 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
2408 window->SetBounds(gfx::Rect(100, 100, 110, 100));
2411 // Layer delegate is NULL but we should still get bounds changed notification.
2412 EXPECT_EQ("100,100 110x100", window->GetTargetBounds().ToString());
2413 EXPECT_TRUE(delegate.bounds_changed());
2415 delegate.clear_bounds_changed();
2417 // Animate to the end: will *not* notify of the change since we are hidden.
2418 base::TimeTicks start_time =
2419 window->layer()->GetAnimator()->last_step_time();
2420 ui::LayerAnimator* animator = window->layer()->GetAnimator();
2421 animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000));
2423 // No bounds changed notification at the end of animation since layer
2424 // delegate is NULL.
2425 EXPECT_FALSE(delegate.bounds_changed());
2426 EXPECT_NE("0,0 100x100", window->layer()->bounds().ToString());
2429 namespace {
2431 // Used by AddChildNotifications to track notification counts.
2432 class AddChildNotificationsObserver : public WindowObserver {
2433 public:
2434 AddChildNotificationsObserver() : added_count_(0), removed_count_(0) {}
2436 std::string CountStringAndReset() {
2437 std::string result = base::IntToString(added_count_) + " " +
2438 base::IntToString(removed_count_);
2439 added_count_ = removed_count_ = 0;
2440 return result;
2443 // WindowObserver overrides:
2444 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE {
2445 added_count_++;
2447 virtual void OnWindowRemovingFromRootWindow(Window* window,
2448 Window* new_root) OVERRIDE {
2449 removed_count_++;
2452 private:
2453 int added_count_;
2454 int removed_count_;
2456 DISALLOW_COPY_AND_ASSIGN(AddChildNotificationsObserver);
2459 } // namespace
2461 // Assertions around when root window notifications are sent.
2462 TEST_F(WindowTest, AddChildNotifications) {
2463 AddChildNotificationsObserver observer;
2464 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
2465 scoped_ptr<Window> w2(CreateTestWindowWithId(1, root_window()));
2466 w2->AddObserver(&observer);
2467 w2->Focus();
2468 EXPECT_TRUE(w2->HasFocus());
2470 // Move |w2| to be a child of |w1|.
2471 w1->AddChild(w2.get());
2472 // Sine we moved in the same root, observer shouldn't be notified.
2473 EXPECT_EQ("0 0", observer.CountStringAndReset());
2474 // |w2| should still have focus after moving.
2475 EXPECT_TRUE(w2->HasFocus());
2478 // Tests that a delegate that destroys itself when the window is destroyed does
2479 // not break.
2480 TEST_F(WindowTest, DelegateDestroysSelfOnWindowDestroy) {
2481 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(
2482 new DestroyWindowDelegate(),
2484 gfx::Rect(10, 20, 30, 40),
2485 root_window()));
2488 class HierarchyObserver : public WindowObserver {
2489 public:
2490 HierarchyObserver(Window* target) : target_(target) {
2491 target_->AddObserver(this);
2493 virtual ~HierarchyObserver() {
2494 target_->RemoveObserver(this);
2497 void ValidateState(
2498 int index,
2499 const WindowObserver::HierarchyChangeParams& params) const {
2500 ParamsMatch(params_[index], params);
2503 void Reset() {
2504 params_.clear();
2507 private:
2508 // Overridden from WindowObserver:
2509 virtual void OnWindowHierarchyChanging(
2510 const HierarchyChangeParams& params) OVERRIDE {
2511 params_.push_back(params);
2513 virtual void OnWindowHierarchyChanged(
2514 const HierarchyChangeParams& params) OVERRIDE {
2515 params_.push_back(params);
2518 void ParamsMatch(const WindowObserver::HierarchyChangeParams& p1,
2519 const WindowObserver::HierarchyChangeParams& p2) const {
2520 EXPECT_EQ(p1.phase, p2.phase);
2521 EXPECT_EQ(p1.target, p2.target);
2522 EXPECT_EQ(p1.new_parent, p2.new_parent);
2523 EXPECT_EQ(p1.old_parent, p2.old_parent);
2524 EXPECT_EQ(p1.receiver, p2.receiver);
2527 Window* target_;
2528 std::vector<WindowObserver::HierarchyChangeParams> params_;
2530 DISALLOW_COPY_AND_ASSIGN(HierarchyObserver);
2533 // Tests hierarchy change notifications.
2534 TEST_F(WindowTest, OnWindowHierarchyChange) {
2536 // Simple add & remove.
2537 HierarchyObserver oroot(root_window());
2539 scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL));
2540 HierarchyObserver o1(w1.get());
2542 // Add.
2543 root_window()->AddChild(w1.get());
2545 WindowObserver::HierarchyChangeParams params;
2546 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2547 params.target = w1.get();
2548 params.old_parent = NULL;
2549 params.new_parent = root_window();
2550 params.receiver = w1.get();
2551 o1.ValidateState(0, params);
2553 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2554 params.receiver = w1.get();
2555 o1.ValidateState(1, params);
2557 params.receiver = root_window();
2558 oroot.ValidateState(0, params);
2560 // Remove.
2561 o1.Reset();
2562 oroot.Reset();
2564 root_window()->RemoveChild(w1.get());
2566 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2567 params.old_parent = root_window();
2568 params.new_parent = NULL;
2569 params.receiver = w1.get();
2571 o1.ValidateState(0, params);
2573 params.receiver = root_window();
2574 oroot.ValidateState(0, params);
2576 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2577 params.receiver = w1.get();
2578 o1.ValidateState(1, params);
2582 // Add & remove of hierarchy. Tests notification order per documentation in
2583 // WindowObserver.
2584 HierarchyObserver o(root_window());
2585 scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL));
2586 Window* w11 = CreateTestWindowWithId(11, w1.get());
2587 w1->AddObserver(&o);
2588 w11->AddObserver(&o);
2590 // Add.
2591 root_window()->AddChild(w1.get());
2593 // Dispatched to target first.
2594 int index = 0;
2595 WindowObserver::HierarchyChangeParams params;
2596 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2597 params.target = w1.get();
2598 params.old_parent = NULL;
2599 params.new_parent = root_window();
2600 params.receiver = w1.get();
2601 o.ValidateState(index++, params);
2603 // Dispatched to target's children.
2604 params.receiver = w11;
2605 o.ValidateState(index++, params);
2607 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2609 // Now process the "changed" phase.
2610 params.receiver = w1.get();
2611 o.ValidateState(index++, params);
2612 params.receiver = w11;
2613 o.ValidateState(index++, params);
2614 params.receiver = root_window();
2615 o.ValidateState(index++, params);
2617 // Remove.
2618 root_window()->RemoveChild(w1.get());
2619 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2620 params.old_parent = root_window();
2621 params.new_parent = NULL;
2622 params.receiver = w1.get();
2623 o.ValidateState(index++, params);
2624 params.receiver = w11;
2625 o.ValidateState(index++, params);
2626 params.receiver = root_window();
2627 o.ValidateState(index++, params);
2628 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2629 params.receiver = w1.get();
2630 o.ValidateState(index++, params);
2631 params.receiver = w11;
2632 o.ValidateState(index++, params);
2634 w1.reset();
2638 // Reparent. Tests notification order per documentation in WindowObserver.
2639 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window()));
2640 Window* w11 = CreateTestWindowWithId(11, w1.get());
2641 Window* w111 = CreateTestWindowWithId(111, w11);
2642 scoped_ptr<Window> w2(CreateTestWindowWithId(2, root_window()));
2644 HierarchyObserver o(root_window());
2645 w1->AddObserver(&o);
2646 w11->AddObserver(&o);
2647 w111->AddObserver(&o);
2648 w2->AddObserver(&o);
2650 w2->AddChild(w11);
2652 // Dispatched to target first.
2653 int index = 0;
2654 WindowObserver::HierarchyChangeParams params;
2655 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING;
2656 params.target = w11;
2657 params.old_parent = w1.get();
2658 params.new_parent = w2.get();
2659 params.receiver = w11;
2660 o.ValidateState(index++, params);
2662 // Then to target's children.
2663 params.receiver = w111;
2664 o.ValidateState(index++, params);
2666 // Then to target's old parent chain.
2667 params.receiver = w1.get();
2668 o.ValidateState(index++, params);
2669 params.receiver = root_window();
2670 o.ValidateState(index++, params);
2672 // "Changed" phase.
2673 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED;
2674 params.receiver = w11;
2675 o.ValidateState(index++, params);
2676 params.receiver = w111;
2677 o.ValidateState(index++, params);
2678 params.receiver = w2.get();
2679 o.ValidateState(index++, params);
2680 params.receiver = root_window();
2681 o.ValidateState(index++, params);
2683 w1.reset();
2684 w2.reset();
2689 // Verifies SchedulePaint() on a layerless window results in damaging the right
2690 // thing.
2691 TEST_F(WindowTest, LayerlessWindowSchedulePaint) {
2692 Window root(NULL);
2693 root.Init(aura::WINDOW_LAYER_NOT_DRAWN);
2694 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2696 Window* layerless_window = new Window(NULL); // Owned by |root|.
2697 layerless_window->Init(WINDOW_LAYER_NONE);
2698 layerless_window->SetBounds(gfx::Rect(10, 11, 12, 13));
2699 root.AddChild(layerless_window);
2701 root.layer()->SendDamagedRects();
2702 layerless_window->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4));
2703 // Note the the region is clipped by the parent hence 100 going to 11.
2704 EXPECT_EQ("11,13 11x4",
2705 gfx::SkIRectToRect(root.layer()->damaged_region().getBounds()).
2706 ToString());
2708 Window* layerless_window2 = new Window(NULL); // Owned by |layerless_window|.
2709 layerless_window2->Init(WINDOW_LAYER_NONE);
2710 layerless_window2->SetBounds(gfx::Rect(1, 2, 3, 4));
2711 layerless_window->AddChild(layerless_window2);
2713 root.layer()->SendDamagedRects();
2714 layerless_window2->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4));
2715 // Note the the region is clipped by the |layerless_window| hence 100 going to
2716 // 2.
2717 EXPECT_EQ("12,15 2x2",
2718 gfx::SkIRectToRect(root.layer()->damaged_region().getBounds()).
2719 ToString());
2722 // Verifies bounds of layerless windows are correctly updated when adding
2723 // removing.
2724 TEST_F(WindowTest, NestedLayerlessWindowsBoundsOnAddRemove) {
2725 // Creates the following structure (all children owned by root):
2726 // root
2727 // w1ll 1,2
2728 // w11ll 3,4
2729 // w111 5,6
2730 // w12 7,8
2731 // w121 9,10
2733 // ll: layer less, eg no layer
2734 Window root(NULL);
2735 root.Init(WINDOW_LAYER_NOT_DRAWN);
2736 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2738 Window* w1ll = new Window(NULL);
2739 w1ll->Init(WINDOW_LAYER_NONE);
2740 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
2742 Window* w11ll = new Window(NULL);
2743 w11ll->Init(WINDOW_LAYER_NONE);
2744 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
2745 w1ll->AddChild(w11ll);
2747 Window* w111 = new Window(NULL);
2748 w111->Init(WINDOW_LAYER_NOT_DRAWN);
2749 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2750 w11ll->AddChild(w111);
2752 Window* w12 = new Window(NULL);
2753 w12->Init(WINDOW_LAYER_NOT_DRAWN);
2754 w12->SetBounds(gfx::Rect(7, 8, 100, 100));
2755 w1ll->AddChild(w12);
2757 Window* w121 = new Window(NULL);
2758 w121->Init(WINDOW_LAYER_NOT_DRAWN);
2759 w121->SetBounds(gfx::Rect(9, 10, 100, 100));
2760 w12->AddChild(w121);
2762 root.AddChild(w1ll);
2764 // All layers should be parented to the root.
2765 EXPECT_EQ(root.layer(), w111->layer()->parent());
2766 EXPECT_EQ(root.layer(), w12->layer()->parent());
2767 EXPECT_EQ(w12->layer(), w121->layer()->parent());
2769 // Ensure bounds are what we expect.
2770 EXPECT_EQ("1,2 100x100", w1ll->bounds().ToString());
2771 EXPECT_EQ("3,4 100x100", w11ll->bounds().ToString());
2772 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2773 EXPECT_EQ("7,8 100x100", w12->bounds().ToString());
2774 EXPECT_EQ("9,10 100x100", w121->bounds().ToString());
2776 // Bounds of layers are relative to the nearest ancestor with a layer.
2777 EXPECT_EQ("8,10 100x100", w12->layer()->bounds().ToString());
2778 EXPECT_EQ("9,12 100x100", w111->layer()->bounds().ToString());
2779 EXPECT_EQ("9,10 100x100", w121->layer()->bounds().ToString());
2781 // Remove and repeat.
2782 root.RemoveChild(w1ll);
2784 EXPECT_TRUE(w111->layer()->parent() == NULL);
2785 EXPECT_TRUE(w12->layer()->parent() == NULL);
2787 // Verify bounds haven't changed again.
2788 EXPECT_EQ("1,2 100x100", w1ll->bounds().ToString());
2789 EXPECT_EQ("3,4 100x100", w11ll->bounds().ToString());
2790 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2791 EXPECT_EQ("7,8 100x100", w12->bounds().ToString());
2792 EXPECT_EQ("9,10 100x100", w121->bounds().ToString());
2794 // Bounds of layers should now match that of windows.
2795 EXPECT_EQ("7,8 100x100", w12->layer()->bounds().ToString());
2796 EXPECT_EQ("5,6 100x100", w111->layer()->bounds().ToString());
2797 EXPECT_EQ("9,10 100x100", w121->layer()->bounds().ToString());
2799 delete w1ll;
2802 // Verifies bounds of layerless windows are correctly updated when bounds
2803 // of ancestor changes.
2804 TEST_F(WindowTest, NestedLayerlessWindowsBoundsOnSetBounds) {
2805 // Creates the following structure (all children owned by root):
2806 // root
2807 // w1ll 1,2
2808 // w11ll 3,4
2809 // w111 5,6
2810 // w12 7,8
2811 // w121 9,10
2813 // ll: layer less, eg no layer
2814 Window root(NULL);
2815 root.Init(WINDOW_LAYER_NOT_DRAWN);
2816 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2818 Window* w1ll = new Window(NULL);
2819 w1ll->Init(WINDOW_LAYER_NONE);
2820 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
2822 Window* w11ll = new Window(NULL);
2823 w11ll->Init(WINDOW_LAYER_NONE);
2824 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
2825 w1ll->AddChild(w11ll);
2827 Window* w111 = new Window(NULL);
2828 w111->Init(WINDOW_LAYER_NOT_DRAWN);
2829 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2830 w11ll->AddChild(w111);
2832 Window* w12 = new Window(NULL);
2833 w12->Init(WINDOW_LAYER_NOT_DRAWN);
2834 w12->SetBounds(gfx::Rect(7, 8, 100, 100));
2835 w1ll->AddChild(w12);
2837 Window* w121 = new Window(NULL);
2838 w121->Init(WINDOW_LAYER_NOT_DRAWN);
2839 w121->SetBounds(gfx::Rect(9, 10, 100, 100));
2840 w12->AddChild(w121);
2842 root.AddChild(w1ll);
2844 w111->SetBounds(gfx::Rect(7, 8, 11, 12));
2845 EXPECT_EQ("7,8 11x12", w111->bounds().ToString());
2846 EXPECT_EQ("7,8 11x12", w111->GetTargetBounds().ToString());
2847 EXPECT_EQ("11,14 11x12", w111->layer()->bounds().ToString());
2849 // Set back.
2850 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2851 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2852 EXPECT_EQ("5,6 100x100", w111->GetTargetBounds().ToString());
2853 EXPECT_EQ("9,12 100x100", w111->layer()->bounds().ToString());
2855 // Setting the bounds of a layerless window needs to adjust the bounds of
2856 // layered children.
2857 w11ll->SetBounds(gfx::Rect(5, 6, 100, 100));
2858 EXPECT_EQ("5,6 100x100", w11ll->bounds().ToString());
2859 EXPECT_EQ("5,6 100x100", w11ll->GetTargetBounds().ToString());
2860 EXPECT_EQ("5,6 100x100", w111->bounds().ToString());
2861 EXPECT_EQ("5,6 100x100", w111->GetTargetBounds().ToString());
2862 EXPECT_EQ("11,14 100x100", w111->layer()->bounds().ToString());
2864 root.RemoveChild(w1ll);
2866 w111->SetBounds(gfx::Rect(7, 8, 11, 12));
2867 EXPECT_EQ("7,8 11x12", w111->bounds().ToString());
2868 EXPECT_EQ("7,8 11x12", w111->GetTargetBounds().ToString());
2869 EXPECT_EQ("7,8 11x12", w111->layer()->bounds().ToString());
2871 delete w1ll;
2874 namespace {
2876 // Tracks the number of times paint is invoked along with what the clip and
2877 // translate was.
2878 class PaintWindowDelegate : public TestWindowDelegate {
2879 public:
2880 PaintWindowDelegate() : paint_count_(0) {}
2881 virtual ~PaintWindowDelegate() {}
2883 const gfx::Rect& most_recent_paint_clip_bounds() const {
2884 return most_recent_paint_clip_bounds_;
2887 const gfx::Vector2d& most_recent_paint_matrix_offset() const {
2888 return most_recent_paint_matrix_offset_;
2891 void clear_paint_count() { paint_count_ = 0; }
2892 int paint_count() const { return paint_count_; }
2894 // TestWindowDelegate::
2895 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
2896 paint_count_++;
2897 canvas->GetClipBounds(&most_recent_paint_clip_bounds_);
2898 const SkMatrix& matrix = canvas->sk_canvas()->getTotalMatrix();
2899 most_recent_paint_matrix_offset_ = gfx::Vector2d(
2900 SkScalarFloorToInt(matrix.getTranslateX()),
2901 SkScalarFloorToInt(matrix.getTranslateY()));
2904 private:
2905 int paint_count_;
2906 gfx::Rect most_recent_paint_clip_bounds_;
2907 gfx::Vector2d most_recent_paint_matrix_offset_;
2909 DISALLOW_COPY_AND_ASSIGN(PaintWindowDelegate);
2912 } // namespace
2914 // Assertions around layerless children being painted when non-layerless window
2915 // is painted.
2916 TEST_F(WindowTest, PaintLayerless) {
2917 // Creates the following structure (all children owned by root):
2918 // root
2919 // w1ll 1,2 40x50
2920 // w11ll 3,4 11x12
2921 // w111 5,6
2923 // ll: layer less, eg no layer
2924 PaintWindowDelegate w1ll_delegate;
2925 PaintWindowDelegate w11ll_delegate;
2926 PaintWindowDelegate w111_delegate;
2928 Window root(NULL);
2929 root.Init(WINDOW_LAYER_NOT_DRAWN);
2930 root.SetBounds(gfx::Rect(0, 0, 100, 100));
2932 Window* w1ll = new Window(&w1ll_delegate);
2933 w1ll->Init(WINDOW_LAYER_NONE);
2934 w1ll->SetBounds(gfx::Rect(1, 2, 40, 50));
2935 w1ll->Show();
2936 root.AddChild(w1ll);
2938 Window* w11ll = new Window(&w11ll_delegate);
2939 w11ll->Init(WINDOW_LAYER_NONE);
2940 w11ll->SetBounds(gfx::Rect(3, 4, 11, 12));
2941 w11ll->Show();
2942 w1ll->AddChild(w11ll);
2944 Window* w111 = new Window(&w111_delegate);
2945 w111->Init(WINDOW_LAYER_NOT_DRAWN);
2946 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
2947 w111->Show();
2948 w11ll->AddChild(w111);
2950 EXPECT_EQ(0, w1ll_delegate.paint_count());
2951 EXPECT_EQ(0, w11ll_delegate.paint_count());
2952 EXPECT_EQ(0, w111_delegate.paint_count());
2954 // Paint the root, this should trigger painting of the two layerless
2955 // descendants but not the layered descendant.
2956 gfx::Canvas canvas(gfx::Size(200, 200), 1.0f, true);
2957 static_cast<ui::LayerDelegate&>(root).OnPaintLayer(&canvas);
2959 // NOTE: SkCanvas::getClipBounds() extends the clip 1 pixel to the left and up
2960 // and 2 pixels down and to the right.
2961 EXPECT_EQ(1, w1ll_delegate.paint_count());
2962 EXPECT_EQ("-1,-1 42x52",
2963 w1ll_delegate.most_recent_paint_clip_bounds().ToString());
2964 EXPECT_EQ("[1 2]",
2965 w1ll_delegate.most_recent_paint_matrix_offset().ToString());
2966 EXPECT_EQ(1, w11ll_delegate.paint_count());
2967 EXPECT_EQ("-1,-1 13x14",
2968 w11ll_delegate.most_recent_paint_clip_bounds().ToString());
2969 EXPECT_EQ("[4 6]",
2970 w11ll_delegate.most_recent_paint_matrix_offset().ToString());
2971 EXPECT_EQ(0, w111_delegate.paint_count());
2974 namespace {
2976 std::string ConvertPointToTargetString(const Window* source,
2977 const Window* target) {
2978 gfx::Point location;
2979 Window::ConvertPointToTarget(source, target, &location);
2980 return location.ToString();
2983 } // namespace
2985 // Assertions around Window::ConvertPointToTarget() with layerless windows.
2986 TEST_F(WindowTest, ConvertPointToTargetLayerless) {
2987 // Creates the following structure (all children owned by root):
2988 // root
2989 // w1ll 1,2
2990 // w11ll 3,4
2991 // w111 5,6
2992 // w12 7,8
2993 // w121 9,10
2995 // ll: layer less, eg no layer
2996 Window root(NULL);
2997 root.Init(WINDOW_LAYER_NOT_DRAWN);
2998 root.SetBounds(gfx::Rect(0, 0, 100, 100));
3000 Window* w1ll = new Window(NULL);
3001 w1ll->Init(WINDOW_LAYER_NONE);
3002 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100));
3004 Window* w11ll = new Window(NULL);
3005 w11ll->Init(WINDOW_LAYER_NONE);
3006 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100));
3007 w1ll->AddChild(w11ll);
3009 Window* w111 = new Window(NULL);
3010 w111->Init(WINDOW_LAYER_NOT_DRAWN);
3011 w111->SetBounds(gfx::Rect(5, 6, 100, 100));
3012 w11ll->AddChild(w111);
3014 Window* w12 = new Window(NULL);
3015 w12->Init(WINDOW_LAYER_NOT_DRAWN);
3016 w12->SetBounds(gfx::Rect(7, 8, 100, 100));
3017 w1ll->AddChild(w12);
3019 Window* w121 = new Window(NULL);
3020 w121->Init(WINDOW_LAYER_NOT_DRAWN);
3021 w121->SetBounds(gfx::Rect(9, 10, 100, 100));
3022 w12->AddChild(w121);
3024 root.AddChild(w1ll);
3026 // w111->w11ll
3027 EXPECT_EQ("5,6", ConvertPointToTargetString(w111, w11ll));
3029 // w111->w1ll
3030 EXPECT_EQ("8,10", ConvertPointToTargetString(w111, w1ll));
3032 // w111->root
3033 EXPECT_EQ("9,12", ConvertPointToTargetString(w111, &root));
3035 // w111->w12
3036 EXPECT_EQ("1,2", ConvertPointToTargetString(w111, w12));
3038 // w111->w121
3039 EXPECT_EQ("-8,-8", ConvertPointToTargetString(w111, w121));
3041 // w11ll->w111
3042 EXPECT_EQ("-5,-6", ConvertPointToTargetString(w11ll, w111));
3044 // w11ll->w11ll
3045 EXPECT_EQ("3,4", ConvertPointToTargetString(w11ll, w1ll));
3047 // w11ll->root
3048 EXPECT_EQ("4,6", ConvertPointToTargetString(w11ll, &root));
3050 // w11ll->w12
3051 EXPECT_EQ("-4,-4", ConvertPointToTargetString(w11ll, w12));
3054 #if !defined(NDEBUG)
3055 // Verifies PrintWindowHierarchy() doesn't crash with a layerless window.
3056 TEST_F(WindowTest, PrintWindowHierarchyNotCrashLayerless) {
3057 Window root(NULL);
3058 root.Init(WINDOW_LAYER_NONE);
3059 root.SetBounds(gfx::Rect(0, 0, 100, 100));
3060 root.PrintWindowHierarchy(0);
3062 #endif
3064 namespace {
3066 // See AddWindowsFromString() for details.
3067 aura::Window* CreateWindowFromDescription(const std::string& description,
3068 WindowDelegate* delegate) {
3069 WindowLayerType window_type = WINDOW_LAYER_NOT_DRAWN;
3070 std::vector<std::string> tokens;
3071 Tokenize(description, ":", &tokens);
3072 DCHECK(!tokens.empty());
3073 std::string name(tokens[0]);
3074 tokens.erase(tokens.begin());
3075 if (!tokens.empty()) {
3076 if (tokens[0] == "ll") {
3077 window_type = WINDOW_LAYER_NONE;
3078 tokens.erase(tokens.begin());
3080 DCHECK(tokens.empty()) << "unknown tokens for creating window "
3081 << description;
3083 Window* window = new Window(delegate);
3084 window->Init(window_type);
3085 window->SetName(name);
3086 // Window name is only propagated to layer in debug builds.
3087 if (window->layer())
3088 window->layer()->set_name(name);
3089 return window;
3092 // Creates and adds a tree of windows to |parent|. |description| consists
3093 // of the following pieces:
3094 // X: Identifies a new window. Consists of a name and optionally ":ll" to
3095 // specify WINDOW_LAYER_NONE, eg "w1:ll".
3096 // []: optionally used to specify the children of the window. Contains any
3097 // number of window identifiers and their corresponding children.
3098 // For example: "[ a [ a1 a2:ll ] b c [ c1 ] ]" creates the tree:
3099 // a
3100 // a1
3101 // a2 -> WINDOW_LAYER_NONE.
3102 // b
3103 // c
3104 // c1
3105 // NOTE: you must have a space after every token.
3106 std::string::size_type AddWindowsFromString(aura::Window* parent,
3107 const std::string& description,
3108 std::string::size_type start_pos,
3109 WindowDelegate* delegate) {
3110 DCHECK(parent);
3111 std::string::size_type end_pos = description.find(' ', start_pos);
3112 while (end_pos != std::string::npos) {
3113 const std::string::size_type part_length = end_pos - start_pos;
3114 const std::string window_description =
3115 description.substr(start_pos, part_length);
3116 if (window_description == "[") {
3117 start_pos = AddWindowsFromString(parent->children().back(),
3118 description,
3119 end_pos + 1,
3120 delegate);
3121 end_pos = description.find(' ', start_pos);
3122 if (end_pos == std::string::npos && start_pos != end_pos)
3123 end_pos = description.length();
3124 } else if (window_description == "]") {
3125 ++end_pos;
3126 break;
3127 } else {
3128 Window* window =
3129 CreateWindowFromDescription(window_description, delegate);
3130 parent->AddChild(window);
3131 start_pos = ++end_pos;
3132 end_pos = description.find(' ', start_pos);
3135 return end_pos;
3138 // Used by BuildRootWindowTreeDescription().
3139 std::string BuildWindowTreeDescription(const aura::Window& window) {
3140 std::string result;
3141 result += window.name();
3142 if (window.children().empty())
3143 return result;
3145 result += " [ ";
3146 for (size_t i = 0; i < window.children().size(); ++i) {
3147 if (i != 0)
3148 result += " ";
3149 result += BuildWindowTreeDescription(*(window.children()[i]));
3151 result += " ]";
3152 return result;
3155 // Creates a string from |window|. See AddWindowsFromString() for details of the
3156 // returned string. This does *not* include the layer type in the description,
3157 // on the name.
3158 std::string BuildRootWindowTreeDescription(const aura::Window& window) {
3159 std::string result;
3160 for (size_t i = 0; i < window.children().size(); ++i) {
3161 if (i != 0)
3162 result += " ";
3163 result += BuildWindowTreeDescription(*(window.children()[i]));
3165 return result;
3168 // Used by BuildRootWindowTreeDescription().
3169 std::string BuildLayerTreeDescription(const ui::Layer& layer) {
3170 std::string result;
3171 result += layer.name();
3172 if (layer.children().empty())
3173 return result;
3175 result += " [ ";
3176 for (size_t i = 0; i < layer.children().size(); ++i) {
3177 if (i != 0)
3178 result += " ";
3179 result += BuildLayerTreeDescription(*(layer.children()[i]));
3181 result += " ]";
3182 return result;
3185 // Builds a string for all the children of |layer|. The returned string is in
3186 // the same format as AddWindowsFromString() but only includes the name of the
3187 // layers.
3188 std::string BuildRootLayerTreeDescription(const ui::Layer& layer) {
3189 std::string result;
3190 for (size_t i = 0; i < layer.children().size(); ++i) {
3191 if (i != 0)
3192 result += " ";
3193 result += BuildLayerTreeDescription(*(layer.children()[i]));
3195 return result;
3198 // Returns the first window whose name matches |name| in |parent|.
3199 aura::Window* FindWindowByName(aura::Window* parent,
3200 const std::string& name) {
3201 if (parent->name() == name)
3202 return parent;
3203 for (size_t i = 0; i < parent->children().size(); ++i) {
3204 aura::Window* child = FindWindowByName(parent->children()[i], name);
3205 if (child)
3206 return child;
3208 return NULL;
3211 } // namespace
3213 // Direction to stack.
3214 enum StackType {
3215 STACK_ABOVE,
3216 STACK_BELOW,
3217 STACK_AT_BOTTOM,
3218 STACK_AT_TOP,
3221 // Permutations of StackChildAt with various data.
3222 TEST_F(WindowTest, StackChildAtLayerless) {
3223 struct TestData {
3224 // Describes the window tree to create. See AddWindowsFromString() for
3225 // details.
3226 const std::string initial_description;
3228 // Identifies the window to move.
3229 const std::string source_window;
3231 // Window to move |source_window| relative to. Not used for STACK_AT_BOTTOM
3232 // or STACK_AT_TOP.
3233 const std::string target_window;
3235 StackType stack_type;
3237 // Expected window and layer results.
3238 const std::string expected_description;
3239 const std::string expected_layer_description;
3240 } data[] = {
3241 // 1 at top.
3243 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3244 "1",
3246 STACK_AT_TOP,
3247 "2 [ 21 ] 1 [ 11 12 ]",
3248 "21 11 12",
3251 // 1 at bottom.
3253 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3254 "1",
3256 STACK_AT_BOTTOM,
3257 "1 [ 11 12 ] 2 [ 21 ]",
3258 "11 12 21",
3261 // 2 at bottom.
3263 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3264 "2",
3266 STACK_AT_BOTTOM,
3267 "2 [ 21 ] 1 [ 11 12 ]",
3268 "21 11 12",
3271 // 3 below 2.
3273 "1:ll [ 11 12 ] 2:ll [ 21 ] 3:ll",
3274 "3",
3275 "2",
3276 STACK_BELOW,
3277 "1 [ 11 12 ] 3 2 [ 21 ]",
3278 "11 12 21",
3281 // 2 below 1.
3283 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3284 "2",
3285 "1",
3286 STACK_BELOW,
3287 "2 [ 21 ] 1 [ 11 12 ]",
3288 "21 11 12",
3291 // 1 above 3.
3293 "1:ll [ 11 12 ] 2:ll [ 21 ] 3:ll",
3294 "1",
3295 "3",
3296 STACK_ABOVE,
3297 "2 [ 21 ] 3 1 [ 11 12 ]",
3298 "21 11 12",
3301 // 1 above 2.
3303 "1:ll [ 11 12 ] 2:ll [ 21 ]",
3304 "1",
3305 "2",
3306 STACK_ABOVE,
3307 "2 [ 21 ] 1 [ 11 12 ]",
3308 "21 11 12",
3311 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
3312 test::TestWindowDelegate delegate;
3313 Window root(NULL);
3314 root.Init(WINDOW_LAYER_NOT_DRAWN);
3315 root.SetBounds(gfx::Rect(0, 0, 100, 100));
3316 AddWindowsFromString(
3317 &root,
3318 data[i].initial_description,
3319 static_cast<std::string::size_type>(0), &delegate);
3320 aura::Window* source = FindWindowByName(&root, data[i].source_window);
3321 ASSERT_TRUE(source != NULL) << "unable to find source window "
3322 << data[i].source_window << " at " << i;
3323 aura::Window* target = FindWindowByName(&root, data[i].target_window);
3324 switch (data[i].stack_type) {
3325 case STACK_ABOVE:
3326 ASSERT_TRUE(target != NULL) << "unable to find target window "
3327 << data[i].target_window << " at " << i;
3328 source->parent()->StackChildAbove(source, target);
3329 break;
3330 case STACK_BELOW:
3331 ASSERT_TRUE(target != NULL) << "unable to find target window "
3332 << data[i].target_window << " at " << i;
3333 source->parent()->StackChildBelow(source, target);
3334 break;
3335 case STACK_AT_BOTTOM:
3336 source->parent()->StackChildAtBottom(source);
3337 break;
3338 case STACK_AT_TOP:
3339 source->parent()->StackChildAtTop(source);
3340 break;
3342 EXPECT_EQ(data[i].expected_layer_description,
3343 BuildRootLayerTreeDescription(*root.layer()))
3344 << "layer tree doesn't match at " << i;
3345 EXPECT_EQ(data[i].expected_description,
3346 BuildRootWindowTreeDescription(root))
3347 << "window tree doesn't match at " << i;
3351 namespace {
3353 class TestLayerAnimationObserver : public ui::LayerAnimationObserver {
3354 public:
3355 TestLayerAnimationObserver()
3356 : animation_completed_(false),
3357 animation_aborted_(false) {}
3358 virtual ~TestLayerAnimationObserver() {}
3360 bool animation_completed() const { return animation_completed_; }
3361 bool animation_aborted() const { return animation_aborted_; }
3363 void Reset() {
3364 animation_completed_ = false;
3365 animation_aborted_ = false;
3368 private:
3369 // ui::LayerAnimationObserver:
3370 virtual void OnLayerAnimationEnded(
3371 ui::LayerAnimationSequence* sequence) OVERRIDE {
3372 animation_completed_ = true;
3375 virtual void OnLayerAnimationAborted(
3376 ui::LayerAnimationSequence* sequence) OVERRIDE {
3377 animation_aborted_ = true;
3380 virtual void OnLayerAnimationScheduled(
3381 ui::LayerAnimationSequence* sequence) OVERRIDE {
3384 bool animation_completed_;
3385 bool animation_aborted_;
3387 DISALLOW_COPY_AND_ASSIGN(TestLayerAnimationObserver);
3392 TEST_F(WindowTest, WindowDestroyCompletesAnimations) {
3393 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
3394 ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
3395 scoped_refptr<ui::LayerAnimator> animator =
3396 ui::LayerAnimator::CreateImplicitAnimator();
3397 TestLayerAnimationObserver observer;
3398 animator->AddObserver(&observer);
3399 // Make sure destroying a Window completes the animation.
3401 scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window()));
3402 window->layer()->SetAnimator(animator);
3404 gfx::Transform transform;
3405 transform.Scale(0.5f, 0.5f);
3406 window->SetTransform(transform);
3408 EXPECT_TRUE(animator->is_animating());
3409 EXPECT_FALSE(observer.animation_completed());
3411 EXPECT_TRUE(animator);
3412 EXPECT_FALSE(animator->is_animating());
3413 EXPECT_TRUE(observer.animation_completed());
3414 EXPECT_FALSE(observer.animation_aborted());
3415 animator->RemoveObserver(&observer);
3416 observer.Reset();
3418 animator = ui::LayerAnimator::CreateImplicitAnimator();
3419 animator->AddObserver(&observer);
3420 ui::Layer layer;
3421 layer.SetAnimator(animator);
3423 scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window()));
3424 window->layer()->Add(&layer);
3426 gfx::Transform transform;
3427 transform.Scale(0.5f, 0.5f);
3428 layer.SetTransform(transform);
3430 EXPECT_TRUE(animator->is_animating());
3431 EXPECT_FALSE(observer.animation_completed());
3434 EXPECT_TRUE(animator);
3435 EXPECT_FALSE(animator->is_animating());
3436 EXPECT_TRUE(observer.animation_completed());
3437 EXPECT_FALSE(observer.animation_aborted());
3438 animator->RemoveObserver(&observer);
3441 } // namespace test
3442 } // namespace aura