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