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