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 <map> 6 7 #include "base/memory/scoped_ptr.h" 8 #include "base/rand_util.h" 9 #include "base/strings/string_util.h" 10 #include "base/strings/stringprintf.h" 11 #include "base/strings/utf_string_conversions.h" 12 #include "ui/base/accelerators/accelerator.h" 13 #include "ui/base/clipboard/clipboard.h" 14 #include "ui/base/l10n/l10n_util.h" 15 #include "ui/compositor/compositor.h" 16 #include "ui/compositor/layer.h" 17 #include "ui/compositor/layer_animator.h" 18 #include "ui/compositor/test/draw_waiter_for_test.h" 19 #include "ui/events/event.h" 20 #include "ui/events/keycodes/keyboard_codes.h" 21 #include "ui/gfx/canvas.h" 22 #include "ui/gfx/path.h" 23 #include "ui/gfx/transform.h" 24 #include "ui/strings/grit/ui_strings.h" 25 #include "ui/views/background.h" 26 #include "ui/views/controls/native/native_view_host.h" 27 #include "ui/views/controls/scroll_view.h" 28 #include "ui/views/controls/textfield/textfield.h" 29 #include "ui/views/focus/view_storage.h" 30 #include "ui/views/test/views_test_base.h" 31 #include "ui/views/view.h" 32 #include "ui/views/views_delegate.h" 33 #include "ui/views/widget/native_widget.h" 34 #include "ui/views/widget/root_view.h" 35 #include "ui/views/window/dialog_client_view.h" 36 #include "ui/views/window/dialog_delegate.h" 37 38 using base::ASCIIToUTF16; 39 40 namespace { 41 42 // Returns true if |ancestor| is an ancestor of |layer|. 43 bool LayerIsAncestor(const ui::Layer* ancestor, const ui::Layer* layer) { 44 while (layer && layer != ancestor) 45 layer = layer->parent(); 46 return layer == ancestor; 47 } 48 49 // Convenience functions for walking a View tree. 50 const views::View* FirstView(const views::View* view) { 51 const views::View* v = view; 52 while (v->has_children()) 53 v = v->child_at(0); 54 return v; 55 } 56 57 const views::View* NextView(const views::View* view) { 58 const views::View* v = view; 59 const views::View* parent = v->parent(); 60 if (!parent) 61 return NULL; 62 int next = parent->GetIndexOf(v) + 1; 63 if (next != parent->child_count()) 64 return FirstView(parent->child_at(next)); 65 return parent; 66 } 67 68 // Convenience functions for walking a Layer tree. 69 const ui::Layer* FirstLayer(const ui::Layer* layer) { 70 const ui::Layer* l = layer; 71 while (l->children().size() > 0) 72 l = l->children()[0]; 73 return l; 74 } 75 76 const ui::Layer* NextLayer(const ui::Layer* layer) { 77 const ui::Layer* parent = layer->parent(); 78 if (!parent) 79 return NULL; 80 const std::vector<ui::Layer*> children = parent->children(); 81 size_t index; 82 for (index = 0; index < children.size(); index++) { 83 if (children[index] == layer) 84 break; 85 } 86 size_t next = index + 1; 87 if (next < children.size()) 88 return FirstLayer(children[next]); 89 return parent; 90 } 91 92 // Given the root nodes of a View tree and a Layer tree, makes sure the two 93 // trees are in sync. 94 bool ViewAndLayerTreeAreConsistent(const views::View* view, 95 const ui::Layer* layer) { 96 const views::View* v = FirstView(view); 97 const ui::Layer* l = FirstLayer(layer); 98 while (v && l) { 99 // Find the view with a layer. 100 while (v && !v->layer()) 101 v = NextView(v); 102 EXPECT_TRUE(v); 103 if (!v) 104 return false; 105 106 // Check if the View tree and the Layer tree are in sync. 107 EXPECT_EQ(l, v->layer()); 108 if (v->layer() != l) 109 return false; 110 111 // Check if the visibility states of the View and the Layer are in sync. 112 EXPECT_EQ(l->IsDrawn(), v->IsDrawn()); 113 if (v->IsDrawn() != l->IsDrawn()) { 114 for (const views::View* vv = v; vv; vv = vv->parent()) 115 LOG(ERROR) << "V: " << vv << " " << vv->visible() << " " 116 << vv->IsDrawn() << " " << vv->layer(); 117 for (const ui::Layer* ll = l; ll; ll = ll->parent()) 118 LOG(ERROR) << "L: " << ll << " " << ll->IsDrawn(); 119 return false; 120 } 121 122 // Check if the size of the View and the Layer are in sync. 123 EXPECT_EQ(l->bounds(), v->bounds()); 124 if (v->bounds() != l->bounds()) 125 return false; 126 127 if (v == view || l == layer) 128 return v == view && l == layer; 129 130 v = NextView(v); 131 l = NextLayer(l); 132 } 133 134 return false; 135 } 136 137 // Constructs a View tree with the specified depth. 138 void ConstructTree(views::View* view, int depth) { 139 if (depth == 0) 140 return; 141 int count = base::RandInt(1, 5); 142 for (int i = 0; i < count; i++) { 143 views::View* v = new views::View; 144 view->AddChildView(v); 145 if (base::RandDouble() > 0.5) 146 v->SetPaintToLayer(true); 147 if (base::RandDouble() < 0.2) 148 v->SetVisible(false); 149 150 ConstructTree(v, depth - 1); 151 } 152 } 153 154 void ScrambleTree(views::View* view) { 155 int count = view->child_count(); 156 if (count == 0) 157 return; 158 for (int i = 0; i < count; i++) { 159 ScrambleTree(view->child_at(i)); 160 } 161 162 if (count > 1) { 163 int a = base::RandInt(0, count - 1); 164 int b = base::RandInt(0, count - 1); 165 166 views::View* view_a = view->child_at(a); 167 views::View* view_b = view->child_at(b); 168 view->ReorderChildView(view_a, b); 169 view->ReorderChildView(view_b, a); 170 } 171 172 if (!view->layer() && base::RandDouble() < 0.1) 173 view->SetPaintToLayer(true); 174 175 if (base::RandDouble() < 0.1) 176 view->SetVisible(!view->visible()); 177 } 178 179 } // namespace 180 181 namespace views { 182 183 typedef ViewsTestBase ViewTest; 184 185 // A derived class for testing purpose. 186 class TestView : public View { 187 public: 188 TestView() 189 : View(), 190 delete_on_pressed_(false), 191 native_theme_(NULL), 192 can_process_events_within_subtree_(true) {} 193 virtual ~TestView() {} 194 195 // Reset all test state 196 void Reset() { 197 did_change_bounds_ = false; 198 last_mouse_event_type_ = 0; 199 location_.SetPoint(0, 0); 200 received_mouse_enter_ = false; 201 received_mouse_exit_ = false; 202 last_clip_.setEmpty(); 203 accelerator_count_map_.clear(); 204 can_process_events_within_subtree_ = true; 205 } 206 207 // Exposed as public for testing. 208 void DoFocus() { 209 views::View::Focus(); 210 } 211 212 void DoBlur() { 213 views::View::Blur(); 214 } 215 216 bool focusable() const { return View::focusable(); } 217 218 void set_can_process_events_within_subtree(bool can_process) { 219 can_process_events_within_subtree_ = can_process; 220 } 221 222 virtual bool CanProcessEventsWithinSubtree() const OVERRIDE { 223 return can_process_events_within_subtree_; 224 } 225 226 virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE; 227 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; 228 virtual bool OnMouseDragged(const ui::MouseEvent& event) OVERRIDE; 229 virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE; 230 virtual void OnMouseEntered(const ui::MouseEvent& event) OVERRIDE; 231 virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE; 232 233 virtual void Paint(gfx::Canvas* canvas, const CullSet& cull_set) OVERRIDE; 234 virtual void SchedulePaintInRect(const gfx::Rect& rect) OVERRIDE; 235 virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE; 236 237 virtual void OnNativeThemeChanged(const ui::NativeTheme* native_theme) 238 OVERRIDE; 239 240 // OnBoundsChanged. 241 bool did_change_bounds_; 242 gfx::Rect new_bounds_; 243 244 // MouseEvent. 245 int last_mouse_event_type_; 246 gfx::Point location_; 247 bool received_mouse_enter_; 248 bool received_mouse_exit_; 249 bool delete_on_pressed_; 250 251 // Painting. 252 std::vector<gfx::Rect> scheduled_paint_rects_; 253 254 // Painting. 255 SkRect last_clip_; 256 257 // Accelerators. 258 std::map<ui::Accelerator, int> accelerator_count_map_; 259 260 // Native theme. 261 const ui::NativeTheme* native_theme_; 262 263 // Value to return from CanProcessEventsWithinSubtree(). 264 bool can_process_events_within_subtree_; 265 }; 266 267 //////////////////////////////////////////////////////////////////////////////// 268 // OnBoundsChanged 269 //////////////////////////////////////////////////////////////////////////////// 270 271 void TestView::OnBoundsChanged(const gfx::Rect& previous_bounds) { 272 did_change_bounds_ = true; 273 new_bounds_ = bounds(); 274 } 275 276 TEST_F(ViewTest, OnBoundsChanged) { 277 TestView v; 278 279 gfx::Rect prev_rect(0, 0, 200, 200); 280 gfx::Rect new_rect(100, 100, 250, 250); 281 282 v.SetBoundsRect(prev_rect); 283 v.Reset(); 284 v.SetBoundsRect(new_rect); 285 286 EXPECT_TRUE(v.did_change_bounds_); 287 EXPECT_EQ(v.new_bounds_, new_rect); 288 EXPECT_EQ(v.bounds(), new_rect); 289 } 290 291 //////////////////////////////////////////////////////////////////////////////// 292 // MouseEvent 293 //////////////////////////////////////////////////////////////////////////////// 294 295 bool TestView::OnMousePressed(const ui::MouseEvent& event) { 296 last_mouse_event_type_ = event.type(); 297 location_.SetPoint(event.x(), event.y()); 298 if (delete_on_pressed_) 299 delete this; 300 return true; 301 } 302 303 bool TestView::OnMouseDragged(const ui::MouseEvent& event) { 304 last_mouse_event_type_ = event.type(); 305 location_.SetPoint(event.x(), event.y()); 306 return true; 307 } 308 309 void TestView::OnMouseReleased(const ui::MouseEvent& event) { 310 last_mouse_event_type_ = event.type(); 311 location_.SetPoint(event.x(), event.y()); 312 } 313 314 void TestView::OnMouseEntered(const ui::MouseEvent& event) { 315 received_mouse_enter_ = true; 316 } 317 318 void TestView::OnMouseExited(const ui::MouseEvent& event) { 319 received_mouse_exit_ = true; 320 } 321 322 TEST_F(ViewTest, MouseEvent) { 323 TestView* v1 = new TestView(); 324 v1->SetBoundsRect(gfx::Rect(0, 0, 300, 300)); 325 326 TestView* v2 = new TestView(); 327 v2->SetBoundsRect(gfx::Rect(100, 100, 100, 100)); 328 329 scoped_ptr<Widget> widget(new Widget); 330 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 331 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 332 params.bounds = gfx::Rect(50, 50, 650, 650); 333 widget->Init(params); 334 internal::RootView* root = 335 static_cast<internal::RootView*>(widget->GetRootView()); 336 337 root->AddChildView(v1); 338 v1->AddChildView(v2); 339 340 v1->Reset(); 341 v2->Reset(); 342 343 gfx::Point p1(110, 120); 344 ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, p1, p1, 345 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); 346 root->OnMousePressed(pressed); 347 EXPECT_EQ(v2->last_mouse_event_type_, ui::ET_MOUSE_PRESSED); 348 EXPECT_EQ(v2->location_.x(), 10); 349 EXPECT_EQ(v2->location_.y(), 20); 350 // Make sure v1 did not receive the event 351 EXPECT_EQ(v1->last_mouse_event_type_, 0); 352 353 // Drag event out of bounds. Should still go to v2 354 v1->Reset(); 355 v2->Reset(); 356 gfx::Point p2(50, 40); 357 ui::MouseEvent dragged(ui::ET_MOUSE_DRAGGED, p2, p2, 358 ui::EF_LEFT_MOUSE_BUTTON, 0); 359 root->OnMouseDragged(dragged); 360 EXPECT_EQ(v2->last_mouse_event_type_, ui::ET_MOUSE_DRAGGED); 361 EXPECT_EQ(v2->location_.x(), -50); 362 EXPECT_EQ(v2->location_.y(), -60); 363 // Make sure v1 did not receive the event 364 EXPECT_EQ(v1->last_mouse_event_type_, 0); 365 366 // Releasted event out of bounds. Should still go to v2 367 v1->Reset(); 368 v2->Reset(); 369 ui::MouseEvent released(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), 0, 370 0); 371 root->OnMouseDragged(released); 372 EXPECT_EQ(v2->last_mouse_event_type_, ui::ET_MOUSE_RELEASED); 373 EXPECT_EQ(v2->location_.x(), -100); 374 EXPECT_EQ(v2->location_.y(), -100); 375 // Make sure v1 did not receive the event 376 EXPECT_EQ(v1->last_mouse_event_type_, 0); 377 378 widget->CloseNow(); 379 } 380 381 // Confirm that a view can be deleted as part of processing a mouse press. 382 TEST_F(ViewTest, DeleteOnPressed) { 383 TestView* v1 = new TestView(); 384 v1->SetBoundsRect(gfx::Rect(0, 0, 300, 300)); 385 386 TestView* v2 = new TestView(); 387 v2->SetBoundsRect(gfx::Rect(100, 100, 100, 100)); 388 389 v1->Reset(); 390 v2->Reset(); 391 392 scoped_ptr<Widget> widget(new Widget); 393 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 394 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 395 params.bounds = gfx::Rect(50, 50, 650, 650); 396 widget->Init(params); 397 View* root = widget->GetRootView(); 398 399 root->AddChildView(v1); 400 v1->AddChildView(v2); 401 402 v2->delete_on_pressed_ = true; 403 gfx::Point point(110, 120); 404 ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, point, point, 405 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); 406 root->OnMousePressed(pressed); 407 EXPECT_EQ(0, v1->child_count()); 408 409 widget->CloseNow(); 410 } 411 412 //////////////////////////////////////////////////////////////////////////////// 413 // Painting 414 //////////////////////////////////////////////////////////////////////////////// 415 416 void TestView::Paint(gfx::Canvas* canvas, const CullSet& cull_set) { 417 canvas->sk_canvas()->getClipBounds(&last_clip_); 418 } 419 420 void TestView::SchedulePaintInRect(const gfx::Rect& rect) { 421 scheduled_paint_rects_.push_back(rect); 422 View::SchedulePaintInRect(rect); 423 } 424 425 void CheckRect(const SkRect& check_rect, const SkRect& target_rect) { 426 EXPECT_EQ(target_rect.fLeft, check_rect.fLeft); 427 EXPECT_EQ(target_rect.fRight, check_rect.fRight); 428 EXPECT_EQ(target_rect.fTop, check_rect.fTop); 429 EXPECT_EQ(target_rect.fBottom, check_rect.fBottom); 430 } 431 432 TEST_F(ViewTest, RemoveNotification) { 433 ViewStorage* vs = ViewStorage::GetInstance(); 434 Widget* widget = new Widget; 435 widget->Init(CreateParams(Widget::InitParams::TYPE_POPUP)); 436 View* root_view = widget->GetRootView(); 437 438 View* v1 = new View; 439 int s1 = vs->CreateStorageID(); 440 vs->StoreView(s1, v1); 441 root_view->AddChildView(v1); 442 View* v11 = new View; 443 int s11 = vs->CreateStorageID(); 444 vs->StoreView(s11, v11); 445 v1->AddChildView(v11); 446 View* v111 = new View; 447 int s111 = vs->CreateStorageID(); 448 vs->StoreView(s111, v111); 449 v11->AddChildView(v111); 450 View* v112 = new View; 451 int s112 = vs->CreateStorageID(); 452 vs->StoreView(s112, v112); 453 v11->AddChildView(v112); 454 View* v113 = new View; 455 int s113 = vs->CreateStorageID(); 456 vs->StoreView(s113, v113); 457 v11->AddChildView(v113); 458 View* v1131 = new View; 459 int s1131 = vs->CreateStorageID(); 460 vs->StoreView(s1131, v1131); 461 v113->AddChildView(v1131); 462 View* v12 = new View; 463 int s12 = vs->CreateStorageID(); 464 vs->StoreView(s12, v12); 465 v1->AddChildView(v12); 466 467 View* v2 = new View; 468 int s2 = vs->CreateStorageID(); 469 vs->StoreView(s2, v2); 470 root_view->AddChildView(v2); 471 View* v21 = new View; 472 int s21 = vs->CreateStorageID(); 473 vs->StoreView(s21, v21); 474 v2->AddChildView(v21); 475 View* v211 = new View; 476 int s211 = vs->CreateStorageID(); 477 vs->StoreView(s211, v211); 478 v21->AddChildView(v211); 479 480 size_t stored_views = vs->view_count(); 481 482 // Try removing a leaf view. 483 v21->RemoveChildView(v211); 484 EXPECT_EQ(stored_views - 1, vs->view_count()); 485 EXPECT_EQ(NULL, vs->RetrieveView(s211)); 486 delete v211; // We won't use this one anymore. 487 488 // Now try removing a view with a hierarchy of depth 1. 489 v11->RemoveChildView(v113); 490 EXPECT_EQ(stored_views - 3, vs->view_count()); 491 EXPECT_EQ(NULL, vs->RetrieveView(s113)); 492 EXPECT_EQ(NULL, vs->RetrieveView(s1131)); 493 delete v113; // We won't use this one anymore. 494 495 // Now remove even more. 496 root_view->RemoveChildView(v1); 497 EXPECT_EQ(NULL, vs->RetrieveView(s1)); 498 EXPECT_EQ(NULL, vs->RetrieveView(s11)); 499 EXPECT_EQ(NULL, vs->RetrieveView(s12)); 500 EXPECT_EQ(NULL, vs->RetrieveView(s111)); 501 EXPECT_EQ(NULL, vs->RetrieveView(s112)); 502 503 // Put v1 back for more tests. 504 root_view->AddChildView(v1); 505 vs->StoreView(s1, v1); 506 507 // Synchronously closing the window deletes the view hierarchy, which should 508 // remove all its views from ViewStorage. 509 widget->CloseNow(); 510 EXPECT_EQ(stored_views - 10, vs->view_count()); 511 EXPECT_EQ(NULL, vs->RetrieveView(s1)); 512 EXPECT_EQ(NULL, vs->RetrieveView(s12)); 513 EXPECT_EQ(NULL, vs->RetrieveView(s11)); 514 EXPECT_EQ(NULL, vs->RetrieveView(s12)); 515 EXPECT_EQ(NULL, vs->RetrieveView(s21)); 516 EXPECT_EQ(NULL, vs->RetrieveView(s111)); 517 EXPECT_EQ(NULL, vs->RetrieveView(s112)); 518 } 519 520 namespace { 521 522 void RotateCounterclockwise(gfx::Transform* transform) { 523 transform->matrix().set3x3(0, -1, 0, 524 1, 0, 0, 525 0, 0, 1); 526 } 527 528 void RotateClockwise(gfx::Transform* transform) { 529 transform->matrix().set3x3( 0, 1, 0, 530 -1, 0, 0, 531 0, 0, 1); 532 } 533 534 } // namespace 535 536 // Tests the correctness of the rect-based targeting algorithm implemented in 537 // View::GetEventHandlerForRect(). See http://goo.gl/3Jp2BD for a description 538 // of rect-based targeting. 539 TEST_F(ViewTest, GetEventHandlerForRect) { 540 Widget* widget = new Widget; 541 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 542 widget->Init(params); 543 View* root_view = widget->GetRootView(); 544 root_view->SetBoundsRect(gfx::Rect(0, 0, 500, 500)); 545 546 // Have this hierarchy of views (the coordinates here are all in 547 // the root view's coordinate space): 548 // v1 (0, 0, 100, 100) 549 // v2 (150, 0, 250, 100) 550 // v3 (0, 200, 150, 100) 551 // v31 (10, 210, 80, 80) 552 // v32 (110, 210, 30, 80) 553 // v4 (300, 200, 100, 100) 554 // v41 (310, 210, 80, 80) 555 // v411 (370, 275, 10, 5) 556 // v5 (450, 197, 30, 36) 557 // v51 (450, 200, 30, 30) 558 559 // The coordinates used for SetBounds are in parent coordinates. 560 561 TestView* v1 = new TestView; 562 v1->SetBounds(0, 0, 100, 100); 563 root_view->AddChildView(v1); 564 565 TestView* v2 = new TestView; 566 v2->SetBounds(150, 0, 250, 100); 567 root_view->AddChildView(v2); 568 569 TestView* v3 = new TestView; 570 v3->SetBounds(0, 200, 150, 100); 571 root_view->AddChildView(v3); 572 573 TestView* v4 = new TestView; 574 v4->SetBounds(300, 200, 100, 100); 575 root_view->AddChildView(v4); 576 577 TestView* v31 = new TestView; 578 v31->SetBounds(10, 10, 80, 80); 579 v3->AddChildView(v31); 580 581 TestView* v32 = new TestView; 582 v32->SetBounds(110, 10, 30, 80); 583 v3->AddChildView(v32); 584 585 TestView* v41 = new TestView; 586 v41->SetBounds(10, 10, 80, 80); 587 v4->AddChildView(v41); 588 589 TestView* v411 = new TestView; 590 v411->SetBounds(60, 65, 10, 5); 591 v41->AddChildView(v411); 592 593 TestView* v5 = new TestView; 594 v5->SetBounds(450, 197, 30, 36); 595 root_view->AddChildView(v5); 596 597 TestView* v51 = new TestView; 598 v51->SetBounds(0, 3, 30, 30); 599 v5->AddChildView(v51); 600 601 // |touch_rect| does not intersect any descendant view of |root_view|. 602 gfx::Rect touch_rect(105, 105, 30, 45); 603 View* result_view = root_view->GetEventHandlerForRect(touch_rect); 604 EXPECT_EQ(root_view, result_view); 605 result_view = NULL; 606 607 // Covers |v1| by at least 60%. 608 touch_rect.SetRect(15, 15, 100, 100); 609 result_view = root_view->GetEventHandlerForRect(touch_rect); 610 EXPECT_EQ(v1, result_view); 611 result_view = NULL; 612 613 // Intersects |v1| but does not cover it by at least 60%. The center 614 // of |touch_rect| is within |v1|. 615 touch_rect.SetRect(50, 50, 5, 10); 616 result_view = root_view->GetEventHandlerForRect(touch_rect); 617 EXPECT_EQ(v1, result_view); 618 result_view = NULL; 619 620 // Intersects |v1| but does not cover it by at least 60%. The center 621 // of |touch_rect| is not within |v1|. 622 touch_rect.SetRect(95, 96, 21, 22); 623 result_view = root_view->GetEventHandlerForRect(touch_rect); 624 EXPECT_EQ(root_view, result_view); 625 result_view = NULL; 626 627 // Intersects |v1| and |v2|, but only covers |v2| by at least 60%. 628 touch_rect.SetRect(95, 10, 300, 120); 629 result_view = root_view->GetEventHandlerForRect(touch_rect); 630 EXPECT_EQ(v2, result_view); 631 result_view = NULL; 632 633 // Covers both |v1| and |v2| by at least 60%, but the center point 634 // of |touch_rect| is closer to the center point of |v2|. 635 touch_rect.SetRect(20, 20, 400, 100); 636 result_view = root_view->GetEventHandlerForRect(touch_rect); 637 EXPECT_EQ(v2, result_view); 638 result_view = NULL; 639 640 // Covers both |v1| and |v2| by at least 60%, but the center point 641 // of |touch_rect| is closer to the center point of |v1|. 642 touch_rect.SetRect(-700, -15, 1050, 110); 643 result_view = root_view->GetEventHandlerForRect(touch_rect); 644 EXPECT_EQ(v1, result_view); 645 result_view = NULL; 646 647 // A mouse click within |v1| will target |v1|. 648 touch_rect.SetRect(15, 15, 1, 1); 649 result_view = root_view->GetEventHandlerForRect(touch_rect); 650 EXPECT_EQ(v1, result_view); 651 result_view = NULL; 652 653 // Intersects |v3| and |v31| by at least 60% and the center point 654 // of |touch_rect| is closer to the center point of |v31|. 655 touch_rect.SetRect(0, 200, 110, 100); 656 result_view = root_view->GetEventHandlerForRect(touch_rect); 657 EXPECT_EQ(v31, result_view); 658 result_view = NULL; 659 660 // Intersects |v3| and |v31|, but neither by at least 60%. The 661 // center point of |touch_rect| lies within |v31|. 662 touch_rect.SetRect(80, 280, 15, 15); 663 result_view = root_view->GetEventHandlerForRect(touch_rect); 664 EXPECT_EQ(v31, result_view); 665 result_view = NULL; 666 667 // Covers |v3|, |v31|, and |v32| all by at least 60%, and the 668 // center point of |touch_rect| is closest to the center point 669 // of |v32|. 670 touch_rect.SetRect(0, 200, 200, 100); 671 result_view = root_view->GetEventHandlerForRect(touch_rect); 672 EXPECT_EQ(v32, result_view); 673 result_view = NULL; 674 675 // Intersects all of |v3|, |v31|, and |v32|, but only covers 676 // |v31| and |v32| by at least 60%. The center point of 677 // |touch_rect| is closest to the center point of |v32|. 678 touch_rect.SetRect(30, 225, 180, 115); 679 result_view = root_view->GetEventHandlerForRect(touch_rect); 680 EXPECT_EQ(v32, result_view); 681 result_view = NULL; 682 683 // A mouse click at the corner of |v3| will target |v3|. 684 touch_rect.SetRect(0, 200, 1, 1); 685 result_view = root_view->GetEventHandlerForRect(touch_rect); 686 EXPECT_EQ(v3, result_view); 687 result_view = NULL; 688 689 // A mouse click within |v32| will target |v32|. 690 touch_rect.SetRect(112, 211, 1, 1); 691 result_view = root_view->GetEventHandlerForRect(touch_rect); 692 EXPECT_EQ(v32, result_view); 693 result_view = NULL; 694 695 // Covers all of |v4|, |v41|, and |v411| by at least 60%. 696 // The center point of |touch_rect| is equally close to 697 // the center points of |v4| and |v41|. 698 touch_rect.SetRect(310, 210, 80, 80); 699 result_view = root_view->GetEventHandlerForRect(touch_rect); 700 EXPECT_EQ(v41, result_view); 701 result_view = NULL; 702 703 // Intersects all of |v4|, |v41|, and |v411| but only covers 704 // |v411| by at least 60%. 705 touch_rect.SetRect(370, 275, 7, 5); 706 result_view = root_view->GetEventHandlerForRect(touch_rect); 707 EXPECT_EQ(v411, result_view); 708 result_view = NULL; 709 710 // Intersects |v4| and |v41| but covers neither by at least 60%. 711 // The center point of |touch_rect| is equally close to the center 712 // points of |v4| and |v41|. 713 touch_rect.SetRect(345, 245, 7, 7); 714 result_view = root_view->GetEventHandlerForRect(touch_rect); 715 EXPECT_EQ(v41, result_view); 716 result_view = NULL; 717 718 // Intersects all of |v4|, |v41|, and |v411| and covers none of 719 // them by at least 60%. The center point of |touch_rect| lies 720 // within |v411|. 721 touch_rect.SetRect(368, 272, 4, 6); 722 result_view = root_view->GetEventHandlerForRect(touch_rect); 723 EXPECT_EQ(v411, result_view); 724 result_view = NULL; 725 726 // Intersects all of |v4|, |v41|, and |v411| and covers none of 727 // them by at least 60%. The center point of |touch_rect| lies 728 // within |v41|. 729 touch_rect.SetRect(365, 270, 7, 7); 730 result_view = root_view->GetEventHandlerForRect(touch_rect); 731 EXPECT_EQ(v41, result_view); 732 result_view = NULL; 733 734 // Intersects all of |v4|, |v41|, and |v411| and covers none of 735 // them by at least 60%. The center point of |touch_rect| lies 736 // within |v4|. 737 touch_rect.SetRect(205, 275, 200, 2); 738 result_view = root_view->GetEventHandlerForRect(touch_rect); 739 EXPECT_EQ(v4, result_view); 740 result_view = NULL; 741 742 // Intersects all of |v4|, |v41|, and |v411| but only covers 743 // |v41| by at least 60%. 744 touch_rect.SetRect(310, 210, 61, 66); 745 result_view = root_view->GetEventHandlerForRect(touch_rect); 746 EXPECT_EQ(v41, result_view); 747 result_view = NULL; 748 749 // A mouse click within |v411| will target |v411|. 750 touch_rect.SetRect(372, 275, 1, 1); 751 result_view = root_view->GetEventHandlerForRect(touch_rect); 752 EXPECT_EQ(v411, result_view); 753 result_view = NULL; 754 755 // A mouse click within |v41| will target |v41|. 756 touch_rect.SetRect(350, 215, 1, 1); 757 result_view = root_view->GetEventHandlerForRect(touch_rect); 758 EXPECT_EQ(v41, result_view); 759 result_view = NULL; 760 761 // Covers |v3|, |v4|, and all of their descendants by at 762 // least 60%. The center point of |touch_rect| is closest 763 // to the center point of |v32|. 764 touch_rect.SetRect(0, 200, 400, 100); 765 result_view = root_view->GetEventHandlerForRect(touch_rect); 766 EXPECT_EQ(v32, result_view); 767 result_view = NULL; 768 769 // Intersects all of |v2|, |v3|, |v32|, |v4|, |v41|, and |v411|. 770 // Covers |v2|, |v32|, |v4|, |v41|, and |v411| by at least 60%. 771 // The center point of |touch_rect| is closest to the center 772 // point of |root_view|. 773 touch_rect.SetRect(110, 15, 375, 450); 774 result_view = root_view->GetEventHandlerForRect(touch_rect); 775 EXPECT_EQ(root_view, result_view); 776 result_view = NULL; 777 778 // Covers all views (except |v5| and |v51|) by at least 60%. The 779 // center point of |touch_rect| is equally close to the center 780 // points of |v2| and |v32|. One is not a descendant of the other, 781 // so in this case the view selected is arbitrary (i.e., 782 // it depends only on the ordering of nodes in the views 783 // hierarchy). 784 touch_rect.SetRect(0, 0, 400, 300); 785 result_view = root_view->GetEventHandlerForRect(touch_rect); 786 EXPECT_EQ(v32, result_view); 787 result_view = NULL; 788 789 // Covers |v5| and |v51| by at least 60%, and the center point of 790 // the touch is located within both views. Since both views share 791 // the same center point, the child view should be selected. 792 touch_rect.SetRect(440, 190, 40, 40); 793 result_view = root_view->GetEventHandlerForRect(touch_rect); 794 EXPECT_EQ(v51, result_view); 795 result_view = NULL; 796 797 // Covers |v5| and |v51| by at least 60%, but the center point of 798 // the touch is not located within either view. Since both views 799 // share the same center point, the child view should be selected. 800 touch_rect.SetRect(455, 187, 60, 60); 801 result_view = root_view->GetEventHandlerForRect(touch_rect); 802 EXPECT_EQ(v51, result_view); 803 result_view = NULL; 804 805 // Covers neither |v5| nor |v51| by at least 60%, but the center 806 // of the touch is located within |v51|. 807 touch_rect.SetRect(450, 197, 10, 10); 808 result_view = root_view->GetEventHandlerForRect(touch_rect); 809 EXPECT_EQ(v51, result_view); 810 result_view = NULL; 811 812 // Covers neither |v5| nor |v51| by at least 60% but intersects both. 813 // The center point is located outside of both views. 814 touch_rect.SetRect(433, 180, 24, 24); 815 result_view = root_view->GetEventHandlerForRect(touch_rect); 816 EXPECT_EQ(root_view, result_view); 817 result_view = NULL; 818 819 // Only intersects |v5| but does not cover it by at least 60%. The 820 // center point of the touch region is located within |v5|. 821 touch_rect.SetRect(449, 196, 3, 3); 822 result_view = root_view->GetEventHandlerForRect(touch_rect); 823 EXPECT_EQ(v5, result_view); 824 result_view = NULL; 825 826 // A mouse click within |v5| (but not |v51|) should target |v5|. 827 touch_rect.SetRect(462, 199, 1, 1); 828 result_view = root_view->GetEventHandlerForRect(touch_rect); 829 EXPECT_EQ(v5, result_view); 830 result_view = NULL; 831 832 // A mouse click |v5| and |v51| should target the child view. 833 touch_rect.SetRect(452, 226, 1, 1); 834 result_view = root_view->GetEventHandlerForRect(touch_rect); 835 EXPECT_EQ(v51, result_view); 836 result_view = NULL; 837 838 // A mouse click on the center of |v5| and |v51| should target 839 // the child view. 840 touch_rect.SetRect(465, 215, 1, 1); 841 result_view = root_view->GetEventHandlerForRect(touch_rect); 842 EXPECT_EQ(v51, result_view); 843 result_view = NULL; 844 845 widget->CloseNow(); 846 } 847 848 // Tests that GetEventHandlerForRect() and GetTooltipHandlerForPoint() behave 849 // as expected when different views in the view hierarchy return false 850 // when CanProcessEventsWithinSubtree() is called. 851 TEST_F(ViewTest, CanProcessEventsWithinSubtree) { 852 Widget* widget = new Widget; 853 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 854 widget->Init(params); 855 View* root_view = widget->GetRootView(); 856 root_view->SetBoundsRect(gfx::Rect(0, 0, 500, 500)); 857 858 // Have this hierarchy of views (the coords here are in the coordinate 859 // space of the root view): 860 // v (0, 0, 100, 100) 861 // - v_child (0, 0, 20, 30) 862 // - v_grandchild (5, 5, 5, 15) 863 864 TestView* v = new TestView; 865 v->SetBounds(0, 0, 100, 100); 866 root_view->AddChildView(v); 867 v->set_notify_enter_exit_on_child(true); 868 869 TestView* v_child = new TestView; 870 v_child->SetBounds(0, 0, 20, 30); 871 v->AddChildView(v_child); 872 873 TestView* v_grandchild = new TestView; 874 v_grandchild->SetBounds(5, 5, 5, 15); 875 v_child->AddChildView(v_grandchild); 876 877 v->Reset(); 878 v_child->Reset(); 879 v_grandchild->Reset(); 880 881 // Define rects and points within the views in the hierarchy. 882 gfx::Rect rect_in_v_grandchild(7, 7, 3, 3); 883 gfx::Point point_in_v_grandchild(rect_in_v_grandchild.origin()); 884 gfx::Rect rect_in_v_child(12, 3, 5, 5); 885 gfx::Point point_in_v_child(rect_in_v_child.origin()); 886 gfx::Rect rect_in_v(50, 50, 25, 30); 887 gfx::Point point_in_v(rect_in_v.origin()); 888 889 // When all three views return true when CanProcessEventsWithinSubtree() 890 // is called, targeting should behave as expected. 891 892 View* result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild); 893 EXPECT_EQ(v_grandchild, result_view); 894 result_view = NULL; 895 result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild); 896 EXPECT_EQ(v_grandchild, result_view); 897 result_view = NULL; 898 899 result_view = root_view->GetEventHandlerForRect(rect_in_v_child); 900 EXPECT_EQ(v_child, result_view); 901 result_view = NULL; 902 result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child); 903 EXPECT_EQ(v_child, result_view); 904 result_view = NULL; 905 906 result_view = root_view->GetEventHandlerForRect(rect_in_v); 907 EXPECT_EQ(v, result_view); 908 result_view = NULL; 909 result_view = root_view->GetTooltipHandlerForPoint(point_in_v); 910 EXPECT_EQ(v, result_view); 911 result_view = NULL; 912 913 // When |v_grandchild| returns false when CanProcessEventsWithinSubtree() 914 // is called, then |v_grandchild| cannot be returned as a target. 915 916 v_grandchild->set_can_process_events_within_subtree(false); 917 918 result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild); 919 EXPECT_EQ(v_child, result_view); 920 result_view = NULL; 921 result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild); 922 EXPECT_EQ(v_child, result_view); 923 result_view = NULL; 924 925 result_view = root_view->GetEventHandlerForRect(rect_in_v_child); 926 EXPECT_EQ(v_child, result_view); 927 result_view = NULL; 928 result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child); 929 EXPECT_EQ(v_child, result_view); 930 result_view = NULL; 931 932 result_view = root_view->GetEventHandlerForRect(rect_in_v); 933 EXPECT_EQ(v, result_view); 934 result_view = NULL; 935 result_view = root_view->GetTooltipHandlerForPoint(point_in_v); 936 EXPECT_EQ(v, result_view); 937 938 // When |v_grandchild| returns false when CanProcessEventsWithinSubtree() 939 // is called, then NULL should be returned as a target if we call 940 // GetTooltipHandlerForPoint() with |v_grandchild| as the root of the 941 // views tree. Note that the location must be in the coordinate space 942 // of the root view (|v_grandchild| in this case), so use (1, 1). 943 944 result_view = v_grandchild; 945 result_view = v_grandchild->GetTooltipHandlerForPoint(gfx::Point(1, 1)); 946 EXPECT_EQ(NULL, result_view); 947 result_view = NULL; 948 949 // When |v_child| returns false when CanProcessEventsWithinSubtree() 950 // is called, then neither |v_child| nor |v_grandchild| can be returned 951 // as a target (|v| should be returned as the target for each case). 952 953 v_grandchild->Reset(); 954 v_child->set_can_process_events_within_subtree(false); 955 956 result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild); 957 EXPECT_EQ(v, result_view); 958 result_view = NULL; 959 result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild); 960 EXPECT_EQ(v, result_view); 961 result_view = NULL; 962 963 result_view = root_view->GetEventHandlerForRect(rect_in_v_child); 964 EXPECT_EQ(v, result_view); 965 result_view = NULL; 966 result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child); 967 EXPECT_EQ(v, result_view); 968 result_view = NULL; 969 970 result_view = root_view->GetEventHandlerForRect(rect_in_v); 971 EXPECT_EQ(v, result_view); 972 result_view = NULL; 973 result_view = root_view->GetTooltipHandlerForPoint(point_in_v); 974 EXPECT_EQ(v, result_view); 975 result_view = NULL; 976 977 // When |v| returns false when CanProcessEventsWithinSubtree() 978 // is called, then none of |v|, |v_child|, and |v_grandchild| can be returned 979 // as a target (|root_view| should be returned as the target for each case). 980 981 v_child->Reset(); 982 v->set_can_process_events_within_subtree(false); 983 984 result_view = root_view->GetEventHandlerForRect(rect_in_v_grandchild); 985 EXPECT_EQ(root_view, result_view); 986 result_view = NULL; 987 result_view = root_view->GetTooltipHandlerForPoint(point_in_v_grandchild); 988 EXPECT_EQ(root_view, result_view); 989 result_view = NULL; 990 991 result_view = root_view->GetEventHandlerForRect(rect_in_v_child); 992 EXPECT_EQ(root_view, result_view); 993 result_view = NULL; 994 result_view = root_view->GetTooltipHandlerForPoint(point_in_v_child); 995 EXPECT_EQ(root_view, result_view); 996 result_view = NULL; 997 998 result_view = root_view->GetEventHandlerForRect(rect_in_v); 999 EXPECT_EQ(root_view, result_view); 1000 result_view = NULL; 1001 result_view = root_view->GetTooltipHandlerForPoint(point_in_v); 1002 EXPECT_EQ(root_view, result_view); 1003 } 1004 1005 TEST_F(ViewTest, NotifyEnterExitOnChild) { 1006 Widget* widget = new Widget; 1007 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 1008 widget->Init(params); 1009 View* root_view = widget->GetRootView(); 1010 root_view->SetBoundsRect(gfx::Rect(0, 0, 500, 500)); 1011 1012 // Have this hierarchy of views (the coords here are in root coord): 1013 // v1 (0, 0, 100, 100) 1014 // - v11 (0, 0, 20, 30) 1015 // - v111 (5, 5, 5, 15) 1016 // - v12 (50, 10, 30, 90) 1017 // - v121 (60, 20, 10, 10) 1018 // v2 (105, 0, 100, 100) 1019 // - v21 (120, 10, 50, 20) 1020 1021 TestView* v1 = new TestView; 1022 v1->SetBounds(0, 0, 100, 100); 1023 root_view->AddChildView(v1); 1024 v1->set_notify_enter_exit_on_child(true); 1025 1026 TestView* v11 = new TestView; 1027 v11->SetBounds(0, 0, 20, 30); 1028 v1->AddChildView(v11); 1029 1030 TestView* v111 = new TestView; 1031 v111->SetBounds(5, 5, 5, 15); 1032 v11->AddChildView(v111); 1033 1034 TestView* v12 = new TestView; 1035 v12->SetBounds(50, 10, 30, 90); 1036 v1->AddChildView(v12); 1037 1038 TestView* v121 = new TestView; 1039 v121->SetBounds(10, 10, 10, 10); 1040 v12->AddChildView(v121); 1041 1042 TestView* v2 = new TestView; 1043 v2->SetBounds(105, 0, 100, 100); 1044 root_view->AddChildView(v2); 1045 1046 TestView* v21 = new TestView; 1047 v21->SetBounds(15, 10, 50, 20); 1048 v2->AddChildView(v21); 1049 1050 v1->Reset(); 1051 v11->Reset(); 1052 v111->Reset(); 1053 v12->Reset(); 1054 v121->Reset(); 1055 v2->Reset(); 1056 v21->Reset(); 1057 1058 // Move the mouse in v111. 1059 gfx::Point p1(6, 6); 1060 ui::MouseEvent move1(ui::ET_MOUSE_MOVED, p1, p1, 0, 0); 1061 root_view->OnMouseMoved(move1); 1062 EXPECT_TRUE(v111->received_mouse_enter_); 1063 EXPECT_FALSE(v11->last_mouse_event_type_); 1064 EXPECT_TRUE(v1->received_mouse_enter_); 1065 1066 v111->Reset(); 1067 v1->Reset(); 1068 1069 // Now, move into v121. 1070 gfx::Point p2(65, 21); 1071 ui::MouseEvent move2(ui::ET_MOUSE_MOVED, p2, p2, 0, 0); 1072 root_view->OnMouseMoved(move2); 1073 EXPECT_TRUE(v111->received_mouse_exit_); 1074 EXPECT_TRUE(v121->received_mouse_enter_); 1075 EXPECT_FALSE(v1->last_mouse_event_type_); 1076 1077 v111->Reset(); 1078 v121->Reset(); 1079 1080 // Now, move into v11. 1081 gfx::Point p3(1, 1); 1082 ui::MouseEvent move3(ui::ET_MOUSE_MOVED, p3, p3, 0, 0); 1083 root_view->OnMouseMoved(move3); 1084 EXPECT_TRUE(v121->received_mouse_exit_); 1085 EXPECT_TRUE(v11->received_mouse_enter_); 1086 EXPECT_FALSE(v1->last_mouse_event_type_); 1087 1088 v121->Reset(); 1089 v11->Reset(); 1090 1091 // Move to v21. 1092 gfx::Point p4(121, 15); 1093 ui::MouseEvent move4(ui::ET_MOUSE_MOVED, p4, p4, 0, 0); 1094 root_view->OnMouseMoved(move4); 1095 EXPECT_TRUE(v21->received_mouse_enter_); 1096 EXPECT_FALSE(v2->last_mouse_event_type_); 1097 EXPECT_TRUE(v11->received_mouse_exit_); 1098 EXPECT_TRUE(v1->received_mouse_exit_); 1099 1100 v21->Reset(); 1101 v11->Reset(); 1102 v1->Reset(); 1103 1104 // Move to v1. 1105 gfx::Point p5(21, 0); 1106 ui::MouseEvent move5(ui::ET_MOUSE_MOVED, p5, p5, 0, 0); 1107 root_view->OnMouseMoved(move5); 1108 EXPECT_TRUE(v21->received_mouse_exit_); 1109 EXPECT_TRUE(v1->received_mouse_enter_); 1110 1111 v21->Reset(); 1112 v1->Reset(); 1113 1114 // Now, move into v11. 1115 gfx::Point p6(15, 15); 1116 ui::MouseEvent mouse6(ui::ET_MOUSE_MOVED, p6, p6, 0, 0); 1117 root_view->OnMouseMoved(mouse6); 1118 EXPECT_TRUE(v11->received_mouse_enter_); 1119 EXPECT_FALSE(v1->last_mouse_event_type_); 1120 1121 v11->Reset(); 1122 v1->Reset(); 1123 1124 // Move back into v1. Although |v1| had already received an ENTER for mouse6, 1125 // and the mouse remains inside |v1| the whole time, it receives another ENTER 1126 // when the mouse leaves v11. 1127 gfx::Point p7(21, 0); 1128 ui::MouseEvent mouse7(ui::ET_MOUSE_MOVED, p7, p7, 0, 0); 1129 root_view->OnMouseMoved(mouse7); 1130 EXPECT_TRUE(v11->received_mouse_exit_); 1131 EXPECT_FALSE(v1->received_mouse_enter_); 1132 1133 widget->CloseNow(); 1134 } 1135 1136 TEST_F(ViewTest, Textfield) { 1137 const base::string16 kText = ASCIIToUTF16( 1138 "Reality is that which, when you stop believing it, doesn't go away."); 1139 const base::string16 kExtraText = ASCIIToUTF16("Pretty deep, Philip!"); 1140 1141 Widget* widget = new Widget; 1142 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 1143 params.bounds = gfx::Rect(0, 0, 100, 100); 1144 widget->Init(params); 1145 View* root_view = widget->GetRootView(); 1146 1147 Textfield* textfield = new Textfield(); 1148 root_view->AddChildView(textfield); 1149 1150 // Test setting, appending text. 1151 textfield->SetText(kText); 1152 EXPECT_EQ(kText, textfield->text()); 1153 textfield->AppendText(kExtraText); 1154 EXPECT_EQ(kText + kExtraText, textfield->text()); 1155 textfield->SetText(base::string16()); 1156 EXPECT_TRUE(textfield->text().empty()); 1157 1158 // Test selection related methods. 1159 textfield->SetText(kText); 1160 EXPECT_TRUE(textfield->GetSelectedText().empty()); 1161 textfield->SelectAll(false); 1162 EXPECT_EQ(kText, textfield->text()); 1163 textfield->ClearSelection(); 1164 EXPECT_TRUE(textfield->GetSelectedText().empty()); 1165 1166 widget->CloseNow(); 1167 } 1168 1169 // Tests that the Textfield view respond appropiately to cut/copy/paste. 1170 TEST_F(ViewTest, TextfieldCutCopyPaste) { 1171 const base::string16 kNormalText = ASCIIToUTF16("Normal"); 1172 const base::string16 kReadOnlyText = ASCIIToUTF16("Read only"); 1173 const base::string16 kPasswordText = 1174 ASCIIToUTF16("Password! ** Secret stuff **"); 1175 1176 ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); 1177 1178 Widget* widget = new Widget; 1179 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 1180 params.bounds = gfx::Rect(0, 0, 100, 100); 1181 widget->Init(params); 1182 View* root_view = widget->GetRootView(); 1183 1184 Textfield* normal = new Textfield(); 1185 Textfield* read_only = new Textfield(); 1186 read_only->SetReadOnly(true); 1187 Textfield* password = new Textfield(); 1188 password->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD); 1189 1190 root_view->AddChildView(normal); 1191 root_view->AddChildView(read_only); 1192 root_view->AddChildView(password); 1193 1194 normal->SetText(kNormalText); 1195 read_only->SetText(kReadOnlyText); 1196 password->SetText(kPasswordText); 1197 1198 // 1199 // Test cut. 1200 // 1201 1202 normal->SelectAll(false); 1203 normal->ExecuteCommand(IDS_APP_CUT); 1204 base::string16 result; 1205 clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result); 1206 EXPECT_EQ(kNormalText, result); 1207 normal->SetText(kNormalText); // Let's revert to the original content. 1208 1209 read_only->SelectAll(false); 1210 read_only->ExecuteCommand(IDS_APP_CUT); 1211 result.clear(); 1212 clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result); 1213 // Cut should have failed, so the clipboard content should not have changed. 1214 EXPECT_EQ(kNormalText, result); 1215 1216 password->SelectAll(false); 1217 password->ExecuteCommand(IDS_APP_CUT); 1218 result.clear(); 1219 clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result); 1220 // Cut should have failed, so the clipboard content should not have changed. 1221 EXPECT_EQ(kNormalText, result); 1222 1223 // 1224 // Test copy. 1225 // 1226 1227 // Start with |read_only| to observe a change in clipboard text. 1228 read_only->SelectAll(false); 1229 read_only->ExecuteCommand(IDS_APP_COPY); 1230 result.clear(); 1231 clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result); 1232 EXPECT_EQ(kReadOnlyText, result); 1233 1234 normal->SelectAll(false); 1235 normal->ExecuteCommand(IDS_APP_COPY); 1236 result.clear(); 1237 clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result); 1238 EXPECT_EQ(kNormalText, result); 1239 1240 password->SelectAll(false); 1241 password->ExecuteCommand(IDS_APP_COPY); 1242 result.clear(); 1243 clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result); 1244 // Text cannot be copied from an obscured field; the clipboard won't change. 1245 EXPECT_EQ(kNormalText, result); 1246 1247 // 1248 // Test paste. 1249 // 1250 1251 // Attempting to paste kNormalText in a read-only text-field should fail. 1252 read_only->SelectAll(false); 1253 read_only->ExecuteCommand(IDS_APP_PASTE); 1254 EXPECT_EQ(kReadOnlyText, read_only->text()); 1255 1256 password->SelectAll(false); 1257 password->ExecuteCommand(IDS_APP_PASTE); 1258 EXPECT_EQ(kNormalText, password->text()); 1259 1260 // Copy from |read_only| to observe a change in the normal textfield text. 1261 read_only->SelectAll(false); 1262 read_only->ExecuteCommand(IDS_APP_COPY); 1263 normal->SelectAll(false); 1264 normal->ExecuteCommand(IDS_APP_PASTE); 1265 EXPECT_EQ(kReadOnlyText, normal->text()); 1266 widget->CloseNow(); 1267 } 1268 1269 //////////////////////////////////////////////////////////////////////////////// 1270 // Accelerators 1271 //////////////////////////////////////////////////////////////////////////////// 1272 bool TestView::AcceleratorPressed(const ui::Accelerator& accelerator) { 1273 accelerator_count_map_[accelerator]++; 1274 return true; 1275 } 1276 1277 // TODO: these tests were initially commented out when getting aura to 1278 // run. Figure out if still valuable and either nuke or fix. 1279 #if 0 1280 TEST_F(ViewTest, ActivateAccelerator) { 1281 // Register a keyboard accelerator before the view is added to a window. 1282 ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE); 1283 TestView* view = new TestView(); 1284 view->Reset(); 1285 view->AddAccelerator(return_accelerator); 1286 EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 0); 1287 1288 // Create a window and add the view as its child. 1289 scoped_ptr<Widget> widget(new Widget); 1290 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 1291 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 1292 params.bounds = gfx::Rect(0, 0, 100, 100); 1293 widget->Init(params); 1294 View* root = widget->GetRootView(); 1295 root->AddChildView(view); 1296 widget->Show(); 1297 1298 // Get the focus manager. 1299 FocusManager* focus_manager = widget->GetFocusManager(); 1300 ASSERT_TRUE(focus_manager); 1301 1302 // Hit the return key and see if it takes effect. 1303 EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator)); 1304 EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 1); 1305 1306 // Hit the escape key. Nothing should happen. 1307 ui::Accelerator escape_accelerator(ui::VKEY_ESCAPE, ui::EF_NONE); 1308 EXPECT_FALSE(focus_manager->ProcessAccelerator(escape_accelerator)); 1309 EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 1); 1310 EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 0); 1311 1312 // Now register the escape key and hit it again. 1313 view->AddAccelerator(escape_accelerator); 1314 EXPECT_TRUE(focus_manager->ProcessAccelerator(escape_accelerator)); 1315 EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 1); 1316 EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 1); 1317 1318 // Remove the return key accelerator. 1319 view->RemoveAccelerator(return_accelerator); 1320 EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator)); 1321 EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 1); 1322 EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 1); 1323 1324 // Add it again. Hit the return key and the escape key. 1325 view->AddAccelerator(return_accelerator); 1326 EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator)); 1327 EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 2); 1328 EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 1); 1329 EXPECT_TRUE(focus_manager->ProcessAccelerator(escape_accelerator)); 1330 EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 2); 1331 EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 2); 1332 1333 // Remove all the accelerators. 1334 view->ResetAccelerators(); 1335 EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator)); 1336 EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 2); 1337 EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 2); 1338 EXPECT_FALSE(focus_manager->ProcessAccelerator(escape_accelerator)); 1339 EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 2); 1340 EXPECT_EQ(view->accelerator_count_map_[escape_accelerator], 2); 1341 1342 widget->CloseNow(); 1343 } 1344 1345 TEST_F(ViewTest, HiddenViewWithAccelerator) { 1346 ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE); 1347 TestView* view = new TestView(); 1348 view->Reset(); 1349 view->AddAccelerator(return_accelerator); 1350 EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 0); 1351 1352 scoped_ptr<Widget> widget(new Widget); 1353 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 1354 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 1355 params.bounds = gfx::Rect(0, 0, 100, 100); 1356 widget->Init(params); 1357 View* root = widget->GetRootView(); 1358 root->AddChildView(view); 1359 widget->Show(); 1360 1361 FocusManager* focus_manager = widget->GetFocusManager(); 1362 ASSERT_TRUE(focus_manager); 1363 1364 view->SetVisible(false); 1365 EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator)); 1366 1367 view->SetVisible(true); 1368 EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator)); 1369 1370 widget->CloseNow(); 1371 } 1372 1373 TEST_F(ViewTest, ViewInHiddenWidgetWithAccelerator) { 1374 ui::Accelerator return_accelerator(ui::VKEY_RETURN, ui::EF_NONE); 1375 TestView* view = new TestView(); 1376 view->Reset(); 1377 view->AddAccelerator(return_accelerator); 1378 EXPECT_EQ(view->accelerator_count_map_[return_accelerator], 0); 1379 1380 scoped_ptr<Widget> widget(new Widget); 1381 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 1382 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 1383 params.bounds = gfx::Rect(0, 0, 100, 100); 1384 widget->Init(params); 1385 View* root = widget->GetRootView(); 1386 root->AddChildView(view); 1387 1388 FocusManager* focus_manager = widget->GetFocusManager(); 1389 ASSERT_TRUE(focus_manager); 1390 1391 EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator)); 1392 EXPECT_EQ(0, view->accelerator_count_map_[return_accelerator]); 1393 1394 widget->Show(); 1395 EXPECT_TRUE(focus_manager->ProcessAccelerator(return_accelerator)); 1396 EXPECT_EQ(1, view->accelerator_count_map_[return_accelerator]); 1397 1398 widget->Hide(); 1399 EXPECT_FALSE(focus_manager->ProcessAccelerator(return_accelerator)); 1400 EXPECT_EQ(1, view->accelerator_count_map_[return_accelerator]); 1401 1402 widget->CloseNow(); 1403 } 1404 1405 //////////////////////////////////////////////////////////////////////////////// 1406 // Mouse-wheel message rerouting 1407 //////////////////////////////////////////////////////////////////////////////// 1408 class ScrollableTestView : public View { 1409 public: 1410 ScrollableTestView() { } 1411 1412 virtual gfx::Size GetPreferredSize() { 1413 return gfx::Size(100, 10000); 1414 } 1415 1416 virtual void Layout() { 1417 SizeToPreferredSize(); 1418 } 1419 }; 1420 1421 class TestViewWithControls : public View { 1422 public: 1423 TestViewWithControls() { 1424 text_field_ = new Textfield(); 1425 AddChildView(text_field_); 1426 } 1427 1428 Textfield* text_field_; 1429 }; 1430 1431 class SimpleWidgetDelegate : public WidgetDelegate { 1432 public: 1433 explicit SimpleWidgetDelegate(View* contents) : contents_(contents) { } 1434 1435 virtual void DeleteDelegate() { delete this; } 1436 1437 virtual View* GetContentsView() { return contents_; } 1438 1439 virtual Widget* GetWidget() { return contents_->GetWidget(); } 1440 virtual const Widget* GetWidget() const { return contents_->GetWidget(); } 1441 1442 private: 1443 View* contents_; 1444 }; 1445 1446 // Tests that the mouse-wheel messages are correctly rerouted to the window 1447 // under the mouse. 1448 // TODO(jcampan): http://crbug.com/10572 Disabled as it fails on the Vista build 1449 // bot. 1450 // Note that this fails for a variety of reasons: 1451 // - focused view is apparently reset across window activations and never 1452 // properly restored 1453 // - this test depends on you not having any other window visible open under the 1454 // area that it opens the test windows. --beng 1455 TEST_F(ViewTest, DISABLED_RerouteMouseWheelTest) { 1456 TestViewWithControls* view_with_controls = new TestViewWithControls(); 1457 Widget* window1 = Widget::CreateWindowWithBounds( 1458 new SimpleWidgetDelegate(view_with_controls), 1459 gfx::Rect(0, 0, 100, 100)); 1460 window1->Show(); 1461 ScrollView* scroll_view = new ScrollView(); 1462 scroll_view->SetContents(new ScrollableTestView()); 1463 Widget* window2 = Widget::CreateWindowWithBounds( 1464 new SimpleWidgetDelegate(scroll_view), 1465 gfx::Rect(200, 200, 100, 100)); 1466 window2->Show(); 1467 EXPECT_EQ(0, scroll_view->GetVisibleRect().y()); 1468 1469 // Make the window1 active, as this is what it would be in real-world. 1470 window1->Activate(); 1471 1472 // Let's send a mouse-wheel message to the different controls and check that 1473 // it is rerouted to the window under the mouse (effectively scrolling the 1474 // scroll-view). 1475 1476 // First to the Window's HWND. 1477 ::SendMessage(view_with_controls->GetWidget()->GetNativeView(), 1478 WM_MOUSEWHEEL, MAKEWPARAM(0, -20), MAKELPARAM(250, 250)); 1479 EXPECT_EQ(20, scroll_view->GetVisibleRect().y()); 1480 1481 window1->CloseNow(); 1482 window2->CloseNow(); 1483 } 1484 #endif // 0 1485 1486 //////////////////////////////////////////////////////////////////////////////// 1487 // Native view hierachy 1488 //////////////////////////////////////////////////////////////////////////////// 1489 class ToplevelWidgetObserverView : public View { 1490 public: 1491 ToplevelWidgetObserverView() : toplevel_(NULL) { 1492 } 1493 virtual ~ToplevelWidgetObserverView() { 1494 } 1495 1496 // View overrides: 1497 virtual void ViewHierarchyChanged( 1498 const ViewHierarchyChangedDetails& details) OVERRIDE { 1499 if (details.is_add) { 1500 toplevel_ = GetWidget() ? GetWidget()->GetTopLevelWidget() : NULL; 1501 } else { 1502 toplevel_ = NULL; 1503 } 1504 } 1505 virtual void NativeViewHierarchyChanged() OVERRIDE { 1506 toplevel_ = GetWidget() ? GetWidget()->GetTopLevelWidget() : NULL; 1507 } 1508 1509 Widget* toplevel() { return toplevel_; } 1510 1511 private: 1512 Widget* toplevel_; 1513 1514 DISALLOW_COPY_AND_ASSIGN(ToplevelWidgetObserverView); 1515 }; 1516 1517 // Test that a view can track the current top level widget by overriding 1518 // View::ViewHierarchyChanged() and View::NativeViewHierarchyChanged(). 1519 TEST_F(ViewTest, NativeViewHierarchyChanged) { 1520 scoped_ptr<Widget> toplevel1(new Widget); 1521 Widget::InitParams toplevel1_params = 1522 CreateParams(Widget::InitParams::TYPE_POPUP); 1523 toplevel1_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 1524 toplevel1->Init(toplevel1_params); 1525 1526 scoped_ptr<Widget> toplevel2(new Widget); 1527 Widget::InitParams toplevel2_params = 1528 CreateParams(Widget::InitParams::TYPE_POPUP); 1529 toplevel2_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 1530 toplevel2->Init(toplevel2_params); 1531 1532 Widget* child = new Widget; 1533 Widget::InitParams child_params(Widget::InitParams::TYPE_CONTROL); 1534 child_params.parent = toplevel1->GetNativeView(); 1535 child->Init(child_params); 1536 1537 ToplevelWidgetObserverView* observer_view = 1538 new ToplevelWidgetObserverView(); 1539 EXPECT_EQ(NULL, observer_view->toplevel()); 1540 1541 child->SetContentsView(observer_view); 1542 EXPECT_EQ(toplevel1, observer_view->toplevel()); 1543 1544 Widget::ReparentNativeView(child->GetNativeView(), 1545 toplevel2->GetNativeView()); 1546 EXPECT_EQ(toplevel2, observer_view->toplevel()); 1547 1548 observer_view->parent()->RemoveChildView(observer_view); 1549 EXPECT_EQ(NULL, observer_view->toplevel()); 1550 1551 // Make |observer_view| |child|'s contents view again so that it gets deleted 1552 // with the widget. 1553 child->SetContentsView(observer_view); 1554 } 1555 1556 //////////////////////////////////////////////////////////////////////////////// 1557 // Transformations 1558 //////////////////////////////////////////////////////////////////////////////// 1559 1560 class TransformPaintView : public TestView { 1561 public: 1562 TransformPaintView() {} 1563 virtual ~TransformPaintView() {} 1564 1565 void ClearScheduledPaintRect() { 1566 scheduled_paint_rect_ = gfx::Rect(); 1567 } 1568 1569 gfx::Rect scheduled_paint_rect() const { return scheduled_paint_rect_; } 1570 1571 // Overridden from View: 1572 virtual void SchedulePaintInRect(const gfx::Rect& rect) OVERRIDE { 1573 gfx::Rect xrect = ConvertRectToParent(rect); 1574 scheduled_paint_rect_.Union(xrect); 1575 } 1576 1577 private: 1578 gfx::Rect scheduled_paint_rect_; 1579 1580 DISALLOW_COPY_AND_ASSIGN(TransformPaintView); 1581 }; 1582 1583 TEST_F(ViewTest, TransformPaint) { 1584 TransformPaintView* v1 = new TransformPaintView(); 1585 v1->SetBoundsRect(gfx::Rect(0, 0, 500, 300)); 1586 1587 TestView* v2 = new TestView(); 1588 v2->SetBoundsRect(gfx::Rect(100, 100, 200, 100)); 1589 1590 Widget* widget = new Widget; 1591 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 1592 params.bounds = gfx::Rect(50, 50, 650, 650); 1593 widget->Init(params); 1594 widget->Show(); 1595 View* root = widget->GetRootView(); 1596 1597 root->AddChildView(v1); 1598 v1->AddChildView(v2); 1599 1600 // At this moment, |v2| occupies (100, 100) to (300, 200) in |root|. 1601 v1->ClearScheduledPaintRect(); 1602 v2->SchedulePaint(); 1603 1604 EXPECT_EQ(gfx::Rect(100, 100, 200, 100), v1->scheduled_paint_rect()); 1605 1606 // Rotate |v1| counter-clockwise. 1607 gfx::Transform transform; 1608 RotateCounterclockwise(&transform); 1609 transform.matrix().set(1, 3, 500.0); 1610 v1->SetTransform(transform); 1611 1612 // |v2| now occupies (100, 200) to (200, 400) in |root|. 1613 1614 v1->ClearScheduledPaintRect(); 1615 v2->SchedulePaint(); 1616 1617 EXPECT_EQ(gfx::Rect(100, 200, 100, 200), v1->scheduled_paint_rect()); 1618 1619 widget->CloseNow(); 1620 } 1621 1622 TEST_F(ViewTest, TransformEvent) { 1623 TestView* v1 = new TestView(); 1624 v1->SetBoundsRect(gfx::Rect(0, 0, 500, 300)); 1625 1626 TestView* v2 = new TestView(); 1627 v2->SetBoundsRect(gfx::Rect(100, 100, 200, 100)); 1628 1629 Widget* widget = new Widget; 1630 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 1631 params.bounds = gfx::Rect(50, 50, 650, 650); 1632 widget->Init(params); 1633 View* root = widget->GetRootView(); 1634 1635 root->AddChildView(v1); 1636 v1->AddChildView(v2); 1637 1638 // At this moment, |v2| occupies (100, 100) to (300, 200) in |root|. 1639 1640 // Rotate |v1| counter-clockwise. 1641 gfx::Transform transform(v1->GetTransform()); 1642 RotateCounterclockwise(&transform); 1643 transform.matrix().set(1, 3, 500.0); 1644 v1->SetTransform(transform); 1645 1646 // |v2| now occupies (100, 200) to (200, 400) in |root|. 1647 v1->Reset(); 1648 v2->Reset(); 1649 1650 gfx::Point p1(110, 210); 1651 ui::MouseEvent pressed(ui::ET_MOUSE_PRESSED, p1, p1, 1652 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); 1653 root->OnMousePressed(pressed); 1654 EXPECT_EQ(0, v1->last_mouse_event_type_); 1655 EXPECT_EQ(ui::ET_MOUSE_PRESSED, v2->last_mouse_event_type_); 1656 EXPECT_EQ(190, v2->location_.x()); 1657 EXPECT_EQ(10, v2->location_.y()); 1658 1659 ui::MouseEvent released(ui::ET_MOUSE_RELEASED, gfx::Point(), gfx::Point(), 0, 1660 0); 1661 root->OnMouseReleased(released); 1662 1663 // Now rotate |v2| inside |v1| clockwise. 1664 transform = v2->GetTransform(); 1665 RotateClockwise(&transform); 1666 transform.matrix().set(0, 3, 100.f); 1667 v2->SetTransform(transform); 1668 1669 // Now, |v2| occupies (100, 100) to (200, 300) in |v1|, and (100, 300) to 1670 // (300, 400) in |root|. 1671 1672 v1->Reset(); 1673 v2->Reset(); 1674 1675 gfx::Point point2(110, 320); 1676 ui::MouseEvent p2(ui::ET_MOUSE_PRESSED, point2, point2, 1677 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); 1678 root->OnMousePressed(p2); 1679 EXPECT_EQ(0, v1->last_mouse_event_type_); 1680 EXPECT_EQ(ui::ET_MOUSE_PRESSED, v2->last_mouse_event_type_); 1681 EXPECT_EQ(10, v2->location_.x()); 1682 EXPECT_EQ(20, v2->location_.y()); 1683 1684 root->OnMouseReleased(released); 1685 1686 v1->SetTransform(gfx::Transform()); 1687 v2->SetTransform(gfx::Transform()); 1688 1689 TestView* v3 = new TestView(); 1690 v3->SetBoundsRect(gfx::Rect(10, 10, 20, 30)); 1691 v2->AddChildView(v3); 1692 1693 // Rotate |v3| clockwise with respect to |v2|. 1694 transform = v1->GetTransform(); 1695 RotateClockwise(&transform); 1696 transform.matrix().set(0, 3, 30.f); 1697 v3->SetTransform(transform); 1698 1699 // Scale |v2| with respect to |v1| along both axis. 1700 transform = v2->GetTransform(); 1701 transform.matrix().set(0, 0, 0.8f); 1702 transform.matrix().set(1, 1, 0.5f); 1703 v2->SetTransform(transform); 1704 1705 // |v3| occupies (108, 105) to (132, 115) in |root|. 1706 1707 v1->Reset(); 1708 v2->Reset(); 1709 v3->Reset(); 1710 1711 gfx::Point point(112, 110); 1712 ui::MouseEvent p3(ui::ET_MOUSE_PRESSED, point, point, 1713 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); 1714 root->OnMousePressed(p3); 1715 1716 EXPECT_EQ(ui::ET_MOUSE_PRESSED, v3->last_mouse_event_type_); 1717 EXPECT_EQ(10, v3->location_.x()); 1718 EXPECT_EQ(25, v3->location_.y()); 1719 1720 root->OnMouseReleased(released); 1721 1722 v1->SetTransform(gfx::Transform()); 1723 v2->SetTransform(gfx::Transform()); 1724 v3->SetTransform(gfx::Transform()); 1725 1726 v1->Reset(); 1727 v2->Reset(); 1728 v3->Reset(); 1729 1730 // Rotate |v3| clockwise with respect to |v2|, and scale it along both axis. 1731 transform = v3->GetTransform(); 1732 RotateClockwise(&transform); 1733 transform.matrix().set(0, 3, 30.f); 1734 // Rotation sets some scaling transformation. Using SetScale would overwrite 1735 // that and pollute the rotation. So combine the scaling with the existing 1736 // transforamtion. 1737 gfx::Transform scale; 1738 scale.Scale(0.8f, 0.5f); 1739 transform.ConcatTransform(scale); 1740 v3->SetTransform(transform); 1741 1742 // Translate |v2| with respect to |v1|. 1743 transform = v2->GetTransform(); 1744 transform.matrix().set(0, 3, 10.f); 1745 transform.matrix().set(1, 3, 10.f); 1746 v2->SetTransform(transform); 1747 1748 // |v3| now occupies (120, 120) to (144, 130) in |root|. 1749 1750 gfx::Point point3(124, 125); 1751 ui::MouseEvent p4(ui::ET_MOUSE_PRESSED, point3, point3, 1752 ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON); 1753 root->OnMousePressed(p4); 1754 1755 EXPECT_EQ(ui::ET_MOUSE_PRESSED, v3->last_mouse_event_type_); 1756 EXPECT_EQ(10, v3->location_.x()); 1757 EXPECT_EQ(25, v3->location_.y()); 1758 1759 root->OnMouseReleased(released); 1760 1761 widget->CloseNow(); 1762 } 1763 1764 TEST_F(ViewTest, TransformVisibleBound) { 1765 gfx::Rect viewport_bounds(0, 0, 100, 100); 1766 1767 scoped_ptr<Widget> widget(new Widget); 1768 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 1769 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 1770 params.bounds = viewport_bounds; 1771 widget->Init(params); 1772 widget->GetRootView()->SetBoundsRect(viewport_bounds); 1773 1774 View* viewport = new View; 1775 widget->SetContentsView(viewport); 1776 View* contents = new View; 1777 viewport->AddChildView(contents); 1778 viewport->SetBoundsRect(viewport_bounds); 1779 contents->SetBoundsRect(gfx::Rect(0, 0, 100, 200)); 1780 1781 View* child = new View; 1782 contents->AddChildView(child); 1783 child->SetBoundsRect(gfx::Rect(10, 90, 50, 50)); 1784 EXPECT_EQ(gfx::Rect(0, 0, 50, 10), child->GetVisibleBounds()); 1785 1786 // Rotate |child| counter-clockwise 1787 gfx::Transform transform; 1788 RotateCounterclockwise(&transform); 1789 transform.matrix().set(1, 3, 50.f); 1790 child->SetTransform(transform); 1791 EXPECT_EQ(gfx::Rect(40, 0, 10, 50), child->GetVisibleBounds()); 1792 1793 widget->CloseNow(); 1794 } 1795 1796 //////////////////////////////////////////////////////////////////////////////// 1797 // OnVisibleBoundsChanged() 1798 1799 class VisibleBoundsView : public View { 1800 public: 1801 VisibleBoundsView() : received_notification_(false) {} 1802 virtual ~VisibleBoundsView() {} 1803 1804 bool received_notification() const { return received_notification_; } 1805 void set_received_notification(bool received) { 1806 received_notification_ = received; 1807 } 1808 1809 private: 1810 // Overridden from View: 1811 virtual bool GetNeedsNotificationWhenVisibleBoundsChange() const OVERRIDE { 1812 return true; 1813 } 1814 virtual void OnVisibleBoundsChanged() OVERRIDE { 1815 received_notification_ = true; 1816 } 1817 1818 bool received_notification_; 1819 1820 DISALLOW_COPY_AND_ASSIGN(VisibleBoundsView); 1821 }; 1822 1823 TEST_F(ViewTest, OnVisibleBoundsChanged) { 1824 gfx::Rect viewport_bounds(0, 0, 100, 100); 1825 1826 scoped_ptr<Widget> widget(new Widget); 1827 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 1828 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 1829 params.bounds = viewport_bounds; 1830 widget->Init(params); 1831 widget->GetRootView()->SetBoundsRect(viewport_bounds); 1832 1833 View* viewport = new View; 1834 widget->SetContentsView(viewport); 1835 View* contents = new View; 1836 viewport->AddChildView(contents); 1837 viewport->SetBoundsRect(viewport_bounds); 1838 contents->SetBoundsRect(gfx::Rect(0, 0, 100, 200)); 1839 1840 // Create a view that cares about visible bounds notifications, and position 1841 // it just outside the visible bounds of the viewport. 1842 VisibleBoundsView* child = new VisibleBoundsView; 1843 contents->AddChildView(child); 1844 child->SetBoundsRect(gfx::Rect(10, 110, 50, 50)); 1845 1846 // The child bound should be fully clipped. 1847 EXPECT_TRUE(child->GetVisibleBounds().IsEmpty()); 1848 1849 // Now scroll the contents, but not enough to make the child visible. 1850 contents->SetY(contents->y() - 1); 1851 1852 // We should have received the notification since the visible bounds may have 1853 // changed (even though they didn't). 1854 EXPECT_TRUE(child->received_notification()); 1855 EXPECT_TRUE(child->GetVisibleBounds().IsEmpty()); 1856 child->set_received_notification(false); 1857 1858 // Now scroll the contents, this time by enough to make the child visible by 1859 // one pixel. 1860 contents->SetY(contents->y() - 10); 1861 EXPECT_TRUE(child->received_notification()); 1862 EXPECT_EQ(1, child->GetVisibleBounds().height()); 1863 child->set_received_notification(false); 1864 1865 widget->CloseNow(); 1866 } 1867 1868 TEST_F(ViewTest, SetBoundsPaint) { 1869 TestView top_view; 1870 TestView* child_view = new TestView; 1871 1872 top_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100)); 1873 top_view.scheduled_paint_rects_.clear(); 1874 child_view->SetBoundsRect(gfx::Rect(10, 10, 20, 20)); 1875 top_view.AddChildView(child_view); 1876 1877 top_view.scheduled_paint_rects_.clear(); 1878 child_view->SetBoundsRect(gfx::Rect(30, 30, 20, 20)); 1879 EXPECT_EQ(2U, top_view.scheduled_paint_rects_.size()); 1880 1881 // There should be 2 rects, spanning from (10, 10) to (50, 50). 1882 gfx::Rect paint_rect = top_view.scheduled_paint_rects_[0]; 1883 paint_rect.Union(top_view.scheduled_paint_rects_[1]); 1884 EXPECT_EQ(gfx::Rect(10, 10, 40, 40), paint_rect); 1885 } 1886 1887 // Assertions around painting and focus gain/lost. 1888 TEST_F(ViewTest, FocusBlurPaints) { 1889 TestView parent_view; 1890 TestView* child_view1 = new TestView; // Owned by |parent_view|. 1891 1892 parent_view.SetBoundsRect(gfx::Rect(0, 0, 100, 100)); 1893 1894 child_view1->SetBoundsRect(gfx::Rect(0, 0, 20, 20)); 1895 parent_view.AddChildView(child_view1); 1896 1897 parent_view.scheduled_paint_rects_.clear(); 1898 child_view1->scheduled_paint_rects_.clear(); 1899 1900 // Focus change shouldn't trigger paints. 1901 child_view1->DoFocus(); 1902 1903 EXPECT_TRUE(parent_view.scheduled_paint_rects_.empty()); 1904 EXPECT_TRUE(child_view1->scheduled_paint_rects_.empty()); 1905 1906 child_view1->DoBlur(); 1907 EXPECT_TRUE(parent_view.scheduled_paint_rects_.empty()); 1908 EXPECT_TRUE(child_view1->scheduled_paint_rects_.empty()); 1909 } 1910 1911 // Verifies SetBounds(same bounds) doesn't trigger a SchedulePaint(). 1912 TEST_F(ViewTest, SetBoundsSameBoundsDoesntSchedulePaint) { 1913 TestView view; 1914 1915 view.SetBoundsRect(gfx::Rect(0, 0, 100, 100)); 1916 view.InvalidateLayout(); 1917 view.scheduled_paint_rects_.clear(); 1918 view.SetBoundsRect(gfx::Rect(0, 0, 100, 100)); 1919 EXPECT_TRUE(view.scheduled_paint_rects_.empty()); 1920 } 1921 1922 // Verifies AddChildView() and RemoveChildView() schedule appropriate paints. 1923 TEST_F(ViewTest, AddAndRemoveSchedulePaints) { 1924 gfx::Rect viewport_bounds(0, 0, 100, 100); 1925 1926 // We have to put the View hierarchy into a Widget or no paints will be 1927 // scheduled. 1928 scoped_ptr<Widget> widget(new Widget); 1929 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 1930 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 1931 params.bounds = viewport_bounds; 1932 widget->Init(params); 1933 widget->GetRootView()->SetBoundsRect(viewport_bounds); 1934 1935 TestView* parent_view = new TestView; 1936 widget->SetContentsView(parent_view); 1937 parent_view->SetBoundsRect(viewport_bounds); 1938 parent_view->scheduled_paint_rects_.clear(); 1939 1940 View* child_view = new View; 1941 child_view->SetBoundsRect(gfx::Rect(0, 0, 20, 20)); 1942 parent_view->AddChildView(child_view); 1943 ASSERT_EQ(1U, parent_view->scheduled_paint_rects_.size()); 1944 EXPECT_EQ(child_view->bounds(), parent_view->scheduled_paint_rects_.front()); 1945 1946 parent_view->scheduled_paint_rects_.clear(); 1947 parent_view->RemoveChildView(child_view); 1948 scoped_ptr<View> child_deleter(child_view); 1949 ASSERT_EQ(1U, parent_view->scheduled_paint_rects_.size()); 1950 EXPECT_EQ(child_view->bounds(), parent_view->scheduled_paint_rects_.front()); 1951 1952 widget->CloseNow(); 1953 } 1954 1955 // Tests conversion methods with a transform. 1956 TEST_F(ViewTest, ConversionsWithTransform) { 1957 TestView top_view; 1958 1959 // View hierarchy used to test scale transforms. 1960 TestView* child = new TestView; 1961 TestView* child_child = new TestView; 1962 1963 // View used to test a rotation transform. 1964 TestView* child_2 = new TestView; 1965 1966 top_view.AddChildView(child); 1967 child->AddChildView(child_child); 1968 1969 top_view.SetBoundsRect(gfx::Rect(0, 0, 1000, 1000)); 1970 1971 child->SetBoundsRect(gfx::Rect(7, 19, 500, 500)); 1972 gfx::Transform transform; 1973 transform.Scale(3.0, 4.0); 1974 child->SetTransform(transform); 1975 1976 child_child->SetBoundsRect(gfx::Rect(17, 13, 100, 100)); 1977 transform.MakeIdentity(); 1978 transform.Scale(5.0, 7.0); 1979 child_child->SetTransform(transform); 1980 1981 top_view.AddChildView(child_2); 1982 child_2->SetBoundsRect(gfx::Rect(700, 725, 100, 100)); 1983 transform.MakeIdentity(); 1984 RotateClockwise(&transform); 1985 child_2->SetTransform(transform); 1986 1987 // Sanity check to make sure basic transforms act as expected. 1988 { 1989 gfx::Transform transform; 1990 transform.Translate(110.0, -110.0); 1991 transform.Scale(100.0, 55.0); 1992 transform.Translate(1.0, 1.0); 1993 1994 // convert to a 3x3 matrix. 1995 const SkMatrix& matrix = transform.matrix(); 1996 1997 EXPECT_EQ(210, matrix.getTranslateX()); 1998 EXPECT_EQ(-55, matrix.getTranslateY()); 1999 EXPECT_EQ(100, matrix.getScaleX()); 2000 EXPECT_EQ(55, matrix.getScaleY()); 2001 EXPECT_EQ(0, matrix.getSkewX()); 2002 EXPECT_EQ(0, matrix.getSkewY()); 2003 } 2004 2005 { 2006 gfx::Transform transform; 2007 transform.Translate(1.0, 1.0); 2008 gfx::Transform t2; 2009 t2.Scale(100.0, 55.0); 2010 gfx::Transform t3; 2011 t3.Translate(110.0, -110.0); 2012 transform.ConcatTransform(t2); 2013 transform.ConcatTransform(t3); 2014 2015 // convert to a 3x3 matrix 2016 const SkMatrix& matrix = transform.matrix(); 2017 2018 EXPECT_EQ(210, matrix.getTranslateX()); 2019 EXPECT_EQ(-55, matrix.getTranslateY()); 2020 EXPECT_EQ(100, matrix.getScaleX()); 2021 EXPECT_EQ(55, matrix.getScaleY()); 2022 EXPECT_EQ(0, matrix.getSkewX()); 2023 EXPECT_EQ(0, matrix.getSkewY()); 2024 } 2025 2026 // Conversions from child->top and top->child. 2027 { 2028 gfx::Point point(5, 5); 2029 View::ConvertPointToTarget(child, &top_view, &point); 2030 EXPECT_EQ(22, point.x()); 2031 EXPECT_EQ(39, point.y()); 2032 2033 gfx::RectF rect(5.0f, 5.0f, 10.0f, 20.0f); 2034 View::ConvertRectToTarget(child, &top_view, &rect); 2035 EXPECT_FLOAT_EQ(22.0f, rect.x()); 2036 EXPECT_FLOAT_EQ(39.0f, rect.y()); 2037 EXPECT_FLOAT_EQ(30.0f, rect.width()); 2038 EXPECT_FLOAT_EQ(80.0f, rect.height()); 2039 2040 point.SetPoint(22, 39); 2041 View::ConvertPointToTarget(&top_view, child, &point); 2042 EXPECT_EQ(5, point.x()); 2043 EXPECT_EQ(5, point.y()); 2044 2045 rect.SetRect(22.0f, 39.0f, 30.0f, 80.0f); 2046 View::ConvertRectToTarget(&top_view, child, &rect); 2047 EXPECT_FLOAT_EQ(5.0f, rect.x()); 2048 EXPECT_FLOAT_EQ(5.0f, rect.y()); 2049 EXPECT_FLOAT_EQ(10.0f, rect.width()); 2050 EXPECT_FLOAT_EQ(20.0f, rect.height()); 2051 } 2052 2053 // Conversions from child_child->top and top->child_child. 2054 { 2055 gfx::Point point(5, 5); 2056 View::ConvertPointToTarget(child_child, &top_view, &point); 2057 EXPECT_EQ(133, point.x()); 2058 EXPECT_EQ(211, point.y()); 2059 2060 gfx::RectF rect(5.0f, 5.0f, 10.0f, 20.0f); 2061 View::ConvertRectToTarget(child_child, &top_view, &rect); 2062 EXPECT_FLOAT_EQ(133.0f, rect.x()); 2063 EXPECT_FLOAT_EQ(211.0f, rect.y()); 2064 EXPECT_FLOAT_EQ(150.0f, rect.width()); 2065 EXPECT_FLOAT_EQ(560.0f, rect.height()); 2066 2067 point.SetPoint(133, 211); 2068 View::ConvertPointToTarget(&top_view, child_child, &point); 2069 EXPECT_EQ(5, point.x()); 2070 EXPECT_EQ(5, point.y()); 2071 2072 rect.SetRect(133.0f, 211.0f, 150.0f, 560.0f); 2073 View::ConvertRectToTarget(&top_view, child_child, &rect); 2074 EXPECT_FLOAT_EQ(5.0f, rect.x()); 2075 EXPECT_FLOAT_EQ(5.0f, rect.y()); 2076 EXPECT_FLOAT_EQ(10.0f, rect.width()); 2077 EXPECT_FLOAT_EQ(20.0f, rect.height()); 2078 } 2079 2080 // Conversions from child_child->child and child->child_child 2081 { 2082 gfx::Point point(5, 5); 2083 View::ConvertPointToTarget(child_child, child, &point); 2084 EXPECT_EQ(42, point.x()); 2085 EXPECT_EQ(48, point.y()); 2086 2087 gfx::RectF rect(5.0f, 5.0f, 10.0f, 20.0f); 2088 View::ConvertRectToTarget(child_child, child, &rect); 2089 EXPECT_FLOAT_EQ(42.0f, rect.x()); 2090 EXPECT_FLOAT_EQ(48.0f, rect.y()); 2091 EXPECT_FLOAT_EQ(50.0f, rect.width()); 2092 EXPECT_FLOAT_EQ(140.0f, rect.height()); 2093 2094 point.SetPoint(42, 48); 2095 View::ConvertPointToTarget(child, child_child, &point); 2096 EXPECT_EQ(5, point.x()); 2097 EXPECT_EQ(5, point.y()); 2098 2099 rect.SetRect(42.0f, 48.0f, 50.0f, 140.0f); 2100 View::ConvertRectToTarget(child, child_child, &rect); 2101 EXPECT_FLOAT_EQ(5.0f, rect.x()); 2102 EXPECT_FLOAT_EQ(5.0f, rect.y()); 2103 EXPECT_FLOAT_EQ(10.0f, rect.width()); 2104 EXPECT_FLOAT_EQ(20.0f, rect.height()); 2105 } 2106 2107 // Conversions from top_view to child with a value that should be negative. 2108 // This ensures we don't round up with negative numbers. 2109 { 2110 gfx::Point point(6, 18); 2111 View::ConvertPointToTarget(&top_view, child, &point); 2112 EXPECT_EQ(-1, point.x()); 2113 EXPECT_EQ(-1, point.y()); 2114 2115 float error = 0.01f; 2116 gfx::RectF rect(6.0f, 18.0f, 10.0f, 39.0f); 2117 View::ConvertRectToTarget(&top_view, child, &rect); 2118 EXPECT_NEAR(-0.33f, rect.x(), error); 2119 EXPECT_NEAR(-0.25f, rect.y(), error); 2120 EXPECT_NEAR(3.33f, rect.width(), error); 2121 EXPECT_NEAR(9.75f, rect.height(), error); 2122 } 2123 2124 // Rect conversions from top_view->child_2 and child_2->top_view. 2125 { 2126 gfx::RectF rect(50.0f, 55.0f, 20.0f, 30.0f); 2127 View::ConvertRectToTarget(child_2, &top_view, &rect); 2128 EXPECT_FLOAT_EQ(615.0f, rect.x()); 2129 EXPECT_FLOAT_EQ(775.0f, rect.y()); 2130 EXPECT_FLOAT_EQ(30.0f, rect.width()); 2131 EXPECT_FLOAT_EQ(20.0f, rect.height()); 2132 2133 rect.SetRect(615.0f, 775.0f, 30.0f, 20.0f); 2134 View::ConvertRectToTarget(&top_view, child_2, &rect); 2135 EXPECT_FLOAT_EQ(50.0f, rect.x()); 2136 EXPECT_FLOAT_EQ(55.0f, rect.y()); 2137 EXPECT_FLOAT_EQ(20.0f, rect.width()); 2138 EXPECT_FLOAT_EQ(30.0f, rect.height()); 2139 } 2140 } 2141 2142 // Tests conversion methods to and from screen coordinates. 2143 TEST_F(ViewTest, ConversionsToFromScreen) { 2144 scoped_ptr<Widget> widget(new Widget); 2145 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 2146 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 2147 params.bounds = gfx::Rect(50, 50, 650, 650); 2148 widget->Init(params); 2149 2150 View* child = new View; 2151 widget->GetRootView()->AddChildView(child); 2152 child->SetBounds(10, 10, 100, 200); 2153 gfx::Transform t; 2154 t.Scale(0.5, 0.5); 2155 child->SetTransform(t); 2156 2157 gfx::Point point_in_screen(100, 90); 2158 gfx::Point point_in_child(80, 60); 2159 2160 gfx::Point point = point_in_screen; 2161 View::ConvertPointFromScreen(child, &point); 2162 EXPECT_EQ(point_in_child.ToString(), point.ToString()); 2163 2164 View::ConvertPointToScreen(child, &point); 2165 EXPECT_EQ(point_in_screen.ToString(), point.ToString()); 2166 } 2167 2168 // Tests conversion methods for rectangles. 2169 TEST_F(ViewTest, ConvertRectWithTransform) { 2170 scoped_ptr<Widget> widget(new Widget); 2171 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 2172 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 2173 params.bounds = gfx::Rect(50, 50, 650, 650); 2174 widget->Init(params); 2175 View* root = widget->GetRootView(); 2176 2177 TestView* v1 = new TestView; 2178 TestView* v2 = new TestView; 2179 root->AddChildView(v1); 2180 v1->AddChildView(v2); 2181 2182 v1->SetBoundsRect(gfx::Rect(10, 10, 500, 500)); 2183 v2->SetBoundsRect(gfx::Rect(20, 20, 100, 200)); 2184 2185 // |v2| now occupies (30, 30) to (130, 230) in |widget| 2186 gfx::Rect rect(5, 5, 15, 40); 2187 EXPECT_EQ(gfx::Rect(25, 25, 15, 40), v2->ConvertRectToParent(rect)); 2188 EXPECT_EQ(gfx::Rect(35, 35, 15, 40), v2->ConvertRectToWidget(rect)); 2189 2190 // Rotate |v2| 2191 gfx::Transform t2; 2192 RotateCounterclockwise(&t2); 2193 t2.matrix().set(1, 3, 100.f); 2194 v2->SetTransform(t2); 2195 2196 // |v2| now occupies (30, 30) to (230, 130) in |widget| 2197 EXPECT_EQ(gfx::Rect(25, 100, 40, 15), v2->ConvertRectToParent(rect)); 2198 EXPECT_EQ(gfx::Rect(35, 110, 40, 15), v2->ConvertRectToWidget(rect)); 2199 2200 // Scale down |v1| 2201 gfx::Transform t1; 2202 t1.Scale(0.5, 0.5); 2203 v1->SetTransform(t1); 2204 2205 // The rectangle should remain the same for |v1|. 2206 EXPECT_EQ(gfx::Rect(25, 100, 40, 15), v2->ConvertRectToParent(rect)); 2207 2208 // |v2| now occupies (20, 20) to (120, 70) in |widget| 2209 EXPECT_EQ(gfx::Rect(22, 60, 21, 8).ToString(), 2210 v2->ConvertRectToWidget(rect).ToString()); 2211 2212 widget->CloseNow(); 2213 } 2214 2215 class ObserverView : public View { 2216 public: 2217 ObserverView(); 2218 virtual ~ObserverView(); 2219 2220 void ResetTestState(); 2221 2222 bool has_add_details() const { return has_add_details_; } 2223 bool has_remove_details() const { return has_remove_details_; } 2224 2225 const ViewHierarchyChangedDetails& add_details() const { 2226 return add_details_; 2227 } 2228 2229 const ViewHierarchyChangedDetails& remove_details() const { 2230 return remove_details_; 2231 } 2232 2233 private: 2234 // View: 2235 virtual void ViewHierarchyChanged( 2236 const ViewHierarchyChangedDetails& details) OVERRIDE; 2237 2238 bool has_add_details_; 2239 bool has_remove_details_; 2240 ViewHierarchyChangedDetails add_details_; 2241 ViewHierarchyChangedDetails remove_details_; 2242 2243 DISALLOW_COPY_AND_ASSIGN(ObserverView); 2244 }; 2245 2246 ObserverView::ObserverView() 2247 : has_add_details_(false), 2248 has_remove_details_(false) { 2249 } 2250 2251 ObserverView::~ObserverView() {} 2252 2253 void ObserverView::ResetTestState() { 2254 has_add_details_ = false; 2255 has_remove_details_ = false; 2256 add_details_ = ViewHierarchyChangedDetails(); 2257 remove_details_ = ViewHierarchyChangedDetails(); 2258 } 2259 2260 void ObserverView::ViewHierarchyChanged( 2261 const ViewHierarchyChangedDetails& details) { 2262 if (details.is_add) { 2263 has_add_details_ = true; 2264 add_details_ = details; 2265 } else { 2266 has_remove_details_ = true; 2267 remove_details_ = details; 2268 } 2269 } 2270 2271 // Verifies that the ViewHierarchyChanged() notification is sent correctly when 2272 // a child view is added or removed to all the views in the hierarchy (up and 2273 // down). 2274 // The tree looks like this: 2275 // v1 2276 // +-- v2 2277 // +-- v3 2278 // +-- v4 (starts here, then get reparented to v1) 2279 TEST_F(ViewTest, ViewHierarchyChanged) { 2280 ObserverView v1; 2281 2282 ObserverView* v3 = new ObserverView(); 2283 2284 // Add |v3| to |v2|. 2285 scoped_ptr<ObserverView> v2(new ObserverView()); 2286 v2->AddChildView(v3); 2287 2288 // Make sure both |v2| and |v3| receive the ViewHierarchyChanged() 2289 // notification. 2290 EXPECT_TRUE(v2->has_add_details()); 2291 EXPECT_FALSE(v2->has_remove_details()); 2292 EXPECT_EQ(v2.get(), v2->add_details().parent); 2293 EXPECT_EQ(v3, v2->add_details().child); 2294 EXPECT_EQ(NULL, v2->add_details().move_view); 2295 2296 EXPECT_TRUE(v3->has_add_details()); 2297 EXPECT_FALSE(v3->has_remove_details()); 2298 EXPECT_EQ(v2.get(), v3->add_details().parent); 2299 EXPECT_EQ(v3, v3->add_details().child); 2300 EXPECT_EQ(NULL, v3->add_details().move_view); 2301 2302 // Reset everything to the initial state. 2303 v2->ResetTestState(); 2304 v3->ResetTestState(); 2305 2306 // Add |v2| to v1. 2307 v1.AddChildView(v2.get()); 2308 2309 // Verifies that |v2| is the child view *added* and the parent view is |v1|. 2310 // Make sure all the views (v1, v2, v3) received _that_ information. 2311 EXPECT_TRUE(v1.has_add_details()); 2312 EXPECT_FALSE(v1.has_remove_details()); 2313 EXPECT_EQ(&v1, v1.add_details().parent); 2314 EXPECT_EQ(v2.get(), v1.add_details().child); 2315 EXPECT_EQ(NULL, v1.add_details().move_view); 2316 2317 EXPECT_TRUE(v2->has_add_details()); 2318 EXPECT_FALSE(v2->has_remove_details()); 2319 EXPECT_EQ(&v1, v2->add_details().parent); 2320 EXPECT_EQ(v2.get(), v2->add_details().child); 2321 EXPECT_EQ(NULL, v2->add_details().move_view); 2322 2323 EXPECT_TRUE(v3->has_add_details()); 2324 EXPECT_FALSE(v3->has_remove_details()); 2325 EXPECT_EQ(&v1, v3->add_details().parent); 2326 EXPECT_EQ(v2.get(), v3->add_details().child); 2327 EXPECT_EQ(NULL, v3->add_details().move_view); 2328 2329 // Reset everything to the initial state. 2330 v1.ResetTestState(); 2331 v2->ResetTestState(); 2332 v3->ResetTestState(); 2333 2334 // Remove |v2| from |v1|. 2335 v1.RemoveChildView(v2.get()); 2336 2337 // Verifies that |v2| is the child view *removed* and the parent view is |v1|. 2338 // Make sure all the views (v1, v2, v3) received _that_ information. 2339 EXPECT_FALSE(v1.has_add_details()); 2340 EXPECT_TRUE(v1.has_remove_details()); 2341 EXPECT_EQ(&v1, v1.remove_details().parent); 2342 EXPECT_EQ(v2.get(), v1.remove_details().child); 2343 EXPECT_EQ(NULL, v1.remove_details().move_view); 2344 2345 EXPECT_FALSE(v2->has_add_details()); 2346 EXPECT_TRUE(v2->has_remove_details()); 2347 EXPECT_EQ(&v1, v2->remove_details().parent); 2348 EXPECT_EQ(v2.get(), v2->remove_details().child); 2349 EXPECT_EQ(NULL, v2->remove_details().move_view); 2350 2351 EXPECT_FALSE(v3->has_add_details()); 2352 EXPECT_TRUE(v3->has_remove_details()); 2353 EXPECT_EQ(&v1, v3->remove_details().parent); 2354 EXPECT_EQ(v3, v3->remove_details().child); 2355 EXPECT_EQ(NULL, v3->remove_details().move_view); 2356 2357 // Verifies notifications when reparenting a view. 2358 ObserverView* v4 = new ObserverView(); 2359 // Add |v4| to |v2|. 2360 v2->AddChildView(v4); 2361 2362 // Reset everything to the initial state. 2363 v1.ResetTestState(); 2364 v2->ResetTestState(); 2365 v3->ResetTestState(); 2366 v4->ResetTestState(); 2367 2368 // Reparent |v4| to |v1|. 2369 v1.AddChildView(v4); 2370 2371 // Verifies that all views receive the correct information for all the child, 2372 // parent and move views. 2373 2374 // |v1| is the new parent, |v4| is the child for add, |v2| is the old parent. 2375 EXPECT_TRUE(v1.has_add_details()); 2376 EXPECT_FALSE(v1.has_remove_details()); 2377 EXPECT_EQ(&v1, v1.add_details().parent); 2378 EXPECT_EQ(v4, v1.add_details().child); 2379 EXPECT_EQ(v2.get(), v1.add_details().move_view); 2380 2381 // |v2| is the old parent, |v4| is the child for remove, |v1| is the new 2382 // parent. 2383 EXPECT_FALSE(v2->has_add_details()); 2384 EXPECT_TRUE(v2->has_remove_details()); 2385 EXPECT_EQ(v2.get(), v2->remove_details().parent); 2386 EXPECT_EQ(v4, v2->remove_details().child); 2387 EXPECT_EQ(&v1, v2->remove_details().move_view); 2388 2389 // |v3| is not impacted by this operation, and hence receives no notification. 2390 EXPECT_FALSE(v3->has_add_details()); 2391 EXPECT_FALSE(v3->has_remove_details()); 2392 2393 // |v4| is the reparented child, so it receives notifications for the remove 2394 // and then the add. |v2| is its old parent, |v1| is its new parent. 2395 EXPECT_TRUE(v4->has_remove_details()); 2396 EXPECT_TRUE(v4->has_add_details()); 2397 EXPECT_EQ(v2.get(), v4->remove_details().parent); 2398 EXPECT_EQ(&v1, v4->add_details().parent); 2399 EXPECT_EQ(v4, v4->add_details().child); 2400 EXPECT_EQ(v4, v4->remove_details().child); 2401 EXPECT_EQ(&v1, v4->remove_details().move_view); 2402 EXPECT_EQ(v2.get(), v4->add_details().move_view); 2403 } 2404 2405 // Verifies if the child views added under the root are all deleted when calling 2406 // RemoveAllChildViews. 2407 // The tree looks like this: 2408 // root 2409 // +-- child1 2410 // +-- foo 2411 // +-- bar0 2412 // +-- bar1 2413 // +-- bar2 2414 // +-- child2 2415 // +-- child3 2416 TEST_F(ViewTest, RemoveAllChildViews) { 2417 View root; 2418 2419 View* child1 = new View; 2420 root.AddChildView(child1); 2421 2422 for (int i = 0; i < 2; ++i) 2423 root.AddChildView(new View); 2424 2425 View* foo = new View; 2426 child1->AddChildView(foo); 2427 2428 // Add some nodes to |foo|. 2429 for (int i = 0; i < 3; ++i) 2430 foo->AddChildView(new View); 2431 2432 EXPECT_EQ(3, root.child_count()); 2433 EXPECT_EQ(1, child1->child_count()); 2434 EXPECT_EQ(3, foo->child_count()); 2435 2436 // Now remove all child views from root. 2437 root.RemoveAllChildViews(true); 2438 2439 EXPECT_EQ(0, root.child_count()); 2440 EXPECT_FALSE(root.has_children()); 2441 } 2442 2443 TEST_F(ViewTest, Contains) { 2444 View v1; 2445 View* v2 = new View; 2446 View* v3 = new View; 2447 2448 v1.AddChildView(v2); 2449 v2->AddChildView(v3); 2450 2451 EXPECT_FALSE(v1.Contains(NULL)); 2452 EXPECT_TRUE(v1.Contains(&v1)); 2453 EXPECT_TRUE(v1.Contains(v2)); 2454 EXPECT_TRUE(v1.Contains(v3)); 2455 2456 EXPECT_FALSE(v2->Contains(NULL)); 2457 EXPECT_TRUE(v2->Contains(v2)); 2458 EXPECT_FALSE(v2->Contains(&v1)); 2459 EXPECT_TRUE(v2->Contains(v3)); 2460 2461 EXPECT_FALSE(v3->Contains(NULL)); 2462 EXPECT_TRUE(v3->Contains(v3)); 2463 EXPECT_FALSE(v3->Contains(&v1)); 2464 EXPECT_FALSE(v3->Contains(v2)); 2465 } 2466 2467 // Verifies if GetIndexOf() returns the correct index for the specified child 2468 // view. 2469 // The tree looks like this: 2470 // root 2471 // +-- child1 2472 // +-- foo1 2473 // +-- child2 2474 TEST_F(ViewTest, GetIndexOf) { 2475 View root; 2476 2477 View* child1 = new View; 2478 root.AddChildView(child1); 2479 2480 View* child2 = new View; 2481 root.AddChildView(child2); 2482 2483 View* foo1 = new View; 2484 child1->AddChildView(foo1); 2485 2486 EXPECT_EQ(-1, root.GetIndexOf(NULL)); 2487 EXPECT_EQ(-1, root.GetIndexOf(&root)); 2488 EXPECT_EQ(0, root.GetIndexOf(child1)); 2489 EXPECT_EQ(1, root.GetIndexOf(child2)); 2490 EXPECT_EQ(-1, root.GetIndexOf(foo1)); 2491 2492 EXPECT_EQ(-1, child1->GetIndexOf(NULL)); 2493 EXPECT_EQ(-1, child1->GetIndexOf(&root)); 2494 EXPECT_EQ(-1, child1->GetIndexOf(child1)); 2495 EXPECT_EQ(-1, child1->GetIndexOf(child2)); 2496 EXPECT_EQ(0, child1->GetIndexOf(foo1)); 2497 2498 EXPECT_EQ(-1, child2->GetIndexOf(NULL)); 2499 EXPECT_EQ(-1, child2->GetIndexOf(&root)); 2500 EXPECT_EQ(-1, child2->GetIndexOf(child2)); 2501 EXPECT_EQ(-1, child2->GetIndexOf(child1)); 2502 EXPECT_EQ(-1, child2->GetIndexOf(foo1)); 2503 } 2504 2505 // Verifies that the child views can be reordered correctly. 2506 TEST_F(ViewTest, ReorderChildren) { 2507 View root; 2508 2509 View* child = new View(); 2510 root.AddChildView(child); 2511 2512 View* foo1 = new View(); 2513 child->AddChildView(foo1); 2514 View* foo2 = new View(); 2515 child->AddChildView(foo2); 2516 View* foo3 = new View(); 2517 child->AddChildView(foo3); 2518 foo1->SetFocusable(true); 2519 foo2->SetFocusable(true); 2520 foo3->SetFocusable(true); 2521 2522 ASSERT_EQ(0, child->GetIndexOf(foo1)); 2523 ASSERT_EQ(1, child->GetIndexOf(foo2)); 2524 ASSERT_EQ(2, child->GetIndexOf(foo3)); 2525 ASSERT_EQ(foo2, foo1->GetNextFocusableView()); 2526 ASSERT_EQ(foo3, foo2->GetNextFocusableView()); 2527 ASSERT_EQ(NULL, foo3->GetNextFocusableView()); 2528 2529 // Move |foo2| at the end. 2530 child->ReorderChildView(foo2, -1); 2531 ASSERT_EQ(0, child->GetIndexOf(foo1)); 2532 ASSERT_EQ(1, child->GetIndexOf(foo3)); 2533 ASSERT_EQ(2, child->GetIndexOf(foo2)); 2534 ASSERT_EQ(foo3, foo1->GetNextFocusableView()); 2535 ASSERT_EQ(foo2, foo3->GetNextFocusableView()); 2536 ASSERT_EQ(NULL, foo2->GetNextFocusableView()); 2537 2538 // Move |foo1| at the end. 2539 child->ReorderChildView(foo1, -1); 2540 ASSERT_EQ(0, child->GetIndexOf(foo3)); 2541 ASSERT_EQ(1, child->GetIndexOf(foo2)); 2542 ASSERT_EQ(2, child->GetIndexOf(foo1)); 2543 ASSERT_EQ(NULL, foo1->GetNextFocusableView()); 2544 ASSERT_EQ(foo2, foo1->GetPreviousFocusableView()); 2545 ASSERT_EQ(foo2, foo3->GetNextFocusableView()); 2546 ASSERT_EQ(foo1, foo2->GetNextFocusableView()); 2547 2548 // Move |foo2| to the front. 2549 child->ReorderChildView(foo2, 0); 2550 ASSERT_EQ(0, child->GetIndexOf(foo2)); 2551 ASSERT_EQ(1, child->GetIndexOf(foo3)); 2552 ASSERT_EQ(2, child->GetIndexOf(foo1)); 2553 ASSERT_EQ(NULL, foo1->GetNextFocusableView()); 2554 ASSERT_EQ(foo3, foo1->GetPreviousFocusableView()); 2555 ASSERT_EQ(foo3, foo2->GetNextFocusableView()); 2556 ASSERT_EQ(foo1, foo3->GetNextFocusableView()); 2557 } 2558 2559 // Verifies that GetViewByID returns the correctly child view from the specified 2560 // ID. 2561 // The tree looks like this: 2562 // v1 2563 // +-- v2 2564 // +-- v3 2565 // +-- v4 2566 TEST_F(ViewTest, GetViewByID) { 2567 View v1; 2568 const int kV1ID = 1; 2569 v1.set_id(kV1ID); 2570 2571 View v2; 2572 const int kV2ID = 2; 2573 v2.set_id(kV2ID); 2574 2575 View v3; 2576 const int kV3ID = 3; 2577 v3.set_id(kV3ID); 2578 2579 View v4; 2580 const int kV4ID = 4; 2581 v4.set_id(kV4ID); 2582 2583 const int kV5ID = 5; 2584 2585 v1.AddChildView(&v2); 2586 v2.AddChildView(&v3); 2587 v2.AddChildView(&v4); 2588 2589 EXPECT_EQ(&v1, v1.GetViewByID(kV1ID)); 2590 EXPECT_EQ(&v2, v1.GetViewByID(kV2ID)); 2591 EXPECT_EQ(&v4, v1.GetViewByID(kV4ID)); 2592 2593 EXPECT_EQ(NULL, v1.GetViewByID(kV5ID)); // No V5 exists. 2594 EXPECT_EQ(NULL, v2.GetViewByID(kV1ID)); // It can get only from child views. 2595 2596 const int kGroup = 1; 2597 v3.SetGroup(kGroup); 2598 v4.SetGroup(kGroup); 2599 2600 View::Views views; 2601 v1.GetViewsInGroup(kGroup, &views); 2602 EXPECT_EQ(2U, views.size()); 2603 2604 View::Views::const_iterator i(std::find(views.begin(), views.end(), &v3)); 2605 EXPECT_NE(views.end(), i); 2606 2607 i = std::find(views.begin(), views.end(), &v4); 2608 EXPECT_NE(views.end(), i); 2609 } 2610 2611 TEST_F(ViewTest, AddExistingChild) { 2612 View v1, v2, v3; 2613 2614 v1.AddChildView(&v2); 2615 v1.AddChildView(&v3); 2616 EXPECT_EQ(0, v1.GetIndexOf(&v2)); 2617 EXPECT_EQ(1, v1.GetIndexOf(&v3)); 2618 2619 // Check that there's no change in order when adding at same index. 2620 v1.AddChildViewAt(&v2, 0); 2621 EXPECT_EQ(0, v1.GetIndexOf(&v2)); 2622 EXPECT_EQ(1, v1.GetIndexOf(&v3)); 2623 v1.AddChildViewAt(&v3, 1); 2624 EXPECT_EQ(0, v1.GetIndexOf(&v2)); 2625 EXPECT_EQ(1, v1.GetIndexOf(&v3)); 2626 2627 // Add it at a different index and check for change in order. 2628 v1.AddChildViewAt(&v2, 1); 2629 EXPECT_EQ(1, v1.GetIndexOf(&v2)); 2630 EXPECT_EQ(0, v1.GetIndexOf(&v3)); 2631 v1.AddChildViewAt(&v2, 0); 2632 EXPECT_EQ(0, v1.GetIndexOf(&v2)); 2633 EXPECT_EQ(1, v1.GetIndexOf(&v3)); 2634 2635 // Check that calling |AddChildView()| does not change the order. 2636 v1.AddChildView(&v2); 2637 EXPECT_EQ(0, v1.GetIndexOf(&v2)); 2638 EXPECT_EQ(1, v1.GetIndexOf(&v3)); 2639 v1.AddChildView(&v3); 2640 EXPECT_EQ(0, v1.GetIndexOf(&v2)); 2641 EXPECT_EQ(1, v1.GetIndexOf(&v3)); 2642 } 2643 2644 //////////////////////////////////////////////////////////////////////////////// 2645 // FocusManager 2646 //////////////////////////////////////////////////////////////////////////////// 2647 2648 // A widget that always claims to be active, regardless of its real activation 2649 // status. 2650 class ActiveWidget : public Widget { 2651 public: 2652 ActiveWidget() {} 2653 virtual ~ActiveWidget() {} 2654 2655 virtual bool IsActive() const OVERRIDE { 2656 return true; 2657 } 2658 2659 private: 2660 DISALLOW_COPY_AND_ASSIGN(ActiveWidget); 2661 }; 2662 2663 TEST_F(ViewTest, AdvanceFocusIfNecessaryForUnfocusableView) { 2664 // Create a widget with two views and give the first one focus. 2665 ActiveWidget widget; 2666 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 2667 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 2668 widget.Init(params); 2669 2670 View* view1 = new View(); 2671 view1->SetFocusable(true); 2672 widget.GetRootView()->AddChildView(view1); 2673 View* view2 = new View(); 2674 view2->SetFocusable(true); 2675 widget.GetRootView()->AddChildView(view2); 2676 2677 FocusManager* focus_manager = widget.GetFocusManager(); 2678 ASSERT_TRUE(focus_manager); 2679 2680 focus_manager->SetFocusedView(view1); 2681 EXPECT_EQ(view1, focus_manager->GetFocusedView()); 2682 2683 // Disable the focused view and check if the next view gets focused. 2684 view1->SetEnabled(false); 2685 EXPECT_EQ(view2, focus_manager->GetFocusedView()); 2686 2687 // Re-enable and re-focus. 2688 view1->SetEnabled(true); 2689 focus_manager->SetFocusedView(view1); 2690 EXPECT_EQ(view1, focus_manager->GetFocusedView()); 2691 2692 // Hide the focused view and check it the next view gets focused. 2693 view1->SetVisible(false); 2694 EXPECT_EQ(view2, focus_manager->GetFocusedView()); 2695 2696 // Re-show and re-focus. 2697 view1->SetVisible(true); 2698 focus_manager->SetFocusedView(view1); 2699 EXPECT_EQ(view1, focus_manager->GetFocusedView()); 2700 2701 // Set the focused view as not focusable and check if the next view gets 2702 // focused. 2703 view1->SetFocusable(false); 2704 EXPECT_EQ(view2, focus_manager->GetFocusedView()); 2705 } 2706 2707 //////////////////////////////////////////////////////////////////////////////// 2708 // Layers 2709 //////////////////////////////////////////////////////////////////////////////// 2710 2711 namespace { 2712 2713 // Test implementation of LayerAnimator. 2714 class TestLayerAnimator : public ui::LayerAnimator { 2715 public: 2716 TestLayerAnimator(); 2717 2718 const gfx::Rect& last_bounds() const { return last_bounds_; } 2719 2720 // LayerAnimator. 2721 virtual void SetBounds(const gfx::Rect& bounds) OVERRIDE; 2722 2723 protected: 2724 virtual ~TestLayerAnimator() { } 2725 2726 private: 2727 gfx::Rect last_bounds_; 2728 2729 DISALLOW_COPY_AND_ASSIGN(TestLayerAnimator); 2730 }; 2731 2732 TestLayerAnimator::TestLayerAnimator() 2733 : ui::LayerAnimator(base::TimeDelta::FromMilliseconds(0)) { 2734 } 2735 2736 void TestLayerAnimator::SetBounds(const gfx::Rect& bounds) { 2737 last_bounds_ = bounds; 2738 } 2739 2740 } // namespace 2741 2742 class ViewLayerTest : public ViewsTestBase { 2743 public: 2744 ViewLayerTest() : widget_(NULL) {} 2745 2746 virtual ~ViewLayerTest() { 2747 } 2748 2749 // Returns the Layer used by the RootView. 2750 ui::Layer* GetRootLayer() { 2751 return widget()->GetLayer(); 2752 } 2753 2754 virtual void SetUp() OVERRIDE { 2755 ViewTest::SetUp(); 2756 widget_ = new Widget; 2757 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 2758 params.bounds = gfx::Rect(50, 50, 200, 200); 2759 widget_->Init(params); 2760 widget_->Show(); 2761 widget_->GetRootView()->SetBounds(0, 0, 200, 200); 2762 } 2763 2764 virtual void TearDown() OVERRIDE { 2765 widget_->CloseNow(); 2766 ViewsTestBase::TearDown(); 2767 } 2768 2769 Widget* widget() { return widget_; } 2770 2771 private: 2772 Widget* widget_; 2773 }; 2774 2775 2776 TEST_F(ViewLayerTest, LayerToggling) { 2777 // Because we lazily create textures the calls to DrawTree are necessary to 2778 // ensure we trigger creation of textures. 2779 ui::Layer* root_layer = widget()->GetLayer(); 2780 View* content_view = new View; 2781 widget()->SetContentsView(content_view); 2782 2783 // Create v1, give it a bounds and verify everything is set up correctly. 2784 View* v1 = new View; 2785 v1->SetPaintToLayer(true); 2786 EXPECT_TRUE(v1->layer() != NULL); 2787 v1->SetBoundsRect(gfx::Rect(20, 30, 140, 150)); 2788 content_view->AddChildView(v1); 2789 ASSERT_TRUE(v1->layer() != NULL); 2790 EXPECT_EQ(root_layer, v1->layer()->parent()); 2791 EXPECT_EQ(gfx::Rect(20, 30, 140, 150), v1->layer()->bounds()); 2792 2793 // Create v2 as a child of v1 and do basic assertion testing. 2794 View* v2 = new View; 2795 v1->AddChildView(v2); 2796 EXPECT_TRUE(v2->layer() == NULL); 2797 v2->SetBoundsRect(gfx::Rect(10, 20, 30, 40)); 2798 v2->SetPaintToLayer(true); 2799 ASSERT_TRUE(v2->layer() != NULL); 2800 EXPECT_EQ(v1->layer(), v2->layer()->parent()); 2801 EXPECT_EQ(gfx::Rect(10, 20, 30, 40), v2->layer()->bounds()); 2802 2803 // Turn off v1s layer. v2 should still have a layer but its parent should have 2804 // changed. 2805 v1->SetPaintToLayer(false); 2806 EXPECT_TRUE(v1->layer() == NULL); 2807 EXPECT_TRUE(v2->layer() != NULL); 2808 EXPECT_EQ(root_layer, v2->layer()->parent()); 2809 ASSERT_EQ(1u, root_layer->children().size()); 2810 EXPECT_EQ(root_layer->children()[0], v2->layer()); 2811 // The bounds of the layer should have changed to be relative to the root view 2812 // now. 2813 EXPECT_EQ(gfx::Rect(30, 50, 30, 40), v2->layer()->bounds()); 2814 2815 // Make v1 have a layer again and verify v2s layer is wired up correctly. 2816 gfx::Transform transform; 2817 transform.Scale(2.0, 2.0); 2818 v1->SetTransform(transform); 2819 EXPECT_TRUE(v1->layer() != NULL); 2820 EXPECT_TRUE(v2->layer() != NULL); 2821 EXPECT_EQ(root_layer, v1->layer()->parent()); 2822 EXPECT_EQ(v1->layer(), v2->layer()->parent()); 2823 ASSERT_EQ(1u, root_layer->children().size()); 2824 EXPECT_EQ(root_layer->children()[0], v1->layer()); 2825 ASSERT_EQ(1u, v1->layer()->children().size()); 2826 EXPECT_EQ(v1->layer()->children()[0], v2->layer()); 2827 EXPECT_EQ(gfx::Rect(10, 20, 30, 40), v2->layer()->bounds()); 2828 } 2829 2830 // Verifies turning on a layer wires up children correctly. 2831 TEST_F(ViewLayerTest, NestedLayerToggling) { 2832 View* content_view = new View; 2833 widget()->SetContentsView(content_view); 2834 2835 // Create v1, give it a bounds and verify everything is set up correctly. 2836 View* v1 = new View; 2837 content_view->AddChildView(v1); 2838 v1->SetBoundsRect(gfx::Rect(20, 30, 140, 150)); 2839 2840 View* v2 = new View; 2841 v1->AddChildView(v2); 2842 2843 View* v3 = new View; 2844 v3->SetPaintToLayer(true); 2845 v2->AddChildView(v3); 2846 ASSERT_TRUE(v3->layer() != NULL); 2847 2848 // At this point we have v1-v2-v3. v3 has a layer, v1 and v2 don't. 2849 2850 v1->SetPaintToLayer(true); 2851 EXPECT_EQ(v1->layer(), v3->layer()->parent()); 2852 } 2853 2854 TEST_F(ViewLayerTest, LayerAnimator) { 2855 View* content_view = new View; 2856 widget()->SetContentsView(content_view); 2857 2858 View* v1 = new View; 2859 content_view->AddChildView(v1); 2860 v1->SetPaintToLayer(true); 2861 EXPECT_TRUE(v1->layer() != NULL); 2862 2863 TestLayerAnimator* animator = new TestLayerAnimator(); 2864 v1->layer()->SetAnimator(animator); 2865 2866 gfx::Rect bounds(1, 2, 3, 4); 2867 v1->SetBoundsRect(bounds); 2868 EXPECT_EQ(bounds, animator->last_bounds()); 2869 // TestLayerAnimator doesn't update the layer. 2870 EXPECT_NE(bounds, v1->layer()->bounds()); 2871 } 2872 2873 // Verifies the bounds of a layer are updated if the bounds of ancestor that 2874 // doesn't have a layer change. 2875 TEST_F(ViewLayerTest, BoundsChangeWithLayer) { 2876 View* content_view = new View; 2877 widget()->SetContentsView(content_view); 2878 2879 View* v1 = new View; 2880 content_view->AddChildView(v1); 2881 v1->SetBoundsRect(gfx::Rect(20, 30, 140, 150)); 2882 2883 View* v2 = new View; 2884 v2->SetBoundsRect(gfx::Rect(10, 11, 40, 50)); 2885 v1->AddChildView(v2); 2886 v2->SetPaintToLayer(true); 2887 ASSERT_TRUE(v2->layer() != NULL); 2888 EXPECT_EQ(gfx::Rect(30, 41, 40, 50), v2->layer()->bounds()); 2889 2890 v1->SetPosition(gfx::Point(25, 36)); 2891 EXPECT_EQ(gfx::Rect(35, 47, 40, 50), v2->layer()->bounds()); 2892 2893 v2->SetPosition(gfx::Point(11, 12)); 2894 EXPECT_EQ(gfx::Rect(36, 48, 40, 50), v2->layer()->bounds()); 2895 2896 // Bounds of the layer should change even if the view is not invisible. 2897 v1->SetVisible(false); 2898 v1->SetPosition(gfx::Point(20, 30)); 2899 EXPECT_EQ(gfx::Rect(31, 42, 40, 50), v2->layer()->bounds()); 2900 2901 v2->SetVisible(false); 2902 v2->SetBoundsRect(gfx::Rect(10, 11, 20, 30)); 2903 EXPECT_EQ(gfx::Rect(30, 41, 20, 30), v2->layer()->bounds()); 2904 } 2905 2906 // Make sure layers are positioned correctly in RTL. 2907 TEST_F(ViewLayerTest, BoundInRTL) { 2908 std::string locale = l10n_util::GetApplicationLocale(std::string()); 2909 base::i18n::SetICUDefaultLocale("he"); 2910 2911 View* view = new View; 2912 widget()->SetContentsView(view); 2913 2914 int content_width = view->width(); 2915 2916 // |v1| is initially not attached to anything. So its layer will have the same 2917 // bounds as the view. 2918 View* v1 = new View; 2919 v1->SetPaintToLayer(true); 2920 v1->SetBounds(10, 10, 20, 10); 2921 EXPECT_EQ(gfx::Rect(10, 10, 20, 10), 2922 v1->layer()->bounds()); 2923 2924 // Once |v1| is attached to the widget, its layer will get RTL-appropriate 2925 // bounds. 2926 view->AddChildView(v1); 2927 EXPECT_EQ(gfx::Rect(content_width - 30, 10, 20, 10), 2928 v1->layer()->bounds()); 2929 gfx::Rect l1bounds = v1->layer()->bounds(); 2930 2931 // Now attach a View to the widget first, then create a layer for it. Make 2932 // sure the bounds are correct. 2933 View* v2 = new View; 2934 v2->SetBounds(50, 10, 30, 10); 2935 EXPECT_FALSE(v2->layer()); 2936 view->AddChildView(v2); 2937 v2->SetPaintToLayer(true); 2938 EXPECT_EQ(gfx::Rect(content_width - 80, 10, 30, 10), 2939 v2->layer()->bounds()); 2940 gfx::Rect l2bounds = v2->layer()->bounds(); 2941 2942 view->SetPaintToLayer(true); 2943 EXPECT_EQ(l1bounds, v1->layer()->bounds()); 2944 EXPECT_EQ(l2bounds, v2->layer()->bounds()); 2945 2946 // Move one of the views. Make sure the layer is positioned correctly 2947 // afterwards. 2948 v1->SetBounds(v1->x() - 5, v1->y(), v1->width(), v1->height()); 2949 l1bounds.set_x(l1bounds.x() + 5); 2950 EXPECT_EQ(l1bounds, v1->layer()->bounds()); 2951 2952 view->SetPaintToLayer(false); 2953 EXPECT_EQ(l1bounds, v1->layer()->bounds()); 2954 EXPECT_EQ(l2bounds, v2->layer()->bounds()); 2955 2956 // Move a view again. 2957 v2->SetBounds(v2->x() + 5, v2->y(), v2->width(), v2->height()); 2958 l2bounds.set_x(l2bounds.x() - 5); 2959 EXPECT_EQ(l2bounds, v2->layer()->bounds()); 2960 2961 // Reset locale. 2962 base::i18n::SetICUDefaultLocale(locale); 2963 } 2964 2965 // Makes sure a transform persists after toggling the visibility. 2966 TEST_F(ViewLayerTest, ToggleVisibilityWithTransform) { 2967 View* view = new View; 2968 gfx::Transform transform; 2969 transform.Scale(2.0, 2.0); 2970 view->SetTransform(transform); 2971 widget()->SetContentsView(view); 2972 EXPECT_EQ(2.0f, view->GetTransform().matrix().get(0, 0)); 2973 2974 view->SetVisible(false); 2975 EXPECT_EQ(2.0f, view->GetTransform().matrix().get(0, 0)); 2976 2977 view->SetVisible(true); 2978 EXPECT_EQ(2.0f, view->GetTransform().matrix().get(0, 0)); 2979 } 2980 2981 // Verifies a transform persists after removing/adding a view with a transform. 2982 TEST_F(ViewLayerTest, ResetTransformOnLayerAfterAdd) { 2983 View* view = new View; 2984 gfx::Transform transform; 2985 transform.Scale(2.0, 2.0); 2986 view->SetTransform(transform); 2987 widget()->SetContentsView(view); 2988 EXPECT_EQ(2.0f, view->GetTransform().matrix().get(0, 0)); 2989 ASSERT_TRUE(view->layer() != NULL); 2990 EXPECT_EQ(2.0f, view->layer()->transform().matrix().get(0, 0)); 2991 2992 View* parent = view->parent(); 2993 parent->RemoveChildView(view); 2994 parent->AddChildView(view); 2995 2996 EXPECT_EQ(2.0f, view->GetTransform().matrix().get(0, 0)); 2997 ASSERT_TRUE(view->layer() != NULL); 2998 EXPECT_EQ(2.0f, view->layer()->transform().matrix().get(0, 0)); 2999 } 3000 3001 // Makes sure that layer visibility is correct after toggling View visibility. 3002 TEST_F(ViewLayerTest, ToggleVisibilityWithLayer) { 3003 View* content_view = new View; 3004 widget()->SetContentsView(content_view); 3005 3006 // The view isn't attached to a widget or a parent view yet. But it should 3007 // still have a layer, but the layer should not be attached to the root 3008 // layer. 3009 View* v1 = new View; 3010 v1->SetPaintToLayer(true); 3011 EXPECT_TRUE(v1->layer()); 3012 EXPECT_FALSE(LayerIsAncestor(widget()->GetCompositor()->root_layer(), 3013 v1->layer())); 3014 3015 // Once the view is attached to a widget, its layer should be attached to the 3016 // root layer and visible. 3017 content_view->AddChildView(v1); 3018 EXPECT_TRUE(LayerIsAncestor(widget()->GetCompositor()->root_layer(), 3019 v1->layer())); 3020 EXPECT_TRUE(v1->layer()->IsDrawn()); 3021 3022 v1->SetVisible(false); 3023 EXPECT_FALSE(v1->layer()->IsDrawn()); 3024 3025 v1->SetVisible(true); 3026 EXPECT_TRUE(v1->layer()->IsDrawn()); 3027 3028 widget()->Hide(); 3029 EXPECT_FALSE(v1->layer()->IsDrawn()); 3030 3031 widget()->Show(); 3032 EXPECT_TRUE(v1->layer()->IsDrawn()); 3033 } 3034 3035 // Tests that the layers in the subtree are orphaned after a View is removed 3036 // from the parent. 3037 TEST_F(ViewLayerTest, OrphanLayerAfterViewRemove) { 3038 View* content_view = new View; 3039 widget()->SetContentsView(content_view); 3040 3041 View* v1 = new View; 3042 content_view->AddChildView(v1); 3043 3044 View* v2 = new View; 3045 v1->AddChildView(v2); 3046 v2->SetPaintToLayer(true); 3047 EXPECT_TRUE(LayerIsAncestor(widget()->GetCompositor()->root_layer(), 3048 v2->layer())); 3049 EXPECT_TRUE(v2->layer()->IsDrawn()); 3050 3051 content_view->RemoveChildView(v1); 3052 3053 EXPECT_FALSE(LayerIsAncestor(widget()->GetCompositor()->root_layer(), 3054 v2->layer())); 3055 3056 // Reparent |v2|. 3057 content_view->AddChildView(v2); 3058 delete v1; 3059 v1 = NULL; 3060 EXPECT_TRUE(LayerIsAncestor(widget()->GetCompositor()->root_layer(), 3061 v2->layer())); 3062 EXPECT_TRUE(v2->layer()->IsDrawn()); 3063 } 3064 3065 class PaintTrackingView : public View { 3066 public: 3067 PaintTrackingView() : painted_(false) { 3068 } 3069 3070 bool painted() const { return painted_; } 3071 void set_painted(bool value) { painted_ = value; } 3072 3073 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { 3074 painted_ = true; 3075 } 3076 3077 private: 3078 bool painted_; 3079 3080 DISALLOW_COPY_AND_ASSIGN(PaintTrackingView); 3081 }; 3082 3083 // Makes sure child views with layers aren't painted when paint starts at an 3084 // ancestor. 3085 TEST_F(ViewLayerTest, DontPaintChildrenWithLayers) { 3086 PaintTrackingView* content_view = new PaintTrackingView; 3087 widget()->SetContentsView(content_view); 3088 content_view->SetPaintToLayer(true); 3089 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3090 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3091 GetRootLayer()->SchedulePaint(gfx::Rect(0, 0, 10, 10)); 3092 content_view->set_painted(false); 3093 // content_view no longer has a dirty rect. Paint from the root and make sure 3094 // PaintTrackingView isn't painted. 3095 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3096 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3097 EXPECT_FALSE(content_view->painted()); 3098 3099 // Make content_view have a dirty rect, paint the layers and make sure 3100 // PaintTrackingView is painted. 3101 content_view->layer()->SchedulePaint(gfx::Rect(0, 0, 10, 10)); 3102 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3103 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3104 EXPECT_TRUE(content_view->painted()); 3105 } 3106 3107 // Tests that the visibility of child layers are updated correctly when a View's 3108 // visibility changes. 3109 TEST_F(ViewLayerTest, VisibilityChildLayers) { 3110 View* v1 = new View; 3111 v1->SetPaintToLayer(true); 3112 widget()->SetContentsView(v1); 3113 3114 View* v2 = new View; 3115 v1->AddChildView(v2); 3116 3117 View* v3 = new View; 3118 v2->AddChildView(v3); 3119 v3->SetVisible(false); 3120 3121 View* v4 = new View; 3122 v4->SetPaintToLayer(true); 3123 v3->AddChildView(v4); 3124 3125 EXPECT_TRUE(v1->layer()->IsDrawn()); 3126 EXPECT_FALSE(v4->layer()->IsDrawn()); 3127 3128 v2->SetVisible(false); 3129 EXPECT_TRUE(v1->layer()->IsDrawn()); 3130 EXPECT_FALSE(v4->layer()->IsDrawn()); 3131 3132 v2->SetVisible(true); 3133 EXPECT_TRUE(v1->layer()->IsDrawn()); 3134 EXPECT_FALSE(v4->layer()->IsDrawn()); 3135 3136 v2->SetVisible(false); 3137 EXPECT_TRUE(v1->layer()->IsDrawn()); 3138 EXPECT_FALSE(v4->layer()->IsDrawn()); 3139 EXPECT_TRUE(ViewAndLayerTreeAreConsistent(v1, v1->layer())); 3140 3141 v3->SetVisible(true); 3142 EXPECT_TRUE(v1->layer()->IsDrawn()); 3143 EXPECT_FALSE(v4->layer()->IsDrawn()); 3144 EXPECT_TRUE(ViewAndLayerTreeAreConsistent(v1, v1->layer())); 3145 3146 // Reparent |v3| to |v1|. 3147 v1->AddChildView(v3); 3148 EXPECT_TRUE(v1->layer()->IsDrawn()); 3149 EXPECT_TRUE(v4->layer()->IsDrawn()); 3150 EXPECT_TRUE(ViewAndLayerTreeAreConsistent(v1, v1->layer())); 3151 } 3152 3153 // This test creates a random View tree, and then randomly reorders child views, 3154 // reparents views etc. Unrelated changes can appear to break this test. So 3155 // marking this as FLAKY. 3156 TEST_F(ViewLayerTest, DISABLED_ViewLayerTreesInSync) { 3157 View* content = new View; 3158 content->SetPaintToLayer(true); 3159 widget()->SetContentsView(content); 3160 widget()->Show(); 3161 3162 ConstructTree(content, 5); 3163 EXPECT_TRUE(ViewAndLayerTreeAreConsistent(content, content->layer())); 3164 3165 ScrambleTree(content); 3166 EXPECT_TRUE(ViewAndLayerTreeAreConsistent(content, content->layer())); 3167 3168 ScrambleTree(content); 3169 EXPECT_TRUE(ViewAndLayerTreeAreConsistent(content, content->layer())); 3170 3171 ScrambleTree(content); 3172 EXPECT_TRUE(ViewAndLayerTreeAreConsistent(content, content->layer())); 3173 } 3174 3175 // Verifies when views are reordered the layer is also reordered. The widget is 3176 // providing the parent layer. 3177 TEST_F(ViewLayerTest, ReorderUnderWidget) { 3178 View* content = new View; 3179 widget()->SetContentsView(content); 3180 View* c1 = new View; 3181 c1->SetPaintToLayer(true); 3182 content->AddChildView(c1); 3183 View* c2 = new View; 3184 c2->SetPaintToLayer(true); 3185 content->AddChildView(c2); 3186 3187 ui::Layer* parent_layer = c1->layer()->parent(); 3188 ASSERT_TRUE(parent_layer); 3189 ASSERT_EQ(2u, parent_layer->children().size()); 3190 EXPECT_EQ(c1->layer(), parent_layer->children()[0]); 3191 EXPECT_EQ(c2->layer(), parent_layer->children()[1]); 3192 3193 // Move c1 to the front. The layers should have moved too. 3194 content->ReorderChildView(c1, -1); 3195 EXPECT_EQ(c1->layer(), parent_layer->children()[1]); 3196 EXPECT_EQ(c2->layer(), parent_layer->children()[0]); 3197 } 3198 3199 // Verifies that the layer of a view can be acquired properly. 3200 TEST_F(ViewLayerTest, AcquireLayer) { 3201 View* content = new View; 3202 widget()->SetContentsView(content); 3203 scoped_ptr<View> c1(new View); 3204 c1->SetPaintToLayer(true); 3205 EXPECT_TRUE(c1->layer()); 3206 content->AddChildView(c1.get()); 3207 3208 scoped_ptr<ui::Layer> layer(c1->AcquireLayer()); 3209 EXPECT_EQ(layer.get(), c1->layer()); 3210 3211 scoped_ptr<ui::Layer> layer2(c1->RecreateLayer()); 3212 EXPECT_NE(c1->layer(), layer2.get()); 3213 3214 // Destroy view before destroying layer. 3215 c1.reset(); 3216 } 3217 3218 // Verify the z-order of the layers as a result of calling RecreateLayer(). 3219 TEST_F(ViewLayerTest, RecreateLayerZOrder) { 3220 scoped_ptr<View> v(new View()); 3221 v->SetPaintToLayer(true); 3222 3223 View* v1 = new View(); 3224 v1->SetPaintToLayer(true); 3225 v->AddChildView(v1); 3226 View* v2 = new View(); 3227 v2->SetPaintToLayer(true); 3228 v->AddChildView(v2); 3229 3230 // Test the initial z-order. 3231 const std::vector<ui::Layer*>& child_layers_pre = v->layer()->children(); 3232 ASSERT_EQ(2u, child_layers_pre.size()); 3233 EXPECT_EQ(v1->layer(), child_layers_pre[0]); 3234 EXPECT_EQ(v2->layer(), child_layers_pre[1]); 3235 3236 scoped_ptr<ui::Layer> v1_old_layer(v1->RecreateLayer()); 3237 3238 // Test the new layer order. We expect: |v1| |v1_old_layer| |v2|. 3239 // for |v1| and |v2|. 3240 const std::vector<ui::Layer*>& child_layers_post = v->layer()->children(); 3241 ASSERT_EQ(3u, child_layers_post.size()); 3242 EXPECT_EQ(v1->layer(), child_layers_post[0]); 3243 EXPECT_EQ(v1_old_layer, child_layers_post[1]); 3244 EXPECT_EQ(v2->layer(), child_layers_post[2]); 3245 } 3246 3247 // Verify the z-order of the layers as a result of calling RecreateLayer when 3248 // the widget is the parent with the layer. 3249 TEST_F(ViewLayerTest, RecreateLayerZOrderWidgetParent) { 3250 View* v = new View(); 3251 widget()->SetContentsView(v); 3252 3253 View* v1 = new View(); 3254 v1->SetPaintToLayer(true); 3255 v->AddChildView(v1); 3256 View* v2 = new View(); 3257 v2->SetPaintToLayer(true); 3258 v->AddChildView(v2); 3259 3260 ui::Layer* root_layer = GetRootLayer(); 3261 3262 // Test the initial z-order. 3263 const std::vector<ui::Layer*>& child_layers_pre = root_layer->children(); 3264 ASSERT_EQ(2u, child_layers_pre.size()); 3265 EXPECT_EQ(v1->layer(), child_layers_pre[0]); 3266 EXPECT_EQ(v2->layer(), child_layers_pre[1]); 3267 3268 scoped_ptr<ui::Layer> v1_old_layer(v1->RecreateLayer()); 3269 3270 // Test the new layer order. We expect: |v1| |v1_old_layer| |v2|. 3271 const std::vector<ui::Layer*>& child_layers_post = root_layer->children(); 3272 ASSERT_EQ(3u, child_layers_post.size()); 3273 EXPECT_EQ(v1->layer(), child_layers_post[0]); 3274 EXPECT_EQ(v1_old_layer, child_layers_post[1]); 3275 EXPECT_EQ(v2->layer(), child_layers_post[2]); 3276 } 3277 3278 // Verifies RecreateLayer() moves all Layers over, even those that don't have 3279 // a View. 3280 TEST_F(ViewLayerTest, RecreateLayerMovesNonViewChildren) { 3281 View v; 3282 v.SetPaintToLayer(true); 3283 View child; 3284 child.SetPaintToLayer(true); 3285 v.AddChildView(&child); 3286 ASSERT_TRUE(v.layer() != NULL); 3287 ASSERT_EQ(1u, v.layer()->children().size()); 3288 EXPECT_EQ(v.layer()->children()[0], child.layer()); 3289 3290 ui::Layer layer(ui::LAYER_NOT_DRAWN); 3291 v.layer()->Add(&layer); 3292 v.layer()->StackAtBottom(&layer); 3293 3294 scoped_ptr<ui::Layer> old_layer(v.RecreateLayer()); 3295 3296 // All children should be moved from old layer to new layer. 3297 ASSERT_TRUE(old_layer.get() != NULL); 3298 EXPECT_TRUE(old_layer->children().empty()); 3299 3300 // And new layer should have the two children. 3301 ASSERT_TRUE(v.layer() != NULL); 3302 ASSERT_EQ(2u, v.layer()->children().size()); 3303 EXPECT_EQ(v.layer()->children()[0], &layer); 3304 EXPECT_EQ(v.layer()->children()[1], child.layer()); 3305 } 3306 3307 class BoundsTreeTestView : public View { 3308 public: 3309 BoundsTreeTestView() {} 3310 3311 virtual void PaintChildren(gfx::Canvas* canvas, 3312 const CullSet& cull_set) OVERRIDE { 3313 // Save out a copy of the cull_set before calling the base implementation. 3314 last_cull_set_.clear(); 3315 if (cull_set.cull_set_) { 3316 for (base::hash_set<intptr_t>::iterator it = cull_set.cull_set_->begin(); 3317 it != cull_set.cull_set_->end(); 3318 ++it) { 3319 last_cull_set_.insert(reinterpret_cast<View*>(*it)); 3320 } 3321 } 3322 View::PaintChildren(canvas, cull_set); 3323 } 3324 3325 std::set<View*> last_cull_set_; 3326 }; 3327 3328 TEST_F(ViewLayerTest, BoundsTreePaintUpdatesCullSet) { 3329 BoundsTreeTestView* test_view = new BoundsTreeTestView; 3330 widget()->SetContentsView(test_view); 3331 3332 View* v1 = new View(); 3333 v1->SetBoundsRect(gfx::Rect(10, 15, 150, 151)); 3334 test_view->AddChildView(v1); 3335 3336 View* v2 = new View(); 3337 v2->SetBoundsRect(gfx::Rect(20, 33, 40, 50)); 3338 v1->AddChildView(v2); 3339 3340 // Schedule a full-view paint to get everyone's rectangles updated. 3341 test_view->SchedulePaintInRect(test_view->bounds()); 3342 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3343 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3344 3345 // Now we have test_view - v1 - v2. Damage to only test_view should only 3346 // return root_view and test_view. 3347 test_view->SchedulePaintInRect(gfx::Rect(0, 0, 1, 1)); 3348 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3349 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3350 EXPECT_EQ(2U, test_view->last_cull_set_.size()); 3351 EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView())); 3352 EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view)); 3353 3354 // Damage to v1 only should only return root_view, test_view, and v1. 3355 test_view->SchedulePaintInRect(gfx::Rect(11, 16, 1, 1)); 3356 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3357 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3358 EXPECT_EQ(3U, test_view->last_cull_set_.size()); 3359 EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView())); 3360 EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view)); 3361 EXPECT_EQ(1U, test_view->last_cull_set_.count(v1)); 3362 3363 // A Damage rect inside v2 should get all 3 views back in the |last_cull_set_| 3364 // on call to TestView::Paint(), along with the widget root view. 3365 test_view->SchedulePaintInRect(gfx::Rect(31, 49, 1, 1)); 3366 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3367 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3368 EXPECT_EQ(4U, test_view->last_cull_set_.size()); 3369 EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView())); 3370 EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view)); 3371 EXPECT_EQ(1U, test_view->last_cull_set_.count(v1)); 3372 EXPECT_EQ(1U, test_view->last_cull_set_.count(v2)); 3373 } 3374 3375 TEST_F(ViewLayerTest, BoundsTreeWithRTL) { 3376 std::string locale = l10n_util::GetApplicationLocale(std::string()); 3377 base::i18n::SetICUDefaultLocale("ar"); 3378 3379 BoundsTreeTestView* test_view = new BoundsTreeTestView; 3380 widget()->SetContentsView(test_view); 3381 3382 // Add child views, which should be in RTL coordinate space of parent view. 3383 View* v1 = new View; 3384 v1->SetBoundsRect(gfx::Rect(10, 12, 25, 26)); 3385 test_view->AddChildView(v1); 3386 3387 View* v2 = new View; 3388 v2->SetBoundsRect(gfx::Rect(5, 6, 7, 8)); 3389 v1->AddChildView(v2); 3390 3391 // Schedule a full-view paint to get everyone's rectangles updated. 3392 test_view->SchedulePaintInRect(test_view->bounds()); 3393 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3394 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3395 3396 // Damage to the right side of the parent view should touch both child views. 3397 gfx::Rect rtl_damage(test_view->bounds().width() - 16, 18, 1, 1); 3398 test_view->SchedulePaintInRect(rtl_damage); 3399 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3400 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3401 EXPECT_EQ(4U, test_view->last_cull_set_.size()); 3402 EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView())); 3403 EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view)); 3404 EXPECT_EQ(1U, test_view->last_cull_set_.count(v1)); 3405 EXPECT_EQ(1U, test_view->last_cull_set_.count(v2)); 3406 3407 // Damage to the left side of the parent view should only touch the 3408 // container views. 3409 gfx::Rect ltr_damage(16, 18, 1, 1); 3410 test_view->SchedulePaintInRect(ltr_damage); 3411 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3412 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3413 EXPECT_EQ(2U, test_view->last_cull_set_.size()); 3414 EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView())); 3415 EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view)); 3416 3417 // Reset locale. 3418 base::i18n::SetICUDefaultLocale(locale); 3419 } 3420 3421 TEST_F(ViewLayerTest, BoundsTreeSetBoundsChangesCullSet) { 3422 BoundsTreeTestView* test_view = new BoundsTreeTestView; 3423 widget()->SetContentsView(test_view); 3424 3425 View* v1 = new View; 3426 v1->SetBoundsRect(gfx::Rect(5, 6, 100, 101)); 3427 test_view->AddChildView(v1); 3428 3429 View* v2 = new View; 3430 v2->SetBoundsRect(gfx::Rect(20, 33, 40, 50)); 3431 v1->AddChildView(v2); 3432 3433 // Schedule a full-view paint to get everyone's rectangles updated. 3434 test_view->SchedulePaintInRect(test_view->bounds()); 3435 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3436 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3437 3438 // Move v1 to a new origin out of the way of our next query. 3439 v1->SetBoundsRect(gfx::Rect(50, 60, 100, 101)); 3440 // The move will force a repaint. 3441 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3442 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3443 3444 // Schedule a paint with damage rect where v1 used to be. 3445 test_view->SchedulePaintInRect(gfx::Rect(5, 6, 10, 11)); 3446 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3447 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3448 3449 // Should only have picked up root_view and test_view. 3450 EXPECT_EQ(2U, test_view->last_cull_set_.size()); 3451 EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView())); 3452 EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view)); 3453 } 3454 3455 TEST_F(ViewLayerTest, BoundsTreeLayerChangeMakesNewTree) { 3456 BoundsTreeTestView* test_view = new BoundsTreeTestView; 3457 widget()->SetContentsView(test_view); 3458 3459 View* v1 = new View; 3460 v1->SetBoundsRect(gfx::Rect(5, 10, 15, 20)); 3461 test_view->AddChildView(v1); 3462 3463 View* v2 = new View; 3464 v2->SetBoundsRect(gfx::Rect(1, 2, 3, 4)); 3465 v1->AddChildView(v2); 3466 3467 // Schedule a full-view paint to get everyone's rectangles updated. 3468 test_view->SchedulePaintInRect(test_view->bounds()); 3469 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3470 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3471 3472 // Set v1 to paint to its own layer, it should remove itself from the 3473 // test_view heiarchy and no longer intersect with damage rects in that cull 3474 // set. 3475 v1->SetPaintToLayer(true); 3476 3477 // Schedule another full-view paint. 3478 test_view->SchedulePaintInRect(test_view->bounds()); 3479 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3480 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3481 // v1 and v2 should no longer be present in the test_view cull_set. 3482 EXPECT_EQ(2U, test_view->last_cull_set_.size()); 3483 EXPECT_EQ(0U, test_view->last_cull_set_.count(v1)); 3484 EXPECT_EQ(0U, test_view->last_cull_set_.count(v2)); 3485 3486 // Now set v1 back to not painting to a layer. 3487 v1->SetPaintToLayer(false); 3488 // Schedule another full-view paint. 3489 test_view->SchedulePaintInRect(test_view->bounds()); 3490 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3491 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3492 // We should be back to the full cull set including v1 and v2. 3493 EXPECT_EQ(4U, test_view->last_cull_set_.size()); 3494 EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView())); 3495 EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view)); 3496 EXPECT_EQ(1U, test_view->last_cull_set_.count(v1)); 3497 EXPECT_EQ(1U, test_view->last_cull_set_.count(v2)); 3498 } 3499 3500 TEST_F(ViewLayerTest, BoundsTreeRemoveChildRemovesBounds) { 3501 BoundsTreeTestView* test_view = new BoundsTreeTestView; 3502 widget()->SetContentsView(test_view); 3503 3504 View* v1 = new View; 3505 v1->SetBoundsRect(gfx::Rect(5, 10, 15, 20)); 3506 test_view->AddChildView(v1); 3507 3508 View* v2 = new View; 3509 v2->SetBoundsRect(gfx::Rect(1, 2, 3, 4)); 3510 v1->AddChildView(v2); 3511 3512 // Schedule a full-view paint to get everyone's rectangles updated. 3513 test_view->SchedulePaintInRect(test_view->bounds()); 3514 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3515 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3516 3517 // Now remove v1 from the root view. 3518 test_view->RemoveChildView(v1); 3519 3520 // Schedule another full-view paint. 3521 test_view->SchedulePaintInRect(test_view->bounds()); 3522 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3523 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3524 // v1 and v2 should no longer be present in the test_view cull_set. 3525 EXPECT_EQ(2U, test_view->last_cull_set_.size()); 3526 EXPECT_EQ(0U, test_view->last_cull_set_.count(v1)); 3527 EXPECT_EQ(0U, test_view->last_cull_set_.count(v2)); 3528 3529 // View v1 and v2 are no longer part of view hierarchy and therefore won't be 3530 // deleted with that hierarchy. 3531 delete v1; 3532 } 3533 3534 TEST_F(ViewLayerTest, BoundsTreeMoveViewMovesBounds) { 3535 BoundsTreeTestView* test_view = new BoundsTreeTestView; 3536 widget()->SetContentsView(test_view); 3537 3538 // Build hierarchy v1 - v2 - v3. 3539 View* v1 = new View; 3540 v1->SetBoundsRect(gfx::Rect(20, 30, 150, 160)); 3541 test_view->AddChildView(v1); 3542 3543 View* v2 = new View; 3544 v2->SetBoundsRect(gfx::Rect(5, 10, 40, 50)); 3545 v1->AddChildView(v2); 3546 3547 View* v3 = new View; 3548 v3->SetBoundsRect(gfx::Rect(1, 2, 3, 4)); 3549 v2->AddChildView(v3); 3550 3551 // Schedule a full-view paint and ensure all views are present in the cull. 3552 test_view->SchedulePaintInRect(test_view->bounds()); 3553 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3554 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3555 EXPECT_EQ(5U, test_view->last_cull_set_.size()); 3556 EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView())); 3557 EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view)); 3558 EXPECT_EQ(1U, test_view->last_cull_set_.count(v1)); 3559 EXPECT_EQ(1U, test_view->last_cull_set_.count(v2)); 3560 EXPECT_EQ(1U, test_view->last_cull_set_.count(v3)); 3561 3562 // Build an unrelated view hierarchy and move v2 in to it. 3563 scoped_ptr<Widget> test_widget(new Widget); 3564 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); 3565 params.bounds = gfx::Rect(10, 10, 500, 500); 3566 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 3567 test_widget->Init(params); 3568 test_widget->Show(); 3569 BoundsTreeTestView* widget_view = new BoundsTreeTestView; 3570 test_widget->SetContentsView(widget_view); 3571 widget_view->AddChildView(v2); 3572 3573 // Now schedule full-view paints in both widgets. 3574 test_view->SchedulePaintInRect(test_view->bounds()); 3575 widget_view->SchedulePaintInRect(widget_view->bounds()); 3576 GetRootLayer()->GetCompositor()->ScheduleDraw(); 3577 ui::DrawWaiterForTest::Wait(GetRootLayer()->GetCompositor()); 3578 3579 // Only v1 should be present in the first cull set. 3580 EXPECT_EQ(3U, test_view->last_cull_set_.size()); 3581 EXPECT_EQ(1U, test_view->last_cull_set_.count(widget()->GetRootView())); 3582 EXPECT_EQ(1U, test_view->last_cull_set_.count(test_view)); 3583 EXPECT_EQ(1U, test_view->last_cull_set_.count(v1)); 3584 3585 // We should find v2 and v3 in the widget_view cull_set. 3586 EXPECT_EQ(4U, widget_view->last_cull_set_.size()); 3587 EXPECT_EQ(1U, widget_view->last_cull_set_.count(test_widget->GetRootView())); 3588 EXPECT_EQ(1U, widget_view->last_cull_set_.count(widget_view)); 3589 EXPECT_EQ(1U, widget_view->last_cull_set_.count(v2)); 3590 EXPECT_EQ(1U, widget_view->last_cull_set_.count(v3)); 3591 } 3592 3593 namespace { 3594 3595 std::string ToString(const gfx::Vector2dF& vector) { 3596 return base::StringPrintf("%.2f %0.2f", vector.x(), vector.y()); 3597 } 3598 3599 } // namespace 3600 3601 TEST_F(ViewLayerTest, SnapLayerToPixel) { 3602 View* v1 = new View; 3603 3604 View* v11 = new View; 3605 v1->AddChildView(v11); 3606 3607 widget()->SetContentsView(v1); 3608 3609 const gfx::Size& size = GetRootLayer()->GetCompositor()->size(); 3610 GetRootLayer()->GetCompositor()->SetScaleAndSize(1.25f, size); 3611 3612 v11->SetBoundsRect(gfx::Rect(1, 1, 10, 10)); 3613 v1->SetBoundsRect(gfx::Rect(1, 1, 10, 10)); 3614 v11->SetPaintToLayer(true); 3615 3616 EXPECT_EQ("0.40 0.40", ToString(v11->layer()->subpixel_position_offset())); 3617 3618 // Creating a layer in parent should update the child view's layer offset. 3619 v1->SetPaintToLayer(true); 3620 EXPECT_EQ("-0.20 -0.20", ToString(v1->layer()->subpixel_position_offset())); 3621 EXPECT_EQ("-0.20 -0.20", ToString(v11->layer()->subpixel_position_offset())); 3622 3623 // DSF change should get propagated and update offsets. 3624 GetRootLayer()->GetCompositor()->SetScaleAndSize(1.5f, size); 3625 EXPECT_EQ("0.33 0.33", ToString(v1->layer()->subpixel_position_offset())); 3626 EXPECT_EQ("0.33 0.33", ToString(v11->layer()->subpixel_position_offset())); 3627 3628 // Deleting parent's layer should update the child view's layer's offset. 3629 v1->SetPaintToLayer(false); 3630 EXPECT_EQ("0.00 0.00", ToString(v11->layer()->subpixel_position_offset())); 3631 3632 // Setting parent view should update the child view's layer's offset. 3633 v1->SetBoundsRect(gfx::Rect(2, 2, 10, 10)); 3634 EXPECT_EQ("0.33 0.33", ToString(v11->layer()->subpixel_position_offset())); 3635 3636 // Setting integral DSF should reset the offset. 3637 GetRootLayer()->GetCompositor()->SetScaleAndSize(2.0f, size); 3638 EXPECT_EQ("0.00 0.00", ToString(v11->layer()->subpixel_position_offset())); 3639 } 3640 3641 TEST_F(ViewTest, FocusableAssertions) { 3642 // View subclasses may change insets based on whether they are focusable, 3643 // which effects the preferred size. To avoid preferred size changing around 3644 // these Views need to key off the last value set to SetFocusable(), not 3645 // whether the View is focusable right now. For this reason it's important 3646 // that focusable() return the last value passed to SetFocusable and not 3647 // whether the View is focusable right now. 3648 TestView view; 3649 view.SetFocusable(true); 3650 EXPECT_TRUE(view.focusable()); 3651 view.SetEnabled(false); 3652 EXPECT_TRUE(view.focusable()); 3653 view.SetFocusable(false); 3654 EXPECT_FALSE(view.focusable()); 3655 } 3656 3657 // Verifies when a view is deleted it is removed from ViewStorage. 3658 TEST_F(ViewTest, UpdateViewStorageOnDelete) { 3659 ViewStorage* view_storage = ViewStorage::GetInstance(); 3660 const int storage_id = view_storage->CreateStorageID(); 3661 { 3662 View view; 3663 view_storage->StoreView(storage_id, &view); 3664 } 3665 EXPECT_TRUE(view_storage->RetrieveView(storage_id) == NULL); 3666 } 3667 3668 //////////////////////////////////////////////////////////////////////////////// 3669 // NativeTheme 3670 //////////////////////////////////////////////////////////////////////////////// 3671 3672 void TestView::OnNativeThemeChanged(const ui::NativeTheme* native_theme) { 3673 native_theme_ = native_theme; 3674 } 3675 3676 TEST_F(ViewTest, OnNativeThemeChanged) { 3677 TestView* test_view = new TestView(); 3678 EXPECT_FALSE(test_view->native_theme_); 3679 TestView* test_view_child = new TestView(); 3680 EXPECT_FALSE(test_view_child->native_theme_); 3681 3682 // Child view added before the widget hierarchy exists should get the 3683 // new native theme notification. 3684 test_view->AddChildView(test_view_child); 3685 3686 scoped_ptr<Widget> widget(new Widget); 3687 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); 3688 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; 3689 widget->Init(params); 3690 3691 widget->GetRootView()->AddChildView(test_view); 3692 EXPECT_TRUE(test_view->native_theme_); 3693 EXPECT_EQ(widget->GetNativeTheme(), test_view->native_theme_); 3694 EXPECT_TRUE(test_view_child->native_theme_); 3695 EXPECT_EQ(widget->GetNativeTheme(), test_view_child->native_theme_); 3696 3697 // Child view added after the widget hierarchy exists should also get the 3698 // notification. 3699 TestView* test_view_child_2 = new TestView(); 3700 test_view->AddChildView(test_view_child_2); 3701 EXPECT_TRUE(test_view_child_2->native_theme_); 3702 EXPECT_EQ(widget->GetNativeTheme(), test_view_child_2->native_theme_); 3703 3704 widget->CloseNow(); 3705 } 3706 3707 } // namespace views 3708