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 #define _USE_MATH_DEFINES // For VC++ to get M_PI. This has to be first. 6 7 #include "ui/views/view.h" 8 9 #include <algorithm> 10 #include <cmath> 11 12 #include "base/debug/trace_event.h" 13 #include "base/logging.h" 14 #include "base/memory/scoped_ptr.h" 15 #include "base/message_loop/message_loop.h" 16 #include "base/strings/stringprintf.h" 17 #include "base/strings/utf_string_conversions.h" 18 #include "third_party/skia/include/core/SkRect.h" 19 #include "ui/accessibility/ax_enums.h" 20 #include "ui/base/cursor/cursor.h" 21 #include "ui/base/dragdrop/drag_drop_types.h" 22 #include "ui/compositor/compositor.h" 23 #include "ui/compositor/layer.h" 24 #include "ui/compositor/layer_animator.h" 25 #include "ui/events/event_target_iterator.h" 26 #include "ui/gfx/canvas.h" 27 #include "ui/gfx/interpolated_transform.h" 28 #include "ui/gfx/path.h" 29 #include "ui/gfx/point3_f.h" 30 #include "ui/gfx/point_conversions.h" 31 #include "ui/gfx/rect_conversions.h" 32 #include "ui/gfx/scoped_canvas.h" 33 #include "ui/gfx/screen.h" 34 #include "ui/gfx/skia_util.h" 35 #include "ui/gfx/transform.h" 36 #include "ui/native_theme/native_theme.h" 37 #include "ui/views/accessibility/native_view_accessibility.h" 38 #include "ui/views/background.h" 39 #include "ui/views/border.h" 40 #include "ui/views/context_menu_controller.h" 41 #include "ui/views/drag_controller.h" 42 #include "ui/views/focus/view_storage.h" 43 #include "ui/views/layout/layout_manager.h" 44 #include "ui/views/rect_based_targeting_utils.h" 45 #include "ui/views/views_delegate.h" 46 #include "ui/views/widget/native_widget_private.h" 47 #include "ui/views/widget/root_view.h" 48 #include "ui/views/widget/tooltip_manager.h" 49 #include "ui/views/widget/widget.h" 50 51 #if defined(OS_WIN) 52 #include "base/win/scoped_gdi_object.h" 53 #endif 54 55 namespace { 56 57 #if defined(OS_WIN) 58 const bool kContextMenuOnMousePress = false; 59 #else 60 const bool kContextMenuOnMousePress = true; 61 #endif 62 63 // The minimum percentage of a view's area that needs to be covered by a rect 64 // representing a touch region in order for that view to be considered by the 65 // rect-based targeting algorithm. 66 static const float kRectTargetOverlap = 0.6f; 67 68 // Default horizontal drag threshold in pixels. 69 // Same as what gtk uses. 70 const int kDefaultHorizontalDragThreshold = 8; 71 72 // Default vertical drag threshold in pixels. 73 // Same as what gtk uses. 74 const int kDefaultVerticalDragThreshold = 8; 75 76 // Returns the top view in |view|'s hierarchy. 77 const views::View* GetHierarchyRoot(const views::View* view) { 78 const views::View* root = view; 79 while (root && root->parent()) 80 root = root->parent(); 81 return root; 82 } 83 84 } // namespace 85 86 namespace views { 87 88 namespace internal { 89 90 } // namespace internal 91 92 // static 93 ViewsDelegate* ViewsDelegate::views_delegate = NULL; 94 95 // static 96 const char View::kViewClassName[] = "View"; 97 98 //////////////////////////////////////////////////////////////////////////////// 99 // View, public: 100 101 // Creation and lifetime ------------------------------------------------------- 102 103 View::View() 104 : owned_by_client_(false), 105 id_(0), 106 group_(-1), 107 parent_(NULL), 108 visible_(true), 109 enabled_(true), 110 notify_enter_exit_on_child_(false), 111 registered_for_visible_bounds_notification_(false), 112 root_bounds_dirty_(true), 113 clip_insets_(0, 0, 0, 0), 114 needs_layout_(true), 115 flip_canvas_on_paint_for_rtl_ui_(false), 116 paint_to_layer_(false), 117 accelerator_focus_manager_(NULL), 118 registered_accelerator_count_(0), 119 next_focusable_view_(NULL), 120 previous_focusable_view_(NULL), 121 focusable_(false), 122 accessibility_focusable_(false), 123 context_menu_controller_(NULL), 124 drag_controller_(NULL), 125 native_view_accessibility_(NULL) { 126 } 127 128 View::~View() { 129 if (parent_) 130 parent_->RemoveChildView(this); 131 132 ViewStorage::GetInstance()->ViewRemoved(this); 133 134 for (Views::const_iterator i(children_.begin()); i != children_.end(); ++i) { 135 (*i)->parent_ = NULL; 136 if (!(*i)->owned_by_client_) 137 delete *i; 138 } 139 140 // Release ownership of the native accessibility object, but it's 141 // reference-counted on some platforms, so it may not be deleted right away. 142 if (native_view_accessibility_) 143 native_view_accessibility_->Destroy(); 144 } 145 146 // Tree operations ------------------------------------------------------------- 147 148 const Widget* View::GetWidget() const { 149 // The root view holds a reference to this view hierarchy's Widget. 150 return parent_ ? parent_->GetWidget() : NULL; 151 } 152 153 Widget* View::GetWidget() { 154 return const_cast<Widget*>(const_cast<const View*>(this)->GetWidget()); 155 } 156 157 void View::AddChildView(View* view) { 158 if (view->parent_ == this) 159 return; 160 AddChildViewAt(view, child_count()); 161 } 162 163 void View::AddChildViewAt(View* view, int index) { 164 CHECK_NE(view, this) << "You cannot add a view as its own child"; 165 DCHECK_GE(index, 0); 166 DCHECK_LE(index, child_count()); 167 168 // If |view| has a parent, remove it from its parent. 169 View* parent = view->parent_; 170 ui::NativeTheme* old_theme = NULL; 171 if (parent) { 172 old_theme = view->GetNativeTheme(); 173 if (parent == this) { 174 ReorderChildView(view, index); 175 return; 176 } 177 parent->DoRemoveChildView(view, true, true, false, this); 178 } 179 180 // Sets the prev/next focus views. 181 InitFocusSiblings(view, index); 182 183 // Let's insert the view. 184 view->parent_ = this; 185 children_.insert(children_.begin() + index, view); 186 187 // Instruct the view to recompute its root bounds on next Paint(). 188 view->SetRootBoundsDirty(true); 189 190 views::Widget* widget = GetWidget(); 191 if (widget) { 192 const ui::NativeTheme* new_theme = view->GetNativeTheme(); 193 if (new_theme != old_theme) 194 view->PropagateNativeThemeChanged(new_theme); 195 } 196 197 ViewHierarchyChangedDetails details(true, this, view, parent); 198 199 for (View* v = this; v; v = v->parent_) 200 v->ViewHierarchyChangedImpl(false, details); 201 202 view->PropagateAddNotifications(details); 203 UpdateTooltip(); 204 if (widget) { 205 RegisterChildrenForVisibleBoundsNotification(view); 206 if (view->visible()) 207 view->SchedulePaint(); 208 } 209 210 if (layout_manager_.get()) 211 layout_manager_->ViewAdded(this, view); 212 213 ReorderLayers(); 214 215 // Make sure the visibility of the child layers are correct. 216 // If any of the parent View is hidden, then the layers of the subtree 217 // rooted at |this| should be hidden. Otherwise, all the child layers should 218 // inherit the visibility of the owner View. 219 UpdateLayerVisibility(); 220 } 221 222 void View::ReorderChildView(View* view, int index) { 223 DCHECK_EQ(view->parent_, this); 224 if (index < 0) 225 index = child_count() - 1; 226 else if (index >= child_count()) 227 return; 228 if (children_[index] == view) 229 return; 230 231 const Views::iterator i(std::find(children_.begin(), children_.end(), view)); 232 DCHECK(i != children_.end()); 233 children_.erase(i); 234 235 // Unlink the view first 236 View* next_focusable = view->next_focusable_view_; 237 View* prev_focusable = view->previous_focusable_view_; 238 if (prev_focusable) 239 prev_focusable->next_focusable_view_ = next_focusable; 240 if (next_focusable) 241 next_focusable->previous_focusable_view_ = prev_focusable; 242 243 // Add it in the specified index now. 244 InitFocusSiblings(view, index); 245 children_.insert(children_.begin() + index, view); 246 247 ReorderLayers(); 248 } 249 250 void View::RemoveChildView(View* view) { 251 DoRemoveChildView(view, true, true, false, NULL); 252 } 253 254 void View::RemoveAllChildViews(bool delete_children) { 255 while (!children_.empty()) 256 DoRemoveChildView(children_.front(), false, false, delete_children, NULL); 257 UpdateTooltip(); 258 } 259 260 bool View::Contains(const View* view) const { 261 for (const View* v = view; v; v = v->parent_) { 262 if (v == this) 263 return true; 264 } 265 return false; 266 } 267 268 int View::GetIndexOf(const View* view) const { 269 Views::const_iterator i(std::find(children_.begin(), children_.end(), view)); 270 return i != children_.end() ? static_cast<int>(i - children_.begin()) : -1; 271 } 272 273 // Size and disposition -------------------------------------------------------- 274 275 void View::SetBounds(int x, int y, int width, int height) { 276 SetBoundsRect(gfx::Rect(x, y, std::max(0, width), std::max(0, height))); 277 } 278 279 void View::SetBoundsRect(const gfx::Rect& bounds) { 280 if (bounds == bounds_) { 281 if (needs_layout_) { 282 needs_layout_ = false; 283 Layout(); 284 } 285 return; 286 } 287 288 if (visible_) { 289 // Paint where the view is currently. 290 SchedulePaintBoundsChanged( 291 bounds_.size() == bounds.size() ? SCHEDULE_PAINT_SIZE_SAME : 292 SCHEDULE_PAINT_SIZE_CHANGED); 293 } 294 295 gfx::Rect prev = bounds_; 296 bounds_ = bounds; 297 BoundsChanged(prev); 298 } 299 300 void View::SetSize(const gfx::Size& size) { 301 SetBounds(x(), y(), size.width(), size.height()); 302 } 303 304 void View::SetPosition(const gfx::Point& position) { 305 SetBounds(position.x(), position.y(), width(), height()); 306 } 307 308 void View::SetX(int x) { 309 SetBounds(x, y(), width(), height()); 310 } 311 312 void View::SetY(int y) { 313 SetBounds(x(), y, width(), height()); 314 } 315 316 gfx::Rect View::GetContentsBounds() const { 317 gfx::Rect contents_bounds(GetLocalBounds()); 318 if (border_.get()) 319 contents_bounds.Inset(border_->GetInsets()); 320 return contents_bounds; 321 } 322 323 gfx::Rect View::GetLocalBounds() const { 324 return gfx::Rect(size()); 325 } 326 327 gfx::Rect View::GetLayerBoundsInPixel() const { 328 return layer()->GetTargetBounds(); 329 } 330 331 gfx::Insets View::GetInsets() const { 332 return border_.get() ? border_->GetInsets() : gfx::Insets(); 333 } 334 335 gfx::Rect View::GetVisibleBounds() const { 336 if (!IsDrawn()) 337 return gfx::Rect(); 338 gfx::Rect vis_bounds(GetLocalBounds()); 339 gfx::Rect ancestor_bounds; 340 const View* view = this; 341 gfx::Transform transform; 342 343 while (view != NULL && !vis_bounds.IsEmpty()) { 344 transform.ConcatTransform(view->GetTransform()); 345 gfx::Transform translation; 346 translation.Translate(static_cast<float>(view->GetMirroredX()), 347 static_cast<float>(view->y())); 348 transform.ConcatTransform(translation); 349 350 vis_bounds = view->ConvertRectToParent(vis_bounds); 351 const View* ancestor = view->parent_; 352 if (ancestor != NULL) { 353 ancestor_bounds.SetRect(0, 0, ancestor->width(), ancestor->height()); 354 vis_bounds.Intersect(ancestor_bounds); 355 } else if (!view->GetWidget()) { 356 // If the view has no Widget, we're not visible. Return an empty rect. 357 return gfx::Rect(); 358 } 359 view = ancestor; 360 } 361 if (vis_bounds.IsEmpty()) 362 return vis_bounds; 363 // Convert back to this views coordinate system. 364 gfx::RectF views_vis_bounds(vis_bounds); 365 transform.TransformRectReverse(&views_vis_bounds); 366 // Partially visible pixels should be considered visible. 367 return gfx::ToEnclosingRect(views_vis_bounds); 368 } 369 370 gfx::Rect View::GetBoundsInScreen() const { 371 gfx::Point origin; 372 View::ConvertPointToScreen(this, &origin); 373 return gfx::Rect(origin, size()); 374 } 375 376 gfx::Size View::GetPreferredSize() const { 377 if (layout_manager_.get()) 378 return layout_manager_->GetPreferredSize(this); 379 return gfx::Size(); 380 } 381 382 int View::GetBaseline() const { 383 return -1; 384 } 385 386 void View::SizeToPreferredSize() { 387 gfx::Size prefsize = GetPreferredSize(); 388 if ((prefsize.width() != width()) || (prefsize.height() != height())) 389 SetBounds(x(), y(), prefsize.width(), prefsize.height()); 390 } 391 392 gfx::Size View::GetMinimumSize() const { 393 return GetPreferredSize(); 394 } 395 396 gfx::Size View::GetMaximumSize() const { 397 return gfx::Size(); 398 } 399 400 int View::GetHeightForWidth(int w) const { 401 if (layout_manager_.get()) 402 return layout_manager_->GetPreferredHeightForWidth(this, w); 403 return GetPreferredSize().height(); 404 } 405 406 void View::SetVisible(bool visible) { 407 if (visible != visible_) { 408 // If the View is currently visible, schedule paint to refresh parent. 409 // TODO(beng): not sure we should be doing this if we have a layer. 410 if (visible_) 411 SchedulePaint(); 412 413 visible_ = visible; 414 415 // Notify the parent. 416 if (parent_) 417 parent_->ChildVisibilityChanged(this); 418 419 // This notifies all sub-views recursively. 420 PropagateVisibilityNotifications(this, visible_); 421 UpdateLayerVisibility(); 422 423 // If we are newly visible, schedule paint. 424 if (visible_) 425 SchedulePaint(); 426 } 427 } 428 429 bool View::IsDrawn() const { 430 return visible_ && parent_ ? parent_->IsDrawn() : false; 431 } 432 433 void View::SetEnabled(bool enabled) { 434 if (enabled != enabled_) { 435 enabled_ = enabled; 436 OnEnabledChanged(); 437 } 438 } 439 440 void View::OnEnabledChanged() { 441 SchedulePaint(); 442 } 443 444 // Transformations ------------------------------------------------------------- 445 446 gfx::Transform View::GetTransform() const { 447 return layer() ? layer()->transform() : gfx::Transform(); 448 } 449 450 void View::SetTransform(const gfx::Transform& transform) { 451 if (transform.IsIdentity()) { 452 if (layer()) { 453 layer()->SetTransform(transform); 454 if (!paint_to_layer_) 455 DestroyLayer(); 456 } else { 457 // Nothing. 458 } 459 } else { 460 if (!layer()) 461 CreateLayer(); 462 layer()->SetTransform(transform); 463 layer()->ScheduleDraw(); 464 } 465 } 466 467 void View::SetPaintToLayer(bool paint_to_layer) { 468 if (paint_to_layer_ == paint_to_layer) 469 return; 470 471 // If this is a change in state we will also need to update bounds trees. 472 if (paint_to_layer) { 473 // Gaining a layer means becoming a paint root. We must remove ourselves 474 // from our old paint root, if we had one. Traverse up view tree to find old 475 // paint root. 476 View* old_paint_root = parent_; 477 while (old_paint_root && !old_paint_root->IsPaintRoot()) 478 old_paint_root = old_paint_root->parent_; 479 480 // Remove our and our children's bounds from the old tree. This will also 481 // mark all of our bounds as dirty. 482 if (old_paint_root && old_paint_root->bounds_tree_) 483 RemoveRootBounds(old_paint_root->bounds_tree_.get()); 484 485 } else { 486 // Losing a layer means we are no longer a paint root, so delete our 487 // bounds tree and mark ourselves as dirty for future insertion into our 488 // new paint root's bounds tree. 489 bounds_tree_.reset(); 490 SetRootBoundsDirty(true); 491 } 492 493 paint_to_layer_ = paint_to_layer; 494 if (paint_to_layer_ && !layer()) { 495 CreateLayer(); 496 } else if (!paint_to_layer_ && layer()) { 497 DestroyLayer(); 498 } 499 } 500 501 // RTL positioning ------------------------------------------------------------- 502 503 gfx::Rect View::GetMirroredBounds() const { 504 gfx::Rect bounds(bounds_); 505 bounds.set_x(GetMirroredX()); 506 return bounds; 507 } 508 509 gfx::Point View::GetMirroredPosition() const { 510 return gfx::Point(GetMirroredX(), y()); 511 } 512 513 int View::GetMirroredX() const { 514 return parent_ ? parent_->GetMirroredXForRect(bounds_) : x(); 515 } 516 517 int View::GetMirroredXForRect(const gfx::Rect& bounds) const { 518 return base::i18n::IsRTL() ? 519 (width() - bounds.x() - bounds.width()) : bounds.x(); 520 } 521 522 int View::GetMirroredXInView(int x) const { 523 return base::i18n::IsRTL() ? width() - x : x; 524 } 525 526 int View::GetMirroredXWithWidthInView(int x, int w) const { 527 return base::i18n::IsRTL() ? width() - x - w : x; 528 } 529 530 // Layout ---------------------------------------------------------------------- 531 532 void View::Layout() { 533 needs_layout_ = false; 534 535 // If we have a layout manager, let it handle the layout for us. 536 if (layout_manager_.get()) 537 layout_manager_->Layout(this); 538 539 // Make sure to propagate the Layout() call to any children that haven't 540 // received it yet through the layout manager and need to be laid out. This 541 // is needed for the case when the child requires a layout but its bounds 542 // weren't changed by the layout manager. If there is no layout manager, we 543 // just propagate the Layout() call down the hierarchy, so whoever receives 544 // the call can take appropriate action. 545 for (int i = 0, count = child_count(); i < count; ++i) { 546 View* child = child_at(i); 547 if (child->needs_layout_ || !layout_manager_.get()) { 548 child->needs_layout_ = false; 549 child->Layout(); 550 } 551 } 552 } 553 554 void View::InvalidateLayout() { 555 // Always invalidate up. This is needed to handle the case of us already being 556 // valid, but not our parent. 557 needs_layout_ = true; 558 if (parent_) 559 parent_->InvalidateLayout(); 560 } 561 562 LayoutManager* View::GetLayoutManager() const { 563 return layout_manager_.get(); 564 } 565 566 void View::SetLayoutManager(LayoutManager* layout_manager) { 567 if (layout_manager_.get()) 568 layout_manager_->Uninstalled(this); 569 570 layout_manager_.reset(layout_manager); 571 if (layout_manager_.get()) 572 layout_manager_->Installed(this); 573 } 574 575 // Attributes ------------------------------------------------------------------ 576 577 const char* View::GetClassName() const { 578 return kViewClassName; 579 } 580 581 const View* View::GetAncestorWithClassName(const std::string& name) const { 582 for (const View* view = this; view; view = view->parent_) { 583 if (!strcmp(view->GetClassName(), name.c_str())) 584 return view; 585 } 586 return NULL; 587 } 588 589 View* View::GetAncestorWithClassName(const std::string& name) { 590 return const_cast<View*>(const_cast<const View*>(this)-> 591 GetAncestorWithClassName(name)); 592 } 593 594 const View* View::GetViewByID(int id) const { 595 if (id == id_) 596 return const_cast<View*>(this); 597 598 for (int i = 0, count = child_count(); i < count; ++i) { 599 const View* view = child_at(i)->GetViewByID(id); 600 if (view) 601 return view; 602 } 603 return NULL; 604 } 605 606 View* View::GetViewByID(int id) { 607 return const_cast<View*>(const_cast<const View*>(this)->GetViewByID(id)); 608 } 609 610 void View::SetGroup(int gid) { 611 // Don't change the group id once it's set. 612 DCHECK(group_ == -1 || group_ == gid); 613 group_ = gid; 614 } 615 616 int View::GetGroup() const { 617 return group_; 618 } 619 620 bool View::IsGroupFocusTraversable() const { 621 return true; 622 } 623 624 void View::GetViewsInGroup(int group, Views* views) { 625 if (group_ == group) 626 views->push_back(this); 627 628 for (int i = 0, count = child_count(); i < count; ++i) 629 child_at(i)->GetViewsInGroup(group, views); 630 } 631 632 View* View::GetSelectedViewForGroup(int group) { 633 Views views; 634 GetWidget()->GetRootView()->GetViewsInGroup(group, &views); 635 return views.empty() ? NULL : views[0]; 636 } 637 638 // Coordinate conversion ------------------------------------------------------- 639 640 // static 641 void View::ConvertPointToTarget(const View* source, 642 const View* target, 643 gfx::Point* point) { 644 DCHECK(source); 645 DCHECK(target); 646 if (source == target) 647 return; 648 649 const View* root = GetHierarchyRoot(target); 650 CHECK_EQ(GetHierarchyRoot(source), root); 651 652 if (source != root) 653 source->ConvertPointForAncestor(root, point); 654 655 if (target != root) 656 target->ConvertPointFromAncestor(root, point); 657 } 658 659 // static 660 void View::ConvertRectToTarget(const View* source, 661 const View* target, 662 gfx::RectF* rect) { 663 DCHECK(source); 664 DCHECK(target); 665 if (source == target) 666 return; 667 668 const View* root = GetHierarchyRoot(target); 669 CHECK_EQ(GetHierarchyRoot(source), root); 670 671 if (source != root) 672 source->ConvertRectForAncestor(root, rect); 673 674 if (target != root) 675 target->ConvertRectFromAncestor(root, rect); 676 } 677 678 // static 679 void View::ConvertPointToWidget(const View* src, gfx::Point* p) { 680 DCHECK(src); 681 DCHECK(p); 682 683 src->ConvertPointForAncestor(NULL, p); 684 } 685 686 // static 687 void View::ConvertPointFromWidget(const View* dest, gfx::Point* p) { 688 DCHECK(dest); 689 DCHECK(p); 690 691 dest->ConvertPointFromAncestor(NULL, p); 692 } 693 694 // static 695 void View::ConvertPointToScreen(const View* src, gfx::Point* p) { 696 DCHECK(src); 697 DCHECK(p); 698 699 // If the view is not connected to a tree, there's nothing we can do. 700 const Widget* widget = src->GetWidget(); 701 if (widget) { 702 ConvertPointToWidget(src, p); 703 *p += widget->GetClientAreaBoundsInScreen().OffsetFromOrigin(); 704 } 705 } 706 707 // static 708 void View::ConvertPointFromScreen(const View* dst, gfx::Point* p) { 709 DCHECK(dst); 710 DCHECK(p); 711 712 const views::Widget* widget = dst->GetWidget(); 713 if (!widget) 714 return; 715 *p -= widget->GetClientAreaBoundsInScreen().OffsetFromOrigin(); 716 views::View::ConvertPointFromWidget(dst, p); 717 } 718 719 gfx::Rect View::ConvertRectToParent(const gfx::Rect& rect) const { 720 gfx::RectF x_rect = rect; 721 GetTransform().TransformRect(&x_rect); 722 x_rect.Offset(GetMirroredPosition().OffsetFromOrigin()); 723 // Pixels we partially occupy in the parent should be included. 724 return gfx::ToEnclosingRect(x_rect); 725 } 726 727 gfx::Rect View::ConvertRectToWidget(const gfx::Rect& rect) const { 728 gfx::Rect x_rect = rect; 729 for (const View* v = this; v; v = v->parent_) 730 x_rect = v->ConvertRectToParent(x_rect); 731 return x_rect; 732 } 733 734 // Painting -------------------------------------------------------------------- 735 736 void View::SchedulePaint() { 737 SchedulePaintInRect(GetLocalBounds()); 738 } 739 740 void View::SchedulePaintInRect(const gfx::Rect& rect) { 741 if (!visible_) 742 return; 743 744 if (layer()) { 745 layer()->SchedulePaint(rect); 746 } else if (parent_) { 747 // Translate the requested paint rect to the parent's coordinate system 748 // then pass this notification up to the parent. 749 parent_->SchedulePaintInRect(ConvertRectToParent(rect)); 750 } 751 } 752 753 void View::Paint(gfx::Canvas* canvas, const CullSet& cull_set) { 754 // The cull_set may allow us to skip painting without canvas construction or 755 // even canvas rect intersection. 756 if (cull_set.ShouldPaint(this)) { 757 TRACE_EVENT1("views", "View::Paint", "class", GetClassName()); 758 759 gfx::ScopedCanvas scoped_canvas(canvas); 760 761 // Paint this View and its children, setting the clip rect to the bounds 762 // of this View and translating the origin to the local bounds' top left 763 // point. 764 // 765 // Note that the X (or left) position we pass to ClipRectInt takes into 766 // consideration whether or not the view uses a right-to-left layout so that 767 // we paint our view in its mirrored position if need be. 768 gfx::Rect clip_rect = bounds(); 769 clip_rect.Inset(clip_insets_); 770 if (parent_) 771 clip_rect.set_x(parent_->GetMirroredXForRect(clip_rect)); 772 canvas->ClipRect(clip_rect); 773 if (canvas->IsClipEmpty()) 774 return; 775 776 // Non-empty clip, translate the graphics such that 0,0 corresponds to where 777 // this view is located (related to its parent). 778 canvas->Translate(GetMirroredPosition().OffsetFromOrigin()); 779 canvas->Transform(GetTransform()); 780 781 // If we are a paint root, we need to construct our own CullSet object for 782 // propagation to our children. 783 if (IsPaintRoot()) { 784 if (!bounds_tree_) 785 bounds_tree_.reset(new BoundsTree(2, 5)); 786 787 // Recompute our bounds tree as needed. 788 UpdateRootBounds(bounds_tree_.get(), gfx::Vector2d()); 789 790 // Grab the clip rect from the supplied canvas to use as the query rect. 791 gfx::Rect canvas_bounds; 792 if (!canvas->GetClipBounds(&canvas_bounds)) { 793 NOTREACHED() << "Failed to get clip bounds from the canvas!"; 794 return; 795 } 796 797 // Now query our bounds_tree_ for a set of damaged views that intersect 798 // our canvas bounds. 799 scoped_ptr<base::hash_set<intptr_t> > damaged_views( 800 new base::hash_set<intptr_t>()); 801 bounds_tree_->AppendIntersectingRecords( 802 canvas_bounds, damaged_views.get()); 803 // Construct a CullSet to wrap the damaged views set, it will delete it 804 // for us on scope exit. 805 CullSet paint_root_cull_set(damaged_views.Pass()); 806 // Paint all descendents using our new cull set. 807 PaintCommon(canvas, paint_root_cull_set); 808 } else { 809 // Not a paint root, so we can proceed as normal. 810 PaintCommon(canvas, cull_set); 811 } 812 } 813 } 814 815 void View::set_background(Background* b) { 816 background_.reset(b); 817 } 818 819 void View::SetBorder(scoped_ptr<Border> b) { border_ = b.Pass(); } 820 821 ui::ThemeProvider* View::GetThemeProvider() const { 822 const Widget* widget = GetWidget(); 823 return widget ? widget->GetThemeProvider() : NULL; 824 } 825 826 const ui::NativeTheme* View::GetNativeTheme() const { 827 const Widget* widget = GetWidget(); 828 return widget ? widget->GetNativeTheme() : ui::NativeTheme::instance(); 829 } 830 831 // Input ----------------------------------------------------------------------- 832 833 View* View::GetEventHandlerForPoint(const gfx::Point& point) { 834 return GetEventHandlerForRect(gfx::Rect(point, gfx::Size(1, 1))); 835 } 836 837 View* View::GetEventHandlerForRect(const gfx::Rect& rect) { 838 // |rect_view| represents the current best candidate to return 839 // if rect-based targeting (i.e., fuzzing) is used. 840 // |rect_view_distance| is used to keep track of the distance 841 // between the center point of |rect_view| and the center 842 // point of |rect|. 843 View* rect_view = NULL; 844 int rect_view_distance = INT_MAX; 845 846 // |point_view| represents the view that would have been returned 847 // from this function call if point-based targeting were used. 848 View* point_view = NULL; 849 850 for (int i = child_count() - 1; i >= 0; --i) { 851 View* child = child_at(i); 852 853 if (!child->CanProcessEventsWithinSubtree()) 854 continue; 855 856 // Ignore any children which are invisible or do not intersect |rect|. 857 if (!child->visible()) 858 continue; 859 gfx::RectF rect_in_child_coords_f(rect); 860 ConvertRectToTarget(this, child, &rect_in_child_coords_f); 861 gfx::Rect rect_in_child_coords = gfx::ToEnclosingRect( 862 rect_in_child_coords_f); 863 if (!child->HitTestRect(rect_in_child_coords)) 864 continue; 865 866 View* cur_view = child->GetEventHandlerForRect(rect_in_child_coords); 867 868 if (views::UsePointBasedTargeting(rect)) 869 return cur_view; 870 871 gfx::RectF cur_view_bounds_f(cur_view->GetLocalBounds()); 872 ConvertRectToTarget(cur_view, this, &cur_view_bounds_f); 873 gfx::Rect cur_view_bounds = gfx::ToEnclosingRect( 874 cur_view_bounds_f); 875 if (views::PercentCoveredBy(cur_view_bounds, rect) >= kRectTargetOverlap) { 876 // |cur_view| is a suitable candidate for rect-based targeting. 877 // Check to see if it is the closest suitable candidate so far. 878 gfx::Point touch_center(rect.CenterPoint()); 879 int cur_dist = views::DistanceSquaredFromCenterToPoint(touch_center, 880 cur_view_bounds); 881 if (!rect_view || cur_dist < rect_view_distance) { 882 rect_view = cur_view; 883 rect_view_distance = cur_dist; 884 } 885 } else if (!rect_view && !point_view) { 886 // Rect-based targeting has not yielded any candidates so far. Check 887 // if point-based targeting would have selected |cur_view|. 888 gfx::Point point_in_child_coords(rect_in_child_coords.CenterPoint()); 889 if (child->HitTestPoint(point_in_child_coords)) 890 point_view = child->GetEventHandlerForPoint(point_in_child_coords); 891 } 892 } 893 894 if (views::UsePointBasedTargeting(rect) || (!rect_view && !point_view)) 895 return this; 896 897 // If |this| is a suitable candidate for rect-based targeting, check to 898 // see if it is closer than the current best suitable candidate so far. 899 gfx::Rect local_bounds(GetLocalBounds()); 900 if (views::PercentCoveredBy(local_bounds, rect) >= kRectTargetOverlap) { 901 gfx::Point touch_center(rect.CenterPoint()); 902 int cur_dist = views::DistanceSquaredFromCenterToPoint(touch_center, 903 local_bounds); 904 if (!rect_view || cur_dist < rect_view_distance) 905 rect_view = this; 906 } 907 908 return rect_view ? rect_view : point_view; 909 } 910 911 bool View::CanProcessEventsWithinSubtree() const { 912 return true; 913 } 914 915 View* View::GetTooltipHandlerForPoint(const gfx::Point& point) { 916 if (!HitTestPoint(point) || !CanProcessEventsWithinSubtree()) 917 return NULL; 918 919 // Walk the child Views recursively looking for the View that most 920 // tightly encloses the specified point. 921 for (int i = child_count() - 1; i >= 0; --i) { 922 View* child = child_at(i); 923 if (!child->visible()) 924 continue; 925 926 gfx::Point point_in_child_coords(point); 927 ConvertPointToTarget(this, child, &point_in_child_coords); 928 View* handler = child->GetTooltipHandlerForPoint(point_in_child_coords); 929 if (handler) 930 return handler; 931 } 932 return this; 933 } 934 935 gfx::NativeCursor View::GetCursor(const ui::MouseEvent& event) { 936 #if defined(OS_WIN) 937 static ui::Cursor arrow; 938 if (!arrow.platform()) 939 arrow.SetPlatformCursor(LoadCursor(NULL, IDC_ARROW)); 940 return arrow; 941 #else 942 return gfx::kNullCursor; 943 #endif 944 } 945 946 bool View::HitTestPoint(const gfx::Point& point) const { 947 return HitTestRect(gfx::Rect(point, gfx::Size(1, 1))); 948 } 949 950 bool View::HitTestRect(const gfx::Rect& rect) const { 951 if (GetLocalBounds().Intersects(rect)) { 952 if (HasHitTestMask()) { 953 gfx::Path mask; 954 HitTestSource source = HIT_TEST_SOURCE_MOUSE; 955 if (!views::UsePointBasedTargeting(rect)) 956 source = HIT_TEST_SOURCE_TOUCH; 957 GetHitTestMask(source, &mask); 958 SkRegion clip_region; 959 clip_region.setRect(0, 0, width(), height()); 960 SkRegion mask_region; 961 return mask_region.setPath(mask, clip_region) && 962 mask_region.intersects(RectToSkIRect(rect)); 963 } 964 // No mask, but inside our bounds. 965 return true; 966 } 967 // Outside our bounds. 968 return false; 969 } 970 971 bool View::IsMouseHovered() { 972 // If we haven't yet been placed in an onscreen view hierarchy, we can't be 973 // hovered. 974 if (!GetWidget()) 975 return false; 976 977 // If mouse events are disabled, then the mouse cursor is invisible and 978 // is therefore not hovering over this button. 979 if (!GetWidget()->IsMouseEventsEnabled()) 980 return false; 981 982 gfx::Point cursor_pos(gfx::Screen::GetScreenFor( 983 GetWidget()->GetNativeView())->GetCursorScreenPoint()); 984 ConvertPointFromScreen(this, &cursor_pos); 985 return HitTestPoint(cursor_pos); 986 } 987 988 bool View::OnMousePressed(const ui::MouseEvent& event) { 989 return false; 990 } 991 992 bool View::OnMouseDragged(const ui::MouseEvent& event) { 993 return false; 994 } 995 996 void View::OnMouseReleased(const ui::MouseEvent& event) { 997 } 998 999 void View::OnMouseCaptureLost() { 1000 } 1001 1002 void View::OnMouseMoved(const ui::MouseEvent& event) { 1003 } 1004 1005 void View::OnMouseEntered(const ui::MouseEvent& event) { 1006 } 1007 1008 void View::OnMouseExited(const ui::MouseEvent& event) { 1009 } 1010 1011 void View::SetMouseHandler(View* new_mouse_handler) { 1012 // |new_mouse_handler| may be NULL. 1013 if (parent_) 1014 parent_->SetMouseHandler(new_mouse_handler); 1015 } 1016 1017 bool View::OnKeyPressed(const ui::KeyEvent& event) { 1018 return false; 1019 } 1020 1021 bool View::OnKeyReleased(const ui::KeyEvent& event) { 1022 return false; 1023 } 1024 1025 bool View::OnMouseWheel(const ui::MouseWheelEvent& event) { 1026 return false; 1027 } 1028 1029 void View::OnKeyEvent(ui::KeyEvent* event) { 1030 bool consumed = (event->type() == ui::ET_KEY_PRESSED) ? OnKeyPressed(*event) : 1031 OnKeyReleased(*event); 1032 if (consumed) 1033 event->StopPropagation(); 1034 } 1035 1036 void View::OnMouseEvent(ui::MouseEvent* event) { 1037 switch (event->type()) { 1038 case ui::ET_MOUSE_PRESSED: 1039 if (ProcessMousePressed(*event)) 1040 event->SetHandled(); 1041 return; 1042 1043 case ui::ET_MOUSE_MOVED: 1044 if ((event->flags() & (ui::EF_LEFT_MOUSE_BUTTON | 1045 ui::EF_RIGHT_MOUSE_BUTTON | 1046 ui::EF_MIDDLE_MOUSE_BUTTON)) == 0) { 1047 OnMouseMoved(*event); 1048 return; 1049 } 1050 // FALL-THROUGH 1051 case ui::ET_MOUSE_DRAGGED: 1052 if (ProcessMouseDragged(*event)) 1053 event->SetHandled(); 1054 return; 1055 1056 case ui::ET_MOUSE_RELEASED: 1057 ProcessMouseReleased(*event); 1058 return; 1059 1060 case ui::ET_MOUSEWHEEL: 1061 if (OnMouseWheel(*static_cast<ui::MouseWheelEvent*>(event))) 1062 event->SetHandled(); 1063 break; 1064 1065 case ui::ET_MOUSE_ENTERED: 1066 if (event->flags() & ui::EF_TOUCH_ACCESSIBILITY) 1067 NotifyAccessibilityEvent(ui::AX_EVENT_HOVER, true); 1068 OnMouseEntered(*event); 1069 break; 1070 1071 case ui::ET_MOUSE_EXITED: 1072 OnMouseExited(*event); 1073 break; 1074 1075 default: 1076 return; 1077 } 1078 } 1079 1080 void View::OnScrollEvent(ui::ScrollEvent* event) { 1081 } 1082 1083 void View::OnTouchEvent(ui::TouchEvent* event) { 1084 NOTREACHED() << "Views should not receive touch events."; 1085 } 1086 1087 void View::OnGestureEvent(ui::GestureEvent* event) { 1088 } 1089 1090 ui::TextInputClient* View::GetTextInputClient() { 1091 return NULL; 1092 } 1093 1094 InputMethod* View::GetInputMethod() { 1095 Widget* widget = GetWidget(); 1096 return widget ? widget->GetInputMethod() : NULL; 1097 } 1098 1099 const InputMethod* View::GetInputMethod() const { 1100 const Widget* widget = GetWidget(); 1101 return widget ? widget->GetInputMethod() : NULL; 1102 } 1103 1104 scoped_ptr<ui::EventTargeter> 1105 View::SetEventTargeter(scoped_ptr<ui::EventTargeter> targeter) { 1106 scoped_ptr<ui::EventTargeter> old_targeter = targeter_.Pass(); 1107 targeter_ = targeter.Pass(); 1108 return old_targeter.Pass(); 1109 } 1110 1111 bool View::CanAcceptEvent(const ui::Event& event) { 1112 return IsDrawn(); 1113 } 1114 1115 ui::EventTarget* View::GetParentTarget() { 1116 return parent_; 1117 } 1118 1119 scoped_ptr<ui::EventTargetIterator> View::GetChildIterator() const { 1120 return scoped_ptr<ui::EventTargetIterator>( 1121 new ui::EventTargetIteratorImpl<View>(children_)); 1122 } 1123 1124 ui::EventTargeter* View::GetEventTargeter() { 1125 return targeter_.get(); 1126 } 1127 1128 const ui::EventTargeter* View::GetEventTargeter() const { 1129 return targeter_.get(); 1130 } 1131 1132 void View::ConvertEventToTarget(ui::EventTarget* target, 1133 ui::LocatedEvent* event) { 1134 event->ConvertLocationToTarget(this, static_cast<View*>(target)); 1135 } 1136 1137 // Accelerators ---------------------------------------------------------------- 1138 1139 void View::AddAccelerator(const ui::Accelerator& accelerator) { 1140 if (!accelerators_.get()) 1141 accelerators_.reset(new std::vector<ui::Accelerator>()); 1142 1143 if (std::find(accelerators_->begin(), accelerators_->end(), accelerator) == 1144 accelerators_->end()) { 1145 accelerators_->push_back(accelerator); 1146 } 1147 RegisterPendingAccelerators(); 1148 } 1149 1150 void View::RemoveAccelerator(const ui::Accelerator& accelerator) { 1151 if (!accelerators_.get()) { 1152 NOTREACHED() << "Removing non-existing accelerator"; 1153 return; 1154 } 1155 1156 std::vector<ui::Accelerator>::iterator i( 1157 std::find(accelerators_->begin(), accelerators_->end(), accelerator)); 1158 if (i == accelerators_->end()) { 1159 NOTREACHED() << "Removing non-existing accelerator"; 1160 return; 1161 } 1162 1163 size_t index = i - accelerators_->begin(); 1164 accelerators_->erase(i); 1165 if (index >= registered_accelerator_count_) { 1166 // The accelerator is not registered to FocusManager. 1167 return; 1168 } 1169 --registered_accelerator_count_; 1170 1171 // Providing we are attached to a Widget and registered with a focus manager, 1172 // we should de-register from that focus manager now. 1173 if (GetWidget() && accelerator_focus_manager_) 1174 accelerator_focus_manager_->UnregisterAccelerator(accelerator, this); 1175 } 1176 1177 void View::ResetAccelerators() { 1178 if (accelerators_.get()) 1179 UnregisterAccelerators(false); 1180 } 1181 1182 bool View::AcceleratorPressed(const ui::Accelerator& accelerator) { 1183 return false; 1184 } 1185 1186 bool View::CanHandleAccelerators() const { 1187 return enabled() && IsDrawn() && GetWidget() && GetWidget()->IsVisible(); 1188 } 1189 1190 // Focus ----------------------------------------------------------------------- 1191 1192 bool View::HasFocus() const { 1193 const FocusManager* focus_manager = GetFocusManager(); 1194 return focus_manager && (focus_manager->GetFocusedView() == this); 1195 } 1196 1197 View* View::GetNextFocusableView() { 1198 return next_focusable_view_; 1199 } 1200 1201 const View* View::GetNextFocusableView() const { 1202 return next_focusable_view_; 1203 } 1204 1205 View* View::GetPreviousFocusableView() { 1206 return previous_focusable_view_; 1207 } 1208 1209 void View::SetNextFocusableView(View* view) { 1210 if (view) 1211 view->previous_focusable_view_ = this; 1212 next_focusable_view_ = view; 1213 } 1214 1215 void View::SetFocusable(bool focusable) { 1216 if (focusable_ == focusable) 1217 return; 1218 1219 focusable_ = focusable; 1220 } 1221 1222 bool View::IsFocusable() const { 1223 return focusable_ && enabled_ && IsDrawn(); 1224 } 1225 1226 bool View::IsAccessibilityFocusable() const { 1227 return (focusable_ || accessibility_focusable_) && enabled_ && IsDrawn(); 1228 } 1229 1230 void View::SetAccessibilityFocusable(bool accessibility_focusable) { 1231 if (accessibility_focusable_ == accessibility_focusable) 1232 return; 1233 1234 accessibility_focusable_ = accessibility_focusable; 1235 } 1236 1237 FocusManager* View::GetFocusManager() { 1238 Widget* widget = GetWidget(); 1239 return widget ? widget->GetFocusManager() : NULL; 1240 } 1241 1242 const FocusManager* View::GetFocusManager() const { 1243 const Widget* widget = GetWidget(); 1244 return widget ? widget->GetFocusManager() : NULL; 1245 } 1246 1247 void View::RequestFocus() { 1248 FocusManager* focus_manager = GetFocusManager(); 1249 if (focus_manager && IsFocusable()) 1250 focus_manager->SetFocusedView(this); 1251 } 1252 1253 bool View::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) { 1254 return false; 1255 } 1256 1257 FocusTraversable* View::GetFocusTraversable() { 1258 return NULL; 1259 } 1260 1261 FocusTraversable* View::GetPaneFocusTraversable() { 1262 return NULL; 1263 } 1264 1265 // Tooltips -------------------------------------------------------------------- 1266 1267 bool View::GetTooltipText(const gfx::Point& p, base::string16* tooltip) const { 1268 return false; 1269 } 1270 1271 bool View::GetTooltipTextOrigin(const gfx::Point& p, gfx::Point* loc) const { 1272 return false; 1273 } 1274 1275 // Context menus --------------------------------------------------------------- 1276 1277 void View::ShowContextMenu(const gfx::Point& p, 1278 ui::MenuSourceType source_type) { 1279 if (!context_menu_controller_) 1280 return; 1281 1282 context_menu_controller_->ShowContextMenuForView(this, p, source_type); 1283 } 1284 1285 // static 1286 bool View::ShouldShowContextMenuOnMousePress() { 1287 return kContextMenuOnMousePress; 1288 } 1289 1290 // Drag and drop --------------------------------------------------------------- 1291 1292 bool View::GetDropFormats( 1293 int* formats, 1294 std::set<OSExchangeData::CustomFormat>* custom_formats) { 1295 return false; 1296 } 1297 1298 bool View::AreDropTypesRequired() { 1299 return false; 1300 } 1301 1302 bool View::CanDrop(const OSExchangeData& data) { 1303 // TODO(sky): when I finish up migration, this should default to true. 1304 return false; 1305 } 1306 1307 void View::OnDragEntered(const ui::DropTargetEvent& event) { 1308 } 1309 1310 int View::OnDragUpdated(const ui::DropTargetEvent& event) { 1311 return ui::DragDropTypes::DRAG_NONE; 1312 } 1313 1314 void View::OnDragExited() { 1315 } 1316 1317 int View::OnPerformDrop(const ui::DropTargetEvent& event) { 1318 return ui::DragDropTypes::DRAG_NONE; 1319 } 1320 1321 void View::OnDragDone() { 1322 } 1323 1324 // static 1325 bool View::ExceededDragThreshold(const gfx::Vector2d& delta) { 1326 return (abs(delta.x()) > GetHorizontalDragThreshold() || 1327 abs(delta.y()) > GetVerticalDragThreshold()); 1328 } 1329 1330 // Accessibility---------------------------------------------------------------- 1331 1332 gfx::NativeViewAccessible View::GetNativeViewAccessible() { 1333 if (!native_view_accessibility_) 1334 native_view_accessibility_ = NativeViewAccessibility::Create(this); 1335 if (native_view_accessibility_) 1336 return native_view_accessibility_->GetNativeObject(); 1337 return NULL; 1338 } 1339 1340 void View::NotifyAccessibilityEvent( 1341 ui::AXEvent event_type, 1342 bool send_native_event) { 1343 if (ViewsDelegate::views_delegate) 1344 ViewsDelegate::views_delegate->NotifyAccessibilityEvent(this, event_type); 1345 1346 if (send_native_event && GetWidget()) { 1347 if (!native_view_accessibility_) 1348 native_view_accessibility_ = NativeViewAccessibility::Create(this); 1349 if (native_view_accessibility_) 1350 native_view_accessibility_->NotifyAccessibilityEvent(event_type); 1351 } 1352 } 1353 1354 // Scrolling ------------------------------------------------------------------- 1355 1356 void View::ScrollRectToVisible(const gfx::Rect& rect) { 1357 // We must take RTL UI mirroring into account when adjusting the position of 1358 // the region. 1359 if (parent_) { 1360 gfx::Rect scroll_rect(rect); 1361 scroll_rect.Offset(GetMirroredX(), y()); 1362 parent_->ScrollRectToVisible(scroll_rect); 1363 } 1364 } 1365 1366 int View::GetPageScrollIncrement(ScrollView* scroll_view, 1367 bool is_horizontal, bool is_positive) { 1368 return 0; 1369 } 1370 1371 int View::GetLineScrollIncrement(ScrollView* scroll_view, 1372 bool is_horizontal, bool is_positive) { 1373 return 0; 1374 } 1375 1376 //////////////////////////////////////////////////////////////////////////////// 1377 // View, protected: 1378 1379 // Size and disposition -------------------------------------------------------- 1380 1381 void View::OnBoundsChanged(const gfx::Rect& previous_bounds) { 1382 } 1383 1384 void View::PreferredSizeChanged() { 1385 InvalidateLayout(); 1386 if (parent_) 1387 parent_->ChildPreferredSizeChanged(this); 1388 } 1389 1390 bool View::NeedsNotificationWhenVisibleBoundsChange() const { 1391 return false; 1392 } 1393 1394 void View::OnVisibleBoundsChanged() { 1395 } 1396 1397 // Tree operations ------------------------------------------------------------- 1398 1399 void View::ViewHierarchyChanged(const ViewHierarchyChangedDetails& details) { 1400 } 1401 1402 void View::VisibilityChanged(View* starting_from, bool is_visible) { 1403 } 1404 1405 void View::NativeViewHierarchyChanged() { 1406 FocusManager* focus_manager = GetFocusManager(); 1407 if (accelerator_focus_manager_ != focus_manager) { 1408 UnregisterAccelerators(true); 1409 1410 if (focus_manager) 1411 RegisterPendingAccelerators(); 1412 } 1413 } 1414 1415 // Painting -------------------------------------------------------------------- 1416 1417 void View::PaintChildren(gfx::Canvas* canvas, const CullSet& cull_set) { 1418 TRACE_EVENT1("views", "View::PaintChildren", "class", GetClassName()); 1419 for (int i = 0, count = child_count(); i < count; ++i) 1420 if (!child_at(i)->layer()) 1421 child_at(i)->Paint(canvas, cull_set); 1422 } 1423 1424 void View::OnPaint(gfx::Canvas* canvas) { 1425 TRACE_EVENT1("views", "View::OnPaint", "class", GetClassName()); 1426 OnPaintBackground(canvas); 1427 OnPaintBorder(canvas); 1428 } 1429 1430 void View::OnPaintBackground(gfx::Canvas* canvas) { 1431 if (background_.get()) { 1432 TRACE_EVENT2("views", "View::OnPaintBackground", 1433 "width", canvas->sk_canvas()->getDevice()->width(), 1434 "height", canvas->sk_canvas()->getDevice()->height()); 1435 background_->Paint(canvas, this); 1436 } 1437 } 1438 1439 void View::OnPaintBorder(gfx::Canvas* canvas) { 1440 if (border_.get()) { 1441 TRACE_EVENT2("views", "View::OnPaintBorder", 1442 "width", canvas->sk_canvas()->getDevice()->width(), 1443 "height", canvas->sk_canvas()->getDevice()->height()); 1444 border_->Paint(*this, canvas); 1445 } 1446 } 1447 1448 bool View::IsPaintRoot() { 1449 return paint_to_layer_ || !parent_; 1450 } 1451 1452 // Accelerated Painting -------------------------------------------------------- 1453 1454 void View::SetFillsBoundsOpaquely(bool fills_bounds_opaquely) { 1455 // This method should not have the side-effect of creating the layer. 1456 if (layer()) 1457 layer()->SetFillsBoundsOpaquely(fills_bounds_opaquely); 1458 } 1459 1460 gfx::Vector2d View::CalculateOffsetToAncestorWithLayer( 1461 ui::Layer** layer_parent) { 1462 if (layer()) { 1463 if (layer_parent) 1464 *layer_parent = layer(); 1465 return gfx::Vector2d(); 1466 } 1467 if (!parent_) 1468 return gfx::Vector2d(); 1469 1470 return gfx::Vector2d(GetMirroredX(), y()) + 1471 parent_->CalculateOffsetToAncestorWithLayer(layer_parent); 1472 } 1473 1474 void View::UpdateParentLayer() { 1475 if (!layer()) 1476 return; 1477 1478 ui::Layer* parent_layer = NULL; 1479 gfx::Vector2d offset(GetMirroredX(), y()); 1480 1481 if (parent_) 1482 offset += parent_->CalculateOffsetToAncestorWithLayer(&parent_layer); 1483 1484 ReparentLayer(offset, parent_layer); 1485 } 1486 1487 void View::MoveLayerToParent(ui::Layer* parent_layer, 1488 const gfx::Point& point) { 1489 gfx::Point local_point(point); 1490 if (parent_layer != layer()) 1491 local_point.Offset(GetMirroredX(), y()); 1492 if (layer() && parent_layer != layer()) { 1493 parent_layer->Add(layer()); 1494 SetLayerBounds(gfx::Rect(local_point.x(), local_point.y(), 1495 width(), height())); 1496 } else { 1497 for (int i = 0, count = child_count(); i < count; ++i) 1498 child_at(i)->MoveLayerToParent(parent_layer, local_point); 1499 } 1500 } 1501 1502 void View::UpdateLayerVisibility() { 1503 bool visible = visible_; 1504 for (const View* v = parent_; visible && v && !v->layer(); v = v->parent_) 1505 visible = v->visible(); 1506 1507 UpdateChildLayerVisibility(visible); 1508 } 1509 1510 void View::UpdateChildLayerVisibility(bool ancestor_visible) { 1511 if (layer()) { 1512 layer()->SetVisible(ancestor_visible && visible_); 1513 } else { 1514 for (int i = 0, count = child_count(); i < count; ++i) 1515 child_at(i)->UpdateChildLayerVisibility(ancestor_visible && visible_); 1516 } 1517 } 1518 1519 void View::UpdateChildLayerBounds(const gfx::Vector2d& offset) { 1520 if (layer()) { 1521 SetLayerBounds(GetLocalBounds() + offset); 1522 } else { 1523 for (int i = 0, count = child_count(); i < count; ++i) { 1524 View* child = child_at(i); 1525 child->UpdateChildLayerBounds( 1526 offset + gfx::Vector2d(child->GetMirroredX(), child->y())); 1527 } 1528 } 1529 } 1530 1531 void View::OnPaintLayer(gfx::Canvas* canvas) { 1532 if (!layer() || !layer()->fills_bounds_opaquely()) 1533 canvas->DrawColor(SK_ColorBLACK, SkXfermode::kClear_Mode); 1534 PaintCommon(canvas, CullSet()); 1535 } 1536 1537 void View::OnDeviceScaleFactorChanged(float device_scale_factor) { 1538 // Repainting with new scale factor will paint the content at the right scale. 1539 } 1540 1541 base::Closure View::PrepareForLayerBoundsChange() { 1542 return base::Closure(); 1543 } 1544 1545 void View::ReorderLayers() { 1546 View* v = this; 1547 while (v && !v->layer()) 1548 v = v->parent(); 1549 1550 Widget* widget = GetWidget(); 1551 if (!v) { 1552 if (widget) { 1553 ui::Layer* layer = widget->GetLayer(); 1554 if (layer) 1555 widget->GetRootView()->ReorderChildLayers(layer); 1556 } 1557 } else { 1558 v->ReorderChildLayers(v->layer()); 1559 } 1560 1561 if (widget) { 1562 // Reorder the widget's child NativeViews in case a child NativeView is 1563 // associated with a view (eg via a NativeViewHost). Always do the 1564 // reordering because the associated NativeView's layer (if it has one) 1565 // is parented to the widget's layer regardless of whether the host view has 1566 // an ancestor with a layer. 1567 widget->ReorderNativeViews(); 1568 } 1569 } 1570 1571 void View::ReorderChildLayers(ui::Layer* parent_layer) { 1572 if (layer() && layer() != parent_layer) { 1573 DCHECK_EQ(parent_layer, layer()->parent()); 1574 parent_layer->StackAtBottom(layer()); 1575 } else { 1576 // Iterate backwards through the children so that a child with a layer 1577 // which is further to the back is stacked above one which is further to 1578 // the front. 1579 for (Views::reverse_iterator it(children_.rbegin()); 1580 it != children_.rend(); ++it) { 1581 (*it)->ReorderChildLayers(parent_layer); 1582 } 1583 } 1584 } 1585 1586 // Input ----------------------------------------------------------------------- 1587 1588 bool View::HasHitTestMask() const { 1589 return false; 1590 } 1591 1592 void View::GetHitTestMask(HitTestSource source, gfx::Path* mask) const { 1593 DCHECK(mask); 1594 } 1595 1596 View::DragInfo* View::GetDragInfo() { 1597 return parent_ ? parent_->GetDragInfo() : NULL; 1598 } 1599 1600 // Focus ----------------------------------------------------------------------- 1601 1602 void View::OnFocus() { 1603 // TODO(beng): Investigate whether it's possible for us to move this to 1604 // Focus(). 1605 // By default, we clear the native focus. This ensures that no visible native 1606 // view as the focus and that we still receive keyboard inputs. 1607 FocusManager* focus_manager = GetFocusManager(); 1608 if (focus_manager) 1609 focus_manager->ClearNativeFocus(); 1610 1611 // TODO(beng): Investigate whether it's possible for us to move this to 1612 // Focus(). 1613 // Notify assistive technologies of the focus change. 1614 NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, true); 1615 } 1616 1617 void View::OnBlur() { 1618 } 1619 1620 void View::Focus() { 1621 OnFocus(); 1622 } 1623 1624 void View::Blur() { 1625 OnBlur(); 1626 } 1627 1628 // Tooltips -------------------------------------------------------------------- 1629 1630 void View::TooltipTextChanged() { 1631 Widget* widget = GetWidget(); 1632 // TooltipManager may be null if there is a problem creating it. 1633 if (widget && widget->GetTooltipManager()) 1634 widget->GetTooltipManager()->TooltipTextChanged(this); 1635 } 1636 1637 // Context menus --------------------------------------------------------------- 1638 1639 gfx::Point View::GetKeyboardContextMenuLocation() { 1640 gfx::Rect vis_bounds = GetVisibleBounds(); 1641 gfx::Point screen_point(vis_bounds.x() + vis_bounds.width() / 2, 1642 vis_bounds.y() + vis_bounds.height() / 2); 1643 ConvertPointToScreen(this, &screen_point); 1644 return screen_point; 1645 } 1646 1647 // Drag and drop --------------------------------------------------------------- 1648 1649 int View::GetDragOperations(const gfx::Point& press_pt) { 1650 return drag_controller_ ? 1651 drag_controller_->GetDragOperationsForView(this, press_pt) : 1652 ui::DragDropTypes::DRAG_NONE; 1653 } 1654 1655 void View::WriteDragData(const gfx::Point& press_pt, OSExchangeData* data) { 1656 DCHECK(drag_controller_); 1657 drag_controller_->WriteDragDataForView(this, press_pt, data); 1658 } 1659 1660 bool View::InDrag() { 1661 Widget* widget = GetWidget(); 1662 return widget ? widget->dragged_view() == this : false; 1663 } 1664 1665 int View::GetHorizontalDragThreshold() { 1666 // TODO(jennyz): This value may need to be adjusted for different platforms 1667 // and for different display density. 1668 return kDefaultHorizontalDragThreshold; 1669 } 1670 1671 int View::GetVerticalDragThreshold() { 1672 // TODO(jennyz): This value may need to be adjusted for different platforms 1673 // and for different display density. 1674 return kDefaultVerticalDragThreshold; 1675 } 1676 1677 // Debugging ------------------------------------------------------------------- 1678 1679 #if !defined(NDEBUG) 1680 1681 std::string View::PrintViewGraph(bool first) { 1682 return DoPrintViewGraph(first, this); 1683 } 1684 1685 std::string View::DoPrintViewGraph(bool first, View* view_with_children) { 1686 // 64-bit pointer = 16 bytes of hex + "0x" + '\0' = 19. 1687 const size_t kMaxPointerStringLength = 19; 1688 1689 std::string result; 1690 1691 if (first) 1692 result.append("digraph {\n"); 1693 1694 // Node characteristics. 1695 char p[kMaxPointerStringLength]; 1696 1697 const std::string class_name(GetClassName()); 1698 size_t base_name_index = class_name.find_last_of('/'); 1699 if (base_name_index == std::string::npos) 1700 base_name_index = 0; 1701 else 1702 base_name_index++; 1703 1704 char bounds_buffer[512]; 1705 1706 // Information about current node. 1707 base::snprintf(p, arraysize(bounds_buffer), "%p", view_with_children); 1708 result.append(" N"); 1709 result.append(p + 2); 1710 result.append(" [label=\""); 1711 1712 result.append(class_name.substr(base_name_index).c_str()); 1713 1714 base::snprintf(bounds_buffer, 1715 arraysize(bounds_buffer), 1716 "\\n bounds: (%d, %d), (%dx%d)", 1717 bounds().x(), 1718 bounds().y(), 1719 bounds().width(), 1720 bounds().height()); 1721 result.append(bounds_buffer); 1722 1723 gfx::DecomposedTransform decomp; 1724 if (!GetTransform().IsIdentity() && 1725 gfx::DecomposeTransform(&decomp, GetTransform())) { 1726 base::snprintf(bounds_buffer, 1727 arraysize(bounds_buffer), 1728 "\\n translation: (%f, %f)", 1729 decomp.translate[0], 1730 decomp.translate[1]); 1731 result.append(bounds_buffer); 1732 1733 base::snprintf(bounds_buffer, 1734 arraysize(bounds_buffer), 1735 "\\n rotation: %3.2f", 1736 std::acos(decomp.quaternion[3]) * 360.0 / M_PI); 1737 result.append(bounds_buffer); 1738 1739 base::snprintf(bounds_buffer, 1740 arraysize(bounds_buffer), 1741 "\\n scale: (%2.4f, %2.4f)", 1742 decomp.scale[0], 1743 decomp.scale[1]); 1744 result.append(bounds_buffer); 1745 } 1746 1747 result.append("\""); 1748 if (!parent_) 1749 result.append(", shape=box"); 1750 if (layer()) { 1751 if (layer()->has_external_content()) 1752 result.append(", color=green"); 1753 else 1754 result.append(", color=red"); 1755 1756 if (layer()->fills_bounds_opaquely()) 1757 result.append(", style=filled"); 1758 } 1759 result.append("]\n"); 1760 1761 // Link to parent. 1762 if (parent_) { 1763 char pp[kMaxPointerStringLength]; 1764 1765 base::snprintf(pp, kMaxPointerStringLength, "%p", parent_); 1766 result.append(" N"); 1767 result.append(pp + 2); 1768 result.append(" -> N"); 1769 result.append(p + 2); 1770 result.append("\n"); 1771 } 1772 1773 // Children. 1774 for (int i = 0, count = view_with_children->child_count(); i < count; ++i) 1775 result.append(view_with_children->child_at(i)->PrintViewGraph(false)); 1776 1777 if (first) 1778 result.append("}\n"); 1779 1780 return result; 1781 } 1782 #endif 1783 1784 //////////////////////////////////////////////////////////////////////////////// 1785 // View, private: 1786 1787 // DropInfo -------------------------------------------------------------------- 1788 1789 void View::DragInfo::Reset() { 1790 possible_drag = false; 1791 start_pt = gfx::Point(); 1792 } 1793 1794 void View::DragInfo::PossibleDrag(const gfx::Point& p) { 1795 possible_drag = true; 1796 start_pt = p; 1797 } 1798 1799 // Painting -------------------------------------------------------------------- 1800 1801 void View::SchedulePaintBoundsChanged(SchedulePaintType type) { 1802 // If we have a layer and the View's size did not change, we do not need to 1803 // schedule any paints since the layer will be redrawn at its new location 1804 // during the next Draw() cycle in the compositor. 1805 if (!layer() || type == SCHEDULE_PAINT_SIZE_CHANGED) { 1806 // Otherwise, if the size changes or we don't have a layer then we need to 1807 // use SchedulePaint to invalidate the area occupied by the View. 1808 SchedulePaint(); 1809 } else if (parent_ && type == SCHEDULE_PAINT_SIZE_SAME) { 1810 // The compositor doesn't Draw() until something on screen changes, so 1811 // if our position changes but nothing is being animated on screen, then 1812 // tell the compositor to redraw the scene. We know layer() exists due to 1813 // the above if clause. 1814 layer()->ScheduleDraw(); 1815 } 1816 } 1817 1818 void View::PaintCommon(gfx::Canvas* canvas, const CullSet& cull_set) { 1819 if (!visible_) 1820 return; 1821 1822 { 1823 // If the View we are about to paint requested the canvas to be flipped, we 1824 // should change the transform appropriately. 1825 // The canvas mirroring is undone once the View is done painting so that we 1826 // don't pass the canvas with the mirrored transform to Views that didn't 1827 // request the canvas to be flipped. 1828 gfx::ScopedCanvas scoped(canvas); 1829 if (FlipCanvasOnPaintForRTLUI()) { 1830 canvas->Translate(gfx::Vector2d(width(), 0)); 1831 canvas->Scale(-1, 1); 1832 } 1833 1834 OnPaint(canvas); 1835 } 1836 1837 PaintChildren(canvas, cull_set); 1838 } 1839 1840 // Tree operations ------------------------------------------------------------- 1841 1842 void View::DoRemoveChildView(View* view, 1843 bool update_focus_cycle, 1844 bool update_tool_tip, 1845 bool delete_removed_view, 1846 View* new_parent) { 1847 DCHECK(view); 1848 1849 const Views::iterator i(std::find(children_.begin(), children_.end(), view)); 1850 scoped_ptr<View> view_to_be_deleted; 1851 if (i != children_.end()) { 1852 if (update_focus_cycle) { 1853 // Let's remove the view from the focus traversal. 1854 View* next_focusable = view->next_focusable_view_; 1855 View* prev_focusable = view->previous_focusable_view_; 1856 if (prev_focusable) 1857 prev_focusable->next_focusable_view_ = next_focusable; 1858 if (next_focusable) 1859 next_focusable->previous_focusable_view_ = prev_focusable; 1860 } 1861 1862 if (GetWidget()) { 1863 UnregisterChildrenForVisibleBoundsNotification(view); 1864 if (view->visible()) 1865 view->SchedulePaint(); 1866 GetWidget()->NotifyWillRemoveView(view); 1867 } 1868 1869 // Remove the bounds of this child and any of its descendants from our 1870 // paint root bounds tree. 1871 BoundsTree* bounds_tree = GetBoundsTreeFromPaintRoot(); 1872 if (bounds_tree) 1873 view->RemoveRootBounds(bounds_tree); 1874 1875 view->PropagateRemoveNotifications(this, new_parent); 1876 view->parent_ = NULL; 1877 view->UpdateLayerVisibility(); 1878 1879 if (delete_removed_view && !view->owned_by_client_) 1880 view_to_be_deleted.reset(view); 1881 1882 children_.erase(i); 1883 } 1884 1885 if (update_tool_tip) 1886 UpdateTooltip(); 1887 1888 if (layout_manager_.get()) 1889 layout_manager_->ViewRemoved(this, view); 1890 } 1891 1892 void View::PropagateRemoveNotifications(View* old_parent, View* new_parent) { 1893 for (int i = 0, count = child_count(); i < count; ++i) 1894 child_at(i)->PropagateRemoveNotifications(old_parent, new_parent); 1895 1896 ViewHierarchyChangedDetails details(false, old_parent, this, new_parent); 1897 for (View* v = this; v; v = v->parent_) 1898 v->ViewHierarchyChangedImpl(true, details); 1899 } 1900 1901 void View::PropagateAddNotifications( 1902 const ViewHierarchyChangedDetails& details) { 1903 for (int i = 0, count = child_count(); i < count; ++i) 1904 child_at(i)->PropagateAddNotifications(details); 1905 ViewHierarchyChangedImpl(true, details); 1906 } 1907 1908 void View::PropagateNativeViewHierarchyChanged() { 1909 for (int i = 0, count = child_count(); i < count; ++i) 1910 child_at(i)->PropagateNativeViewHierarchyChanged(); 1911 NativeViewHierarchyChanged(); 1912 } 1913 1914 void View::ViewHierarchyChangedImpl( 1915 bool register_accelerators, 1916 const ViewHierarchyChangedDetails& details) { 1917 if (register_accelerators) { 1918 if (details.is_add) { 1919 // If you get this registration, you are part of a subtree that has been 1920 // added to the view hierarchy. 1921 if (GetFocusManager()) 1922 RegisterPendingAccelerators(); 1923 } else { 1924 if (details.child == this) 1925 UnregisterAccelerators(true); 1926 } 1927 } 1928 1929 if (details.is_add && layer() && !layer()->parent()) { 1930 UpdateParentLayer(); 1931 Widget* widget = GetWidget(); 1932 if (widget) 1933 widget->UpdateRootLayers(); 1934 } else if (!details.is_add && details.child == this) { 1935 // Make sure the layers belonging to the subtree rooted at |child| get 1936 // removed from layers that do not belong in the same subtree. 1937 OrphanLayers(); 1938 Widget* widget = GetWidget(); 1939 if (widget) 1940 widget->UpdateRootLayers(); 1941 } 1942 1943 ViewHierarchyChanged(details); 1944 details.parent->needs_layout_ = true; 1945 } 1946 1947 void View::PropagateNativeThemeChanged(const ui::NativeTheme* theme) { 1948 for (int i = 0, count = child_count(); i < count; ++i) 1949 child_at(i)->PropagateNativeThemeChanged(theme); 1950 OnNativeThemeChanged(theme); 1951 } 1952 1953 // Size and disposition -------------------------------------------------------- 1954 1955 void View::PropagateVisibilityNotifications(View* start, bool is_visible) { 1956 for (int i = 0, count = child_count(); i < count; ++i) 1957 child_at(i)->PropagateVisibilityNotifications(start, is_visible); 1958 VisibilityChangedImpl(start, is_visible); 1959 } 1960 1961 void View::VisibilityChangedImpl(View* starting_from, bool is_visible) { 1962 VisibilityChanged(starting_from, is_visible); 1963 } 1964 1965 void View::BoundsChanged(const gfx::Rect& previous_bounds) { 1966 // Mark our bounds as dirty for the paint root, also see if we need to 1967 // recompute our children's bounds due to origin change. 1968 bool origin_changed = 1969 previous_bounds.OffsetFromOrigin() != bounds_.OffsetFromOrigin(); 1970 SetRootBoundsDirty(origin_changed); 1971 1972 if (visible_) { 1973 // Paint the new bounds. 1974 SchedulePaintBoundsChanged( 1975 bounds_.size() == previous_bounds.size() ? SCHEDULE_PAINT_SIZE_SAME : 1976 SCHEDULE_PAINT_SIZE_CHANGED); 1977 } 1978 1979 if (layer()) { 1980 if (parent_) { 1981 SetLayerBounds(GetLocalBounds() + 1982 gfx::Vector2d(GetMirroredX(), y()) + 1983 parent_->CalculateOffsetToAncestorWithLayer(NULL)); 1984 } else { 1985 SetLayerBounds(bounds_); 1986 } 1987 } else { 1988 // If our bounds have changed, then any descendant layer bounds may have 1989 // changed. Update them accordingly. 1990 UpdateChildLayerBounds(CalculateOffsetToAncestorWithLayer(NULL)); 1991 } 1992 1993 OnBoundsChanged(previous_bounds); 1994 1995 if (previous_bounds.size() != size()) { 1996 needs_layout_ = false; 1997 Layout(); 1998 } 1999 2000 if (NeedsNotificationWhenVisibleBoundsChange()) 2001 OnVisibleBoundsChanged(); 2002 2003 // Notify interested Views that visible bounds within the root view may have 2004 // changed. 2005 if (descendants_to_notify_.get()) { 2006 for (Views::iterator i(descendants_to_notify_->begin()); 2007 i != descendants_to_notify_->end(); ++i) { 2008 (*i)->OnVisibleBoundsChanged(); 2009 } 2010 } 2011 } 2012 2013 // static 2014 void View::RegisterChildrenForVisibleBoundsNotification(View* view) { 2015 if (view->NeedsNotificationWhenVisibleBoundsChange()) 2016 view->RegisterForVisibleBoundsNotification(); 2017 for (int i = 0; i < view->child_count(); ++i) 2018 RegisterChildrenForVisibleBoundsNotification(view->child_at(i)); 2019 } 2020 2021 // static 2022 void View::UnregisterChildrenForVisibleBoundsNotification(View* view) { 2023 if (view->NeedsNotificationWhenVisibleBoundsChange()) 2024 view->UnregisterForVisibleBoundsNotification(); 2025 for (int i = 0; i < view->child_count(); ++i) 2026 UnregisterChildrenForVisibleBoundsNotification(view->child_at(i)); 2027 } 2028 2029 void View::RegisterForVisibleBoundsNotification() { 2030 if (registered_for_visible_bounds_notification_) 2031 return; 2032 2033 registered_for_visible_bounds_notification_ = true; 2034 for (View* ancestor = parent_; ancestor; ancestor = ancestor->parent_) 2035 ancestor->AddDescendantToNotify(this); 2036 } 2037 2038 void View::UnregisterForVisibleBoundsNotification() { 2039 if (!registered_for_visible_bounds_notification_) 2040 return; 2041 2042 registered_for_visible_bounds_notification_ = false; 2043 for (View* ancestor = parent_; ancestor; ancestor = ancestor->parent_) 2044 ancestor->RemoveDescendantToNotify(this); 2045 } 2046 2047 void View::AddDescendantToNotify(View* view) { 2048 DCHECK(view); 2049 if (!descendants_to_notify_.get()) 2050 descendants_to_notify_.reset(new Views); 2051 descendants_to_notify_->push_back(view); 2052 } 2053 2054 void View::RemoveDescendantToNotify(View* view) { 2055 DCHECK(view && descendants_to_notify_.get()); 2056 Views::iterator i(std::find( 2057 descendants_to_notify_->begin(), descendants_to_notify_->end(), view)); 2058 DCHECK(i != descendants_to_notify_->end()); 2059 descendants_to_notify_->erase(i); 2060 if (descendants_to_notify_->empty()) 2061 descendants_to_notify_.reset(); 2062 } 2063 2064 void View::SetLayerBounds(const gfx::Rect& bounds) { 2065 layer()->SetBounds(bounds); 2066 } 2067 2068 void View::SetRootBoundsDirty(bool origin_changed) { 2069 root_bounds_dirty_ = true; 2070 2071 if (origin_changed) { 2072 // Inform our children that their root bounds are dirty, as their relative 2073 // coordinates in paint root space have changed since ours have changed. 2074 for (Views::const_iterator i(children_.begin()); i != children_.end(); 2075 ++i) { 2076 if (!(*i)->IsPaintRoot()) 2077 (*i)->SetRootBoundsDirty(origin_changed); 2078 } 2079 } 2080 } 2081 2082 void View::UpdateRootBounds(BoundsTree* tree, const gfx::Vector2d& offset) { 2083 // No need to recompute bounds if we haven't flagged ours as dirty. 2084 TRACE_EVENT1("views", "View::UpdateRootBounds", "class", GetClassName()); 2085 2086 // Add our own offset to the provided offset, for our own bounds update and 2087 // for propagation to our children if needed. 2088 gfx::Vector2d view_offset = offset + GetMirroredBounds().OffsetFromOrigin(); 2089 2090 // If our bounds have changed we must re-insert our new bounds to the tree. 2091 if (root_bounds_dirty_) { 2092 root_bounds_dirty_ = false; 2093 gfx::Rect bounds( 2094 view_offset.x(), view_offset.y(), bounds_.width(), bounds_.height()); 2095 tree->Insert(bounds, reinterpret_cast<intptr_t>(this)); 2096 } 2097 2098 // Update our children's bounds if needed. 2099 for (Views::const_iterator i(children_.begin()); i != children_.end(); ++i) { 2100 // We don't descend in to layer views for bounds recomputation, as they 2101 // manage their own RTree as paint roots. 2102 if (!(*i)->IsPaintRoot()) 2103 (*i)->UpdateRootBounds(tree, view_offset); 2104 } 2105 } 2106 2107 void View::RemoveRootBounds(BoundsTree* tree) { 2108 tree->Remove(reinterpret_cast<intptr_t>(this)); 2109 2110 root_bounds_dirty_ = true; 2111 2112 for (Views::const_iterator i(children_.begin()); i != children_.end(); ++i) { 2113 if (!(*i)->IsPaintRoot()) 2114 (*i)->RemoveRootBounds(tree); 2115 } 2116 } 2117 2118 View::BoundsTree* View::GetBoundsTreeFromPaintRoot() { 2119 BoundsTree* bounds_tree = bounds_tree_.get(); 2120 View* paint_root = this; 2121 while (!bounds_tree && !paint_root->IsPaintRoot()) { 2122 // Assumption is that if IsPaintRoot() is false then parent_ is valid. 2123 DCHECK(paint_root); 2124 paint_root = paint_root->parent_; 2125 bounds_tree = paint_root->bounds_tree_.get(); 2126 } 2127 2128 return bounds_tree; 2129 } 2130 2131 // Transformations ------------------------------------------------------------- 2132 2133 bool View::GetTransformRelativeTo(const View* ancestor, 2134 gfx::Transform* transform) const { 2135 const View* p = this; 2136 2137 while (p && p != ancestor) { 2138 transform->ConcatTransform(p->GetTransform()); 2139 gfx::Transform translation; 2140 translation.Translate(static_cast<float>(p->GetMirroredX()), 2141 static_cast<float>(p->y())); 2142 transform->ConcatTransform(translation); 2143 2144 p = p->parent_; 2145 } 2146 2147 return p == ancestor; 2148 } 2149 2150 // Coordinate conversion ------------------------------------------------------- 2151 2152 bool View::ConvertPointForAncestor(const View* ancestor, 2153 gfx::Point* point) const { 2154 gfx::Transform trans; 2155 // TODO(sad): Have some way of caching the transformation results. 2156 bool result = GetTransformRelativeTo(ancestor, &trans); 2157 gfx::Point3F p(*point); 2158 trans.TransformPoint(&p); 2159 *point = gfx::ToFlooredPoint(p.AsPointF()); 2160 return result; 2161 } 2162 2163 bool View::ConvertPointFromAncestor(const View* ancestor, 2164 gfx::Point* point) const { 2165 gfx::Transform trans; 2166 bool result = GetTransformRelativeTo(ancestor, &trans); 2167 gfx::Point3F p(*point); 2168 trans.TransformPointReverse(&p); 2169 *point = gfx::ToFlooredPoint(p.AsPointF()); 2170 return result; 2171 } 2172 2173 bool View::ConvertRectForAncestor(const View* ancestor, 2174 gfx::RectF* rect) const { 2175 gfx::Transform trans; 2176 // TODO(sad): Have some way of caching the transformation results. 2177 bool result = GetTransformRelativeTo(ancestor, &trans); 2178 trans.TransformRect(rect); 2179 return result; 2180 } 2181 2182 bool View::ConvertRectFromAncestor(const View* ancestor, 2183 gfx::RectF* rect) const { 2184 gfx::Transform trans; 2185 bool result = GetTransformRelativeTo(ancestor, &trans); 2186 trans.TransformRectReverse(rect); 2187 return result; 2188 } 2189 2190 // Accelerated painting -------------------------------------------------------- 2191 2192 void View::CreateLayer() { 2193 // A new layer is being created for the view. So all the layers of the 2194 // sub-tree can inherit the visibility of the corresponding view. 2195 for (int i = 0, count = child_count(); i < count; ++i) 2196 child_at(i)->UpdateChildLayerVisibility(true); 2197 2198 SetLayer(new ui::Layer()); 2199 layer()->set_delegate(this); 2200 #if !defined(NDEBUG) 2201 layer()->set_name(GetClassName()); 2202 #endif 2203 2204 UpdateParentLayers(); 2205 UpdateLayerVisibility(); 2206 2207 // The new layer needs to be ordered in the layer tree according 2208 // to the view tree. Children of this layer were added in order 2209 // in UpdateParentLayers(). 2210 if (parent()) 2211 parent()->ReorderLayers(); 2212 2213 Widget* widget = GetWidget(); 2214 if (widget) 2215 widget->UpdateRootLayers(); 2216 } 2217 2218 void View::UpdateParentLayers() { 2219 // Attach all top-level un-parented layers. 2220 if (layer() && !layer()->parent()) { 2221 UpdateParentLayer(); 2222 } else { 2223 for (int i = 0, count = child_count(); i < count; ++i) 2224 child_at(i)->UpdateParentLayers(); 2225 } 2226 } 2227 2228 void View::OrphanLayers() { 2229 if (layer()) { 2230 if (layer()->parent()) 2231 layer()->parent()->Remove(layer()); 2232 2233 // The layer belonging to this View has already been orphaned. It is not 2234 // necessary to orphan the child layers. 2235 return; 2236 } 2237 for (int i = 0, count = child_count(); i < count; ++i) 2238 child_at(i)->OrphanLayers(); 2239 } 2240 2241 void View::ReparentLayer(const gfx::Vector2d& offset, ui::Layer* parent_layer) { 2242 layer()->SetBounds(GetLocalBounds() + offset); 2243 DCHECK_NE(layer(), parent_layer); 2244 if (parent_layer) 2245 parent_layer->Add(layer()); 2246 layer()->SchedulePaint(GetLocalBounds()); 2247 MoveLayerToParent(layer(), gfx::Point()); 2248 } 2249 2250 void View::DestroyLayer() { 2251 ui::Layer* new_parent = layer()->parent(); 2252 std::vector<ui::Layer*> children = layer()->children(); 2253 for (size_t i = 0; i < children.size(); ++i) { 2254 layer()->Remove(children[i]); 2255 if (new_parent) 2256 new_parent->Add(children[i]); 2257 } 2258 2259 LayerOwner::DestroyLayer(); 2260 2261 if (new_parent) 2262 ReorderLayers(); 2263 2264 UpdateChildLayerBounds(CalculateOffsetToAncestorWithLayer(NULL)); 2265 2266 SchedulePaint(); 2267 2268 Widget* widget = GetWidget(); 2269 if (widget) 2270 widget->UpdateRootLayers(); 2271 } 2272 2273 // Input ----------------------------------------------------------------------- 2274 2275 bool View::ProcessMousePressed(const ui::MouseEvent& event) { 2276 int drag_operations = 2277 (enabled_ && event.IsOnlyLeftMouseButton() && 2278 HitTestPoint(event.location())) ? 2279 GetDragOperations(event.location()) : 0; 2280 ContextMenuController* context_menu_controller = event.IsRightMouseButton() ? 2281 context_menu_controller_ : 0; 2282 View::DragInfo* drag_info = GetDragInfo(); 2283 2284 // TODO(sky): for debugging 360238. 2285 int storage_id = 0; 2286 if (event.IsOnlyRightMouseButton() && context_menu_controller && 2287 kContextMenuOnMousePress && HitTestPoint(event.location())) { 2288 ViewStorage* view_storage = ViewStorage::GetInstance(); 2289 storage_id = view_storage->CreateStorageID(); 2290 view_storage->StoreView(storage_id, this); 2291 } 2292 2293 const bool enabled = enabled_; 2294 const bool result = OnMousePressed(event); 2295 2296 if (!enabled) 2297 return result; 2298 2299 if (event.IsOnlyRightMouseButton() && context_menu_controller && 2300 kContextMenuOnMousePress) { 2301 // Assume that if there is a context menu controller we won't be deleted 2302 // from mouse pressed. 2303 gfx::Point location(event.location()); 2304 if (HitTestPoint(location)) { 2305 if (storage_id != 0) 2306 CHECK_EQ(this, ViewStorage::GetInstance()->RetrieveView(storage_id)); 2307 ConvertPointToScreen(this, &location); 2308 ShowContextMenu(location, ui::MENU_SOURCE_MOUSE); 2309 return true; 2310 } 2311 } 2312 2313 // WARNING: we may have been deleted, don't use any View variables. 2314 if (drag_operations != ui::DragDropTypes::DRAG_NONE) { 2315 drag_info->PossibleDrag(event.location()); 2316 return true; 2317 } 2318 return !!context_menu_controller || result; 2319 } 2320 2321 bool View::ProcessMouseDragged(const ui::MouseEvent& event) { 2322 // Copy the field, that way if we're deleted after drag and drop no harm is 2323 // done. 2324 ContextMenuController* context_menu_controller = context_menu_controller_; 2325 const bool possible_drag = GetDragInfo()->possible_drag; 2326 if (possible_drag && 2327 ExceededDragThreshold(GetDragInfo()->start_pt - event.location()) && 2328 (!drag_controller_ || 2329 drag_controller_->CanStartDragForView( 2330 this, GetDragInfo()->start_pt, event.location()))) { 2331 DoDrag(event, GetDragInfo()->start_pt, 2332 ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE); 2333 } else { 2334 if (OnMouseDragged(event)) 2335 return true; 2336 // Fall through to return value based on context menu controller. 2337 } 2338 // WARNING: we may have been deleted. 2339 return (context_menu_controller != NULL) || possible_drag; 2340 } 2341 2342 void View::ProcessMouseReleased(const ui::MouseEvent& event) { 2343 if (!kContextMenuOnMousePress && context_menu_controller_ && 2344 event.IsOnlyRightMouseButton()) { 2345 // Assume that if there is a context menu controller we won't be deleted 2346 // from mouse released. 2347 gfx::Point location(event.location()); 2348 OnMouseReleased(event); 2349 if (HitTestPoint(location)) { 2350 ConvertPointToScreen(this, &location); 2351 ShowContextMenu(location, ui::MENU_SOURCE_MOUSE); 2352 } 2353 } else { 2354 OnMouseReleased(event); 2355 } 2356 // WARNING: we may have been deleted. 2357 } 2358 2359 // Accelerators ---------------------------------------------------------------- 2360 2361 void View::RegisterPendingAccelerators() { 2362 if (!accelerators_.get() || 2363 registered_accelerator_count_ == accelerators_->size()) { 2364 // No accelerators are waiting for registration. 2365 return; 2366 } 2367 2368 if (!GetWidget()) { 2369 // The view is not yet attached to a widget, defer registration until then. 2370 return; 2371 } 2372 2373 accelerator_focus_manager_ = GetFocusManager(); 2374 if (!accelerator_focus_manager_) { 2375 // Some crash reports seem to show that we may get cases where we have no 2376 // focus manager (see bug #1291225). This should never be the case, just 2377 // making sure we don't crash. 2378 NOTREACHED(); 2379 return; 2380 } 2381 for (std::vector<ui::Accelerator>::const_iterator i( 2382 accelerators_->begin() + registered_accelerator_count_); 2383 i != accelerators_->end(); ++i) { 2384 accelerator_focus_manager_->RegisterAccelerator( 2385 *i, ui::AcceleratorManager::kNormalPriority, this); 2386 } 2387 registered_accelerator_count_ = accelerators_->size(); 2388 } 2389 2390 void View::UnregisterAccelerators(bool leave_data_intact) { 2391 if (!accelerators_.get()) 2392 return; 2393 2394 if (GetWidget()) { 2395 if (accelerator_focus_manager_) { 2396 accelerator_focus_manager_->UnregisterAccelerators(this); 2397 accelerator_focus_manager_ = NULL; 2398 } 2399 if (!leave_data_intact) { 2400 accelerators_->clear(); 2401 accelerators_.reset(); 2402 } 2403 registered_accelerator_count_ = 0; 2404 } 2405 } 2406 2407 // Focus ----------------------------------------------------------------------- 2408 2409 void View::InitFocusSiblings(View* v, int index) { 2410 int count = child_count(); 2411 2412 if (count == 0) { 2413 v->next_focusable_view_ = NULL; 2414 v->previous_focusable_view_ = NULL; 2415 } else { 2416 if (index == count) { 2417 // We are inserting at the end, but the end of the child list may not be 2418 // the last focusable element. Let's try to find an element with no next 2419 // focusable element to link to. 2420 View* last_focusable_view = NULL; 2421 for (Views::iterator i(children_.begin()); i != children_.end(); ++i) { 2422 if (!(*i)->next_focusable_view_) { 2423 last_focusable_view = *i; 2424 break; 2425 } 2426 } 2427 if (last_focusable_view == NULL) { 2428 // Hum... there is a cycle in the focus list. Let's just insert ourself 2429 // after the last child. 2430 View* prev = children_[index - 1]; 2431 v->previous_focusable_view_ = prev; 2432 v->next_focusable_view_ = prev->next_focusable_view_; 2433 prev->next_focusable_view_->previous_focusable_view_ = v; 2434 prev->next_focusable_view_ = v; 2435 } else { 2436 last_focusable_view->next_focusable_view_ = v; 2437 v->next_focusable_view_ = NULL; 2438 v->previous_focusable_view_ = last_focusable_view; 2439 } 2440 } else { 2441 View* prev = children_[index]->GetPreviousFocusableView(); 2442 v->previous_focusable_view_ = prev; 2443 v->next_focusable_view_ = children_[index]; 2444 if (prev) 2445 prev->next_focusable_view_ = v; 2446 children_[index]->previous_focusable_view_ = v; 2447 } 2448 } 2449 } 2450 2451 // System events --------------------------------------------------------------- 2452 2453 void View::PropagateThemeChanged() { 2454 for (int i = child_count() - 1; i >= 0; --i) 2455 child_at(i)->PropagateThemeChanged(); 2456 OnThemeChanged(); 2457 } 2458 2459 void View::PropagateLocaleChanged() { 2460 for (int i = child_count() - 1; i >= 0; --i) 2461 child_at(i)->PropagateLocaleChanged(); 2462 OnLocaleChanged(); 2463 } 2464 2465 // Tooltips -------------------------------------------------------------------- 2466 2467 void View::UpdateTooltip() { 2468 Widget* widget = GetWidget(); 2469 // TODO(beng): The TooltipManager NULL check can be removed when we 2470 // consolidate Init() methods and make views_unittests Init() all 2471 // Widgets that it uses. 2472 if (widget && widget->GetTooltipManager()) 2473 widget->GetTooltipManager()->UpdateTooltip(); 2474 } 2475 2476 // Drag and drop --------------------------------------------------------------- 2477 2478 bool View::DoDrag(const ui::LocatedEvent& event, 2479 const gfx::Point& press_pt, 2480 ui::DragDropTypes::DragEventSource source) { 2481 int drag_operations = GetDragOperations(press_pt); 2482 if (drag_operations == ui::DragDropTypes::DRAG_NONE) 2483 return false; 2484 2485 Widget* widget = GetWidget(); 2486 // We should only start a drag from an event, implying we have a widget. 2487 DCHECK(widget); 2488 2489 // Don't attempt to start a drag while in the process of dragging. This is 2490 // especially important on X where we can get multiple mouse move events when 2491 // we start the drag. 2492 if (widget->dragged_view()) 2493 return false; 2494 2495 OSExchangeData data; 2496 WriteDragData(press_pt, &data); 2497 2498 // Message the RootView to do the drag and drop. That way if we're removed 2499 // the RootView can detect it and avoid calling us back. 2500 gfx::Point widget_location(event.location()); 2501 ConvertPointToWidget(this, &widget_location); 2502 widget->RunShellDrag(this, data, widget_location, drag_operations, source); 2503 // WARNING: we may have been deleted. 2504 return true; 2505 } 2506 2507 } // namespace views 2508