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. 4 5 #include "ui/aura/window.h" 6 7 #include <string> 8 #include <utility> 9 #include <vector> 10 11 #include "base/basictypes.h" 12 #include "base/compiler_specific.h" 13 #include "base/strings/string_number_conversions.h" 14 #include "base/strings/string_util.h" 15 #include "base/strings/stringprintf.h" 16 #include "testing/gtest/include/gtest/gtest.h" 17 #include "ui/aura/client/capture_client.h" 18 #include "ui/aura/client/focus_change_observer.h" 19 #include "ui/aura/client/visibility_client.h" 20 #include "ui/aura/client/window_tree_client.h" 21 #include "ui/aura/test/aura_test_base.h" 22 #include "ui/aura/test/aura_test_utils.h" 23 #include "ui/aura/test/test_window_delegate.h" 24 #include "ui/aura/test/test_windows.h" 25 #include "ui/aura/test/window_test_api.h" 26 #include "ui/aura/window_delegate.h" 27 #include "ui/aura/window_event_dispatcher.h" 28 #include "ui/aura/window_observer.h" 29 #include "ui/aura/window_property.h" 30 #include "ui/aura/window_tree_host.h" 31 #include "ui/base/hit_test.h" 32 #include "ui/compositor/layer.h" 33 #include "ui/compositor/layer_animation_observer.h" 34 #include "ui/compositor/scoped_animation_duration_scale_mode.h" 35 #include "ui/compositor/scoped_layer_animation_settings.h" 36 #include "ui/compositor/test/test_layers.h" 37 #include "ui/events/event.h" 38 #include "ui/events/event_utils.h" 39 #include "ui/events/gestures/gesture_configuration.h" 40 #include "ui/events/keycodes/keyboard_codes.h" 41 #include "ui/events/test/event_generator.h" 42 #include "ui/gfx/canvas.h" 43 #include "ui/gfx/screen.h" 44 #include "ui/gfx/skia_util.h" 45 #include "ui/gfx/vector2d.h" 46 47 DECLARE_WINDOW_PROPERTY_TYPE(const char*) 48 DECLARE_WINDOW_PROPERTY_TYPE(int) 49 50 namespace aura { 51 namespace test { 52 53 class WindowTest : public AuraTestBase { 54 public: 55 WindowTest() : max_separation_(0) { 56 } 57 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); 65 } 66 67 virtual void TearDown() OVERRIDE { 68 AuraTestBase::TearDown(); 69 ui::GestureConfiguration:: 70 set_max_separation_for_gesture_touches_in_pixels(max_separation_); 71 } 72 73 private: 74 int max_separation_; 75 76 DISALLOW_COPY_AND_ASSIGN(WindowTest); 77 }; 78 79 namespace { 80 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) {} 88 89 void clear_destroying_count() { destroying_count_ = 0; } 90 int destroying_count() const { return destroying_count_; } 91 92 void clear_destroyed_count() { destroyed_count_ = 0; } 93 int destroyed_count() const { return destroyed_count_; } 94 95 bool in_destroying() const { return in_destroying_; } 96 97 virtual void OnWindowDestroying(Window* window) OVERRIDE { 98 EXPECT_FALSE(in_destroying_); 99 in_destroying_ = true; 100 destroying_count_++; 101 } 102 103 virtual void OnWindowDestroyed(Window* window) OVERRIDE { 104 EXPECT_TRUE(in_destroying_); 105 in_destroying_ = false; 106 destroyed_count_++; 107 } 108 109 private: 110 int destroying_count_; 111 int destroyed_count_; 112 bool in_destroying_; 113 114 DISALLOW_COPY_AND_ASSIGN(DestroyTrackingDelegateImpl); 115 }; 116 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) { 124 } 125 126 virtual void OnWindowDestroying(Window* window) OVERRIDE { 127 EXPECT_TRUE(parent_delegate_->in_destroying()); 128 DestroyTrackingDelegateImpl::OnWindowDestroying(window); 129 } 130 131 private: 132 DestroyTrackingDelegateImpl* parent_delegate_; 133 134 DISALLOW_COPY_AND_ASSIGN(ChildWindowDelegateImpl); 135 }; 136 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) { 142 } 143 144 void set_window(Window* window) { window_ = window; } 145 146 virtual void OnWindowDestroyed(Window* window) OVERRIDE { 147 EXPECT_FALSE(window_->parent()); 148 } 149 150 private: 151 Window* window_; 152 DISALLOW_COPY_AND_ASSIGN(DestroyOrphanDelegate); 153 }; 154 155 // Used in verifying mouse capture. 156 class CaptureWindowDelegateImpl : public TestWindowDelegate { 157 public: 158 CaptureWindowDelegateImpl() { 159 ResetCounts(); 160 } 161 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; 168 } 169 170 int capture_changed_event_count() const { 171 return capture_changed_event_count_; 172 } 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_; } 177 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_++; 182 } 183 virtual void OnTouchEvent(ui::TouchEvent* event) OVERRIDE { 184 touch_event_count_++; 185 } 186 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { 187 gesture_event_count_++; 188 } 189 virtual void OnCaptureLost() OVERRIDE { 190 capture_lost_count_++; 191 } 192 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_; 199 200 DISALLOW_COPY_AND_ASSIGN(CaptureWindowDelegateImpl); 201 }; 202 203 // Keeps track of the location of the gesture. 204 class GestureTrackPositionDelegate : public TestWindowDelegate { 205 public: 206 GestureTrackPositionDelegate() {} 207 208 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE { 209 position_ = event->location(); 210 event->StopPropagation(); 211 } 212 213 const gfx::Point& position() const { return position_; } 214 215 private: 216 gfx::Point position_; 217 218 DISALLOW_COPY_AND_ASSIGN(GestureTrackPositionDelegate); 219 }; 220 221 base::TimeDelta getTime() { 222 return ui::EventTimeForNow(); 223 } 224 225 class SelfEventHandlingWindowDelegate : public TestWindowDelegate { 226 public: 227 SelfEventHandlingWindowDelegate() {} 228 229 virtual bool ShouldDescendIntoChildForEventHandling( 230 Window* child, 231 const gfx::Point& location) OVERRIDE { 232 return false; 233 } 234 235 private: 236 DISALLOW_COPY_AND_ASSIGN(SelfEventHandlingWindowDelegate); 237 }; 238 239 // The delegate deletes itself when the window is being destroyed. 240 class DestroyWindowDelegate : public TestWindowDelegate { 241 public: 242 DestroyWindowDelegate() {} 243 244 private: 245 virtual ~DestroyWindowDelegate() {} 246 247 // Overridden from WindowDelegate. 248 virtual void OnWindowDestroyed(Window* window) OVERRIDE { 249 delete this; 250 } 251 252 DISALLOW_COPY_AND_ASSIGN(DestroyWindowDelegate); 253 }; 254 255 } // namespace 256 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())); 262 263 EXPECT_EQ(NULL, w1->GetChildById(57)); 264 EXPECT_EQ(w12.get(), w1->GetChildById(12)); 265 EXPECT_EQ(w111.get(), w1->GetChildById(111)); 266 } 267 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); 277 278 parent.AddChild(&child1); 279 child1.AddChild(&child2); 280 281 EXPECT_TRUE(parent.Contains(&parent)); 282 EXPECT_TRUE(parent.Contains(&child1)); 283 EXPECT_TRUE(parent.Contains(&child2)); 284 285 EXPECT_FALSE(parent.Contains(NULL)); 286 EXPECT_FALSE(child1.Contains(&parent)); 287 EXPECT_FALSE(child2.Contains(&child1)); 288 } 289 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))); 299 } 300 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))); 309 } 310 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); 320 } 321 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())); 332 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()); 349 } 350 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()); 362 } 363 364 // Test Window::ConvertPointToWindow() with transform to root_window. 365 TEST_F(WindowTest, MoveCursorToWithTransformRootWindow) { 366 gfx::Transform transform; 367 transform.Translate(100.0, 100.0); 368 transform.Rotate(90.0); 369 transform.Scale(2.0, 5.0); 370 host()->SetRootTransform(transform); 371 host()->MoveCursorTo(gfx::Point(10, 10)); 372 #if !defined(OS_WIN) 373 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413.OD 374 EXPECT_EQ("50,120", QueryLatestMousePositionRequestInHost(host()).ToString()); 375 #endif 376 EXPECT_EQ("10,10", gfx::Screen::GetScreenFor( 377 root_window())->GetCursorScreenPoint().ToString()); 378 } 379 380 // Tests Window::ConvertPointToWindow() with transform to non-root windows. 381 TEST_F(WindowTest, MoveCursorToWithTransformWindow) { 382 scoped_ptr<Window> w1( 383 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500), 384 root_window())); 385 386 gfx::Transform transform1; 387 transform1.Scale(2, 2); 388 w1->SetTransform(transform1); 389 w1->MoveCursorTo(gfx::Point(10, 10)); 390 EXPECT_EQ("30,30", 391 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString()); 392 393 gfx::Transform transform2; 394 transform2.Translate(-10, 20); 395 w1->SetTransform(transform2); 396 w1->MoveCursorTo(gfx::Point(10, 10)); 397 EXPECT_EQ("10,40", 398 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString()); 399 400 gfx::Transform transform3; 401 transform3.Rotate(90.0); 402 w1->SetTransform(transform3); 403 w1->MoveCursorTo(gfx::Point(5, 5)); 404 EXPECT_EQ("5,15", 405 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString()); 406 407 gfx::Transform transform4; 408 transform4.Translate(100.0, 100.0); 409 transform4.Rotate(90.0); 410 transform4.Scale(2.0, 5.0); 411 w1->SetTransform(transform4); 412 w1->MoveCursorTo(gfx::Point(10, 10)); 413 EXPECT_EQ("60,130", 414 gfx::Screen::GetScreenFor(w1.get())->GetCursorScreenPoint().ToString()); 415 } 416 417 // Test Window::ConvertPointToWindow() with complex transforms to both root and 418 // non-root windows. 419 // Test Window::ConvertPointToWindow() with transform to root_window. 420 TEST_F(WindowTest, MoveCursorToWithComplexTransform) { 421 scoped_ptr<Window> w1( 422 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500), 423 root_window())); 424 scoped_ptr<Window> w11( 425 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get())); 426 scoped_ptr<Window> w111( 427 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get())); 428 scoped_ptr<Window> w1111( 429 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get())); 430 431 Window* root = root_window(); 432 433 // The root window expects transforms that produce integer rects. 434 gfx::Transform root_transform; 435 root_transform.Translate(60.0, 70.0); 436 root_transform.Rotate(-90.0); 437 root_transform.Translate(-50.0, -50.0); 438 root_transform.Scale(2.0, 3.0); 439 440 gfx::Transform transform; 441 transform.Translate(10.0, 20.0); 442 transform.Rotate(10.0); 443 transform.Scale(0.3f, 0.5f); 444 host()->SetRootTransform(root_transform); 445 w1->SetTransform(transform); 446 w11->SetTransform(transform); 447 w111->SetTransform(transform); 448 w1111->SetTransform(transform); 449 450 w1111->MoveCursorTo(gfx::Point(10, 10)); 451 452 #if !defined(OS_WIN) 453 // TODO(yoshiki): fix this to build on Windows. See crbug.com/133413. 454 EXPECT_EQ("169,80", QueryLatestMousePositionRequestInHost(host()).ToString()); 455 #endif 456 EXPECT_EQ("20,53", 457 gfx::Screen::GetScreenFor(root)->GetCursorScreenPoint().ToString()); 458 } 459 460 TEST_F(WindowTest, GetEventHandlerForPoint) { 461 scoped_ptr<Window> w1( 462 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 500, 500), 463 root_window())); 464 scoped_ptr<Window> w11( 465 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(5, 5, 100, 100), w1.get())); 466 scoped_ptr<Window> w111( 467 CreateTestWindow(SK_ColorCYAN, 111, gfx::Rect(5, 5, 75, 75), w11.get())); 468 scoped_ptr<Window> w1111( 469 CreateTestWindow(SK_ColorRED, 1111, gfx::Rect(5, 5, 50, 50), w111.get())); 470 scoped_ptr<Window> w12( 471 CreateTestWindow(SK_ColorMAGENTA, 12, gfx::Rect(10, 420, 25, 25), 472 w1.get())); 473 scoped_ptr<Window> w121( 474 CreateTestWindow(SK_ColorYELLOW, 121, gfx::Rect(5, 5, 5, 5), w12.get())); 475 scoped_ptr<Window> w13( 476 CreateTestWindow(SK_ColorGRAY, 13, gfx::Rect(5, 470, 50, 50), w1.get())); 477 478 Window* root = root_window(); 479 w1->parent()->SetBounds(gfx::Rect(500, 500)); 480 EXPECT_EQ(NULL, root->GetEventHandlerForPoint(gfx::Point(5, 5))); 481 EXPECT_EQ(w1.get(), root->GetEventHandlerForPoint(gfx::Point(11, 11))); 482 EXPECT_EQ(w11.get(), root->GetEventHandlerForPoint(gfx::Point(16, 16))); 483 EXPECT_EQ(w111.get(), root->GetEventHandlerForPoint(gfx::Point(21, 21))); 484 EXPECT_EQ(w1111.get(), root->GetEventHandlerForPoint(gfx::Point(26, 26))); 485 EXPECT_EQ(w12.get(), root->GetEventHandlerForPoint(gfx::Point(21, 431))); 486 EXPECT_EQ(w121.get(), root->GetEventHandlerForPoint(gfx::Point(26, 436))); 487 EXPECT_EQ(w13.get(), root->GetEventHandlerForPoint(gfx::Point(26, 481))); 488 } 489 490 TEST_F(WindowTest, GetEventHandlerForPointWithOverride) { 491 // If our child is flush to our top-left corner he gets events just inside the 492 // window edges. 493 scoped_ptr<Window> parent( 494 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 20, 400, 500), 495 root_window())); 496 scoped_ptr<Window> child( 497 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(0, 0, 60, 70), parent.get())); 498 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0))); 499 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(1, 1))); 500 501 // We can override the hit test bounds of the parent to make the parent grab 502 // events along that edge. 503 parent->set_hit_test_bounds_override_inner(gfx::Insets(1, 1, 1, 1)); 504 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0))); 505 EXPECT_EQ(child.get(), parent->GetEventHandlerForPoint(gfx::Point(1, 1))); 506 } 507 508 TEST_F(WindowTest, GetEventHandlerForPointWithOverrideDescendingOrder) { 509 scoped_ptr<SelfEventHandlingWindowDelegate> parent_delegate( 510 new SelfEventHandlingWindowDelegate); 511 scoped_ptr<Window> parent(CreateTestWindowWithDelegate( 512 parent_delegate.get(), 1, gfx::Rect(10, 20, 400, 500), root_window())); 513 scoped_ptr<Window> child( 514 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(0, 0, 390, 480), 515 parent.get())); 516 517 // We can override ShouldDescendIntoChildForEventHandling to make the parent 518 // grab all events. 519 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(0, 0))); 520 EXPECT_EQ(parent.get(), parent->GetEventHandlerForPoint(gfx::Point(50, 50))); 521 } 522 523 TEST_F(WindowTest, GetTopWindowContainingPoint) { 524 Window* root = root_window(); 525 root->SetBounds(gfx::Rect(0, 0, 300, 300)); 526 527 scoped_ptr<Window> w1( 528 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(10, 10, 100, 100), 529 root_window())); 530 scoped_ptr<Window> w11( 531 CreateTestWindow(SK_ColorGREEN, 11, gfx::Rect(0, 0, 120, 120), w1.get())); 532 533 scoped_ptr<Window> w2( 534 CreateTestWindow(SK_ColorRED, 2, gfx::Rect(5, 5, 55, 55), 535 root_window())); 536 537 scoped_ptr<Window> w3( 538 CreateTestWindowWithDelegate( 539 NULL, 3, gfx::Rect(200, 200, 100, 100), root_window())); 540 scoped_ptr<Window> w31( 541 CreateTestWindow(SK_ColorCYAN, 31, gfx::Rect(0, 0, 50, 50), w3.get())); 542 scoped_ptr<Window> w311( 543 CreateTestWindow(SK_ColorBLUE, 311, gfx::Rect(0, 0, 10, 10), w31.get())); 544 545 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(0, 0))); 546 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(5, 5))); 547 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(10, 10))); 548 EXPECT_EQ(w2.get(), root->GetTopWindowContainingPoint(gfx::Point(59, 59))); 549 EXPECT_EQ(w1.get(), root->GetTopWindowContainingPoint(gfx::Point(60, 60))); 550 EXPECT_EQ(w1.get(), root->GetTopWindowContainingPoint(gfx::Point(109, 109))); 551 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(110, 110))); 552 EXPECT_EQ(w31.get(), root->GetTopWindowContainingPoint(gfx::Point(200, 200))); 553 EXPECT_EQ(w31.get(), root->GetTopWindowContainingPoint(gfx::Point(220, 220))); 554 EXPECT_EQ(NULL, root->GetTopWindowContainingPoint(gfx::Point(260, 260))); 555 } 556 557 TEST_F(WindowTest, GetToplevelWindow) { 558 const gfx::Rect kBounds(0, 0, 10, 10); 559 TestWindowDelegate delegate; 560 561 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window())); 562 scoped_ptr<Window> w11( 563 CreateTestWindowWithDelegate(&delegate, 11, kBounds, w1.get())); 564 scoped_ptr<Window> w111(CreateTestWindowWithId(111, w11.get())); 565 scoped_ptr<Window> w1111( 566 CreateTestWindowWithDelegate(&delegate, 1111, kBounds, w111.get())); 567 568 EXPECT_TRUE(root_window()->GetToplevelWindow() == NULL); 569 EXPECT_TRUE(w1->GetToplevelWindow() == NULL); 570 EXPECT_EQ(w11.get(), w11->GetToplevelWindow()); 571 EXPECT_EQ(w11.get(), w111->GetToplevelWindow()); 572 EXPECT_EQ(w11.get(), w1111->GetToplevelWindow()); 573 } 574 575 class AddedToRootWindowObserver : public WindowObserver { 576 public: 577 AddedToRootWindowObserver() : called_(false) {} 578 579 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE { 580 called_ = true; 581 } 582 583 bool called() const { return called_; } 584 585 private: 586 bool called_; 587 588 DISALLOW_COPY_AND_ASSIGN(AddedToRootWindowObserver); 589 }; 590 591 TEST_F(WindowTest, WindowAddedToRootWindowShouldNotifyChildAndNotParent) { 592 AddedToRootWindowObserver parent_observer; 593 AddedToRootWindowObserver child_observer; 594 scoped_ptr<Window> parent_window(CreateTestWindowWithId(1, root_window())); 595 scoped_ptr<Window> child_window(new Window(NULL)); 596 child_window->Init(aura::WINDOW_LAYER_TEXTURED); 597 child_window->Show(); 598 599 parent_window->AddObserver(&parent_observer); 600 child_window->AddObserver(&child_observer); 601 602 parent_window->AddChild(child_window.get()); 603 604 EXPECT_FALSE(parent_observer.called()); 605 EXPECT_TRUE(child_observer.called()); 606 607 parent_window->RemoveObserver(&parent_observer); 608 child_window->RemoveObserver(&child_observer); 609 } 610 611 // Various destruction assertions. 612 TEST_F(WindowTest, DestroyTest) { 613 DestroyTrackingDelegateImpl parent_delegate; 614 ChildWindowDelegateImpl child_delegate(&parent_delegate); 615 { 616 scoped_ptr<Window> parent( 617 CreateTestWindowWithDelegate(&parent_delegate, 0, gfx::Rect(), 618 root_window())); 619 CreateTestWindowWithDelegate(&child_delegate, 0, gfx::Rect(), parent.get()); 620 } 621 // Both the parent and child should have been destroyed. 622 EXPECT_EQ(1, parent_delegate.destroying_count()); 623 EXPECT_EQ(1, parent_delegate.destroyed_count()); 624 EXPECT_EQ(1, child_delegate.destroying_count()); 625 EXPECT_EQ(1, child_delegate.destroyed_count()); 626 } 627 628 // Tests that a window is orphaned before OnWindowDestroyed is called. 629 TEST_F(WindowTest, OrphanedBeforeOnDestroyed) { 630 TestWindowDelegate parent_delegate; 631 DestroyOrphanDelegate child_delegate; 632 { 633 scoped_ptr<Window> parent( 634 CreateTestWindowWithDelegate(&parent_delegate, 0, gfx::Rect(), 635 root_window())); 636 scoped_ptr<Window> child(CreateTestWindowWithDelegate(&child_delegate, 0, 637 gfx::Rect(), parent.get())); 638 child_delegate.set_window(child.get()); 639 } 640 } 641 642 // Make sure StackChildAtTop moves both the window and layer to the front. 643 TEST_F(WindowTest, StackChildAtTop) { 644 Window parent(NULL); 645 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN); 646 Window child1(NULL); 647 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN); 648 Window child2(NULL); 649 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN); 650 651 parent.AddChild(&child1); 652 parent.AddChild(&child2); 653 ASSERT_EQ(2u, parent.children().size()); 654 EXPECT_EQ(&child1, parent.children()[0]); 655 EXPECT_EQ(&child2, parent.children()[1]); 656 ASSERT_EQ(2u, parent.layer()->children().size()); 657 EXPECT_EQ(child1.layer(), parent.layer()->children()[0]); 658 EXPECT_EQ(child2.layer(), parent.layer()->children()[1]); 659 660 parent.StackChildAtTop(&child1); 661 ASSERT_EQ(2u, parent.children().size()); 662 EXPECT_EQ(&child1, parent.children()[1]); 663 EXPECT_EQ(&child2, parent.children()[0]); 664 ASSERT_EQ(2u, parent.layer()->children().size()); 665 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]); 666 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]); 667 } 668 669 // Make sure StackChildBelow works. 670 TEST_F(WindowTest, StackChildBelow) { 671 Window parent(NULL); 672 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN); 673 Window child1(NULL); 674 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN); 675 child1.set_id(1); 676 Window child2(NULL); 677 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN); 678 child2.set_id(2); 679 Window child3(NULL); 680 child3.Init(aura::WINDOW_LAYER_NOT_DRAWN); 681 child3.set_id(3); 682 683 parent.AddChild(&child1); 684 parent.AddChild(&child2); 685 parent.AddChild(&child3); 686 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent)); 687 688 parent.StackChildBelow(&child1, &child2); 689 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(&parent)); 690 691 parent.StackChildBelow(&child2, &child1); 692 EXPECT_EQ("2 1 3", ChildWindowIDsAsString(&parent)); 693 694 parent.StackChildBelow(&child3, &child2); 695 EXPECT_EQ("3 2 1", ChildWindowIDsAsString(&parent)); 696 697 parent.StackChildBelow(&child3, &child1); 698 EXPECT_EQ("2 3 1", ChildWindowIDsAsString(&parent)); 699 } 700 701 // Various assertions for StackChildAbove. 702 TEST_F(WindowTest, StackChildAbove) { 703 Window parent(NULL); 704 parent.Init(aura::WINDOW_LAYER_NOT_DRAWN); 705 Window child1(NULL); 706 child1.Init(aura::WINDOW_LAYER_NOT_DRAWN); 707 Window child2(NULL); 708 child2.Init(aura::WINDOW_LAYER_NOT_DRAWN); 709 Window child3(NULL); 710 child3.Init(aura::WINDOW_LAYER_NOT_DRAWN); 711 712 parent.AddChild(&child1); 713 parent.AddChild(&child2); 714 715 // Move 1 in front of 2. 716 parent.StackChildAbove(&child1, &child2); 717 ASSERT_EQ(2u, parent.children().size()); 718 EXPECT_EQ(&child2, parent.children()[0]); 719 EXPECT_EQ(&child1, parent.children()[1]); 720 ASSERT_EQ(2u, parent.layer()->children().size()); 721 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]); 722 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]); 723 724 // Add 3, resulting in order [2, 1, 3], then move 2 in front of 1, resulting 725 // in [1, 2, 3]. 726 parent.AddChild(&child3); 727 parent.StackChildAbove(&child2, &child1); 728 ASSERT_EQ(3u, parent.children().size()); 729 EXPECT_EQ(&child1, parent.children()[0]); 730 EXPECT_EQ(&child2, parent.children()[1]); 731 EXPECT_EQ(&child3, parent.children()[2]); 732 ASSERT_EQ(3u, parent.layer()->children().size()); 733 EXPECT_EQ(child1.layer(), parent.layer()->children()[0]); 734 EXPECT_EQ(child2.layer(), parent.layer()->children()[1]); 735 EXPECT_EQ(child3.layer(), parent.layer()->children()[2]); 736 737 // Move 1 in front of 3, resulting in [2, 3, 1]. 738 parent.StackChildAbove(&child1, &child3); 739 ASSERT_EQ(3u, parent.children().size()); 740 EXPECT_EQ(&child2, parent.children()[0]); 741 EXPECT_EQ(&child3, parent.children()[1]); 742 EXPECT_EQ(&child1, parent.children()[2]); 743 ASSERT_EQ(3u, parent.layer()->children().size()); 744 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]); 745 EXPECT_EQ(child3.layer(), parent.layer()->children()[1]); 746 EXPECT_EQ(child1.layer(), parent.layer()->children()[2]); 747 748 // Moving 1 in front of 2 should lower it, resulting in [2, 1, 3]. 749 parent.StackChildAbove(&child1, &child2); 750 ASSERT_EQ(3u, parent.children().size()); 751 EXPECT_EQ(&child2, parent.children()[0]); 752 EXPECT_EQ(&child1, parent.children()[1]); 753 EXPECT_EQ(&child3, parent.children()[2]); 754 ASSERT_EQ(3u, parent.layer()->children().size()); 755 EXPECT_EQ(child2.layer(), parent.layer()->children()[0]); 756 EXPECT_EQ(child1.layer(), parent.layer()->children()[1]); 757 EXPECT_EQ(child3.layer(), parent.layer()->children()[2]); 758 } 759 760 // Various capture assertions. 761 TEST_F(WindowTest, CaptureTests) { 762 CaptureWindowDelegateImpl delegate; 763 scoped_ptr<Window> window(CreateTestWindowWithDelegate( 764 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window())); 765 EXPECT_FALSE(window->HasCapture()); 766 767 delegate.ResetCounts(); 768 769 // Do a capture. 770 window->SetCapture(); 771 EXPECT_TRUE(window->HasCapture()); 772 EXPECT_EQ(0, delegate.capture_lost_count()); 773 EXPECT_EQ(0, delegate.capture_changed_event_count()); 774 ui::test::EventGenerator generator(root_window(), gfx::Point(50, 50)); 775 generator.PressLeftButton(); 776 EXPECT_EQ(1, delegate.mouse_event_count()); 777 generator.ReleaseLeftButton(); 778 779 EXPECT_EQ(2, delegate.mouse_event_count()); 780 delegate.ResetCounts(); 781 782 ui::TouchEvent touchev( 783 ui::ET_TOUCH_PRESSED, gfx::Point(50, 50), 0, getTime()); 784 DispatchEventUsingWindowDispatcher(&touchev); 785 EXPECT_EQ(1, delegate.touch_event_count()); 786 delegate.ResetCounts(); 787 788 window->ReleaseCapture(); 789 EXPECT_FALSE(window->HasCapture()); 790 EXPECT_EQ(1, delegate.capture_lost_count()); 791 EXPECT_EQ(1, delegate.capture_changed_event_count()); 792 EXPECT_EQ(1, delegate.mouse_event_count()); 793 EXPECT_EQ(0, delegate.touch_event_count()); 794 795 generator.PressLeftButton(); 796 EXPECT_EQ(1, delegate.mouse_event_count()); 797 798 ui::TouchEvent touchev2( 799 ui::ET_TOUCH_PRESSED, gfx::Point(250, 250), 1, getTime()); 800 DispatchEventUsingWindowDispatcher(&touchev2); 801 EXPECT_EQ(0, delegate.touch_event_count()); 802 803 // Removing the capture window from parent should reset the capture window 804 // in the root window. 805 window->SetCapture(); 806 EXPECT_EQ(window.get(), aura::client::GetCaptureWindow(root_window())); 807 window->parent()->RemoveChild(window.get()); 808 EXPECT_FALSE(window->HasCapture()); 809 EXPECT_EQ(NULL, aura::client::GetCaptureWindow(root_window())); 810 } 811 812 TEST_F(WindowTest, TouchCaptureCancelsOtherTouches) { 813 CaptureWindowDelegateImpl delegate1; 814 scoped_ptr<Window> w1(CreateTestWindowWithDelegate( 815 &delegate1, 0, gfx::Rect(0, 0, 50, 50), root_window())); 816 CaptureWindowDelegateImpl delegate2; 817 scoped_ptr<Window> w2(CreateTestWindowWithDelegate( 818 &delegate2, 0, gfx::Rect(50, 50, 50, 50), root_window())); 819 820 // Press on w1. 821 ui::TouchEvent press1( 822 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime()); 823 DispatchEventUsingWindowDispatcher(&press1); 824 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN. 825 EXPECT_EQ(2, delegate1.gesture_event_count()); 826 delegate1.ResetCounts(); 827 828 // Capturing to w2 should cause the touch to be canceled. 829 w2->SetCapture(); 830 EXPECT_EQ(1, delegate1.touch_event_count()); 831 EXPECT_EQ(0, delegate2.touch_event_count()); 832 delegate1.ResetCounts(); 833 delegate2.ResetCounts(); 834 835 // Events now go to w2. 836 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, getTime()); 837 DispatchEventUsingWindowDispatcher(&move); 838 EXPECT_EQ(0, delegate1.gesture_event_count()); 839 EXPECT_EQ(0, delegate1.touch_event_count()); 840 EXPECT_EQ(0, delegate2.gesture_event_count()); 841 EXPECT_EQ(1, delegate2.touch_event_count()); 842 843 ui::TouchEvent release( 844 ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, getTime()); 845 DispatchEventUsingWindowDispatcher(&release); 846 EXPECT_EQ(0, delegate1.gesture_event_count()); 847 EXPECT_EQ(0, delegate2.gesture_event_count()); 848 849 // A new press is captured by w2. 850 ui::TouchEvent press2( 851 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime()); 852 DispatchEventUsingWindowDispatcher(&press2); 853 EXPECT_EQ(0, delegate1.gesture_event_count()); 854 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN. 855 EXPECT_EQ(2, delegate2.gesture_event_count()); 856 delegate1.ResetCounts(); 857 delegate2.ResetCounts(); 858 859 // And releasing capture changes nothing. 860 w2->ReleaseCapture(); 861 EXPECT_EQ(0, delegate1.gesture_event_count()); 862 EXPECT_EQ(0, delegate1.touch_event_count()); 863 EXPECT_EQ(0, delegate2.gesture_event_count()); 864 EXPECT_EQ(0, delegate2.touch_event_count()); 865 } 866 867 TEST_F(WindowTest, TouchCaptureDoesntCancelCapturedTouches) { 868 CaptureWindowDelegateImpl delegate; 869 scoped_ptr<Window> window(CreateTestWindowWithDelegate( 870 &delegate, 0, gfx::Rect(0, 0, 50, 50), root_window())); 871 base::TimeDelta time = getTime(); 872 const int kTimeDelta = 100; 873 874 ui::TouchEvent press( 875 ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, time); 876 DispatchEventUsingWindowDispatcher(&press); 877 878 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN. 879 EXPECT_EQ(2, delegate.gesture_event_count()); 880 EXPECT_EQ(1, delegate.touch_event_count()); 881 delegate.ResetCounts(); 882 883 window->SetCapture(); 884 EXPECT_EQ(0, delegate.gesture_event_count()); 885 EXPECT_EQ(0, delegate.touch_event_count()); 886 delegate.ResetCounts(); 887 888 // On move We will get TOUCH_MOVED, GESTURE_TAP_CANCEL, 889 // GESTURE_SCROLL_START and GESTURE_SCROLL_UPDATE. 890 time += base::TimeDelta::FromMilliseconds(kTimeDelta); 891 ui::TouchEvent move(ui::ET_TOUCH_MOVED, gfx::Point(10, 20), 0, time); 892 DispatchEventUsingWindowDispatcher(&move); 893 EXPECT_EQ(1, delegate.touch_event_count()); 894 EXPECT_EQ(3, delegate.gesture_event_count()); 895 delegate.ResetCounts(); 896 897 // Release capture shouldn't change anything. 898 window->ReleaseCapture(); 899 EXPECT_EQ(0, delegate.touch_event_count()); 900 EXPECT_EQ(0, delegate.gesture_event_count()); 901 delegate.ResetCounts(); 902 903 // On move we still get TOUCH_MOVED and GESTURE_SCROLL_UPDATE. 904 time += base::TimeDelta::FromMilliseconds(kTimeDelta); 905 ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(10, 30), 0, time); 906 DispatchEventUsingWindowDispatcher(&move2); 907 EXPECT_EQ(1, delegate.touch_event_count()); 908 EXPECT_EQ(1, delegate.gesture_event_count()); 909 delegate.ResetCounts(); 910 911 // And on release we get TOUCH_RELEASED, GESTURE_SCROLL_END, GESTURE_END 912 time += base::TimeDelta::FromMilliseconds(kTimeDelta); 913 ui::TouchEvent release( 914 ui::ET_TOUCH_RELEASED, gfx::Point(10, 20), 0, time); 915 DispatchEventUsingWindowDispatcher(&release); 916 EXPECT_EQ(1, delegate.touch_event_count()); 917 EXPECT_EQ(2, delegate.gesture_event_count()); 918 } 919 920 921 // Assertions around SetCapture() and touch/gestures. 922 TEST_F(WindowTest, TransferCaptureTouchEvents) { 923 // Touch on |w1|. 924 CaptureWindowDelegateImpl d1; 925 scoped_ptr<Window> w1(CreateTestWindowWithDelegate( 926 &d1, 0, gfx::Rect(0, 0, 20, 20), root_window())); 927 ui::TouchEvent p1(ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 0, getTime()); 928 DispatchEventUsingWindowDispatcher(&p1); 929 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN. 930 EXPECT_EQ(1, d1.touch_event_count()); 931 EXPECT_EQ(2, d1.gesture_event_count()); 932 d1.ResetCounts(); 933 934 // Touch on |w2| with a different id. 935 CaptureWindowDelegateImpl d2; 936 scoped_ptr<Window> w2(CreateTestWindowWithDelegate( 937 &d2, 0, gfx::Rect(40, 0, 40, 20), root_window())); 938 ui::TouchEvent p2(ui::ET_TOUCH_PRESSED, gfx::Point(41, 10), 1, getTime()); 939 DispatchEventUsingWindowDispatcher(&p2); 940 EXPECT_EQ(0, d1.touch_event_count()); 941 EXPECT_EQ(0, d1.gesture_event_count()); 942 // We will get both GESTURE_BEGIN and GESTURE_TAP_DOWN for new target window. 943 EXPECT_EQ(1, d2.touch_event_count()); 944 EXPECT_EQ(2, d2.gesture_event_count()); 945 d1.ResetCounts(); 946 d2.ResetCounts(); 947 948 // Set capture on |w2|, this should send a cancel (TAP_CANCEL, END) to |w1| 949 // but not |w2|. 950 w2->SetCapture(); 951 EXPECT_EQ(1, d1.touch_event_count()); 952 EXPECT_EQ(2, d1.gesture_event_count()); 953 EXPECT_EQ(0, d2.touch_event_count()); 954 EXPECT_EQ(0, d2.gesture_event_count()); 955 d1.ResetCounts(); 956 d2.ResetCounts(); 957 958 CaptureWindowDelegateImpl d3; 959 scoped_ptr<Window> w3(CreateTestWindowWithDelegate( 960 &d3, 0, gfx::Rect(0, 0, 100, 101), root_window())); 961 // Set capture on w3. No new events should be received. 962 // Note this difference in behavior between the first and second capture 963 // is confusing and error prone. http://crbug.com/236930 964 w3->SetCapture(); 965 EXPECT_EQ(0, d1.touch_event_count()); 966 EXPECT_EQ(0, d1.gesture_event_count()); 967 EXPECT_EQ(0, d2.touch_event_count()); 968 EXPECT_EQ(0, d2.gesture_event_count()); 969 EXPECT_EQ(0, d3.touch_event_count()); 970 EXPECT_EQ(0, d3.gesture_event_count()); 971 972 // Move touch id originally associated with |w2|. Since capture was transfered 973 // from 2 to 3 only |w3| should get the event. 974 ui::TouchEvent m3(ui::ET_TOUCH_MOVED, gfx::Point(110, 105), 1, getTime()); 975 DispatchEventUsingWindowDispatcher(&m3); 976 EXPECT_EQ(0, d1.touch_event_count()); 977 EXPECT_EQ(0, d1.gesture_event_count()); 978 EXPECT_EQ(0, d2.touch_event_count()); 979 EXPECT_EQ(0, d2.gesture_event_count()); 980 // |w3| gets a TOUCH_MOVE, TAP_CANCEL and two scroll related events. 981 EXPECT_EQ(1, d3.touch_event_count()); 982 EXPECT_EQ(3, d3.gesture_event_count()); 983 d1.ResetCounts(); 984 d2.ResetCounts(); 985 d3.ResetCounts(); 986 987 // When we release capture, no touches are canceled. 988 w3->ReleaseCapture(); 989 EXPECT_EQ(0, d1.touch_event_count()); 990 EXPECT_EQ(0, d1.gesture_event_count()); 991 EXPECT_EQ(0, d2.touch_event_count()); 992 EXPECT_EQ(0, d2.gesture_event_count()); 993 EXPECT_EQ(0, d3.touch_event_count()); 994 EXPECT_EQ(0, d3.gesture_event_count()); 995 996 // And when we move the touch again, |w3| still gets the events. 997 ui::TouchEvent m4(ui::ET_TOUCH_MOVED, gfx::Point(120, 105), 1, getTime()); 998 DispatchEventUsingWindowDispatcher(&m4); 999 EXPECT_EQ(0, d1.touch_event_count()); 1000 EXPECT_EQ(0, d1.gesture_event_count()); 1001 EXPECT_EQ(0, d2.touch_event_count()); 1002 EXPECT_EQ(0, d2.gesture_event_count()); 1003 EXPECT_EQ(1, d3.touch_event_count()); 1004 EXPECT_EQ(1, d3.gesture_event_count()); 1005 d1.ResetCounts(); 1006 d2.ResetCounts(); 1007 d3.ResetCounts(); 1008 } 1009 1010 // Changes capture while capture is already ongoing. 1011 TEST_F(WindowTest, ChangeCaptureWhileMouseDown) { 1012 CaptureWindowDelegateImpl delegate; 1013 scoped_ptr<Window> window(CreateTestWindowWithDelegate( 1014 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window())); 1015 CaptureWindowDelegateImpl delegate2; 1016 scoped_ptr<Window> w2(CreateTestWindowWithDelegate( 1017 &delegate2, 0, gfx::Rect(20, 20, 20, 20), root_window())); 1018 1019 // Execute the scheduled draws so that mouse events are not 1020 // aggregated. 1021 RunAllPendingInMessageLoop(); 1022 1023 EXPECT_FALSE(window->HasCapture()); 1024 1025 // Do a capture. 1026 delegate.ResetCounts(); 1027 window->SetCapture(); 1028 EXPECT_TRUE(window->HasCapture()); 1029 EXPECT_EQ(0, delegate.capture_lost_count()); 1030 EXPECT_EQ(0, delegate.capture_changed_event_count()); 1031 ui::test::EventGenerator generator(root_window(), gfx::Point(50, 50)); 1032 generator.PressLeftButton(); 1033 EXPECT_EQ(0, delegate.capture_lost_count()); 1034 EXPECT_EQ(0, delegate.capture_changed_event_count()); 1035 EXPECT_EQ(1, delegate.mouse_event_count()); 1036 1037 // Set capture to |w2|, should implicitly unset capture for |window|. 1038 delegate.ResetCounts(); 1039 delegate2.ResetCounts(); 1040 w2->SetCapture(); 1041 1042 generator.MoveMouseTo(gfx::Point(40, 40), 2); 1043 EXPECT_EQ(1, delegate.capture_lost_count()); 1044 EXPECT_EQ(1, delegate.capture_changed_event_count()); 1045 EXPECT_EQ(1, delegate.mouse_event_count()); 1046 EXPECT_EQ(2, delegate2.mouse_event_count()); 1047 } 1048 1049 // Verifies capture is reset when a window is destroyed. 1050 TEST_F(WindowTest, ReleaseCaptureOnDestroy) { 1051 CaptureWindowDelegateImpl delegate; 1052 scoped_ptr<Window> window(CreateTestWindowWithDelegate( 1053 &delegate, 0, gfx::Rect(0, 0, 20, 20), root_window())); 1054 EXPECT_FALSE(window->HasCapture()); 1055 1056 // Do a capture. 1057 window->SetCapture(); 1058 EXPECT_TRUE(window->HasCapture()); 1059 1060 // Destroy the window. 1061 window.reset(); 1062 1063 // Make sure the root window doesn't reference the window anymore. 1064 EXPECT_EQ(NULL, host()->dispatcher()->mouse_pressed_handler()); 1065 EXPECT_EQ(NULL, aura::client::GetCaptureWindow(root_window())); 1066 } 1067 1068 TEST_F(WindowTest, GetBoundsInRootWindow) { 1069 scoped_ptr<Window> viewport(CreateTestWindowWithBounds( 1070 gfx::Rect(0, 0, 300, 300), root_window())); 1071 scoped_ptr<Window> child(CreateTestWindowWithBounds( 1072 gfx::Rect(0, 0, 100, 100), viewport.get())); 1073 // Sanity check. 1074 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString()); 1075 1076 // The |child| window's screen bounds should move along with the |viewport|. 1077 viewport->SetBounds(gfx::Rect(-100, -100, 300, 300)); 1078 EXPECT_EQ("-100,-100 100x100", child->GetBoundsInRootWindow().ToString()); 1079 1080 // The |child| window is moved to the 0,0 in screen coordinates. 1081 // |GetBoundsInRootWindow()| should return 0,0. 1082 child->SetBounds(gfx::Rect(100, 100, 100, 100)); 1083 EXPECT_EQ("0,0 100x100", child->GetBoundsInRootWindow().ToString()); 1084 } 1085 1086 class MouseEnterExitWindowDelegate : public TestWindowDelegate { 1087 public: 1088 MouseEnterExitWindowDelegate() : entered_(false), exited_(false) {} 1089 1090 virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE { 1091 switch (event->type()) { 1092 case ui::ET_MOUSE_ENTERED: 1093 EXPECT_TRUE(event->flags() & ui::EF_IS_SYNTHESIZED); 1094 entered_ = true; 1095 break; 1096 case ui::ET_MOUSE_EXITED: 1097 EXPECT_TRUE(event->flags() & ui::EF_IS_SYNTHESIZED); 1098 exited_ = true; 1099 break; 1100 default: 1101 break; 1102 } 1103 } 1104 1105 bool entered() const { return entered_; } 1106 bool exited() const { return exited_; } 1107 1108 // Clear the entered / exited states. 1109 void ResetExpectations() { 1110 entered_ = false; 1111 exited_ = false; 1112 } 1113 1114 private: 1115 bool entered_; 1116 bool exited_; 1117 1118 DISALLOW_COPY_AND_ASSIGN(MouseEnterExitWindowDelegate); 1119 }; 1120 1121 1122 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for 1123 // mouse transitions from window to window. 1124 TEST_F(WindowTest, MouseEnterExit) { 1125 MouseEnterExitWindowDelegate d1; 1126 scoped_ptr<Window> w1( 1127 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50), 1128 root_window())); 1129 MouseEnterExitWindowDelegate d2; 1130 scoped_ptr<Window> w2( 1131 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50), 1132 root_window())); 1133 1134 ui::test::EventGenerator generator(root_window()); 1135 generator.MoveMouseToCenterOf(w1.get()); 1136 EXPECT_TRUE(d1.entered()); 1137 EXPECT_FALSE(d1.exited()); 1138 EXPECT_FALSE(d2.entered()); 1139 EXPECT_FALSE(d2.exited()); 1140 1141 generator.MoveMouseToCenterOf(w2.get()); 1142 EXPECT_TRUE(d1.entered()); 1143 EXPECT_TRUE(d1.exited()); 1144 EXPECT_TRUE(d2.entered()); 1145 EXPECT_FALSE(d2.exited()); 1146 } 1147 1148 // Verifies that the WindowDelegate receives MouseExit from ET_MOUSE_EXITED. 1149 TEST_F(WindowTest, WindowTreeHostExit) { 1150 MouseEnterExitWindowDelegate d1; 1151 scoped_ptr<Window> w1( 1152 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50), 1153 root_window())); 1154 1155 ui::test::EventGenerator generator(root_window()); 1156 generator.MoveMouseToCenterOf(w1.get()); 1157 EXPECT_TRUE(d1.entered()); 1158 EXPECT_FALSE(d1.exited()); 1159 d1.ResetExpectations(); 1160 1161 ui::MouseEvent exit_event( 1162 ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(), 0, 0); 1163 DispatchEventUsingWindowDispatcher(&exit_event); 1164 EXPECT_FALSE(d1.entered()); 1165 EXPECT_TRUE(d1.exited()); 1166 } 1167 1168 // Verifies that the WindowDelegate receives MouseExit and MouseEnter events for 1169 // mouse transitions from window to window, even if the entered window sets 1170 // and releases capture. 1171 TEST_F(WindowTest, MouseEnterExitWithClick) { 1172 MouseEnterExitWindowDelegate d1; 1173 scoped_ptr<Window> w1( 1174 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50), 1175 root_window())); 1176 MouseEnterExitWindowDelegate d2; 1177 scoped_ptr<Window> w2( 1178 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(70, 70, 50, 50), 1179 root_window())); 1180 1181 ui::test::EventGenerator generator(root_window()); 1182 generator.MoveMouseToCenterOf(w1.get()); 1183 EXPECT_TRUE(d1.entered()); 1184 EXPECT_FALSE(d1.exited()); 1185 EXPECT_FALSE(d2.entered()); 1186 EXPECT_FALSE(d2.exited()); 1187 1188 // Emmulate what Views does on a click by grabbing and releasing capture. 1189 generator.PressLeftButton(); 1190 w1->SetCapture(); 1191 w1->ReleaseCapture(); 1192 generator.ReleaseLeftButton(); 1193 1194 generator.MoveMouseToCenterOf(w2.get()); 1195 EXPECT_TRUE(d1.entered()); 1196 EXPECT_TRUE(d1.exited()); 1197 EXPECT_TRUE(d2.entered()); 1198 EXPECT_FALSE(d2.exited()); 1199 } 1200 1201 TEST_F(WindowTest, MouseEnterExitWhenDeleteWithCapture) { 1202 MouseEnterExitWindowDelegate delegate; 1203 scoped_ptr<Window> window( 1204 CreateTestWindowWithDelegate(&delegate, 1, gfx::Rect(10, 10, 50, 50), 1205 root_window())); 1206 1207 ui::test::EventGenerator generator(root_window()); 1208 generator.MoveMouseToCenterOf(window.get()); 1209 EXPECT_TRUE(delegate.entered()); 1210 EXPECT_FALSE(delegate.exited()); 1211 1212 // Emmulate what Views does on a click by grabbing and releasing capture. 1213 generator.PressLeftButton(); 1214 window->SetCapture(); 1215 1216 delegate.ResetExpectations(); 1217 generator.MoveMouseTo(0, 0); 1218 EXPECT_FALSE(delegate.entered()); 1219 EXPECT_FALSE(delegate.exited()); 1220 1221 delegate.ResetExpectations(); 1222 window.reset(); 1223 EXPECT_FALSE(delegate.entered()); 1224 EXPECT_FALSE(delegate.exited()); 1225 } 1226 1227 // Verifies that enter / exits are sent if windows appear and are deleted 1228 // under the current mouse position.. 1229 TEST_F(WindowTest, MouseEnterExitWithDelete) { 1230 MouseEnterExitWindowDelegate d1; 1231 scoped_ptr<Window> w1( 1232 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50), 1233 root_window())); 1234 1235 ui::test::EventGenerator generator(root_window()); 1236 generator.MoveMouseToCenterOf(w1.get()); 1237 EXPECT_TRUE(d1.entered()); 1238 EXPECT_FALSE(d1.exited()); 1239 d1.ResetExpectations(); 1240 1241 MouseEnterExitWindowDelegate d2; 1242 { 1243 scoped_ptr<Window> w2( 1244 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50), 1245 root_window())); 1246 // Enters / exits can be sent asynchronously. 1247 RunAllPendingInMessageLoop(); 1248 EXPECT_FALSE(d1.entered()); 1249 EXPECT_TRUE(d1.exited()); 1250 EXPECT_TRUE(d2.entered()); 1251 EXPECT_FALSE(d2.exited()); 1252 d1.ResetExpectations(); 1253 d2.ResetExpectations(); 1254 } 1255 // Enters / exits can be sent asynchronously. 1256 RunAllPendingInMessageLoop(); 1257 EXPECT_TRUE(d2.exited()); 1258 EXPECT_TRUE(d1.entered()); 1259 } 1260 1261 // Verifies that enter / exits are sent if windows appear and are hidden 1262 // under the current mouse position.. 1263 TEST_F(WindowTest, MouseEnterExitWithHide) { 1264 MouseEnterExitWindowDelegate d1; 1265 scoped_ptr<Window> w1( 1266 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50), 1267 root_window())); 1268 1269 ui::test::EventGenerator generator(root_window()); 1270 generator.MoveMouseToCenterOf(w1.get()); 1271 EXPECT_TRUE(d1.entered()); 1272 EXPECT_FALSE(d1.exited()); 1273 1274 MouseEnterExitWindowDelegate d2; 1275 scoped_ptr<Window> w2( 1276 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50), 1277 root_window())); 1278 // Enters / exits can be send asynchronously. 1279 RunAllPendingInMessageLoop(); 1280 EXPECT_TRUE(d1.entered()); 1281 EXPECT_TRUE(d1.exited()); 1282 EXPECT_TRUE(d2.entered()); 1283 EXPECT_FALSE(d2.exited()); 1284 1285 d1.ResetExpectations(); 1286 w2->Hide(); 1287 // Enters / exits can be send asynchronously. 1288 RunAllPendingInMessageLoop(); 1289 EXPECT_TRUE(d2.exited()); 1290 EXPECT_TRUE(d1.entered()); 1291 } 1292 1293 TEST_F(WindowTest, MouseEnterExitWithParentHide) { 1294 MouseEnterExitWindowDelegate d1; 1295 scoped_ptr<Window> w1( 1296 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50), 1297 root_window())); 1298 MouseEnterExitWindowDelegate d2; 1299 Window* w2 = CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50), 1300 w1.get()); 1301 ui::test::EventGenerator generator(root_window()); 1302 generator.MoveMouseToCenterOf(w2); 1303 // Enters / exits can be send asynchronously. 1304 RunAllPendingInMessageLoop(); 1305 EXPECT_TRUE(d2.entered()); 1306 EXPECT_FALSE(d2.exited()); 1307 1308 d2.ResetExpectations(); 1309 w1->Hide(); 1310 RunAllPendingInMessageLoop(); 1311 EXPECT_FALSE(d2.entered()); 1312 EXPECT_TRUE(d2.exited()); 1313 1314 w1.reset(); 1315 } 1316 1317 TEST_F(WindowTest, MouseEnterExitWithParentDelete) { 1318 MouseEnterExitWindowDelegate d1; 1319 scoped_ptr<Window> w1( 1320 CreateTestWindowWithDelegate(&d1, 1, gfx::Rect(10, 10, 50, 50), 1321 root_window())); 1322 MouseEnterExitWindowDelegate d2; 1323 Window* w2 = CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(10, 10, 50, 50), 1324 w1.get()); 1325 ui::test::EventGenerator generator(root_window()); 1326 generator.MoveMouseToCenterOf(w2); 1327 1328 // Enters / exits can be send asynchronously. 1329 RunAllPendingInMessageLoop(); 1330 EXPECT_TRUE(d2.entered()); 1331 EXPECT_FALSE(d2.exited()); 1332 1333 d2.ResetExpectations(); 1334 w1.reset(); 1335 RunAllPendingInMessageLoop(); 1336 EXPECT_FALSE(d2.entered()); 1337 EXPECT_TRUE(d2.exited()); 1338 } 1339 1340 // Creates a window with a delegate (w111) that can handle events at a lower 1341 // z-index than a window without a delegate (w12). w12 is sized to fill the 1342 // entire bounds of the container. This test verifies that 1343 // GetEventHandlerForPoint() skips w12 even though its bounds contain the event, 1344 // because it has no children that can handle the event and it has no delegate 1345 // allowing it to handle the event itself. 1346 TEST_F(WindowTest, GetEventHandlerForPoint_NoDelegate) { 1347 TestWindowDelegate d111; 1348 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(NULL, 1, 1349 gfx::Rect(0, 0, 500, 500), root_window())); 1350 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(NULL, 11, 1351 gfx::Rect(0, 0, 500, 500), w1.get())); 1352 scoped_ptr<Window> w111(CreateTestWindowWithDelegate(&d111, 111, 1353 gfx::Rect(50, 50, 450, 450), w11.get())); 1354 scoped_ptr<Window> w12(CreateTestWindowWithDelegate(NULL, 12, 1355 gfx::Rect(0, 0, 500, 500), w1.get())); 1356 1357 gfx::Point target_point = w111->bounds().CenterPoint(); 1358 EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(target_point)); 1359 } 1360 1361 class VisibilityWindowDelegate : public TestWindowDelegate { 1362 public: 1363 VisibilityWindowDelegate() 1364 : shown_(0), 1365 hidden_(0) { 1366 } 1367 1368 int shown() const { return shown_; } 1369 int hidden() const { return hidden_; } 1370 void Clear() { 1371 shown_ = 0; 1372 hidden_ = 0; 1373 } 1374 1375 virtual void OnWindowTargetVisibilityChanged(bool visible) OVERRIDE { 1376 if (visible) 1377 shown_++; 1378 else 1379 hidden_++; 1380 } 1381 1382 private: 1383 int shown_; 1384 int hidden_; 1385 1386 DISALLOW_COPY_AND_ASSIGN(VisibilityWindowDelegate); 1387 }; 1388 1389 // Verifies show/hide propagate correctly to children and the layer. 1390 TEST_F(WindowTest, Visibility) { 1391 VisibilityWindowDelegate d; 1392 VisibilityWindowDelegate d2; 1393 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(&d, 1, gfx::Rect(), 1394 root_window())); 1395 scoped_ptr<Window> w2( 1396 CreateTestWindowWithDelegate(&d2, 2, gfx::Rect(), w1.get())); 1397 scoped_ptr<Window> w3(CreateTestWindowWithId(3, w2.get())); 1398 1399 // Create shows all the windows. 1400 EXPECT_TRUE(w1->IsVisible()); 1401 EXPECT_TRUE(w2->IsVisible()); 1402 EXPECT_TRUE(w3->IsVisible()); 1403 EXPECT_EQ(1, d.shown()); 1404 1405 d.Clear(); 1406 w1->Hide(); 1407 EXPECT_FALSE(w1->IsVisible()); 1408 EXPECT_FALSE(w2->IsVisible()); 1409 EXPECT_FALSE(w3->IsVisible()); 1410 EXPECT_EQ(1, d.hidden()); 1411 EXPECT_EQ(0, d.shown()); 1412 1413 w2->Show(); 1414 EXPECT_FALSE(w1->IsVisible()); 1415 EXPECT_FALSE(w2->IsVisible()); 1416 EXPECT_FALSE(w3->IsVisible()); 1417 1418 w3->Hide(); 1419 EXPECT_FALSE(w1->IsVisible()); 1420 EXPECT_FALSE(w2->IsVisible()); 1421 EXPECT_FALSE(w3->IsVisible()); 1422 1423 d.Clear(); 1424 w1->Show(); 1425 EXPECT_TRUE(w1->IsVisible()); 1426 EXPECT_TRUE(w2->IsVisible()); 1427 EXPECT_FALSE(w3->IsVisible()); 1428 EXPECT_EQ(0, d.hidden()); 1429 EXPECT_EQ(1, d.shown()); 1430 1431 w3->Show(); 1432 EXPECT_TRUE(w1->IsVisible()); 1433 EXPECT_TRUE(w2->IsVisible()); 1434 EXPECT_TRUE(w3->IsVisible()); 1435 1436 // Verify that if an ancestor isn't visible and we change the visibility of a 1437 // child window that OnChildWindowVisibilityChanged() is still invoked. 1438 w1->Hide(); 1439 d2.Clear(); 1440 w2->Hide(); 1441 EXPECT_EQ(1, d2.hidden()); 1442 EXPECT_EQ(0, d2.shown()); 1443 d2.Clear(); 1444 w2->Show(); 1445 EXPECT_EQ(0, d2.hidden()); 1446 EXPECT_EQ(1, d2.shown()); 1447 } 1448 1449 TEST_F(WindowTest, IgnoreEventsTest) { 1450 TestWindowDelegate d11; 1451 TestWindowDelegate d12; 1452 TestWindowDelegate d111; 1453 TestWindowDelegate d121; 1454 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(NULL, 1, 1455 gfx::Rect(0, 0, 500, 500), root_window())); 1456 scoped_ptr<Window> w11(CreateTestWindowWithDelegate(&d11, 11, 1457 gfx::Rect(0, 0, 500, 500), w1.get())); 1458 scoped_ptr<Window> w111(CreateTestWindowWithDelegate(&d111, 111, 1459 gfx::Rect(50, 50, 450, 450), w11.get())); 1460 scoped_ptr<Window> w12(CreateTestWindowWithDelegate(&d12, 12, 1461 gfx::Rect(0, 0, 500, 500), w1.get())); 1462 scoped_ptr<Window> w121(CreateTestWindowWithDelegate(&d121, 121, 1463 gfx::Rect(150, 150, 50, 50), w12.get())); 1464 1465 EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10))); 1466 w12->set_ignore_events(true); 1467 EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10))); 1468 w12->set_ignore_events(false); 1469 1470 EXPECT_EQ(w121.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160))); 1471 w121->set_ignore_events(true); 1472 EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160))); 1473 w12->set_ignore_events(true); 1474 EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160))); 1475 w111->set_ignore_events(true); 1476 EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160))); 1477 } 1478 1479 // Tests transformation on the root window. 1480 TEST_F(WindowTest, Transform) { 1481 gfx::Size size = host()->GetBounds().size(); 1482 EXPECT_EQ(gfx::Rect(size), 1483 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint( 1484 gfx::Point()).bounds()); 1485 1486 // Rotate it clock-wise 90 degrees. 1487 gfx::Transform transform; 1488 transform.Translate(size.height(), 0); 1489 transform.Rotate(90.0); 1490 host()->SetRootTransform(transform); 1491 1492 // The size should be the transformed size. 1493 gfx::Size transformed_size(size.height(), size.width()); 1494 EXPECT_EQ(transformed_size.ToString(), 1495 root_window()->bounds().size().ToString()); 1496 EXPECT_EQ( 1497 gfx::Rect(transformed_size).ToString(), 1498 gfx::Screen::GetScreenFor(root_window())->GetDisplayNearestPoint( 1499 gfx::Point()).bounds().ToString()); 1500 1501 // Host size shouldn't change. 1502 EXPECT_EQ(size.ToString(), host()->GetBounds().size().ToString()); 1503 } 1504 1505 TEST_F(WindowTest, TransformGesture) { 1506 gfx::Size size = host()->GetBounds().size(); 1507 1508 scoped_ptr<GestureTrackPositionDelegate> delegate( 1509 new GestureTrackPositionDelegate); 1510 scoped_ptr<Window> window(CreateTestWindowWithDelegate(delegate.get(), -1234, 1511 gfx::Rect(0, 0, 20, 20), root_window())); 1512 1513 // Rotate the root-window clock-wise 90 degrees. 1514 gfx::Transform transform; 1515 transform.Translate(size.height(), 0.0); 1516 transform.Rotate(90.0); 1517 host()->SetRootTransform(transform); 1518 1519 ui::TouchEvent press( 1520 ui::ET_TOUCH_PRESSED, gfx::Point(size.height() - 10, 10), 0, getTime()); 1521 DispatchEventUsingWindowDispatcher(&press); 1522 EXPECT_EQ(gfx::Point(10, 10).ToString(), delegate->position().ToString()); 1523 } 1524 1525 namespace { 1526 DEFINE_WINDOW_PROPERTY_KEY(int, kIntKey, -2); 1527 DEFINE_WINDOW_PROPERTY_KEY(const char*, kStringKey, "squeamish"); 1528 } 1529 1530 TEST_F(WindowTest, Property) { 1531 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window())); 1532 1533 static const char native_prop_key[] = "fnord"; 1534 1535 // Non-existent properties should return the default values. 1536 EXPECT_EQ(-2, w->GetProperty(kIntKey)); 1537 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey)); 1538 EXPECT_EQ(NULL, w->GetNativeWindowProperty(native_prop_key)); 1539 1540 // A set property value should be returned again (even if it's the default 1541 // value). 1542 w->SetProperty(kIntKey, INT_MAX); 1543 EXPECT_EQ(INT_MAX, w->GetProperty(kIntKey)); 1544 w->SetProperty(kIntKey, -2); 1545 EXPECT_EQ(-2, w->GetProperty(kIntKey)); 1546 w->SetProperty(kIntKey, INT_MIN); 1547 EXPECT_EQ(INT_MIN, w->GetProperty(kIntKey)); 1548 1549 w->SetProperty(kStringKey, static_cast<const char*>(NULL)); 1550 EXPECT_EQ(NULL, w->GetProperty(kStringKey)); 1551 w->SetProperty(kStringKey, "squeamish"); 1552 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey)); 1553 w->SetProperty(kStringKey, "ossifrage"); 1554 EXPECT_EQ(std::string("ossifrage"), w->GetProperty(kStringKey)); 1555 1556 w->SetNativeWindowProperty(native_prop_key, &*w); 1557 EXPECT_EQ(&*w, w->GetNativeWindowProperty(native_prop_key)); 1558 w->SetNativeWindowProperty(native_prop_key, NULL); 1559 EXPECT_EQ(NULL, w->GetNativeWindowProperty(native_prop_key)); 1560 1561 // ClearProperty should restore the default value. 1562 w->ClearProperty(kIntKey); 1563 EXPECT_EQ(-2, w->GetProperty(kIntKey)); 1564 w->ClearProperty(kStringKey); 1565 EXPECT_EQ(std::string("squeamish"), w->GetProperty(kStringKey)); 1566 } 1567 1568 namespace { 1569 1570 class TestProperty { 1571 public: 1572 TestProperty() {} 1573 virtual ~TestProperty() { 1574 last_deleted_ = this; 1575 } 1576 static TestProperty* last_deleted() { return last_deleted_; } 1577 1578 private: 1579 static TestProperty* last_deleted_; 1580 DISALLOW_COPY_AND_ASSIGN(TestProperty); 1581 }; 1582 1583 TestProperty* TestProperty::last_deleted_ = NULL; 1584 1585 DEFINE_OWNED_WINDOW_PROPERTY_KEY(TestProperty, kOwnedKey, NULL); 1586 1587 } // namespace 1588 1589 TEST_F(WindowTest, OwnedProperty) { 1590 scoped_ptr<Window> w(CreateTestWindowWithId(0, root_window())); 1591 EXPECT_EQ(NULL, w->GetProperty(kOwnedKey)); 1592 TestProperty* p1 = new TestProperty(); 1593 w->SetProperty(kOwnedKey, p1); 1594 EXPECT_EQ(p1, w->GetProperty(kOwnedKey)); 1595 EXPECT_EQ(NULL, TestProperty::last_deleted()); 1596 1597 TestProperty* p2 = new TestProperty(); 1598 w->SetProperty(kOwnedKey, p2); 1599 EXPECT_EQ(p2, w->GetProperty(kOwnedKey)); 1600 EXPECT_EQ(p1, TestProperty::last_deleted()); 1601 1602 w->ClearProperty(kOwnedKey); 1603 EXPECT_EQ(NULL, w->GetProperty(kOwnedKey)); 1604 EXPECT_EQ(p2, TestProperty::last_deleted()); 1605 1606 TestProperty* p3 = new TestProperty(); 1607 w->SetProperty(kOwnedKey, p3); 1608 EXPECT_EQ(p3, w->GetProperty(kOwnedKey)); 1609 EXPECT_EQ(p2, TestProperty::last_deleted()); 1610 w.reset(); 1611 EXPECT_EQ(p3, TestProperty::last_deleted()); 1612 } 1613 1614 TEST_F(WindowTest, SetBoundsInternalShouldCheckTargetBounds) { 1615 // We cannot short-circuit animations in this test. 1616 ui::ScopedAnimationDurationScaleMode test_duration_mode( 1617 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); 1618 1619 scoped_ptr<Window> w1( 1620 CreateTestWindowWithBounds(gfx::Rect(0, 0, 100, 100), root_window())); 1621 1622 EXPECT_FALSE(!w1->layer()); 1623 w1->layer()->GetAnimator()->set_disable_timer_for_test(true); 1624 ui::LayerAnimator* animator = w1->layer()->GetAnimator(); 1625 1626 EXPECT_EQ("0,0 100x100", w1->bounds().ToString()); 1627 EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString()); 1628 1629 // Animate to a different position. 1630 { 1631 ui::ScopedLayerAnimationSettings settings(w1->layer()->GetAnimator()); 1632 w1->SetBounds(gfx::Rect(100, 100, 100, 100)); 1633 } 1634 1635 EXPECT_EQ("0,0 100x100", w1->bounds().ToString()); 1636 EXPECT_EQ("100,100 100x100", w1->layer()->GetTargetBounds().ToString()); 1637 1638 // Animate back to the first position. The animation hasn't started yet, so 1639 // the current bounds are still (0, 0, 100, 100), but the target bounds are 1640 // (100, 100, 100, 100). If we step the animator ahead, we should find that 1641 // we're at (0, 0, 100, 100). That is, the second animation should be applied. 1642 { 1643 ui::ScopedLayerAnimationSettings settings(w1->layer()->GetAnimator()); 1644 w1->SetBounds(gfx::Rect(0, 0, 100, 100)); 1645 } 1646 1647 EXPECT_EQ("0,0 100x100", w1->bounds().ToString()); 1648 EXPECT_EQ("0,0 100x100", w1->layer()->GetTargetBounds().ToString()); 1649 1650 // Confirm that the target bounds are reached. 1651 base::TimeTicks start_time = 1652 w1->layer()->GetAnimator()->last_step_time(); 1653 1654 animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); 1655 1656 EXPECT_EQ("0,0 100x100", w1->bounds().ToString()); 1657 } 1658 1659 1660 typedef std::pair<const void*, intptr_t> PropertyChangeInfo; 1661 1662 class WindowObserverTest : public WindowTest, 1663 public WindowObserver { 1664 public: 1665 struct VisibilityInfo { 1666 bool window_visible; 1667 bool visible_param; 1668 }; 1669 1670 WindowObserverTest() 1671 : added_count_(0), 1672 removed_count_(0), 1673 destroyed_count_(0), 1674 old_property_value_(-3) { 1675 } 1676 1677 virtual ~WindowObserverTest() {} 1678 1679 const VisibilityInfo* GetVisibilityInfo() const { 1680 return visibility_info_.get(); 1681 } 1682 1683 void ResetVisibilityInfo() { 1684 visibility_info_.reset(); 1685 } 1686 1687 // Returns a description of the WindowObserver methods that have been invoked. 1688 std::string WindowObserverCountStateAndClear() { 1689 std::string result( 1690 base::StringPrintf("added=%d removed=%d", 1691 added_count_, removed_count_)); 1692 added_count_ = removed_count_ = 0; 1693 return result; 1694 } 1695 1696 int DestroyedCountAndClear() { 1697 int result = destroyed_count_; 1698 destroyed_count_ = 0; 1699 return result; 1700 } 1701 1702 // Return a tuple of the arguments passed in OnPropertyChanged callback. 1703 PropertyChangeInfo PropertyChangeInfoAndClear() { 1704 PropertyChangeInfo result(property_key_, old_property_value_); 1705 property_key_ = NULL; 1706 old_property_value_ = -3; 1707 return result; 1708 } 1709 1710 std::string TransformNotificationsAndClear() { 1711 std::string result; 1712 for (std::vector<std::pair<int, int> >::iterator it = 1713 transform_notifications_.begin(); 1714 it != transform_notifications_.end(); 1715 ++it) { 1716 base::StringAppendF(&result, "(%d,%d)", it->first, it->second); 1717 } 1718 transform_notifications_.clear(); 1719 return result; 1720 } 1721 1722 private: 1723 virtual void OnWindowAdded(Window* new_window) OVERRIDE { 1724 added_count_++; 1725 } 1726 1727 virtual void OnWillRemoveWindow(Window* window) OVERRIDE { 1728 removed_count_++; 1729 } 1730 1731 virtual void OnWindowVisibilityChanged(Window* window, 1732 bool visible) OVERRIDE { 1733 visibility_info_.reset(new VisibilityInfo); 1734 visibility_info_->window_visible = window->IsVisible(); 1735 visibility_info_->visible_param = visible; 1736 } 1737 1738 virtual void OnWindowDestroyed(Window* window) OVERRIDE { 1739 EXPECT_FALSE(window->parent()); 1740 destroyed_count_++; 1741 } 1742 1743 virtual void OnWindowPropertyChanged(Window* window, 1744 const void* key, 1745 intptr_t old) OVERRIDE { 1746 property_key_ = key; 1747 old_property_value_ = old; 1748 } 1749 1750 virtual void OnAncestorWindowTransformed(Window* source, 1751 Window* window) OVERRIDE { 1752 transform_notifications_.push_back( 1753 std::make_pair(source->id(), window->id())); 1754 } 1755 1756 int added_count_; 1757 int removed_count_; 1758 int destroyed_count_; 1759 scoped_ptr<VisibilityInfo> visibility_info_; 1760 const void* property_key_; 1761 intptr_t old_property_value_; 1762 std::vector<std::pair<int, int> > transform_notifications_; 1763 1764 DISALLOW_COPY_AND_ASSIGN(WindowObserverTest); 1765 }; 1766 1767 // Various assertions for WindowObserver. 1768 TEST_F(WindowObserverTest, WindowObserver) { 1769 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window())); 1770 w1->AddObserver(this); 1771 1772 // Create a new window as a child of w1, our observer should be notified. 1773 scoped_ptr<Window> w2(CreateTestWindowWithId(2, w1.get())); 1774 EXPECT_EQ("added=1 removed=0", WindowObserverCountStateAndClear()); 1775 1776 // Delete w2, which should result in the remove notification. 1777 w2.reset(); 1778 EXPECT_EQ("added=0 removed=1", WindowObserverCountStateAndClear()); 1779 1780 // Create a window that isn't parented to w1, we shouldn't get any 1781 // notification. 1782 scoped_ptr<Window> w3(CreateTestWindowWithId(3, root_window())); 1783 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear()); 1784 1785 // Similarly destroying w3 shouldn't notify us either. 1786 w3.reset(); 1787 EXPECT_EQ("added=0 removed=0", WindowObserverCountStateAndClear()); 1788 w1->RemoveObserver(this); 1789 } 1790 1791 // Test if OnWindowVisibilityChagned is invoked with expected 1792 // parameters. 1793 TEST_F(WindowObserverTest, WindowVisibility) { 1794 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window())); 1795 scoped_ptr<Window> w2(CreateTestWindowWithId(1, w1.get())); 1796 w2->AddObserver(this); 1797 1798 // Hide should make the window invisible and the passed visible 1799 // parameter is false. 1800 w2->Hide(); 1801 EXPECT_FALSE(!GetVisibilityInfo()); 1802 EXPECT_FALSE(!GetVisibilityInfo()); 1803 if (!GetVisibilityInfo()) 1804 return; 1805 EXPECT_FALSE(GetVisibilityInfo()->window_visible); 1806 EXPECT_FALSE(GetVisibilityInfo()->visible_param); 1807 1808 // If parent isn't visible, showing window won't make the window visible, but 1809 // passed visible value must be true. 1810 w1->Hide(); 1811 ResetVisibilityInfo(); 1812 EXPECT_TRUE(!GetVisibilityInfo()); 1813 w2->Show(); 1814 EXPECT_FALSE(!GetVisibilityInfo()); 1815 if (!GetVisibilityInfo()) 1816 return; 1817 EXPECT_FALSE(GetVisibilityInfo()->window_visible); 1818 EXPECT_TRUE(GetVisibilityInfo()->visible_param); 1819 1820 // If parent is visible, showing window will make the window 1821 // visible and the passed visible value is true. 1822 w1->Show(); 1823 w2->Hide(); 1824 ResetVisibilityInfo(); 1825 w2->Show(); 1826 EXPECT_FALSE(!GetVisibilityInfo()); 1827 if (!GetVisibilityInfo()) 1828 return; 1829 EXPECT_TRUE(GetVisibilityInfo()->window_visible); 1830 EXPECT_TRUE(GetVisibilityInfo()->visible_param); 1831 } 1832 1833 // Test if OnWindowDestroyed is invoked as expected. 1834 TEST_F(WindowObserverTest, WindowDestroyed) { 1835 // Delete a window should fire a destroyed notification. 1836 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window())); 1837 w1->AddObserver(this); 1838 w1.reset(); 1839 EXPECT_EQ(1, DestroyedCountAndClear()); 1840 1841 // Observe on child and delete parent window should fire a notification. 1842 scoped_ptr<Window> parent(CreateTestWindowWithId(1, root_window())); 1843 Window* child = CreateTestWindowWithId(1, parent.get()); // owned by parent 1844 child->AddObserver(this); 1845 parent.reset(); 1846 EXPECT_EQ(1, DestroyedCountAndClear()); 1847 } 1848 1849 TEST_F(WindowObserverTest, PropertyChanged) { 1850 // Setting property should fire a property change notification. 1851 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window())); 1852 w1->AddObserver(this); 1853 1854 static const WindowProperty<int> prop = {-2}; 1855 static const char native_prop_key[] = "fnord"; 1856 1857 w1->SetProperty(&prop, 1); 1858 EXPECT_EQ(PropertyChangeInfo(&prop, -2), PropertyChangeInfoAndClear()); 1859 w1->SetProperty(&prop, -2); 1860 EXPECT_EQ(PropertyChangeInfo(&prop, 1), PropertyChangeInfoAndClear()); 1861 w1->SetProperty(&prop, 3); 1862 EXPECT_EQ(PropertyChangeInfo(&prop, -2), PropertyChangeInfoAndClear()); 1863 w1->ClearProperty(&prop); 1864 EXPECT_EQ(PropertyChangeInfo(&prop, 3), PropertyChangeInfoAndClear()); 1865 1866 w1->SetNativeWindowProperty(native_prop_key, &*w1); 1867 EXPECT_EQ(PropertyChangeInfo(native_prop_key, 0), 1868 PropertyChangeInfoAndClear()); 1869 w1->SetNativeWindowProperty(native_prop_key, NULL); 1870 EXPECT_EQ(PropertyChangeInfo(native_prop_key, 1871 reinterpret_cast<intptr_t>(&*w1)), 1872 PropertyChangeInfoAndClear()); 1873 1874 // Sanity check to see if |PropertyChangeInfoAndClear| really clears. 1875 EXPECT_EQ(PropertyChangeInfo( 1876 reinterpret_cast<const void*>(NULL), -3), PropertyChangeInfoAndClear()); 1877 } 1878 1879 TEST_F(WindowObserverTest, AncestorTransformed) { 1880 // Create following window hierarchy: 1881 // root_window 1882 // +-- w1 1883 // +-- w2 1884 // +-- w3 1885 // +-- w4 1886 // Then, apply a transform to |w1| and ensure all its descendants are 1887 // notified. 1888 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window())); 1889 w1->AddObserver(this); 1890 scoped_ptr<Window> w2(CreateTestWindowWithId(2, w1.get())); 1891 w2->AddObserver(this); 1892 scoped_ptr<Window> w3(CreateTestWindowWithId(3, w1.get())); 1893 w3->AddObserver(this); 1894 scoped_ptr<Window> w4(CreateTestWindowWithId(4, w3.get())); 1895 w4->AddObserver(this); 1896 1897 EXPECT_EQ(std::string(), TransformNotificationsAndClear()); 1898 1899 gfx::Transform transform; 1900 transform.Translate(10, 10); 1901 w1->SetTransform(transform); 1902 1903 EXPECT_EQ("(1,1)(1,2)(1,3)(1,4)", TransformNotificationsAndClear()); 1904 } 1905 1906 TEST_F(WindowTest, AcquireLayer) { 1907 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window())); 1908 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window())); 1909 ui::Layer* parent = window1->parent()->layer(); 1910 EXPECT_EQ(2U, parent->children().size()); 1911 1912 WindowTestApi window1_test_api(window1.get()); 1913 WindowTestApi window2_test_api(window2.get()); 1914 1915 EXPECT_TRUE(window1_test_api.OwnsLayer()); 1916 EXPECT_TRUE(window2_test_api.OwnsLayer()); 1917 1918 // After acquisition, window1 should not own its layer, but it should still 1919 // be available to the window. 1920 scoped_ptr<ui::Layer> window1_layer(window1->AcquireLayer()); 1921 EXPECT_FALSE(window1_test_api.OwnsLayer()); 1922 EXPECT_TRUE(window1_layer.get() == window1->layer()); 1923 1924 // The acquired layer's owner should be set NULL and re-acquring 1925 // should return NULL. 1926 EXPECT_FALSE(window1_layer->owner()); 1927 scoped_ptr<ui::Layer> window1_layer_reacquired(window1->AcquireLayer()); 1928 EXPECT_FALSE(window1_layer_reacquired.get()); 1929 1930 // Upon destruction, window1's layer should still be valid, and in the layer 1931 // hierarchy, but window2's should be gone, and no longer in the hierarchy. 1932 window1.reset(); 1933 window2.reset(); 1934 1935 // This should be set by the window's destructor. 1936 EXPECT_TRUE(window1_layer->delegate() == NULL); 1937 EXPECT_EQ(1U, parent->children().size()); 1938 } 1939 1940 // Make sure that properties which should persist from the old layer to the new 1941 // layer actually do. 1942 TEST_F(WindowTest, RecreateLayer) { 1943 // Set properties to non default values. 1944 Window w(new ColorTestWindowDelegate(SK_ColorWHITE)); 1945 w.set_id(1); 1946 w.Init(aura::WINDOW_LAYER_SOLID_COLOR); 1947 w.SetBounds(gfx::Rect(0, 0, 100, 100)); 1948 1949 ui::Layer* layer = w.layer(); 1950 layer->SetVisible(false); 1951 layer->SetMasksToBounds(true); 1952 1953 ui::Layer child_layer; 1954 layer->Add(&child_layer); 1955 1956 scoped_ptr<ui::Layer> old_layer(w.RecreateLayer()); 1957 layer = w.layer(); 1958 EXPECT_EQ(ui::LAYER_SOLID_COLOR, layer->type()); 1959 EXPECT_FALSE(layer->visible()); 1960 EXPECT_EQ(1u, layer->children().size()); 1961 EXPECT_TRUE(layer->GetMasksToBounds()); 1962 EXPECT_EQ("0,0 100x100", w.bounds().ToString()); 1963 EXPECT_EQ("0,0 100x100", layer->bounds().ToString()); 1964 } 1965 1966 // Verify that RecreateLayer() stacks the old layer above the newly creatd 1967 // layer. 1968 TEST_F(WindowTest, RecreateLayerZOrder) { 1969 scoped_ptr<Window> w( 1970 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(0, 0, 100, 100), 1971 root_window())); 1972 scoped_ptr<ui::Layer> old_layer(w->RecreateLayer()); 1973 1974 const std::vector<ui::Layer*>& child_layers = 1975 root_window()->layer()->children(); 1976 ASSERT_EQ(2u, child_layers.size()); 1977 EXPECT_EQ(w->layer(), child_layers[0]); 1978 EXPECT_EQ(old_layer.get(), child_layers[1]); 1979 } 1980 1981 // Ensure that acquiring a layer then recreating a layer does not crash 1982 // and that RecreateLayer returns null. 1983 TEST_F(WindowTest, AcquireThenRecreateLayer) { 1984 scoped_ptr<Window> w( 1985 CreateTestWindow(SK_ColorWHITE, 1, gfx::Rect(0, 0, 100, 100), 1986 root_window())); 1987 scoped_ptr<ui::Layer> acquired_layer(w->AcquireLayer()); 1988 scoped_ptr<ui::Layer> doubly_acquired_layer(w->RecreateLayer()); 1989 EXPECT_EQ(NULL, doubly_acquired_layer.get()); 1990 1991 // Destroy window before layer gets destroyed. 1992 w.reset(); 1993 } 1994 1995 TEST_F(WindowTest, StackWindowAtBottomBelowWindowWhoseLayerHasNoDelegate) { 1996 scoped_ptr<Window> window1(CreateTestWindowWithId(1, root_window())); 1997 window1->layer()->set_name("1"); 1998 scoped_ptr<Window> window2(CreateTestWindowWithId(2, root_window())); 1999 window2->layer()->set_name("2"); 2000 scoped_ptr<Window> window3(CreateTestWindowWithId(3, root_window())); 2001 window3->layer()->set_name("3"); 2002 2003 EXPECT_EQ("1 2 3", ChildWindowIDsAsString(root_window())); 2004 EXPECT_EQ("1 2 3", 2005 ui::test::ChildLayerNamesAsString(*root_window()->layer())); 2006 window1->layer()->set_delegate(NULL); 2007 root_window()->StackChildAtBottom(window3.get()); 2008 2009 // Window 3 should have moved to the bottom. 2010 EXPECT_EQ("3 1 2", ChildWindowIDsAsString(root_window())); 2011 EXPECT_EQ("3 1 2", 2012 ui::test::ChildLayerNamesAsString(*root_window()->layer())); 2013 } 2014 2015 class TestVisibilityClient : public client::VisibilityClient { 2016 public: 2017 explicit TestVisibilityClient(Window* root_window) 2018 : ignore_visibility_changes_(false) { 2019 client::SetVisibilityClient(root_window, this); 2020 } 2021 virtual ~TestVisibilityClient() { 2022 } 2023 2024 void set_ignore_visibility_changes(bool ignore_visibility_changes) { 2025 ignore_visibility_changes_ = ignore_visibility_changes; 2026 } 2027 2028 // Overridden from client::VisibilityClient: 2029 virtual void UpdateLayerVisibility(aura::Window* window, 2030 bool visible) OVERRIDE { 2031 if (!ignore_visibility_changes_) 2032 window->layer()->SetVisible(visible); 2033 } 2034 2035 private: 2036 bool ignore_visibility_changes_; 2037 DISALLOW_COPY_AND_ASSIGN(TestVisibilityClient); 2038 }; 2039 2040 TEST_F(WindowTest, VisibilityClientIsVisible) { 2041 TestVisibilityClient client(root_window()); 2042 2043 scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window())); 2044 EXPECT_TRUE(window->IsVisible()); 2045 EXPECT_TRUE(window->layer()->visible()); 2046 2047 window->Hide(); 2048 EXPECT_FALSE(window->IsVisible()); 2049 EXPECT_FALSE(window->layer()->visible()); 2050 window->Show(); 2051 2052 client.set_ignore_visibility_changes(true); 2053 window->Hide(); 2054 EXPECT_FALSE(window->IsVisible()); 2055 EXPECT_TRUE(window->layer()->visible()); 2056 } 2057 2058 // Tests mouse events on window change. 2059 TEST_F(WindowTest, MouseEventsOnWindowChange) { 2060 gfx::Size size = host()->GetBounds().size(); 2061 2062 ui::test::EventGenerator generator(root_window()); 2063 generator.MoveMouseTo(50, 50); 2064 2065 EventCountDelegate d1; 2066 scoped_ptr<Window> w1(CreateTestWindowWithDelegate(&d1, 1, 2067 gfx::Rect(0, 0, 100, 100), root_window())); 2068 RunAllPendingInMessageLoop(); 2069 // The format of result is "Enter/Mouse/Leave". 2070 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset()); 2071 2072 // Adding new window. 2073 EventCountDelegate d11; 2074 scoped_ptr<Window> w11(CreateTestWindowWithDelegate( 2075 &d11, 1, gfx::Rect(0, 0, 100, 100), w1.get())); 2076 RunAllPendingInMessageLoop(); 2077 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset()); 2078 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset()); 2079 2080 // Move bounds. 2081 w11->SetBounds(gfx::Rect(0, 0, 10, 10)); 2082 RunAllPendingInMessageLoop(); 2083 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset()); 2084 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset()); 2085 2086 w11->SetBounds(gfx::Rect(0, 0, 60, 60)); 2087 RunAllPendingInMessageLoop(); 2088 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset()); 2089 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset()); 2090 2091 // Detach, then re-attach. 2092 w1->RemoveChild(w11.get()); 2093 RunAllPendingInMessageLoop(); 2094 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset()); 2095 // Window is detached, so no event is set. 2096 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset()); 2097 2098 w1->AddChild(w11.get()); 2099 RunAllPendingInMessageLoop(); 2100 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset()); 2101 // Window is detached, so no event is set. 2102 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset()); 2103 2104 // Visibility Change 2105 w11->Hide(); 2106 RunAllPendingInMessageLoop(); 2107 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset()); 2108 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset()); 2109 2110 w11->Show(); 2111 RunAllPendingInMessageLoop(); 2112 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset()); 2113 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset()); 2114 2115 // Transform: move d11 by 100 100. 2116 gfx::Transform transform; 2117 transform.Translate(100, 100); 2118 w11->SetTransform(transform); 2119 RunAllPendingInMessageLoop(); 2120 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset()); 2121 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset()); 2122 2123 w11->SetTransform(gfx::Transform()); 2124 RunAllPendingInMessageLoop(); 2125 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset()); 2126 EXPECT_EQ("1 1 0", d11.GetMouseMotionCountsAndReset()); 2127 2128 // Closing a window. 2129 w11.reset(); 2130 RunAllPendingInMessageLoop(); 2131 EXPECT_EQ("1 1 0", d1.GetMouseMotionCountsAndReset()); 2132 2133 // Make sure we don't synthesize events if the mouse 2134 // is outside of the root window. 2135 generator.MoveMouseTo(-10, -10); 2136 EXPECT_EQ("0 0 1", d1.GetMouseMotionCountsAndReset()); 2137 2138 // Adding new windows. 2139 w11.reset(CreateTestWindowWithDelegate( 2140 &d11, 1, gfx::Rect(0, 0, 100, 100), w1.get())); 2141 RunAllPendingInMessageLoop(); 2142 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset()); 2143 EXPECT_EQ("0 0 1", d11.GetMouseMotionCountsAndReset()); 2144 2145 // Closing windows 2146 w11.reset(); 2147 RunAllPendingInMessageLoop(); 2148 EXPECT_EQ("0 0 0", d1.GetMouseMotionCountsAndReset()); 2149 EXPECT_EQ("0 0 0", d11.GetMouseMotionCountsAndReset()); 2150 } 2151 2152 class RootWindowAttachmentObserver : public WindowObserver { 2153 public: 2154 RootWindowAttachmentObserver() : added_count_(0), removed_count_(0) {} 2155 virtual ~RootWindowAttachmentObserver() {} 2156 2157 int added_count() const { return added_count_; } 2158 int removed_count() const { return removed_count_; } 2159 2160 void Clear() { 2161 added_count_ = 0; 2162 removed_count_ = 0; 2163 } 2164 2165 // Overridden from WindowObserver: 2166 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE { 2167 ++added_count_; 2168 } 2169 virtual void OnWindowRemovingFromRootWindow(Window* window, 2170 Window* new_root) OVERRIDE { 2171 ++removed_count_; 2172 } 2173 2174 private: 2175 int added_count_; 2176 int removed_count_; 2177 2178 DISALLOW_COPY_AND_ASSIGN(RootWindowAttachmentObserver); 2179 }; 2180 2181 TEST_F(WindowTest, RootWindowAttachment) { 2182 RootWindowAttachmentObserver observer; 2183 2184 // Test a direct add/remove from the RootWindow. 2185 scoped_ptr<Window> w1(new Window(NULL)); 2186 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN); 2187 w1->AddObserver(&observer); 2188 2189 ParentWindow(w1.get()); 2190 EXPECT_EQ(1, observer.added_count()); 2191 EXPECT_EQ(0, observer.removed_count()); 2192 2193 w1.reset(); 2194 EXPECT_EQ(1, observer.added_count()); 2195 EXPECT_EQ(1, observer.removed_count()); 2196 2197 observer.Clear(); 2198 2199 // Test an indirect add/remove from the RootWindow. 2200 w1.reset(new Window(NULL)); 2201 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN); 2202 Window* w11 = new Window(NULL); 2203 w11->Init(aura::WINDOW_LAYER_NOT_DRAWN); 2204 w11->AddObserver(&observer); 2205 w1->AddChild(w11); 2206 EXPECT_EQ(0, observer.added_count()); 2207 EXPECT_EQ(0, observer.removed_count()); 2208 2209 ParentWindow(w1.get()); 2210 EXPECT_EQ(1, observer.added_count()); 2211 EXPECT_EQ(0, observer.removed_count()); 2212 2213 w1.reset(); // Deletes w11. 2214 w11 = NULL; 2215 EXPECT_EQ(1, observer.added_count()); 2216 EXPECT_EQ(1, observer.removed_count()); 2217 2218 observer.Clear(); 2219 2220 // Test an indirect add/remove with nested observers. 2221 w1.reset(new Window(NULL)); 2222 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN); 2223 w11 = new Window(NULL); 2224 w11->Init(aura::WINDOW_LAYER_NOT_DRAWN); 2225 w11->AddObserver(&observer); 2226 w1->AddChild(w11); 2227 Window* w111 = new Window(NULL); 2228 w111->Init(aura::WINDOW_LAYER_NOT_DRAWN); 2229 w111->AddObserver(&observer); 2230 w11->AddChild(w111); 2231 2232 EXPECT_EQ(0, observer.added_count()); 2233 EXPECT_EQ(0, observer.removed_count()); 2234 2235 ParentWindow(w1.get()); 2236 EXPECT_EQ(2, observer.added_count()); 2237 EXPECT_EQ(0, observer.removed_count()); 2238 2239 w1.reset(); // Deletes w11 and w111. 2240 w11 = NULL; 2241 w111 = NULL; 2242 EXPECT_EQ(2, observer.added_count()); 2243 EXPECT_EQ(2, observer.removed_count()); 2244 } 2245 2246 class BoundsChangedWindowObserver : public WindowObserver { 2247 public: 2248 BoundsChangedWindowObserver() : root_set_(false) {} 2249 2250 virtual void OnWindowBoundsChanged(Window* window, 2251 const gfx::Rect& old_bounds, 2252 const gfx::Rect& new_bounds) OVERRIDE { 2253 root_set_ = window->GetRootWindow() != NULL; 2254 } 2255 2256 bool root_set() const { return root_set_; } 2257 2258 private: 2259 bool root_set_; 2260 2261 DISALLOW_COPY_AND_ASSIGN(BoundsChangedWindowObserver); 2262 }; 2263 2264 TEST_F(WindowTest, RootWindowSetWhenReparenting) { 2265 Window parent1(NULL); 2266 parent1.Init(aura::WINDOW_LAYER_NOT_DRAWN); 2267 Window parent2(NULL); 2268 parent2.Init(aura::WINDOW_LAYER_NOT_DRAWN); 2269 ParentWindow(&parent1); 2270 ParentWindow(&parent2); 2271 parent1.SetBounds(gfx::Rect(10, 10, 300, 300)); 2272 parent2.SetBounds(gfx::Rect(20, 20, 300, 300)); 2273 2274 BoundsChangedWindowObserver observer; 2275 Window child(NULL); 2276 child.Init(aura::WINDOW_LAYER_NOT_DRAWN); 2277 child.SetBounds(gfx::Rect(5, 5, 100, 100)); 2278 parent1.AddChild(&child); 2279 2280 // We need animations to start in order to observe the bounds changes. 2281 ui::ScopedAnimationDurationScaleMode test_duration_mode( 2282 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); 2283 ui::ScopedLayerAnimationSettings settings1(child.layer()->GetAnimator()); 2284 settings1.SetTransitionDuration(base::TimeDelta::FromMilliseconds(100)); 2285 gfx::Rect new_bounds(gfx::Rect(35, 35, 50, 50)); 2286 child.SetBounds(new_bounds); 2287 2288 child.AddObserver(&observer); 2289 2290 // Reparenting the |child| will cause it to get moved. During this move 2291 // the window should still have root window set. 2292 parent2.AddChild(&child); 2293 EXPECT_TRUE(observer.root_set()); 2294 2295 // Animations should stop and the bounds should be as set before the |child| 2296 // got reparented. 2297 EXPECT_EQ(new_bounds.ToString(), child.GetTargetBounds().ToString()); 2298 EXPECT_EQ(new_bounds.ToString(), child.bounds().ToString()); 2299 EXPECT_EQ("55,55 50x50", child.GetBoundsInRootWindow().ToString()); 2300 } 2301 2302 TEST_F(WindowTest, OwnedByParentFalse) { 2303 // By default, a window is owned by its parent. If this is set to false, the 2304 // window will not be destroyed when its parent is. 2305 2306 scoped_ptr<Window> w1(new Window(NULL)); 2307 w1->Init(aura::WINDOW_LAYER_NOT_DRAWN); 2308 scoped_ptr<Window> w2(new Window(NULL)); 2309 w2->set_owned_by_parent(false); 2310 w2->Init(aura::WINDOW_LAYER_NOT_DRAWN); 2311 w1->AddChild(w2.get()); 2312 2313 w1.reset(); 2314 2315 // We should be able to deref w2 still, but its parent should now be NULL. 2316 EXPECT_EQ(NULL, w2->parent()); 2317 } 2318 2319 namespace { 2320 2321 // Used By DeleteWindowFromOnWindowDestroyed. Destroys a Window from 2322 // OnWindowDestroyed(). 2323 class OwningWindowDelegate : public TestWindowDelegate { 2324 public: 2325 OwningWindowDelegate() {} 2326 2327 void SetOwnedWindow(Window* window) { 2328 owned_window_.reset(window); 2329 } 2330 2331 virtual void OnWindowDestroyed(Window* window) OVERRIDE { 2332 owned_window_.reset(NULL); 2333 } 2334 2335 private: 2336 scoped_ptr<Window> owned_window_; 2337 2338 DISALLOW_COPY_AND_ASSIGN(OwningWindowDelegate); 2339 }; 2340 2341 } // namespace 2342 2343 // Creates a window with two child windows. When the first child window is 2344 // destroyed (WindowDelegate::OnWindowDestroyed) it deletes the second child. 2345 // This synthesizes BrowserView and the status bubble. Both are children of the 2346 // same parent and destroying BrowserView triggers it destroying the status 2347 // bubble. 2348 TEST_F(WindowTest, DeleteWindowFromOnWindowDestroyed) { 2349 scoped_ptr<Window> parent(new Window(NULL)); 2350 parent->Init(aura::WINDOW_LAYER_NOT_DRAWN); 2351 OwningWindowDelegate delegate; 2352 Window* c1 = new Window(&delegate); 2353 c1->Init(aura::WINDOW_LAYER_NOT_DRAWN); 2354 parent->AddChild(c1); 2355 Window* c2 = new Window(NULL); 2356 c2->Init(aura::WINDOW_LAYER_NOT_DRAWN); 2357 parent->AddChild(c2); 2358 delegate.SetOwnedWindow(c2); 2359 parent.reset(); 2360 } 2361 2362 namespace { 2363 2364 // Used by DelegateNotifiedAsBoundsChange to verify OnBoundsChanged() is 2365 // invoked. 2366 class BoundsChangeDelegate : public TestWindowDelegate { 2367 public: 2368 BoundsChangeDelegate() : bounds_changed_(false) {} 2369 2370 void clear_bounds_changed() { bounds_changed_ = false; } 2371 bool bounds_changed() const { 2372 return bounds_changed_; 2373 } 2374 2375 // Window 2376 virtual void OnBoundsChanged(const gfx::Rect& old_bounds, 2377 const gfx::Rect& new_bounds) OVERRIDE { 2378 bounds_changed_ = true; 2379 } 2380 2381 private: 2382 // Was OnBoundsChanged() invoked? 2383 bool bounds_changed_; 2384 2385 DISALLOW_COPY_AND_ASSIGN(BoundsChangeDelegate); 2386 }; 2387 2388 } // namespace 2389 2390 // Verifies the delegate is notified when the actual bounds of the layer 2391 // change. 2392 TEST_F(WindowTest, DelegateNotifiedAsBoundsChange) { 2393 BoundsChangeDelegate delegate; 2394 2395 // We cannot short-circuit animations in this test. 2396 ui::ScopedAnimationDurationScaleMode test_duration_mode( 2397 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); 2398 2399 scoped_ptr<Window> window( 2400 CreateTestWindowWithDelegate(&delegate, 1, 2401 gfx::Rect(0, 0, 100, 100), root_window())); 2402 window->layer()->GetAnimator()->set_disable_timer_for_test(true); 2403 2404 delegate.clear_bounds_changed(); 2405 2406 // Animate to a different position. 2407 { 2408 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); 2409 window->SetBounds(gfx::Rect(100, 100, 100, 100)); 2410 } 2411 2412 // Bounds shouldn't immediately have changed. 2413 EXPECT_EQ("0,0 100x100", window->bounds().ToString()); 2414 EXPECT_FALSE(delegate.bounds_changed()); 2415 2416 // Animate to the end, which should notify of the change. 2417 base::TimeTicks start_time = 2418 window->layer()->GetAnimator()->last_step_time(); 2419 ui::LayerAnimator* animator = window->layer()->GetAnimator(); 2420 animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); 2421 EXPECT_TRUE(delegate.bounds_changed()); 2422 EXPECT_NE("0,0 100x100", window->bounds().ToString()); 2423 } 2424 2425 // Verifies the delegate is notified when the actual bounds of the layer 2426 // change even when the window is not the layer's delegate 2427 TEST_F(WindowTest, DelegateNotifiedAsBoundsChangeInHiddenLayer) { 2428 BoundsChangeDelegate delegate; 2429 2430 // We cannot short-circuit animations in this test. 2431 ui::ScopedAnimationDurationScaleMode test_duration_mode( 2432 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); 2433 2434 scoped_ptr<Window> window( 2435 CreateTestWindowWithDelegate(&delegate, 1, 2436 gfx::Rect(0, 0, 100, 100), root_window())); 2437 window->layer()->GetAnimator()->set_disable_timer_for_test(true); 2438 2439 delegate.clear_bounds_changed(); 2440 2441 // Suppress paint on the window since it is hidden (should reset the layer's 2442 // delegate to NULL) 2443 window->SuppressPaint(); 2444 EXPECT_EQ(NULL, window->layer()->delegate()); 2445 2446 // Animate to a different position. 2447 { 2448 ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator()); 2449 window->SetBounds(gfx::Rect(100, 100, 110, 100)); 2450 } 2451 2452 // Layer delegate is NULL but we should still get bounds changed notification. 2453 EXPECT_EQ("100,100 110x100", window->GetTargetBounds().ToString()); 2454 EXPECT_TRUE(delegate.bounds_changed()); 2455 2456 delegate.clear_bounds_changed(); 2457 2458 // Animate to the end: will *not* notify of the change since we are hidden. 2459 base::TimeTicks start_time = 2460 window->layer()->GetAnimator()->last_step_time(); 2461 ui::LayerAnimator* animator = window->layer()->GetAnimator(); 2462 animator->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); 2463 2464 // No bounds changed notification at the end of animation since layer 2465 // delegate is NULL. 2466 EXPECT_FALSE(delegate.bounds_changed()); 2467 EXPECT_NE("0,0 100x100", window->layer()->bounds().ToString()); 2468 } 2469 2470 namespace { 2471 2472 // Used by AddChildNotifications to track notification counts. 2473 class AddChildNotificationsObserver : public WindowObserver { 2474 public: 2475 AddChildNotificationsObserver() : added_count_(0), removed_count_(0) {} 2476 2477 std::string CountStringAndReset() { 2478 std::string result = base::IntToString(added_count_) + " " + 2479 base::IntToString(removed_count_); 2480 added_count_ = removed_count_ = 0; 2481 return result; 2482 } 2483 2484 // WindowObserver overrides: 2485 virtual void OnWindowAddedToRootWindow(Window* window) OVERRIDE { 2486 added_count_++; 2487 } 2488 virtual void OnWindowRemovingFromRootWindow(Window* window, 2489 Window* new_root) OVERRIDE { 2490 removed_count_++; 2491 } 2492 2493 private: 2494 int added_count_; 2495 int removed_count_; 2496 2497 DISALLOW_COPY_AND_ASSIGN(AddChildNotificationsObserver); 2498 }; 2499 2500 } // namespace 2501 2502 // Assertions around when root window notifications are sent. 2503 TEST_F(WindowTest, AddChildNotifications) { 2504 AddChildNotificationsObserver observer; 2505 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window())); 2506 scoped_ptr<Window> w2(CreateTestWindowWithId(1, root_window())); 2507 w2->AddObserver(&observer); 2508 w2->Focus(); 2509 EXPECT_TRUE(w2->HasFocus()); 2510 2511 // Move |w2| to be a child of |w1|. 2512 w1->AddChild(w2.get()); 2513 // Sine we moved in the same root, observer shouldn't be notified. 2514 EXPECT_EQ("0 0", observer.CountStringAndReset()); 2515 // |w2| should still have focus after moving. 2516 EXPECT_TRUE(w2->HasFocus()); 2517 } 2518 2519 // Tests that a delegate that destroys itself when the window is destroyed does 2520 // not break. 2521 TEST_F(WindowTest, DelegateDestroysSelfOnWindowDestroy) { 2522 scoped_ptr<Window> w1(CreateTestWindowWithDelegate( 2523 new DestroyWindowDelegate(), 2524 0, 2525 gfx::Rect(10, 20, 30, 40), 2526 root_window())); 2527 } 2528 2529 class HierarchyObserver : public WindowObserver { 2530 public: 2531 HierarchyObserver(Window* target) : target_(target) { 2532 target_->AddObserver(this); 2533 } 2534 virtual ~HierarchyObserver() { 2535 target_->RemoveObserver(this); 2536 } 2537 2538 void ValidateState( 2539 int index, 2540 const WindowObserver::HierarchyChangeParams& params) const { 2541 ParamsMatch(params_[index], params); 2542 } 2543 2544 void Reset() { 2545 params_.clear(); 2546 } 2547 2548 private: 2549 // Overridden from WindowObserver: 2550 virtual void OnWindowHierarchyChanging( 2551 const HierarchyChangeParams& params) OVERRIDE { 2552 params_.push_back(params); 2553 } 2554 virtual void OnWindowHierarchyChanged( 2555 const HierarchyChangeParams& params) OVERRIDE { 2556 params_.push_back(params); 2557 } 2558 2559 void ParamsMatch(const WindowObserver::HierarchyChangeParams& p1, 2560 const WindowObserver::HierarchyChangeParams& p2) const { 2561 EXPECT_EQ(p1.phase, p2.phase); 2562 EXPECT_EQ(p1.target, p2.target); 2563 EXPECT_EQ(p1.new_parent, p2.new_parent); 2564 EXPECT_EQ(p1.old_parent, p2.old_parent); 2565 EXPECT_EQ(p1.receiver, p2.receiver); 2566 } 2567 2568 Window* target_; 2569 std::vector<WindowObserver::HierarchyChangeParams> params_; 2570 2571 DISALLOW_COPY_AND_ASSIGN(HierarchyObserver); 2572 }; 2573 2574 // Tests hierarchy change notifications. 2575 TEST_F(WindowTest, OnWindowHierarchyChange) { 2576 { 2577 // Simple add & remove. 2578 HierarchyObserver oroot(root_window()); 2579 2580 scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL)); 2581 HierarchyObserver o1(w1.get()); 2582 2583 // Add. 2584 root_window()->AddChild(w1.get()); 2585 2586 WindowObserver::HierarchyChangeParams params; 2587 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING; 2588 params.target = w1.get(); 2589 params.old_parent = NULL; 2590 params.new_parent = root_window(); 2591 params.receiver = w1.get(); 2592 o1.ValidateState(0, params); 2593 2594 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED; 2595 params.receiver = w1.get(); 2596 o1.ValidateState(1, params); 2597 2598 params.receiver = root_window(); 2599 oroot.ValidateState(0, params); 2600 2601 // Remove. 2602 o1.Reset(); 2603 oroot.Reset(); 2604 2605 root_window()->RemoveChild(w1.get()); 2606 2607 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING; 2608 params.old_parent = root_window(); 2609 params.new_parent = NULL; 2610 params.receiver = w1.get(); 2611 2612 o1.ValidateState(0, params); 2613 2614 params.receiver = root_window(); 2615 oroot.ValidateState(0, params); 2616 2617 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED; 2618 params.receiver = w1.get(); 2619 o1.ValidateState(1, params); 2620 } 2621 2622 { 2623 // Add & remove of hierarchy. Tests notification order per documentation in 2624 // WindowObserver. 2625 HierarchyObserver o(root_window()); 2626 scoped_ptr<Window> w1(CreateTestWindowWithId(1, NULL)); 2627 Window* w11 = CreateTestWindowWithId(11, w1.get()); 2628 w1->AddObserver(&o); 2629 w11->AddObserver(&o); 2630 2631 // Add. 2632 root_window()->AddChild(w1.get()); 2633 2634 // Dispatched to target first. 2635 int index = 0; 2636 WindowObserver::HierarchyChangeParams params; 2637 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING; 2638 params.target = w1.get(); 2639 params.old_parent = NULL; 2640 params.new_parent = root_window(); 2641 params.receiver = w1.get(); 2642 o.ValidateState(index++, params); 2643 2644 // Dispatched to target's children. 2645 params.receiver = w11; 2646 o.ValidateState(index++, params); 2647 2648 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED; 2649 2650 // Now process the "changed" phase. 2651 params.receiver = w1.get(); 2652 o.ValidateState(index++, params); 2653 params.receiver = w11; 2654 o.ValidateState(index++, params); 2655 params.receiver = root_window(); 2656 o.ValidateState(index++, params); 2657 2658 // Remove. 2659 root_window()->RemoveChild(w1.get()); 2660 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING; 2661 params.old_parent = root_window(); 2662 params.new_parent = NULL; 2663 params.receiver = w1.get(); 2664 o.ValidateState(index++, params); 2665 params.receiver = w11; 2666 o.ValidateState(index++, params); 2667 params.receiver = root_window(); 2668 o.ValidateState(index++, params); 2669 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED; 2670 params.receiver = w1.get(); 2671 o.ValidateState(index++, params); 2672 params.receiver = w11; 2673 o.ValidateState(index++, params); 2674 2675 w1.reset(); 2676 } 2677 2678 { 2679 // Reparent. Tests notification order per documentation in WindowObserver. 2680 scoped_ptr<Window> w1(CreateTestWindowWithId(1, root_window())); 2681 Window* w11 = CreateTestWindowWithId(11, w1.get()); 2682 Window* w111 = CreateTestWindowWithId(111, w11); 2683 scoped_ptr<Window> w2(CreateTestWindowWithId(2, root_window())); 2684 2685 HierarchyObserver o(root_window()); 2686 w1->AddObserver(&o); 2687 w11->AddObserver(&o); 2688 w111->AddObserver(&o); 2689 w2->AddObserver(&o); 2690 2691 w2->AddChild(w11); 2692 2693 // Dispatched to target first. 2694 int index = 0; 2695 WindowObserver::HierarchyChangeParams params; 2696 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGING; 2697 params.target = w11; 2698 params.old_parent = w1.get(); 2699 params.new_parent = w2.get(); 2700 params.receiver = w11; 2701 o.ValidateState(index++, params); 2702 2703 // Then to target's children. 2704 params.receiver = w111; 2705 o.ValidateState(index++, params); 2706 2707 // Then to target's old parent chain. 2708 params.receiver = w1.get(); 2709 o.ValidateState(index++, params); 2710 params.receiver = root_window(); 2711 o.ValidateState(index++, params); 2712 2713 // "Changed" phase. 2714 params.phase = WindowObserver::HierarchyChangeParams::HIERARCHY_CHANGED; 2715 params.receiver = w11; 2716 o.ValidateState(index++, params); 2717 params.receiver = w111; 2718 o.ValidateState(index++, params); 2719 params.receiver = w2.get(); 2720 o.ValidateState(index++, params); 2721 params.receiver = root_window(); 2722 o.ValidateState(index++, params); 2723 2724 w1.reset(); 2725 w2.reset(); 2726 } 2727 2728 } 2729 2730 // Verifies SchedulePaint() on a layerless window results in damaging the right 2731 // thing. 2732 TEST_F(WindowTest, LayerlessWindowSchedulePaint) { 2733 Window root(NULL); 2734 root.Init(aura::WINDOW_LAYER_NOT_DRAWN); 2735 root.SetBounds(gfx::Rect(0, 0, 100, 100)); 2736 2737 Window* layerless_window = new Window(NULL); // Owned by |root|. 2738 layerless_window->Init(WINDOW_LAYER_NONE); 2739 layerless_window->SetBounds(gfx::Rect(10, 11, 12, 13)); 2740 root.AddChild(layerless_window); 2741 2742 root.layer()->SendDamagedRects(); 2743 layerless_window->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4)); 2744 // Note the the region is clipped by the parent hence 100 going to 11. 2745 EXPECT_EQ("11,13 11x4", 2746 gfx::SkIRectToRect(root.layer()->damaged_region().getBounds()). 2747 ToString()); 2748 2749 Window* layerless_window2 = new Window(NULL); // Owned by |layerless_window|. 2750 layerless_window2->Init(WINDOW_LAYER_NONE); 2751 layerless_window2->SetBounds(gfx::Rect(1, 2, 3, 4)); 2752 layerless_window->AddChild(layerless_window2); 2753 2754 root.layer()->SendDamagedRects(); 2755 layerless_window2->SchedulePaintInRect(gfx::Rect(1, 2, 100, 4)); 2756 // Note the the region is clipped by the |layerless_window| hence 100 going to 2757 // 2. 2758 EXPECT_EQ("12,15 2x2", 2759 gfx::SkIRectToRect(root.layer()->damaged_region().getBounds()). 2760 ToString()); 2761 } 2762 2763 // Verifies bounds of layerless windows are correctly updated when adding 2764 // removing. 2765 TEST_F(WindowTest, NestedLayerlessWindowsBoundsOnAddRemove) { 2766 // Creates the following structure (all children owned by root): 2767 // root 2768 // w1ll 1,2 2769 // w11ll 3,4 2770 // w111 5,6 2771 // w12 7,8 2772 // w121 9,10 2773 // 2774 // ll: layer less, eg no layer 2775 Window root(NULL); 2776 root.Init(WINDOW_LAYER_NOT_DRAWN); 2777 root.SetBounds(gfx::Rect(0, 0, 100, 100)); 2778 2779 Window* w1ll = new Window(NULL); 2780 w1ll->Init(WINDOW_LAYER_NONE); 2781 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100)); 2782 2783 Window* w11ll = new Window(NULL); 2784 w11ll->Init(WINDOW_LAYER_NONE); 2785 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100)); 2786 w1ll->AddChild(w11ll); 2787 2788 Window* w111 = new Window(NULL); 2789 w111->Init(WINDOW_LAYER_NOT_DRAWN); 2790 w111->SetBounds(gfx::Rect(5, 6, 100, 100)); 2791 w11ll->AddChild(w111); 2792 2793 Window* w12 = new Window(NULL); 2794 w12->Init(WINDOW_LAYER_NOT_DRAWN); 2795 w12->SetBounds(gfx::Rect(7, 8, 100, 100)); 2796 w1ll->AddChild(w12); 2797 2798 Window* w121 = new Window(NULL); 2799 w121->Init(WINDOW_LAYER_NOT_DRAWN); 2800 w121->SetBounds(gfx::Rect(9, 10, 100, 100)); 2801 w12->AddChild(w121); 2802 2803 root.AddChild(w1ll); 2804 2805 // All layers should be parented to the root. 2806 EXPECT_EQ(root.layer(), w111->layer()->parent()); 2807 EXPECT_EQ(root.layer(), w12->layer()->parent()); 2808 EXPECT_EQ(w12->layer(), w121->layer()->parent()); 2809 2810 // Ensure bounds are what we expect. 2811 EXPECT_EQ("1,2 100x100", w1ll->bounds().ToString()); 2812 EXPECT_EQ("3,4 100x100", w11ll->bounds().ToString()); 2813 EXPECT_EQ("5,6 100x100", w111->bounds().ToString()); 2814 EXPECT_EQ("7,8 100x100", w12->bounds().ToString()); 2815 EXPECT_EQ("9,10 100x100", w121->bounds().ToString()); 2816 2817 // Bounds of layers are relative to the nearest ancestor with a layer. 2818 EXPECT_EQ("8,10 100x100", w12->layer()->bounds().ToString()); 2819 EXPECT_EQ("9,12 100x100", w111->layer()->bounds().ToString()); 2820 EXPECT_EQ("9,10 100x100", w121->layer()->bounds().ToString()); 2821 2822 // Remove and repeat. 2823 root.RemoveChild(w1ll); 2824 2825 EXPECT_TRUE(w111->layer()->parent() == NULL); 2826 EXPECT_TRUE(w12->layer()->parent() == NULL); 2827 2828 // Verify bounds haven't changed again. 2829 EXPECT_EQ("1,2 100x100", w1ll->bounds().ToString()); 2830 EXPECT_EQ("3,4 100x100", w11ll->bounds().ToString()); 2831 EXPECT_EQ("5,6 100x100", w111->bounds().ToString()); 2832 EXPECT_EQ("7,8 100x100", w12->bounds().ToString()); 2833 EXPECT_EQ("9,10 100x100", w121->bounds().ToString()); 2834 2835 // Bounds of layers should now match that of windows. 2836 EXPECT_EQ("7,8 100x100", w12->layer()->bounds().ToString()); 2837 EXPECT_EQ("5,6 100x100", w111->layer()->bounds().ToString()); 2838 EXPECT_EQ("9,10 100x100", w121->layer()->bounds().ToString()); 2839 2840 delete w1ll; 2841 } 2842 2843 // Verifies bounds of layerless windows are correctly updated when bounds 2844 // of ancestor changes. 2845 TEST_F(WindowTest, NestedLayerlessWindowsBoundsOnSetBounds) { 2846 // Creates the following structure (all children owned by root): 2847 // root 2848 // w1ll 1,2 2849 // w11ll 3,4 2850 // w111 5,6 2851 // w12 7,8 2852 // w121 9,10 2853 // 2854 // ll: layer less, eg no layer 2855 Window root(NULL); 2856 root.Init(WINDOW_LAYER_NOT_DRAWN); 2857 root.SetBounds(gfx::Rect(0, 0, 100, 100)); 2858 2859 Window* w1ll = new Window(NULL); 2860 w1ll->Init(WINDOW_LAYER_NONE); 2861 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100)); 2862 2863 Window* w11ll = new Window(NULL); 2864 w11ll->Init(WINDOW_LAYER_NONE); 2865 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100)); 2866 w1ll->AddChild(w11ll); 2867 2868 Window* w111 = new Window(NULL); 2869 w111->Init(WINDOW_LAYER_NOT_DRAWN); 2870 w111->SetBounds(gfx::Rect(5, 6, 100, 100)); 2871 w11ll->AddChild(w111); 2872 2873 Window* w12 = new Window(NULL); 2874 w12->Init(WINDOW_LAYER_NOT_DRAWN); 2875 w12->SetBounds(gfx::Rect(7, 8, 100, 100)); 2876 w1ll->AddChild(w12); 2877 2878 Window* w121 = new Window(NULL); 2879 w121->Init(WINDOW_LAYER_NOT_DRAWN); 2880 w121->SetBounds(gfx::Rect(9, 10, 100, 100)); 2881 w12->AddChild(w121); 2882 2883 root.AddChild(w1ll); 2884 2885 w111->SetBounds(gfx::Rect(7, 8, 11, 12)); 2886 EXPECT_EQ("7,8 11x12", w111->bounds().ToString()); 2887 EXPECT_EQ("7,8 11x12", w111->GetTargetBounds().ToString()); 2888 EXPECT_EQ("11,14 11x12", w111->layer()->bounds().ToString()); 2889 2890 // Set back. 2891 w111->SetBounds(gfx::Rect(5, 6, 100, 100)); 2892 EXPECT_EQ("5,6 100x100", w111->bounds().ToString()); 2893 EXPECT_EQ("5,6 100x100", w111->GetTargetBounds().ToString()); 2894 EXPECT_EQ("9,12 100x100", w111->layer()->bounds().ToString()); 2895 2896 // Setting the bounds of a layerless window needs to adjust the bounds of 2897 // layered children. 2898 w11ll->SetBounds(gfx::Rect(5, 6, 100, 100)); 2899 EXPECT_EQ("5,6 100x100", w11ll->bounds().ToString()); 2900 EXPECT_EQ("5,6 100x100", w11ll->GetTargetBounds().ToString()); 2901 EXPECT_EQ("5,6 100x100", w111->bounds().ToString()); 2902 EXPECT_EQ("5,6 100x100", w111->GetTargetBounds().ToString()); 2903 EXPECT_EQ("11,14 100x100", w111->layer()->bounds().ToString()); 2904 2905 root.RemoveChild(w1ll); 2906 2907 w111->SetBounds(gfx::Rect(7, 8, 11, 12)); 2908 EXPECT_EQ("7,8 11x12", w111->bounds().ToString()); 2909 EXPECT_EQ("7,8 11x12", w111->GetTargetBounds().ToString()); 2910 EXPECT_EQ("7,8 11x12", w111->layer()->bounds().ToString()); 2911 2912 delete w1ll; 2913 } 2914 2915 namespace { 2916 2917 // Tracks the number of times paint is invoked along with what the clip and 2918 // translate was. 2919 class PaintWindowDelegate : public TestWindowDelegate { 2920 public: 2921 PaintWindowDelegate() : paint_count_(0) {} 2922 virtual ~PaintWindowDelegate() {} 2923 2924 const gfx::Rect& most_recent_paint_clip_bounds() const { 2925 return most_recent_paint_clip_bounds_; 2926 } 2927 2928 const gfx::Vector2d& most_recent_paint_matrix_offset() const { 2929 return most_recent_paint_matrix_offset_; 2930 } 2931 2932 void clear_paint_count() { paint_count_ = 0; } 2933 int paint_count() const { return paint_count_; } 2934 2935 // TestWindowDelegate:: 2936 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { 2937 paint_count_++; 2938 canvas->GetClipBounds(&most_recent_paint_clip_bounds_); 2939 const SkMatrix& matrix = canvas->sk_canvas()->getTotalMatrix(); 2940 most_recent_paint_matrix_offset_ = gfx::Vector2d( 2941 SkScalarFloorToInt(matrix.getTranslateX()), 2942 SkScalarFloorToInt(matrix.getTranslateY())); 2943 } 2944 2945 private: 2946 int paint_count_; 2947 gfx::Rect most_recent_paint_clip_bounds_; 2948 gfx::Vector2d most_recent_paint_matrix_offset_; 2949 2950 DISALLOW_COPY_AND_ASSIGN(PaintWindowDelegate); 2951 }; 2952 2953 } // namespace 2954 2955 // Assertions around layerless children being painted when non-layerless window 2956 // is painted. 2957 TEST_F(WindowTest, PaintLayerless) { 2958 // Creates the following structure (all children owned by root): 2959 // root 2960 // w1ll 1,2 40x50 2961 // w11ll 3,4 11x12 2962 // w111 5,6 2963 // 2964 // ll: layer less, eg no layer 2965 PaintWindowDelegate w1ll_delegate; 2966 PaintWindowDelegate w11ll_delegate; 2967 PaintWindowDelegate w111_delegate; 2968 2969 Window root(NULL); 2970 root.Init(WINDOW_LAYER_NOT_DRAWN); 2971 root.SetBounds(gfx::Rect(0, 0, 100, 100)); 2972 2973 Window* w1ll = new Window(&w1ll_delegate); 2974 w1ll->Init(WINDOW_LAYER_NONE); 2975 w1ll->SetBounds(gfx::Rect(1, 2, 40, 50)); 2976 w1ll->Show(); 2977 root.AddChild(w1ll); 2978 2979 Window* w11ll = new Window(&w11ll_delegate); 2980 w11ll->Init(WINDOW_LAYER_NONE); 2981 w11ll->SetBounds(gfx::Rect(3, 4, 11, 12)); 2982 w11ll->Show(); 2983 w1ll->AddChild(w11ll); 2984 2985 Window* w111 = new Window(&w111_delegate); 2986 w111->Init(WINDOW_LAYER_NOT_DRAWN); 2987 w111->SetBounds(gfx::Rect(5, 6, 100, 100)); 2988 w111->Show(); 2989 w11ll->AddChild(w111); 2990 2991 EXPECT_EQ(0, w1ll_delegate.paint_count()); 2992 EXPECT_EQ(0, w11ll_delegate.paint_count()); 2993 EXPECT_EQ(0, w111_delegate.paint_count()); 2994 2995 // Paint the root, this should trigger painting of the two layerless 2996 // descendants but not the layered descendant. 2997 gfx::Canvas canvas(gfx::Size(200, 200), 1.0f, true); 2998 static_cast<ui::LayerDelegate&>(root).OnPaintLayer(&canvas); 2999 3000 // NOTE: SkCanvas::getClipBounds() extends the clip 1 pixel to the left and up 3001 // and 2 pixels down and to the right. 3002 EXPECT_EQ(1, w1ll_delegate.paint_count()); 3003 EXPECT_EQ("-1,-1 42x52", 3004 w1ll_delegate.most_recent_paint_clip_bounds().ToString()); 3005 EXPECT_EQ("[1 2]", 3006 w1ll_delegate.most_recent_paint_matrix_offset().ToString()); 3007 EXPECT_EQ(1, w11ll_delegate.paint_count()); 3008 EXPECT_EQ("-1,-1 13x14", 3009 w11ll_delegate.most_recent_paint_clip_bounds().ToString()); 3010 EXPECT_EQ("[4 6]", 3011 w11ll_delegate.most_recent_paint_matrix_offset().ToString()); 3012 EXPECT_EQ(0, w111_delegate.paint_count()); 3013 } 3014 3015 namespace { 3016 3017 std::string ConvertPointToTargetString(const Window* source, 3018 const Window* target) { 3019 gfx::Point location; 3020 Window::ConvertPointToTarget(source, target, &location); 3021 return location.ToString(); 3022 } 3023 3024 } // namespace 3025 3026 // Assertions around Window::ConvertPointToTarget() with layerless windows. 3027 TEST_F(WindowTest, ConvertPointToTargetLayerless) { 3028 // Creates the following structure (all children owned by root): 3029 // root 3030 // w1ll 1,2 3031 // w11ll 3,4 3032 // w111 5,6 3033 // w12 7,8 3034 // w121 9,10 3035 // 3036 // ll: layer less, eg no layer 3037 Window root(NULL); 3038 root.Init(WINDOW_LAYER_NOT_DRAWN); 3039 root.SetBounds(gfx::Rect(0, 0, 100, 100)); 3040 3041 Window* w1ll = new Window(NULL); 3042 w1ll->Init(WINDOW_LAYER_NONE); 3043 w1ll->SetBounds(gfx::Rect(1, 2, 100, 100)); 3044 3045 Window* w11ll = new Window(NULL); 3046 w11ll->Init(WINDOW_LAYER_NONE); 3047 w11ll->SetBounds(gfx::Rect(3, 4, 100, 100)); 3048 w1ll->AddChild(w11ll); 3049 3050 Window* w111 = new Window(NULL); 3051 w111->Init(WINDOW_LAYER_NOT_DRAWN); 3052 w111->SetBounds(gfx::Rect(5, 6, 100, 100)); 3053 w11ll->AddChild(w111); 3054 3055 Window* w12 = new Window(NULL); 3056 w12->Init(WINDOW_LAYER_NOT_DRAWN); 3057 w12->SetBounds(gfx::Rect(7, 8, 100, 100)); 3058 w1ll->AddChild(w12); 3059 3060 Window* w121 = new Window(NULL); 3061 w121->Init(WINDOW_LAYER_NOT_DRAWN); 3062 w121->SetBounds(gfx::Rect(9, 10, 100, 100)); 3063 w12->AddChild(w121); 3064 3065 root.AddChild(w1ll); 3066 3067 // w111->w11ll 3068 EXPECT_EQ("5,6", ConvertPointToTargetString(w111, w11ll)); 3069 3070 // w111->w1ll 3071 EXPECT_EQ("8,10", ConvertPointToTargetString(w111, w1ll)); 3072 3073 // w111->root 3074 EXPECT_EQ("9,12", ConvertPointToTargetString(w111, &root)); 3075 3076 // w111->w12 3077 EXPECT_EQ("1,2", ConvertPointToTargetString(w111, w12)); 3078 3079 // w111->w121 3080 EXPECT_EQ("-8,-8", ConvertPointToTargetString(w111, w121)); 3081 3082 // w11ll->w111 3083 EXPECT_EQ("-5,-6", ConvertPointToTargetString(w11ll, w111)); 3084 3085 // w11ll->w11ll 3086 EXPECT_EQ("3,4", ConvertPointToTargetString(w11ll, w1ll)); 3087 3088 // w11ll->root 3089 EXPECT_EQ("4,6", ConvertPointToTargetString(w11ll, &root)); 3090 3091 // w11ll->w12 3092 EXPECT_EQ("-4,-4", ConvertPointToTargetString(w11ll, w12)); 3093 } 3094 3095 #if !defined(NDEBUG) 3096 // Verifies PrintWindowHierarchy() doesn't crash with a layerless window. 3097 TEST_F(WindowTest, PrintWindowHierarchyNotCrashLayerless) { 3098 Window root(NULL); 3099 root.Init(WINDOW_LAYER_NONE); 3100 root.SetBounds(gfx::Rect(0, 0, 100, 100)); 3101 root.PrintWindowHierarchy(0); 3102 } 3103 #endif 3104 3105 namespace { 3106 3107 // See AddWindowsFromString() for details. 3108 aura::Window* CreateWindowFromDescription(const std::string& description, 3109 WindowDelegate* delegate) { 3110 WindowLayerType window_type = WINDOW_LAYER_NOT_DRAWN; 3111 std::vector<std::string> tokens; 3112 Tokenize(description, ":", &tokens); 3113 DCHECK(!tokens.empty()); 3114 std::string name(tokens[0]); 3115 tokens.erase(tokens.begin()); 3116 if (!tokens.empty()) { 3117 if (tokens[0] == "ll") { 3118 window_type = WINDOW_LAYER_NONE; 3119 tokens.erase(tokens.begin()); 3120 } 3121 DCHECK(tokens.empty()) << "unknown tokens for creating window " 3122 << description; 3123 } 3124 Window* window = new Window(delegate); 3125 window->Init(window_type); 3126 window->SetName(name); 3127 // Window name is only propagated to layer in debug builds. 3128 if (window->layer()) 3129 window->layer()->set_name(name); 3130 return window; 3131 } 3132 3133 // Creates and adds a tree of windows to |parent|. |description| consists 3134 // of the following pieces: 3135 // X: Identifies a new window. Consists of a name and optionally ":ll" to 3136 // specify WINDOW_LAYER_NONE, eg "w1:ll". 3137 // []: optionally used to specify the children of the window. Contains any 3138 // number of window identifiers and their corresponding children. 3139 // For example: "[ a [ a1 a2:ll ] b c [ c1 ] ]" creates the tree: 3140 // a 3141 // a1 3142 // a2 -> WINDOW_LAYER_NONE. 3143 // b 3144 // c 3145 // c1 3146 // NOTE: you must have a space after every token. 3147 std::string::size_type AddWindowsFromString(aura::Window* parent, 3148 const std::string& description, 3149 std::string::size_type start_pos, 3150 WindowDelegate* delegate) { 3151 DCHECK(parent); 3152 std::string::size_type end_pos = description.find(' ', start_pos); 3153 while (end_pos != std::string::npos) { 3154 const std::string::size_type part_length = end_pos - start_pos; 3155 const std::string window_description = 3156 description.substr(start_pos, part_length); 3157 if (window_description == "[") { 3158 start_pos = AddWindowsFromString(parent->children().back(), 3159 description, 3160 end_pos + 1, 3161 delegate); 3162 end_pos = description.find(' ', start_pos); 3163 if (end_pos == std::string::npos && start_pos != end_pos) 3164 end_pos = description.length(); 3165 } else if (window_description == "]") { 3166 ++end_pos; 3167 break; 3168 } else { 3169 Window* window = 3170 CreateWindowFromDescription(window_description, delegate); 3171 parent->AddChild(window); 3172 start_pos = ++end_pos; 3173 end_pos = description.find(' ', start_pos); 3174 } 3175 } 3176 return end_pos; 3177 } 3178 3179 // Used by BuildRootWindowTreeDescription(). 3180 std::string BuildWindowTreeDescription(const aura::Window& window) { 3181 std::string result; 3182 result += window.name(); 3183 if (window.children().empty()) 3184 return result; 3185 3186 result += " [ "; 3187 for (size_t i = 0; i < window.children().size(); ++i) { 3188 if (i != 0) 3189 result += " "; 3190 result += BuildWindowTreeDescription(*(window.children()[i])); 3191 } 3192 result += " ]"; 3193 return result; 3194 } 3195 3196 // Creates a string from |window|. See AddWindowsFromString() for details of the 3197 // returned string. This does *not* include the layer type in the description, 3198 // on the name. 3199 std::string BuildRootWindowTreeDescription(const aura::Window& window) { 3200 std::string result; 3201 for (size_t i = 0; i < window.children().size(); ++i) { 3202 if (i != 0) 3203 result += " "; 3204 result += BuildWindowTreeDescription(*(window.children()[i])); 3205 } 3206 return result; 3207 } 3208 3209 // Used by BuildRootWindowTreeDescription(). 3210 std::string BuildLayerTreeDescription(const ui::Layer& layer) { 3211 std::string result; 3212 result += layer.name(); 3213 if (layer.children().empty()) 3214 return result; 3215 3216 result += " [ "; 3217 for (size_t i = 0; i < layer.children().size(); ++i) { 3218 if (i != 0) 3219 result += " "; 3220 result += BuildLayerTreeDescription(*(layer.children()[i])); 3221 } 3222 result += " ]"; 3223 return result; 3224 } 3225 3226 // Builds a string for all the children of |layer|. The returned string is in 3227 // the same format as AddWindowsFromString() but only includes the name of the 3228 // layers. 3229 std::string BuildRootLayerTreeDescription(const ui::Layer& layer) { 3230 std::string result; 3231 for (size_t i = 0; i < layer.children().size(); ++i) { 3232 if (i != 0) 3233 result += " "; 3234 result += BuildLayerTreeDescription(*(layer.children()[i])); 3235 } 3236 return result; 3237 } 3238 3239 // Returns the first window whose name matches |name| in |parent|. 3240 aura::Window* FindWindowByName(aura::Window* parent, 3241 const std::string& name) { 3242 if (parent->name() == name) 3243 return parent; 3244 for (size_t i = 0; i < parent->children().size(); ++i) { 3245 aura::Window* child = FindWindowByName(parent->children()[i], name); 3246 if (child) 3247 return child; 3248 } 3249 return NULL; 3250 } 3251 3252 } // namespace 3253 3254 // Direction to stack. 3255 enum StackType { 3256 STACK_ABOVE, 3257 STACK_BELOW, 3258 STACK_AT_BOTTOM, 3259 STACK_AT_TOP, 3260 }; 3261 3262 // Permutations of StackChildAt with various data. 3263 TEST_F(WindowTest, StackChildAtLayerless) { 3264 struct TestData { 3265 // Describes the window tree to create. See AddWindowsFromString() for 3266 // details. 3267 const std::string initial_description; 3268 3269 // Identifies the window to move. 3270 const std::string source_window; 3271 3272 // Window to move |source_window| relative to. Not used for STACK_AT_BOTTOM 3273 // or STACK_AT_TOP. 3274 const std::string target_window; 3275 3276 StackType stack_type; 3277 3278 // Expected window and layer results. 3279 const std::string expected_description; 3280 const std::string expected_layer_description; 3281 } data[] = { 3282 // 1 at top. 3283 { 3284 "1:ll [ 11 12 ] 2:ll [ 21 ]", 3285 "1", 3286 "", 3287 STACK_AT_TOP, 3288 "2 [ 21 ] 1 [ 11 12 ]", 3289 "21 11 12", 3290 }, 3291 3292 // 1 at bottom. 3293 { 3294 "1:ll [ 11 12 ] 2:ll [ 21 ]", 3295 "1", 3296 "", 3297 STACK_AT_BOTTOM, 3298 "1 [ 11 12 ] 2 [ 21 ]", 3299 "11 12 21", 3300 }, 3301 3302 // 2 at bottom. 3303 { 3304 "1:ll [ 11 12 ] 2:ll [ 21 ]", 3305 "2", 3306 "", 3307 STACK_AT_BOTTOM, 3308 "2 [ 21 ] 1 [ 11 12 ]", 3309 "21 11 12", 3310 }, 3311 3312 // 3 below 2. 3313 { 3314 "1:ll [ 11 12 ] 2:ll [ 21 ] 3:ll", 3315 "3", 3316 "2", 3317 STACK_BELOW, 3318 "1 [ 11 12 ] 3 2 [ 21 ]", 3319 "11 12 21", 3320 }, 3321 3322 // 2 below 1. 3323 { 3324 "1:ll [ 11 12 ] 2:ll [ 21 ]", 3325 "2", 3326 "1", 3327 STACK_BELOW, 3328 "2 [ 21 ] 1 [ 11 12 ]", 3329 "21 11 12", 3330 }, 3331 3332 // 1 above 3. 3333 { 3334 "1:ll [ 11 12 ] 2:ll [ 21 ] 3:ll", 3335 "1", 3336 "3", 3337 STACK_ABOVE, 3338 "2 [ 21 ] 3 1 [ 11 12 ]", 3339 "21 11 12", 3340 }, 3341 3342 // 1 above 2. 3343 { 3344 "1:ll [ 11 12 ] 2:ll [ 21 ]", 3345 "1", 3346 "2", 3347 STACK_ABOVE, 3348 "2 [ 21 ] 1 [ 11 12 ]", 3349 "21 11 12", 3350 }, 3351 }; 3352 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) { 3353 test::TestWindowDelegate delegate; 3354 Window root(NULL); 3355 root.Init(WINDOW_LAYER_NOT_DRAWN); 3356 root.SetBounds(gfx::Rect(0, 0, 100, 100)); 3357 AddWindowsFromString( 3358 &root, 3359 data[i].initial_description, 3360 static_cast<std::string::size_type>(0), &delegate); 3361 aura::Window* source = FindWindowByName(&root, data[i].source_window); 3362 ASSERT_TRUE(source != NULL) << "unable to find source window " 3363 << data[i].source_window << " at " << i; 3364 aura::Window* target = FindWindowByName(&root, data[i].target_window); 3365 switch (data[i].stack_type) { 3366 case STACK_ABOVE: 3367 ASSERT_TRUE(target != NULL) << "unable to find target window " 3368 << data[i].target_window << " at " << i; 3369 source->parent()->StackChildAbove(source, target); 3370 break; 3371 case STACK_BELOW: 3372 ASSERT_TRUE(target != NULL) << "unable to find target window " 3373 << data[i].target_window << " at " << i; 3374 source->parent()->StackChildBelow(source, target); 3375 break; 3376 case STACK_AT_BOTTOM: 3377 source->parent()->StackChildAtBottom(source); 3378 break; 3379 case STACK_AT_TOP: 3380 source->parent()->StackChildAtTop(source); 3381 break; 3382 } 3383 EXPECT_EQ(data[i].expected_layer_description, 3384 BuildRootLayerTreeDescription(*root.layer())) 3385 << "layer tree doesn't match at " << i; 3386 EXPECT_EQ(data[i].expected_description, 3387 BuildRootWindowTreeDescription(root)) 3388 << "window tree doesn't match at " << i; 3389 } 3390 } 3391 3392 namespace { 3393 3394 class TestLayerAnimationObserver : public ui::LayerAnimationObserver { 3395 public: 3396 TestLayerAnimationObserver() 3397 : animation_completed_(false), 3398 animation_aborted_(false) {} 3399 virtual ~TestLayerAnimationObserver() {} 3400 3401 bool animation_completed() const { return animation_completed_; } 3402 bool animation_aborted() const { return animation_aborted_; } 3403 3404 void Reset() { 3405 animation_completed_ = false; 3406 animation_aborted_ = false; 3407 } 3408 3409 private: 3410 // ui::LayerAnimationObserver: 3411 virtual void OnLayerAnimationEnded( 3412 ui::LayerAnimationSequence* sequence) OVERRIDE { 3413 animation_completed_ = true; 3414 } 3415 3416 virtual void OnLayerAnimationAborted( 3417 ui::LayerAnimationSequence* sequence) OVERRIDE { 3418 animation_aborted_ = true; 3419 } 3420 3421 virtual void OnLayerAnimationScheduled( 3422 ui::LayerAnimationSequence* sequence) OVERRIDE { 3423 } 3424 3425 bool animation_completed_; 3426 bool animation_aborted_; 3427 3428 DISALLOW_COPY_AND_ASSIGN(TestLayerAnimationObserver); 3429 }; 3430 3431 } 3432 3433 TEST_F(WindowTest, WindowDestroyCompletesAnimations) { 3434 ui::ScopedAnimationDurationScaleMode test_duration_mode( 3435 ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); 3436 scoped_refptr<ui::LayerAnimator> animator = 3437 ui::LayerAnimator::CreateImplicitAnimator(); 3438 TestLayerAnimationObserver observer; 3439 animator->AddObserver(&observer); 3440 // Make sure destroying a Window completes the animation. 3441 { 3442 scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window())); 3443 window->layer()->SetAnimator(animator.get()); 3444 3445 gfx::Transform transform; 3446 transform.Scale(0.5f, 0.5f); 3447 window->SetTransform(transform); 3448 3449 EXPECT_TRUE(animator->is_animating()); 3450 EXPECT_FALSE(observer.animation_completed()); 3451 } 3452 EXPECT_TRUE(animator.get()); 3453 EXPECT_FALSE(animator->is_animating()); 3454 EXPECT_TRUE(observer.animation_completed()); 3455 EXPECT_FALSE(observer.animation_aborted()); 3456 animator->RemoveObserver(&observer); 3457 observer.Reset(); 3458 3459 animator = ui::LayerAnimator::CreateImplicitAnimator(); 3460 animator->AddObserver(&observer); 3461 ui::Layer layer; 3462 layer.SetAnimator(animator.get()); 3463 { 3464 scoped_ptr<Window> window(CreateTestWindowWithId(1, root_window())); 3465 window->layer()->Add(&layer); 3466 3467 gfx::Transform transform; 3468 transform.Scale(0.5f, 0.5f); 3469 layer.SetTransform(transform); 3470 3471 EXPECT_TRUE(animator->is_animating()); 3472 EXPECT_FALSE(observer.animation_completed()); 3473 } 3474 3475 EXPECT_TRUE(animator.get()); 3476 EXPECT_FALSE(animator->is_animating()); 3477 EXPECT_TRUE(observer.animation_completed()); 3478 EXPECT_FALSE(observer.animation_aborted()); 3479 animator->RemoveObserver(&observer); 3480 } 3481 3482 } // namespace test 3483 } // namespace aura 3484