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