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