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