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.
5 #define _USE_MATH_DEFINES // For VC++ to get M_PI. This has to be first.
7 #include "ui/views/view.h"
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/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/scoped_canvas.h"
32 #include "ui/gfx/screen.h"
33 #include "ui/gfx/skia_util.h"
34 #include "ui/gfx/transform.h"
35 #include "ui/native_theme/native_theme.h"
36 #include "ui/views/accessibility/native_view_accessibility.h"
37 #include "ui/views/background.h"
38 #include "ui/views/context_menu_controller.h"
39 #include "ui/views/drag_controller.h"
40 #include "ui/views/layout/layout_manager.h"
41 #include "ui/views/rect_based_targeting_utils.h"
42 #include "ui/views/views_delegate.h"
43 #include "ui/views/widget/native_widget_private.h"
44 #include "ui/views/widget/root_view.h"
45 #include "ui/views/widget/tooltip_manager.h"
46 #include "ui/views/widget/widget.h"
49 #include "ui/base/cursor/cursor.h"
53 #include "base/win/scoped_gdi_object.h"
58 // Whether to use accelerated compositing when necessary (e.g. when a view has a
61 bool use_acceleration_when_possible
= true;
63 bool use_acceleration_when_possible
= false;
67 const bool kContextMenuOnMousePress
= false;
69 const bool kContextMenuOnMousePress
= true;
72 // The minimum percentage of a view's area that needs to be covered by a rect
73 // representing a touch region in order for that view to be considered by the
74 // rect-based targeting algorithm.
75 static const float kRectTargetOverlap
= 0.6f
;
77 // Returns the top view in |view|'s hierarchy.
78 const views::View
* GetHierarchyRoot(const views::View
* view
) {
79 const views::View
* root
= view
;
80 while (root
&& root
->parent())
81 root
= root
->parent();
91 // This event handler receives events in the post-target phase and takes care of
93 // - Generates context menu, or initiates drag-and-drop, from gesture events.
94 class PostEventDispatchHandler
: public ui::EventHandler
{
96 explicit PostEventDispatchHandler(View
* owner
)
98 touch_dnd_enabled_(switches::IsTouchDragDropEnabled()) {
100 virtual ~PostEventDispatchHandler() {}
103 // Overridden from ui::EventHandler:
104 virtual void OnGestureEvent(ui::GestureEvent
* event
) OVERRIDE
{
105 DCHECK_EQ(ui::EP_POSTTARGET
, event
->phase());
106 if (event
->handled())
109 if (touch_dnd_enabled_
) {
110 if (event
->type() == ui::ET_GESTURE_LONG_PRESS
&&
111 (!owner_
->drag_controller() ||
112 owner_
->drag_controller()->CanStartDragForView(
113 owner_
, event
->location(), event
->location()))) {
114 if (owner_
->DoDrag(*event
, event
->location(),
115 ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH
)) {
116 event
->StopPropagation();
122 if (owner_
->context_menu_controller() &&
123 (event
->type() == ui::ET_GESTURE_LONG_PRESS
||
124 event
->type() == ui::ET_GESTURE_LONG_TAP
||
125 event
->type() == ui::ET_GESTURE_TWO_FINGER_TAP
)) {
126 gfx::Point
location(event
->location());
127 View::ConvertPointToScreen(owner_
, &location
);
128 owner_
->ShowContextMenu(location
, ui::MENU_SOURCE_TOUCH
);
129 event
->StopPropagation();
134 bool touch_dnd_enabled_
;
136 DISALLOW_COPY_AND_ASSIGN(PostEventDispatchHandler
);
139 } // namespace internal
142 ViewsDelegate
* ViewsDelegate::views_delegate
= NULL
;
145 const char View::kViewClassName
[] = "View";
147 ////////////////////////////////////////////////////////////////////////////////
150 // Creation and lifetime -------------------------------------------------------
153 : owned_by_client_(false),
159 notify_enter_exit_on_child_(false),
160 registered_for_visible_bounds_notification_(false),
161 clip_insets_(0, 0, 0, 0),
163 focus_border_(FocusBorder::CreateDashedFocusBorder()),
164 flip_canvas_on_paint_for_rtl_ui_(false),
165 paint_to_layer_(false),
166 accelerator_focus_manager_(NULL
),
167 registered_accelerator_count_(0),
168 next_focusable_view_(NULL
),
169 previous_focusable_view_(NULL
),
171 accessibility_focusable_(false),
172 context_menu_controller_(NULL
),
173 drag_controller_(NULL
),
174 post_dispatch_handler_(new internal::PostEventDispatchHandler(this)),
175 native_view_accessibility_(NULL
) {
176 AddPostTargetHandler(post_dispatch_handler_
.get());
181 parent_
->RemoveChildView(this);
183 for (Views::const_iterator
i(children_
.begin()); i
!= children_
.end(); ++i
) {
184 (*i
)->parent_
= NULL
;
185 if (!(*i
)->owned_by_client_
)
189 // Release ownership of the native accessibility object, but it's
190 // reference-counted on some platforms, so it may not be deleted right away.
191 if (native_view_accessibility_
)
192 native_view_accessibility_
->Destroy();
195 // Tree operations -------------------------------------------------------------
197 const Widget
* View::GetWidget() const {
198 // The root view holds a reference to this view hierarchy's Widget.
199 return parent_
? parent_
->GetWidget() : NULL
;
202 Widget
* View::GetWidget() {
203 return const_cast<Widget
*>(const_cast<const View
*>(this)->GetWidget());
206 void View::AddChildView(View
* view
) {
207 if (view
->parent_
== this)
209 AddChildViewAt(view
, child_count());
212 void View::AddChildViewAt(View
* view
, int index
) {
213 CHECK_NE(view
, this) << "You cannot add a view as its own child";
215 DCHECK_LE(index
, child_count());
217 // If |view| has a parent, remove it from its parent.
218 View
* parent
= view
->parent_
;
219 const ui::NativeTheme
* old_theme
= view
->GetNativeTheme();
221 if (parent
== this) {
222 ReorderChildView(view
, index
);
225 parent
->DoRemoveChildView(view
, true, true, false, this);
228 // Sets the prev/next focus views.
229 InitFocusSiblings(view
, index
);
231 // Let's insert the view.
232 view
->parent_
= this;
233 children_
.insert(children_
.begin() + index
, view
);
235 ViewHierarchyChangedDetails
details(true, this, view
, parent
);
237 for (View
* v
= this; v
; v
= v
->parent_
)
238 v
->ViewHierarchyChangedImpl(false, details
);
240 view
->PropagateAddNotifications(details
);
242 views::Widget
* widget
= GetWidget();
244 RegisterChildrenForVisibleBoundsNotification(view
);
245 const ui::NativeTheme
* new_theme
= widget
->GetNativeTheme();
246 if (new_theme
!= old_theme
)
247 PropagateNativeThemeChanged(new_theme
);
250 if (layout_manager_
.get())
251 layout_manager_
->ViewAdded(this, view
);
253 if (use_acceleration_when_possible
)
256 // Make sure the visibility of the child layers are correct.
257 // If any of the parent View is hidden, then the layers of the subtree
258 // rooted at |this| should be hidden. Otherwise, all the child layers should
259 // inherit the visibility of the owner View.
260 UpdateLayerVisibility();
263 void View::ReorderChildView(View
* view
, int index
) {
264 DCHECK_EQ(view
->parent_
, this);
266 index
= child_count() - 1;
267 else if (index
>= child_count())
269 if (children_
[index
] == view
)
272 const Views::iterator
i(std::find(children_
.begin(), children_
.end(), view
));
273 DCHECK(i
!= children_
.end());
276 // Unlink the view first
277 View
* next_focusable
= view
->next_focusable_view_
;
278 View
* prev_focusable
= view
->previous_focusable_view_
;
280 prev_focusable
->next_focusable_view_
= next_focusable
;
282 next_focusable
->previous_focusable_view_
= prev_focusable
;
284 // Add it in the specified index now.
285 InitFocusSiblings(view
, index
);
286 children_
.insert(children_
.begin() + index
, view
);
288 if (use_acceleration_when_possible
)
292 void View::RemoveChildView(View
* view
) {
293 DoRemoveChildView(view
, true, true, false, NULL
);
296 void View::RemoveAllChildViews(bool delete_children
) {
297 while (!children_
.empty())
298 DoRemoveChildView(children_
.front(), false, false, delete_children
, NULL
);
302 bool View::Contains(const View
* view
) const {
303 for (const View
* v
= view
; v
; v
= v
->parent_
) {
310 int View::GetIndexOf(const View
* view
) const {
311 Views::const_iterator
i(std::find(children_
.begin(), children_
.end(), view
));
312 return i
!= children_
.end() ? static_cast<int>(i
- children_
.begin()) : -1;
315 // Size and disposition --------------------------------------------------------
317 void View::SetBounds(int x
, int y
, int width
, int height
) {
318 SetBoundsRect(gfx::Rect(x
, y
, std::max(0, width
), std::max(0, height
)));
321 void View::SetBoundsRect(const gfx::Rect
& bounds
) {
322 if (bounds
== bounds_
) {
324 needs_layout_
= false;
332 // Paint where the view is currently.
333 SchedulePaintBoundsChanged(
334 bounds_
.size() == bounds
.size() ? SCHEDULE_PAINT_SIZE_SAME
:
335 SCHEDULE_PAINT_SIZE_CHANGED
);
338 gfx::Rect prev
= bounds_
;
343 void View::SetSize(const gfx::Size
& size
) {
344 SetBounds(x(), y(), size
.width(), size
.height());
347 void View::SetPosition(const gfx::Point
& position
) {
348 SetBounds(position
.x(), position
.y(), width(), height());
351 void View::SetX(int x
) {
352 SetBounds(x
, y(), width(), height());
355 void View::SetY(int y
) {
356 SetBounds(x(), y
, width(), height());
359 gfx::Rect
View::GetContentsBounds() const {
360 gfx::Rect
contents_bounds(GetLocalBounds());
362 contents_bounds
.Inset(border_
->GetInsets());
363 return contents_bounds
;
366 gfx::Rect
View::GetLocalBounds() const {
367 return gfx::Rect(size());
370 gfx::Rect
View::GetLayerBoundsInPixel() const {
371 return layer()->GetTargetBounds();
374 gfx::Insets
View::GetInsets() const {
375 return border_
.get() ? border_
->GetInsets() : gfx::Insets();
378 gfx::Rect
View::GetVisibleBounds() const {
381 gfx::Rect
vis_bounds(GetLocalBounds());
382 gfx::Rect ancestor_bounds
;
383 const View
* view
= this;
384 gfx::Transform transform
;
386 while (view
!= NULL
&& !vis_bounds
.IsEmpty()) {
387 transform
.ConcatTransform(view
->GetTransform());
388 gfx::Transform translation
;
389 translation
.Translate(static_cast<float>(view
->GetMirroredX()),
390 static_cast<float>(view
->y()));
391 transform
.ConcatTransform(translation
);
393 vis_bounds
= view
->ConvertRectToParent(vis_bounds
);
394 const View
* ancestor
= view
->parent_
;
395 if (ancestor
!= NULL
) {
396 ancestor_bounds
.SetRect(0, 0, ancestor
->width(), ancestor
->height());
397 vis_bounds
.Intersect(ancestor_bounds
);
398 } else if (!view
->GetWidget()) {
399 // If the view has no Widget, we're not visible. Return an empty rect.
404 if (vis_bounds
.IsEmpty())
406 // Convert back to this views coordinate system.
407 gfx::RectF
views_vis_bounds(vis_bounds
);
408 transform
.TransformRectReverse(&views_vis_bounds
);
409 // Partially visible pixels should be considered visible.
410 return gfx::ToEnclosingRect(views_vis_bounds
);
413 gfx::Rect
View::GetBoundsInScreen() const {
415 View::ConvertPointToScreen(this, &origin
);
416 return gfx::Rect(origin
, size());
419 gfx::Size
View::GetPreferredSize() {
420 if (layout_manager_
.get())
421 return layout_manager_
->GetPreferredSize(this);
425 int View::GetBaseline() const {
429 void View::SizeToPreferredSize() {
430 gfx::Size prefsize
= GetPreferredSize();
431 if ((prefsize
.width() != width()) || (prefsize
.height() != height()))
432 SetBounds(x(), y(), prefsize
.width(), prefsize
.height());
435 gfx::Size
View::GetMinimumSize() {
436 return GetPreferredSize();
439 gfx::Size
View::GetMaximumSize() {
443 int View::GetHeightForWidth(int w
) {
444 if (layout_manager_
.get())
445 return layout_manager_
->GetPreferredHeightForWidth(this, w
);
446 return GetPreferredSize().height();
449 void View::SetVisible(bool visible
) {
450 if (visible
!= visible_
) {
451 // If the View is currently visible, schedule paint to refresh parent.
452 // TODO(beng): not sure we should be doing this if we have a layer.
458 // Notify the parent.
460 parent_
->ChildVisibilityChanged(this);
462 // This notifies all sub-views recursively.
463 PropagateVisibilityNotifications(this, visible_
);
464 UpdateLayerVisibility();
466 // If we are newly visible, schedule paint.
472 bool View::IsDrawn() const {
473 return visible_
&& parent_
? parent_
->IsDrawn() : false;
476 void View::SetEnabled(bool enabled
) {
477 if (enabled
!= enabled_
) {
483 void View::OnEnabledChanged() {
487 // Transformations -------------------------------------------------------------
489 gfx::Transform
View::GetTransform() const {
490 return layer() ? layer()->transform() : gfx::Transform();
493 void View::SetTransform(const gfx::Transform
& transform
) {
494 if (transform
.IsIdentity()) {
496 layer()->SetTransform(transform
);
497 if (!paint_to_layer_
)
505 layer()->SetTransform(transform
);
506 layer()->ScheduleDraw();
510 void View::SetPaintToLayer(bool paint_to_layer
) {
511 paint_to_layer_
= paint_to_layer
;
512 if (paint_to_layer_
&& !layer()) {
514 } else if (!paint_to_layer_
&& layer()) {
519 ui::Layer
* View::RecreateLayer() {
520 ui::Layer
* layer
= AcquireLayer();
525 layer_
->set_scale_content(layer
->scale_content());
529 // RTL positioning -------------------------------------------------------------
531 gfx::Rect
View::GetMirroredBounds() const {
532 gfx::Rect
bounds(bounds_
);
533 bounds
.set_x(GetMirroredX());
537 gfx::Point
View::GetMirroredPosition() const {
538 return gfx::Point(GetMirroredX(), y());
541 int View::GetMirroredX() const {
542 return parent_
? parent_
->GetMirroredXForRect(bounds_
) : x();
545 int View::GetMirroredXForRect(const gfx::Rect
& bounds
) const {
546 return base::i18n::IsRTL() ?
547 (width() - bounds
.x() - bounds
.width()) : bounds
.x();
550 int View::GetMirroredXInView(int x
) const {
551 return base::i18n::IsRTL() ? width() - x
: x
;
554 int View::GetMirroredXWithWidthInView(int x
, int w
) const {
555 return base::i18n::IsRTL() ? width() - x
- w
: x
;
558 // Layout ----------------------------------------------------------------------
560 void View::Layout() {
561 needs_layout_
= false;
563 // If we have a layout manager, let it handle the layout for us.
564 if (layout_manager_
.get())
565 layout_manager_
->Layout(this);
567 // Make sure to propagate the Layout() call to any children that haven't
568 // received it yet through the layout manager and need to be laid out. This
569 // is needed for the case when the child requires a layout but its bounds
570 // weren't changed by the layout manager. If there is no layout manager, we
571 // just propagate the Layout() call down the hierarchy, so whoever receives
572 // the call can take appropriate action.
573 for (int i
= 0, count
= child_count(); i
< count
; ++i
) {
574 View
* child
= child_at(i
);
575 if (child
->needs_layout_
|| !layout_manager_
.get()) {
576 child
->needs_layout_
= false;
582 void View::InvalidateLayout() {
583 // Always invalidate up. This is needed to handle the case of us already being
584 // valid, but not our parent.
585 needs_layout_
= true;
587 parent_
->InvalidateLayout();
590 LayoutManager
* View::GetLayoutManager() const {
591 return layout_manager_
.get();
594 void View::SetLayoutManager(LayoutManager
* layout_manager
) {
595 if (layout_manager_
.get())
596 layout_manager_
->Uninstalled(this);
598 layout_manager_
.reset(layout_manager
);
599 if (layout_manager_
.get())
600 layout_manager_
->Installed(this);
603 // Attributes ------------------------------------------------------------------
605 const char* View::GetClassName() const {
606 return kViewClassName
;
609 View
* View::GetAncestorWithClassName(const std::string
& name
) {
610 for (View
* view
= this; view
; view
= view
->parent_
) {
611 if (!strcmp(view
->GetClassName(), name
.c_str()))
617 const View
* View::GetViewByID(int id
) const {
619 return const_cast<View
*>(this);
621 for (int i
= 0, count
= child_count(); i
< count
; ++i
) {
622 const View
* view
= child_at(i
)->GetViewByID(id
);
629 View
* View::GetViewByID(int id
) {
630 return const_cast<View
*>(const_cast<const View
*>(this)->GetViewByID(id
));
633 void View::SetGroup(int gid
) {
634 // Don't change the group id once it's set.
635 DCHECK(group_
== -1 || group_
== gid
);
639 int View::GetGroup() const {
643 bool View::IsGroupFocusTraversable() const {
647 void View::GetViewsInGroup(int group
, Views
* views
) {
649 views
->push_back(this);
651 for (int i
= 0, count
= child_count(); i
< count
; ++i
)
652 child_at(i
)->GetViewsInGroup(group
, views
);
655 View
* View::GetSelectedViewForGroup(int group
) {
657 GetWidget()->GetRootView()->GetViewsInGroup(group
, &views
);
658 return views
.empty() ? NULL
: views
[0];
661 // Coordinate conversion -------------------------------------------------------
664 void View::ConvertPointToTarget(const View
* source
,
667 if (source
== target
)
670 // |source| can be NULL.
671 const View
* root
= GetHierarchyRoot(target
);
673 CHECK_EQ(GetHierarchyRoot(source
), root
);
676 source
->ConvertPointForAncestor(root
, point
);
680 target
->ConvertPointFromAncestor(root
, point
);
682 // API defines NULL |source| as returning the point in screen coordinates.
685 root
->GetWidget()->GetClientAreaBoundsInScreen().OffsetFromOrigin();
690 void View::ConvertRectToTarget(const View
* source
,
693 if (source
== target
)
696 // |source| can be NULL.
697 const View
* root
= GetHierarchyRoot(target
);
699 CHECK_EQ(GetHierarchyRoot(source
), root
);
702 source
->ConvertRectForAncestor(root
, rect
);
706 target
->ConvertRectFromAncestor(root
, rect
);
708 // API defines NULL |source| as returning the point in screen coordinates.
710 rect
->set_origin(rect
->origin() -
711 root
->GetWidget()->GetClientAreaBoundsInScreen().OffsetFromOrigin());
716 void View::ConvertPointToWidget(const View
* src
, gfx::Point
* p
) {
720 src
->ConvertPointForAncestor(NULL
, p
);
724 void View::ConvertPointFromWidget(const View
* dest
, gfx::Point
* p
) {
728 dest
->ConvertPointFromAncestor(NULL
, p
);
732 void View::ConvertPointToScreen(const View
* src
, gfx::Point
* p
) {
736 // If the view is not connected to a tree, there's nothing we can do.
737 const Widget
* widget
= src
->GetWidget();
739 ConvertPointToWidget(src
, p
);
740 *p
+= widget
->GetClientAreaBoundsInScreen().OffsetFromOrigin();
745 void View::ConvertPointFromScreen(const View
* dst
, gfx::Point
* p
) {
749 const views::Widget
* widget
= dst
->GetWidget();
752 *p
-= widget
->GetClientAreaBoundsInScreen().OffsetFromOrigin();
753 views::View::ConvertPointFromWidget(dst
, p
);
756 gfx::Rect
View::ConvertRectToParent(const gfx::Rect
& rect
) const {
757 gfx::RectF x_rect
= rect
;
758 GetTransform().TransformRect(&x_rect
);
759 x_rect
.Offset(GetMirroredPosition().OffsetFromOrigin());
760 // Pixels we partially occupy in the parent should be included.
761 return gfx::ToEnclosingRect(x_rect
);
764 gfx::Rect
View::ConvertRectToWidget(const gfx::Rect
& rect
) const {
765 gfx::Rect x_rect
= rect
;
766 for (const View
* v
= this; v
; v
= v
->parent_
)
767 x_rect
= v
->ConvertRectToParent(x_rect
);
771 // Painting --------------------------------------------------------------------
773 void View::SchedulePaint() {
774 SchedulePaintInRect(GetLocalBounds());
777 void View::SchedulePaintInRect(const gfx::Rect
& rect
) {
782 layer()->SchedulePaint(rect
);
783 } else if (parent_
) {
784 // Translate the requested paint rect to the parent's coordinate system
785 // then pass this notification up to the parent.
786 parent_
->SchedulePaintInRect(ConvertRectToParent(rect
));
790 void View::Paint(gfx::Canvas
* canvas
) {
791 TRACE_EVENT1("views", "View::Paint", "class", GetClassName());
793 gfx::ScopedCanvas
scoped_canvas(canvas
);
795 // Paint this View and its children, setting the clip rect to the bounds
796 // of this View and translating the origin to the local bounds' top left
799 // Note that the X (or left) position we pass to ClipRectInt takes into
800 // consideration whether or not the view uses a right-to-left layout so that
801 // we paint our view in its mirrored position if need be.
802 gfx::Rect clip_rect
= bounds();
803 clip_rect
.Inset(clip_insets_
);
805 clip_rect
.set_x(parent_
->GetMirroredXForRect(clip_rect
));
806 if (!canvas
->ClipRect(clip_rect
))
809 // Non-empty clip, translate the graphics such that 0,0 corresponds to
810 // where this view is located (related to its parent).
811 canvas
->Translate(GetMirroredPosition().OffsetFromOrigin());
812 canvas
->Transform(GetTransform());
817 ui::ThemeProvider
* View::GetThemeProvider() const {
818 const Widget
* widget
= GetWidget();
819 return widget
? widget
->GetThemeProvider() : NULL
;
822 const ui::NativeTheme
* View::GetNativeTheme() const {
823 const Widget
* widget
= GetWidget();
824 return widget
? widget
->GetNativeTheme() : ui::NativeTheme::instance();
827 // Accelerated Painting --------------------------------------------------------
830 void View::set_use_acceleration_when_possible(bool use
) {
831 use_acceleration_when_possible
= use
;
835 bool View::get_use_acceleration_when_possible() {
836 return use_acceleration_when_possible
;
839 // Input -----------------------------------------------------------------------
841 View
* View::GetEventHandlerForPoint(const gfx::Point
& point
) {
842 return GetEventHandlerForRect(gfx::Rect(point
, gfx::Size(1, 1)));
845 View
* View::GetEventHandlerForRect(const gfx::Rect
& rect
) {
846 // |rect_view| represents the current best candidate to return
847 // if rect-based targeting (i.e., fuzzing) is used.
848 // |rect_view_distance| is used to keep track of the distance
849 // between the center point of |rect_view| and the center
851 View
* rect_view
= NULL
;
852 int rect_view_distance
= INT_MAX
;
854 // |point_view| represents the view that would have been returned
855 // from this function call if point-based targeting were used.
856 View
* point_view
= NULL
;
858 for (int i
= child_count() - 1; i
>= 0; --i
) {
859 View
* child
= child_at(i
);
861 // Ignore any children which are invisible or do not intersect |rect|.
862 if (!child
->visible())
864 gfx::RectF
rect_in_child_coords_f(rect
);
865 ConvertRectToTarget(this, child
, &rect_in_child_coords_f
);
866 gfx::Rect rect_in_child_coords
= gfx::ToEnclosingRect(
867 rect_in_child_coords_f
);
868 if (!child
->HitTestRect(rect_in_child_coords
))
871 View
* cur_view
= child
->GetEventHandlerForRect(rect_in_child_coords
);
873 if (views::UsePointBasedTargeting(rect
))
876 gfx::RectF
cur_view_bounds_f(cur_view
->GetLocalBounds());
877 ConvertRectToTarget(cur_view
, this, &cur_view_bounds_f
);
878 gfx::Rect cur_view_bounds
= gfx::ToEnclosingRect(
880 if (views::PercentCoveredBy(cur_view_bounds
, rect
) >= kRectTargetOverlap
) {
881 // |cur_view| is a suitable candidate for rect-based targeting.
882 // Check to see if it is the closest suitable candidate so far.
883 gfx::Point
touch_center(rect
.CenterPoint());
884 int cur_dist
= views::DistanceSquaredFromCenterLineToPoint(
885 touch_center
, cur_view_bounds
);
886 if (!rect_view
|| cur_dist
< rect_view_distance
) {
887 rect_view
= cur_view
;
888 rect_view_distance
= cur_dist
;
890 } else if (!rect_view
&& !point_view
) {
891 // Rect-based targeting has not yielded any candidates so far. Check
892 // if point-based targeting would have selected |cur_view|.
893 gfx::Point
point_in_child_coords(rect_in_child_coords
.CenterPoint());
894 if (child
->HitTestPoint(point_in_child_coords
))
895 point_view
= child
->GetEventHandlerForPoint(point_in_child_coords
);
899 if (views::UsePointBasedTargeting(rect
) || (!rect_view
&& !point_view
))
902 // If |this| is a suitable candidate for rect-based targeting, check to
903 // see if it is closer than the current best suitable candidate so far.
904 gfx::Rect
local_bounds(GetLocalBounds());
905 if (views::PercentCoveredBy(local_bounds
, rect
) >= kRectTargetOverlap
) {
906 gfx::Point
touch_center(rect
.CenterPoint());
907 int cur_dist
= views::DistanceSquaredFromCenterLineToPoint(touch_center
,
909 if (!rect_view
|| cur_dist
< rect_view_distance
)
913 return rect_view
? rect_view
: point_view
;
916 View
* View::GetTooltipHandlerForPoint(const gfx::Point
& point
) {
917 if (!HitTestPoint(point
))
920 // Walk the child Views recursively looking for the View that most
921 // tightly encloses the specified point.
922 for (int i
= child_count() - 1; i
>= 0; --i
) {
923 View
* child
= child_at(i
);
924 if (!child
->visible())
927 gfx::Point
point_in_child_coords(point
);
928 ConvertPointToTarget(this, child
, &point_in_child_coords
);
929 View
* handler
= child
->GetTooltipHandlerForPoint(point_in_child_coords
);
936 gfx::NativeCursor
View::GetCursor(const ui::MouseEvent
& event
) {
938 #if defined(USE_AURA)
939 static ui::Cursor arrow
;
940 if (!arrow
.platform())
941 arrow
.SetPlatformCursor(LoadCursor(NULL
, IDC_ARROW
));
944 static HCURSOR arrow
= LoadCursor(NULL
, IDC_ARROW
);
948 return gfx::kNullCursor
;
952 bool View::HitTestPoint(const gfx::Point
& point
) const {
953 return HitTestRect(gfx::Rect(point
, gfx::Size(1, 1)));
956 bool View::HitTestRect(const gfx::Rect
& rect
) const {
957 if (GetLocalBounds().Intersects(rect
)) {
958 if (HasHitTestMask()) {
960 HitTestSource source
= HIT_TEST_SOURCE_MOUSE
;
961 if (!views::UsePointBasedTargeting(rect
))
962 source
= HIT_TEST_SOURCE_TOUCH
;
963 GetHitTestMask(source
, &mask
);
964 #if defined(USE_AURA)
965 // TODO: should we use this every where?
966 SkRegion clip_region
;
967 clip_region
.setRect(0, 0, width(), height());
968 SkRegion mask_region
;
969 return mask_region
.setPath(mask
, clip_region
) &&
970 mask_region
.intersects(RectToSkIRect(rect
));
971 #elif defined(OS_WIN)
972 base::win::ScopedRegion
rgn(mask
.CreateNativeRegion());
973 const RECT
r(rect
.ToRECT());
974 return RectInRegion(rgn
, &r
) != 0;
977 // No mask, but inside our bounds.
980 // Outside our bounds.
984 bool View::IsMouseHovered() {
985 // If we haven't yet been placed in an onscreen view hierarchy, we can't be
990 // If mouse events are disabled, then the mouse cursor is invisible and
991 // is therefore not hovering over this button.
992 if (!GetWidget()->IsMouseEventsEnabled())
995 gfx::Point
cursor_pos(gfx::Screen::GetScreenFor(
996 GetWidget()->GetNativeView())->GetCursorScreenPoint());
997 ConvertPointToTarget(NULL
, this, &cursor_pos
);
998 return HitTestPoint(cursor_pos
);
1001 bool View::OnMousePressed(const ui::MouseEvent
& event
) {
1005 bool View::OnMouseDragged(const ui::MouseEvent
& event
) {
1009 void View::OnMouseReleased(const ui::MouseEvent
& event
) {
1012 void View::OnMouseCaptureLost() {
1015 void View::OnMouseMoved(const ui::MouseEvent
& event
) {
1018 void View::OnMouseEntered(const ui::MouseEvent
& event
) {
1021 void View::OnMouseExited(const ui::MouseEvent
& event
) {
1024 void View::SetMouseHandler(View
* new_mouse_handler
) {
1025 // |new_mouse_handler| may be NULL.
1027 parent_
->SetMouseHandler(new_mouse_handler
);
1030 bool View::OnKeyPressed(const ui::KeyEvent
& event
) {
1034 bool View::OnKeyReleased(const ui::KeyEvent
& event
) {
1038 bool View::OnMouseWheel(const ui::MouseWheelEvent
& event
) {
1042 void View::OnKeyEvent(ui::KeyEvent
* event
) {
1043 bool consumed
= (event
->type() == ui::ET_KEY_PRESSED
) ? OnKeyPressed(*event
) :
1044 OnKeyReleased(*event
);
1046 event
->StopPropagation();
1049 void View::OnMouseEvent(ui::MouseEvent
* event
) {
1050 switch (event
->type()) {
1051 case ui::ET_MOUSE_PRESSED
:
1052 if (ProcessMousePressed(*event
))
1053 event
->SetHandled();
1056 case ui::ET_MOUSE_MOVED
:
1057 if ((event
->flags() & (ui::EF_LEFT_MOUSE_BUTTON
|
1058 ui::EF_RIGHT_MOUSE_BUTTON
|
1059 ui::EF_MIDDLE_MOUSE_BUTTON
)) == 0) {
1060 OnMouseMoved(*event
);
1064 case ui::ET_MOUSE_DRAGGED
:
1065 if (ProcessMouseDragged(*event
))
1066 event
->SetHandled();
1069 case ui::ET_MOUSE_RELEASED
:
1070 ProcessMouseReleased(*event
);
1073 case ui::ET_MOUSEWHEEL
:
1074 if (OnMouseWheel(*static_cast<ui::MouseWheelEvent
*>(event
)))
1075 event
->SetHandled();
1078 case ui::ET_MOUSE_ENTERED
:
1079 OnMouseEntered(*event
);
1082 case ui::ET_MOUSE_EXITED
:
1083 OnMouseExited(*event
);
1091 void View::OnScrollEvent(ui::ScrollEvent
* event
) {
1094 void View::OnTouchEvent(ui::TouchEvent
* event
) {
1097 void View::OnGestureEvent(ui::GestureEvent
* event
) {
1100 ui::TextInputClient
* View::GetTextInputClient() {
1104 InputMethod
* View::GetInputMethod() {
1105 Widget
* widget
= GetWidget();
1106 return widget
? widget
->GetInputMethod() : NULL
;
1109 const InputMethod
* View::GetInputMethod() const {
1110 const Widget
* widget
= GetWidget();
1111 return widget
? widget
->GetInputMethod() : NULL
;
1114 bool View::CanAcceptEvent(const ui::Event
& event
) {
1115 return event
.dispatch_to_hidden_targets() || IsDrawn();
1118 ui::EventTarget
* View::GetParentTarget() {
1122 // Accelerators ----------------------------------------------------------------
1124 void View::AddAccelerator(const ui::Accelerator
& accelerator
) {
1125 if (!accelerators_
.get())
1126 accelerators_
.reset(new std::vector
<ui::Accelerator
>());
1128 if (std::find(accelerators_
->begin(), accelerators_
->end(), accelerator
) ==
1129 accelerators_
->end()) {
1130 accelerators_
->push_back(accelerator
);
1132 RegisterPendingAccelerators();
1135 void View::RemoveAccelerator(const ui::Accelerator
& accelerator
) {
1136 if (!accelerators_
.get()) {
1137 NOTREACHED() << "Removing non-existing accelerator";
1141 std::vector
<ui::Accelerator
>::iterator
i(
1142 std::find(accelerators_
->begin(), accelerators_
->end(), accelerator
));
1143 if (i
== accelerators_
->end()) {
1144 NOTREACHED() << "Removing non-existing accelerator";
1148 size_t index
= i
- accelerators_
->begin();
1149 accelerators_
->erase(i
);
1150 if (index
>= registered_accelerator_count_
) {
1151 // The accelerator is not registered to FocusManager.
1154 --registered_accelerator_count_
;
1156 // Providing we are attached to a Widget and registered with a focus manager,
1157 // we should de-register from that focus manager now.
1158 if (GetWidget() && accelerator_focus_manager_
)
1159 accelerator_focus_manager_
->UnregisterAccelerator(accelerator
, this);
1162 void View::ResetAccelerators() {
1163 if (accelerators_
.get())
1164 UnregisterAccelerators(false);
1167 bool View::AcceleratorPressed(const ui::Accelerator
& accelerator
) {
1171 bool View::CanHandleAccelerators() const {
1172 return enabled() && IsDrawn() && GetWidget() && GetWidget()->IsVisible();
1175 // Focus -----------------------------------------------------------------------
1177 bool View::HasFocus() const {
1178 const FocusManager
* focus_manager
= GetFocusManager();
1179 return focus_manager
&& (focus_manager
->GetFocusedView() == this);
1182 View
* View::GetNextFocusableView() {
1183 return next_focusable_view_
;
1186 const View
* View::GetNextFocusableView() const {
1187 return next_focusable_view_
;
1190 View
* View::GetPreviousFocusableView() {
1191 return previous_focusable_view_
;
1194 void View::SetNextFocusableView(View
* view
) {
1196 view
->previous_focusable_view_
= this;
1197 next_focusable_view_
= view
;
1200 bool View::IsFocusable() const {
1201 return focusable_
&& enabled_
&& IsDrawn();
1204 bool View::IsAccessibilityFocusable() const {
1205 return (focusable_
|| accessibility_focusable_
) && enabled_
&& IsDrawn();
1208 FocusManager
* View::GetFocusManager() {
1209 Widget
* widget
= GetWidget();
1210 return widget
? widget
->GetFocusManager() : NULL
;
1213 const FocusManager
* View::GetFocusManager() const {
1214 const Widget
* widget
= GetWidget();
1215 return widget
? widget
->GetFocusManager() : NULL
;
1218 void View::RequestFocus() {
1219 FocusManager
* focus_manager
= GetFocusManager();
1220 if (focus_manager
&& IsFocusable())
1221 focus_manager
->SetFocusedView(this);
1224 bool View::SkipDefaultKeyEventProcessing(const ui::KeyEvent
& event
) {
1228 FocusTraversable
* View::GetFocusTraversable() {
1232 FocusTraversable
* View::GetPaneFocusTraversable() {
1236 // Tooltips --------------------------------------------------------------------
1238 bool View::GetTooltipText(const gfx::Point
& p
, string16
* tooltip
) const {
1242 bool View::GetTooltipTextOrigin(const gfx::Point
& p
, gfx::Point
* loc
) const {
1246 // Context menus ---------------------------------------------------------------
1248 void View::ShowContextMenu(const gfx::Point
& p
,
1249 ui::MenuSourceType source_type
) {
1250 if (!context_menu_controller_
)
1253 context_menu_controller_
->ShowContextMenuForView(this, p
, source_type
);
1257 bool View::ShouldShowContextMenuOnMousePress() {
1258 return kContextMenuOnMousePress
;
1261 // Drag and drop ---------------------------------------------------------------
1263 bool View::GetDropFormats(
1265 std::set
<OSExchangeData::CustomFormat
>* custom_formats
) {
1269 bool View::AreDropTypesRequired() {
1273 bool View::CanDrop(const OSExchangeData
& data
) {
1274 // TODO(sky): when I finish up migration, this should default to true.
1278 void View::OnDragEntered(const ui::DropTargetEvent
& event
) {
1281 int View::OnDragUpdated(const ui::DropTargetEvent
& event
) {
1282 return ui::DragDropTypes::DRAG_NONE
;
1285 void View::OnDragExited() {
1288 int View::OnPerformDrop(const ui::DropTargetEvent
& event
) {
1289 return ui::DragDropTypes::DRAG_NONE
;
1292 void View::OnDragDone() {
1296 bool View::ExceededDragThreshold(const gfx::Vector2d
& delta
) {
1297 return (abs(delta
.x()) > GetHorizontalDragThreshold() ||
1298 abs(delta
.y()) > GetVerticalDragThreshold());
1301 // Accessibility----------------------------------------------------------------
1303 gfx::NativeViewAccessible
View::GetNativeViewAccessible() {
1304 if (!native_view_accessibility_
)
1305 native_view_accessibility_
= NativeViewAccessibility::Create(this);
1306 if (native_view_accessibility_
)
1307 return native_view_accessibility_
->GetNativeObject();
1311 void View::NotifyAccessibilityEvent(
1312 ui::AccessibilityTypes::Event event_type
,
1313 bool send_native_event
) {
1314 if (ViewsDelegate::views_delegate
)
1315 ViewsDelegate::views_delegate
->NotifyAccessibilityEvent(this, event_type
);
1317 if (send_native_event
) {
1318 if (!native_view_accessibility_
)
1319 native_view_accessibility_
= NativeViewAccessibility::Create(this);
1320 if (native_view_accessibility_
)
1321 native_view_accessibility_
->NotifyAccessibilityEvent(event_type
);
1325 // Scrolling -------------------------------------------------------------------
1327 void View::ScrollRectToVisible(const gfx::Rect
& rect
) {
1328 // We must take RTL UI mirroring into account when adjusting the position of
1331 gfx::Rect
scroll_rect(rect
);
1332 scroll_rect
.Offset(GetMirroredX(), y());
1333 parent_
->ScrollRectToVisible(scroll_rect
);
1337 int View::GetPageScrollIncrement(ScrollView
* scroll_view
,
1338 bool is_horizontal
, bool is_positive
) {
1342 int View::GetLineScrollIncrement(ScrollView
* scroll_view
,
1343 bool is_horizontal
, bool is_positive
) {
1347 ////////////////////////////////////////////////////////////////////////////////
1350 // Size and disposition --------------------------------------------------------
1352 void View::OnBoundsChanged(const gfx::Rect
& previous_bounds
) {
1355 void View::PreferredSizeChanged() {
1358 parent_
->ChildPreferredSizeChanged(this);
1361 bool View::NeedsNotificationWhenVisibleBoundsChange() const {
1365 void View::OnVisibleBoundsChanged() {
1368 // Tree operations -------------------------------------------------------------
1370 void View::ViewHierarchyChanged(const ViewHierarchyChangedDetails
& details
) {
1373 void View::VisibilityChanged(View
* starting_from
, bool is_visible
) {
1376 void View::NativeViewHierarchyChanged() {
1377 FocusManager
* focus_manager
= GetFocusManager();
1378 if (accelerator_focus_manager_
!= focus_manager
) {
1379 UnregisterAccelerators(true);
1382 RegisterPendingAccelerators();
1386 // Painting --------------------------------------------------------------------
1388 void View::PaintChildren(gfx::Canvas
* canvas
) {
1389 TRACE_EVENT1("views", "View::PaintChildren", "class", GetClassName());
1390 for (int i
= 0, count
= child_count(); i
< count
; ++i
)
1391 if (!child_at(i
)->layer())
1392 child_at(i
)->Paint(canvas
);
1395 void View::OnPaint(gfx::Canvas
* canvas
) {
1396 TRACE_EVENT1("views", "View::OnPaint", "class", GetClassName());
1397 OnPaintBackground(canvas
);
1398 OnPaintFocusBorder(canvas
);
1399 OnPaintBorder(canvas
);
1402 void View::OnPaintBackground(gfx::Canvas
* canvas
) {
1403 if (background_
.get()) {
1404 TRACE_EVENT2("views", "View::OnPaintBackground",
1405 "width", canvas
->sk_canvas()->getDevice()->width(),
1406 "height", canvas
->sk_canvas()->getDevice()->height());
1407 background_
->Paint(canvas
, this);
1411 void View::OnPaintBorder(gfx::Canvas
* canvas
) {
1412 if (border_
.get()) {
1413 TRACE_EVENT2("views", "View::OnPaintBorder",
1414 "width", canvas
->sk_canvas()->getDevice()->width(),
1415 "height", canvas
->sk_canvas()->getDevice()->height());
1416 border_
->Paint(*this, canvas
);
1420 void View::OnPaintFocusBorder(gfx::Canvas
* canvas
) {
1421 if (focus_border_
.get() &&
1422 HasFocus() && (focusable() || IsAccessibilityFocusable())) {
1423 TRACE_EVENT2("views", "views::OnPaintFocusBorder",
1424 "width", canvas
->sk_canvas()->getDevice()->width(),
1425 "height", canvas
->sk_canvas()->getDevice()->height());
1426 focus_border_
->Paint(*this, canvas
);
1430 // Accelerated Painting --------------------------------------------------------
1432 void View::SetFillsBoundsOpaquely(bool fills_bounds_opaquely
) {
1433 // This method should not have the side-effect of creating the layer.
1435 layer()->SetFillsBoundsOpaquely(fills_bounds_opaquely
);
1438 gfx::Vector2d
View::CalculateOffsetToAncestorWithLayer(
1439 ui::Layer
** layer_parent
) {
1442 *layer_parent
= layer();
1443 return gfx::Vector2d();
1446 return gfx::Vector2d();
1448 return gfx::Vector2d(GetMirroredX(), y()) +
1449 parent_
->CalculateOffsetToAncestorWithLayer(layer_parent
);
1452 void View::UpdateParentLayer() {
1456 ui::Layer
* parent_layer
= NULL
;
1457 gfx::Vector2d
offset(GetMirroredX(), y());
1460 offset
+= parent_
->CalculateOffsetToAncestorWithLayer(&parent_layer
);
1462 ReparentLayer(offset
, parent_layer
);
1465 void View::MoveLayerToParent(ui::Layer
* parent_layer
,
1466 const gfx::Point
& point
) {
1467 gfx::Point
local_point(point
);
1468 if (parent_layer
!= layer())
1469 local_point
.Offset(GetMirroredX(), y());
1470 if (layer() && parent_layer
!= layer()) {
1471 parent_layer
->Add(layer());
1472 SetLayerBounds(gfx::Rect(local_point
.x(), local_point
.y(),
1473 width(), height()));
1475 for (int i
= 0, count
= child_count(); i
< count
; ++i
)
1476 child_at(i
)->MoveLayerToParent(parent_layer
, local_point
);
1480 void View::UpdateLayerVisibility() {
1481 if (!use_acceleration_when_possible
)
1483 bool visible
= visible_
;
1484 for (const View
* v
= parent_
; visible
&& v
&& !v
->layer(); v
= v
->parent_
)
1485 visible
= v
->visible();
1487 UpdateChildLayerVisibility(visible
);
1490 void View::UpdateChildLayerVisibility(bool ancestor_visible
) {
1492 layer()->SetVisible(ancestor_visible
&& visible_
);
1494 for (int i
= 0, count
= child_count(); i
< count
; ++i
)
1495 child_at(i
)->UpdateChildLayerVisibility(ancestor_visible
&& visible_
);
1499 void View::UpdateChildLayerBounds(const gfx::Vector2d
& offset
) {
1501 SetLayerBounds(GetLocalBounds() + offset
);
1503 for (int i
= 0, count
= child_count(); i
< count
; ++i
) {
1504 View
* child
= child_at(i
);
1505 child
->UpdateChildLayerBounds(
1506 offset
+ gfx::Vector2d(child
->GetMirroredX(), child
->y()));
1511 void View::OnPaintLayer(gfx::Canvas
* canvas
) {
1512 if (!layer() || !layer()->fills_bounds_opaquely())
1513 canvas
->DrawColor(SK_ColorBLACK
, SkXfermode::kClear_Mode
);
1514 PaintCommon(canvas
);
1517 void View::OnDeviceScaleFactorChanged(float device_scale_factor
) {
1518 // Repainting with new scale factor will paint the content at the right scale.
1521 base::Closure
View::PrepareForLayerBoundsChange() {
1522 return base::Closure();
1525 void View::ReorderLayers() {
1527 while (v
&& !v
->layer())
1530 Widget
* widget
= GetWidget();
1533 ui::Layer
* layer
= widget
->GetLayer();
1535 widget
->GetRootView()->ReorderChildLayers(layer
);
1538 v
->ReorderChildLayers(v
->layer());
1542 // Reorder the widget's child NativeViews in case a child NativeView is
1543 // associated with a view (eg via a NativeViewHost). Always do the
1544 // reordering because the associated NativeView's layer (if it has one)
1545 // is parented to the widget's layer regardless of whether the host view has
1546 // an ancestor with a layer.
1547 widget
->ReorderNativeViews();
1551 void View::ReorderChildLayers(ui::Layer
* parent_layer
) {
1552 if (layer() && layer() != parent_layer
) {
1553 DCHECK_EQ(parent_layer
, layer()->parent());
1554 parent_layer
->StackAtBottom(layer());
1556 // Iterate backwards through the children so that a child with a layer
1557 // which is further to the back is stacked above one which is further to
1559 for (Views::const_reverse_iterator
it(children_
.rbegin());
1560 it
!= children_
.rend(); ++it
) {
1561 (*it
)->ReorderChildLayers(parent_layer
);
1566 // Input -----------------------------------------------------------------------
1568 bool View::HasHitTestMask() const {
1572 void View::GetHitTestMask(HitTestSource source
, gfx::Path
* mask
) const {
1576 View::DragInfo
* View::GetDragInfo() {
1577 return parent_
? parent_
->GetDragInfo() : NULL
;
1580 // Focus -----------------------------------------------------------------------
1582 void View::OnFocus() {
1583 // TODO(beng): Investigate whether it's possible for us to move this to
1585 // By default, we clear the native focus. This ensures that no visible native
1586 // view as the focus and that we still receive keyboard inputs.
1587 FocusManager
* focus_manager
= GetFocusManager();
1589 focus_manager
->ClearNativeFocus();
1591 // TODO(beng): Investigate whether it's possible for us to move this to
1593 // Notify assistive technologies of the focus change.
1594 NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_FOCUS
, true);
1597 void View::OnBlur() {
1600 void View::Focus() {
1610 // Tooltips --------------------------------------------------------------------
1612 void View::TooltipTextChanged() {
1613 Widget
* widget
= GetWidget();
1614 // TooltipManager may be null if there is a problem creating it.
1615 if (widget
&& widget
->GetTooltipManager())
1616 widget
->GetTooltipManager()->TooltipTextChanged(this);
1619 // Context menus ---------------------------------------------------------------
1621 gfx::Point
View::GetKeyboardContextMenuLocation() {
1622 gfx::Rect vis_bounds
= GetVisibleBounds();
1623 gfx::Point
screen_point(vis_bounds
.x() + vis_bounds
.width() / 2,
1624 vis_bounds
.y() + vis_bounds
.height() / 2);
1625 ConvertPointToScreen(this, &screen_point
);
1626 return screen_point
;
1629 // Drag and drop ---------------------------------------------------------------
1631 int View::GetDragOperations(const gfx::Point
& press_pt
) {
1632 return drag_controller_
?
1633 drag_controller_
->GetDragOperationsForView(this, press_pt
) :
1634 ui::DragDropTypes::DRAG_NONE
;
1637 void View::WriteDragData(const gfx::Point
& press_pt
, OSExchangeData
* data
) {
1638 DCHECK(drag_controller_
);
1639 drag_controller_
->WriteDragDataForView(this, press_pt
, data
);
1642 bool View::InDrag() {
1643 Widget
* widget
= GetWidget();
1644 return widget
? widget
->dragged_view() == this : false;
1647 // Debugging -------------------------------------------------------------------
1649 #if !defined(NDEBUG)
1651 std::string
View::PrintViewGraph(bool first
) {
1652 return DoPrintViewGraph(first
, this);
1655 std::string
View::DoPrintViewGraph(bool first
, View
* view_with_children
) {
1656 // 64-bit pointer = 16 bytes of hex + "0x" + '\0' = 19.
1657 const size_t kMaxPointerStringLength
= 19;
1662 result
.append("digraph {\n");
1664 // Node characteristics.
1665 char p
[kMaxPointerStringLength
];
1667 const std::string
class_name(GetClassName());
1668 size_t base_name_index
= class_name
.find_last_of('/');
1669 if (base_name_index
== std::string::npos
)
1670 base_name_index
= 0;
1674 char bounds_buffer
[512];
1676 // Information about current node.
1677 base::snprintf(p
, arraysize(bounds_buffer
), "%p", view_with_children
);
1678 result
.append(" N");
1679 result
.append(p
+ 2);
1680 result
.append(" [label=\"");
1682 result
.append(class_name
.substr(base_name_index
).c_str());
1684 base::snprintf(bounds_buffer
,
1685 arraysize(bounds_buffer
),
1686 "\\n bounds: (%d, %d), (%dx%d)",
1691 result
.append(bounds_buffer
);
1693 gfx::DecomposedTransform decomp
;
1694 if (!GetTransform().IsIdentity() &&
1695 gfx::DecomposeTransform(&decomp
, GetTransform())) {
1696 base::snprintf(bounds_buffer
,
1697 arraysize(bounds_buffer
),
1698 "\\n translation: (%f, %f)",
1699 decomp
.translate
[0],
1700 decomp
.translate
[1]);
1701 result
.append(bounds_buffer
);
1703 base::snprintf(bounds_buffer
,
1704 arraysize(bounds_buffer
),
1705 "\\n rotation: %3.2f",
1706 std::acos(decomp
.quaternion
[3]) * 360.0 / M_PI
);
1707 result
.append(bounds_buffer
);
1709 base::snprintf(bounds_buffer
,
1710 arraysize(bounds_buffer
),
1711 "\\n scale: (%2.4f, %2.4f)",
1714 result
.append(bounds_buffer
);
1717 result
.append("\"");
1719 result
.append(", shape=box");
1721 if (layer()->texture())
1722 result
.append(", color=green");
1724 result
.append(", color=red");
1726 if (layer()->fills_bounds_opaquely())
1727 result
.append(", style=filled");
1729 result
.append("]\n");
1733 char pp
[kMaxPointerStringLength
];
1735 base::snprintf(pp
, kMaxPointerStringLength
, "%p", parent_
);
1736 result
.append(" N");
1737 result
.append(pp
+ 2);
1738 result
.append(" -> N");
1739 result
.append(p
+ 2);
1740 result
.append("\n");
1744 for (int i
= 0, count
= view_with_children
->child_count(); i
< count
; ++i
)
1745 result
.append(view_with_children
->child_at(i
)->PrintViewGraph(false));
1748 result
.append("}\n");
1755 ////////////////////////////////////////////////////////////////////////////////
1758 // DropInfo --------------------------------------------------------------------
1760 void View::DragInfo::Reset() {
1761 possible_drag
= false;
1762 start_pt
= gfx::Point();
1765 void View::DragInfo::PossibleDrag(const gfx::Point
& p
) {
1766 possible_drag
= true;
1770 // Painting --------------------------------------------------------------------
1772 void View::SchedulePaintBoundsChanged(SchedulePaintType type
) {
1773 // If we have a layer and the View's size did not change, we do not need to
1774 // schedule any paints since the layer will be redrawn at its new location
1775 // during the next Draw() cycle in the compositor.
1776 if (!layer() || type
== SCHEDULE_PAINT_SIZE_CHANGED
) {
1777 // Otherwise, if the size changes or we don't have a layer then we need to
1778 // use SchedulePaint to invalidate the area occupied by the View.
1780 } else if (parent_
&& type
== SCHEDULE_PAINT_SIZE_SAME
) {
1781 // The compositor doesn't Draw() until something on screen changes, so
1782 // if our position changes but nothing is being animated on screen, then
1783 // tell the compositor to redraw the scene. We know layer() exists due to
1784 // the above if clause.
1785 layer()->ScheduleDraw();
1789 void View::PaintCommon(gfx::Canvas
* canvas
) {
1794 // If the View we are about to paint requested the canvas to be flipped, we
1795 // should change the transform appropriately.
1796 // The canvas mirroring is undone once the View is done painting so that we
1797 // don't pass the canvas with the mirrored transform to Views that didn't
1798 // request the canvas to be flipped.
1799 gfx::ScopedCanvas
scoped(canvas
);
1800 if (FlipCanvasOnPaintForRTLUI()) {
1801 canvas
->Translate(gfx::Vector2d(width(), 0));
1802 canvas
->Scale(-1, 1);
1808 PaintChildren(canvas
);
1811 // Tree operations -------------------------------------------------------------
1813 void View::DoRemoveChildView(View
* view
,
1814 bool update_focus_cycle
,
1815 bool update_tool_tip
,
1816 bool delete_removed_view
,
1819 const Views::iterator
i(std::find(children_
.begin(), children_
.end(), view
));
1820 scoped_ptr
<View
> view_to_be_deleted
;
1821 if (i
!= children_
.end()) {
1822 if (update_focus_cycle
) {
1823 // Let's remove the view from the focus traversal.
1824 View
* next_focusable
= view
->next_focusable_view_
;
1825 View
* prev_focusable
= view
->previous_focusable_view_
;
1827 prev_focusable
->next_focusable_view_
= next_focusable
;
1829 next_focusable
->previous_focusable_view_
= prev_focusable
;
1833 UnregisterChildrenForVisibleBoundsNotification(view
);
1834 view
->PropagateRemoveNotifications(this, new_parent
);
1835 view
->parent_
= NULL
;
1836 view
->UpdateLayerVisibility();
1838 if (delete_removed_view
&& !view
->owned_by_client_
)
1839 view_to_be_deleted
.reset(view
);
1844 if (update_tool_tip
)
1847 if (layout_manager_
.get())
1848 layout_manager_
->ViewRemoved(this, view
);
1851 void View::PropagateRemoveNotifications(View
* old_parent
, View
* new_parent
) {
1852 for (int i
= 0, count
= child_count(); i
< count
; ++i
)
1853 child_at(i
)->PropagateRemoveNotifications(old_parent
, new_parent
);
1855 ViewHierarchyChangedDetails
details(false, old_parent
, this, new_parent
);
1856 for (View
* v
= this; v
; v
= v
->parent_
)
1857 v
->ViewHierarchyChangedImpl(true, details
);
1860 void View::PropagateAddNotifications(
1861 const ViewHierarchyChangedDetails
& details
) {
1862 for (int i
= 0, count
= child_count(); i
< count
; ++i
)
1863 child_at(i
)->PropagateAddNotifications(details
);
1864 ViewHierarchyChangedImpl(true, details
);
1867 void View::PropagateNativeViewHierarchyChanged() {
1868 for (int i
= 0, count
= child_count(); i
< count
; ++i
)
1869 child_at(i
)->PropagateNativeViewHierarchyChanged();
1870 NativeViewHierarchyChanged();
1873 void View::ViewHierarchyChangedImpl(
1874 bool register_accelerators
,
1875 const ViewHierarchyChangedDetails
& details
) {
1876 if (register_accelerators
) {
1877 if (details
.is_add
) {
1878 // If you get this registration, you are part of a subtree that has been
1879 // added to the view hierarchy.
1880 if (GetFocusManager())
1881 RegisterPendingAccelerators();
1883 if (details
.child
== this)
1884 UnregisterAccelerators(true);
1888 if (details
.is_add
&& layer() && !layer()->parent()) {
1889 UpdateParentLayer();
1890 Widget
* widget
= GetWidget();
1892 widget
->UpdateRootLayers();
1893 } else if (!details
.is_add
&& details
.child
== this) {
1894 // Make sure the layers belonging to the subtree rooted at |child| get
1895 // removed from layers that do not belong in the same subtree.
1897 if (use_acceleration_when_possible
) {
1898 Widget
* widget
= GetWidget();
1900 widget
->UpdateRootLayers();
1904 ViewHierarchyChanged(details
);
1905 details
.parent
->needs_layout_
= true;
1908 void View::PropagateNativeThemeChanged(const ui::NativeTheme
* theme
) {
1909 for (int i
= 0, count
= child_count(); i
< count
; ++i
)
1910 child_at(i
)->PropagateNativeThemeChanged(theme
);
1911 OnNativeThemeChanged(theme
);
1914 // Size and disposition --------------------------------------------------------
1916 void View::PropagateVisibilityNotifications(View
* start
, bool is_visible
) {
1917 for (int i
= 0, count
= child_count(); i
< count
; ++i
)
1918 child_at(i
)->PropagateVisibilityNotifications(start
, is_visible
);
1919 VisibilityChangedImpl(start
, is_visible
);
1922 void View::VisibilityChangedImpl(View
* starting_from
, bool is_visible
) {
1923 VisibilityChanged(starting_from
, is_visible
);
1926 void View::BoundsChanged(const gfx::Rect
& previous_bounds
) {
1928 // Paint the new bounds.
1929 SchedulePaintBoundsChanged(
1930 bounds_
.size() == previous_bounds
.size() ? SCHEDULE_PAINT_SIZE_SAME
:
1931 SCHEDULE_PAINT_SIZE_CHANGED
);
1934 if (use_acceleration_when_possible
) {
1937 SetLayerBounds(GetLocalBounds() +
1938 gfx::Vector2d(GetMirroredX(), y()) +
1939 parent_
->CalculateOffsetToAncestorWithLayer(NULL
));
1941 SetLayerBounds(bounds_
);
1943 // TODO(beng): this seems redundant with the SchedulePaint at the top of
1944 // this function. explore collapsing.
1945 if (previous_bounds
.size() != bounds_
.size() &&
1946 !layer()->layer_updated_externally()) {
1947 // If our bounds have changed then we need to update the complete
1949 layer()->SchedulePaint(GetLocalBounds());
1952 // If our bounds have changed, then any descendant layer bounds may
1953 // have changed. Update them accordingly.
1954 UpdateChildLayerBounds(CalculateOffsetToAncestorWithLayer(NULL
));
1958 OnBoundsChanged(previous_bounds
);
1960 if (previous_bounds
.size() != size()) {
1961 needs_layout_
= false;
1965 if (NeedsNotificationWhenVisibleBoundsChange())
1966 OnVisibleBoundsChanged();
1968 // Notify interested Views that visible bounds within the root view may have
1970 if (descendants_to_notify_
.get()) {
1971 for (Views::iterator
i(descendants_to_notify_
->begin());
1972 i
!= descendants_to_notify_
->end(); ++i
) {
1973 (*i
)->OnVisibleBoundsChanged();
1979 void View::RegisterChildrenForVisibleBoundsNotification(View
* view
) {
1980 if (view
->NeedsNotificationWhenVisibleBoundsChange())
1981 view
->RegisterForVisibleBoundsNotification();
1982 for (int i
= 0; i
< view
->child_count(); ++i
)
1983 RegisterChildrenForVisibleBoundsNotification(view
->child_at(i
));
1987 void View::UnregisterChildrenForVisibleBoundsNotification(View
* view
) {
1988 if (view
->NeedsNotificationWhenVisibleBoundsChange())
1989 view
->UnregisterForVisibleBoundsNotification();
1990 for (int i
= 0; i
< view
->child_count(); ++i
)
1991 UnregisterChildrenForVisibleBoundsNotification(view
->child_at(i
));
1994 void View::RegisterForVisibleBoundsNotification() {
1995 if (registered_for_visible_bounds_notification_
)
1998 registered_for_visible_bounds_notification_
= true;
1999 for (View
* ancestor
= parent_
; ancestor
; ancestor
= ancestor
->parent_
)
2000 ancestor
->AddDescendantToNotify(this);
2003 void View::UnregisterForVisibleBoundsNotification() {
2004 if (!registered_for_visible_bounds_notification_
)
2007 registered_for_visible_bounds_notification_
= false;
2008 for (View
* ancestor
= parent_
; ancestor
; ancestor
= ancestor
->parent_
)
2009 ancestor
->RemoveDescendantToNotify(this);
2012 void View::AddDescendantToNotify(View
* view
) {
2014 if (!descendants_to_notify_
.get())
2015 descendants_to_notify_
.reset(new Views
);
2016 descendants_to_notify_
->push_back(view
);
2019 void View::RemoveDescendantToNotify(View
* view
) {
2020 DCHECK(view
&& descendants_to_notify_
.get());
2021 Views::iterator
i(std::find(
2022 descendants_to_notify_
->begin(), descendants_to_notify_
->end(), view
));
2023 DCHECK(i
!= descendants_to_notify_
->end());
2024 descendants_to_notify_
->erase(i
);
2025 if (descendants_to_notify_
->empty())
2026 descendants_to_notify_
.reset();
2029 void View::SetLayerBounds(const gfx::Rect
& bounds
) {
2030 layer()->SetBounds(bounds
);
2033 // Transformations -------------------------------------------------------------
2035 bool View::GetTransformRelativeTo(const View
* ancestor
,
2036 gfx::Transform
* transform
) const {
2037 const View
* p
= this;
2039 while (p
&& p
!= ancestor
) {
2040 transform
->ConcatTransform(p
->GetTransform());
2041 gfx::Transform translation
;
2042 translation
.Translate(static_cast<float>(p
->GetMirroredX()),
2043 static_cast<float>(p
->y()));
2044 transform
->ConcatTransform(translation
);
2049 return p
== ancestor
;
2052 // Coordinate conversion -------------------------------------------------------
2054 bool View::ConvertPointForAncestor(const View
* ancestor
,
2055 gfx::Point
* point
) const {
2056 gfx::Transform trans
;
2057 // TODO(sad): Have some way of caching the transformation results.
2058 bool result
= GetTransformRelativeTo(ancestor
, &trans
);
2059 gfx::Point3F
p(*point
);
2060 trans
.TransformPoint(&p
);
2061 *point
= gfx::ToFlooredPoint(p
.AsPointF());
2065 bool View::ConvertPointFromAncestor(const View
* ancestor
,
2066 gfx::Point
* point
) const {
2067 gfx::Transform trans
;
2068 bool result
= GetTransformRelativeTo(ancestor
, &trans
);
2069 gfx::Point3F
p(*point
);
2070 trans
.TransformPointReverse(&p
);
2071 *point
= gfx::ToFlooredPoint(p
.AsPointF());
2075 bool View::ConvertRectForAncestor(const View
* ancestor
,
2076 gfx::RectF
* rect
) const {
2077 gfx::Transform trans
;
2078 // TODO(sad): Have some way of caching the transformation results.
2079 bool result
= GetTransformRelativeTo(ancestor
, &trans
);
2080 trans
.TransformRect(rect
);
2084 bool View::ConvertRectFromAncestor(const View
* ancestor
,
2085 gfx::RectF
* rect
) const {
2086 gfx::Transform trans
;
2087 bool result
= GetTransformRelativeTo(ancestor
, &trans
);
2088 trans
.TransformRectReverse(rect
);
2092 // Accelerated painting --------------------------------------------------------
2094 void View::CreateLayer() {
2095 // A new layer is being created for the view. So all the layers of the
2096 // sub-tree can inherit the visibility of the corresponding view.
2097 for (int i
= 0, count
= child_count(); i
< count
; ++i
)
2098 child_at(i
)->UpdateChildLayerVisibility(true);
2100 layer_
= new ui::Layer();
2101 layer_owner_
.reset(layer_
);
2102 layer_
->set_delegate(this);
2103 #if !defined(NDEBUG)
2104 layer_
->set_name(GetClassName());
2107 UpdateParentLayers();
2108 UpdateLayerVisibility();
2110 // The new layer needs to be ordered in the layer tree according
2111 // to the view tree. Children of this layer were added in order
2112 // in UpdateParentLayers().
2114 parent()->ReorderLayers();
2116 Widget
* widget
= GetWidget();
2118 widget
->UpdateRootLayers();
2121 void View::UpdateParentLayers() {
2122 // Attach all top-level un-parented layers.
2123 if (layer() && !layer()->parent()) {
2124 UpdateParentLayer();
2126 for (int i
= 0, count
= child_count(); i
< count
; ++i
)
2127 child_at(i
)->UpdateParentLayers();
2131 void View::OrphanLayers() {
2133 if (layer()->parent())
2134 layer()->parent()->Remove(layer());
2136 // The layer belonging to this View has already been orphaned. It is not
2137 // necessary to orphan the child layers.
2140 for (int i
= 0, count
= child_count(); i
< count
; ++i
)
2141 child_at(i
)->OrphanLayers();
2144 void View::ReparentLayer(const gfx::Vector2d
& offset
, ui::Layer
* parent_layer
) {
2145 layer_
->SetBounds(GetLocalBounds() + offset
);
2146 DCHECK_NE(layer(), parent_layer
);
2148 parent_layer
->Add(layer());
2149 layer_
->SchedulePaint(GetLocalBounds());
2150 MoveLayerToParent(layer(), gfx::Point());
2153 void View::DestroyLayer() {
2154 ui::Layer
* new_parent
= layer()->parent();
2155 std::vector
<ui::Layer
*> children
= layer()->children();
2156 for (size_t i
= 0; i
< children
.size(); ++i
) {
2157 layer()->Remove(children
[i
]);
2159 new_parent
->Add(children
[i
]);
2163 layer_owner_
.reset();
2168 UpdateChildLayerBounds(CalculateOffsetToAncestorWithLayer(NULL
));
2172 Widget
* widget
= GetWidget();
2174 widget
->UpdateRootLayers();
2177 // Input -----------------------------------------------------------------------
2179 bool View::ProcessMousePressed(const ui::MouseEvent
& event
) {
2180 int drag_operations
=
2181 (enabled_
&& event
.IsOnlyLeftMouseButton() &&
2182 HitTestPoint(event
.location())) ?
2183 GetDragOperations(event
.location()) : 0;
2184 ContextMenuController
* context_menu_controller
= event
.IsRightMouseButton() ?
2185 context_menu_controller_
: 0;
2186 View::DragInfo
* drag_info
= GetDragInfo();
2188 const bool enabled
= enabled_
;
2189 const bool result
= OnMousePressed(event
);
2194 if (event
.IsOnlyRightMouseButton() && context_menu_controller
&&
2195 kContextMenuOnMousePress
) {
2196 // Assume that if there is a context menu controller we won't be deleted
2197 // from mouse pressed.
2198 gfx::Point
location(event
.location());
2199 if (HitTestPoint(location
)) {
2200 ConvertPointToScreen(this, &location
);
2201 ShowContextMenu(location
, ui::MENU_SOURCE_MOUSE
);
2206 // WARNING: we may have been deleted, don't use any View variables.
2207 if (drag_operations
!= ui::DragDropTypes::DRAG_NONE
) {
2208 drag_info
->PossibleDrag(event
.location());
2211 return !!context_menu_controller
|| result
;
2214 bool View::ProcessMouseDragged(const ui::MouseEvent
& event
) {
2215 // Copy the field, that way if we're deleted after drag and drop no harm is
2217 ContextMenuController
* context_menu_controller
= context_menu_controller_
;
2218 const bool possible_drag
= GetDragInfo()->possible_drag
;
2219 if (possible_drag
&&
2220 ExceededDragThreshold(GetDragInfo()->start_pt
- event
.location()) &&
2221 (!drag_controller_
||
2222 drag_controller_
->CanStartDragForView(
2223 this, GetDragInfo()->start_pt
, event
.location()))) {
2224 DoDrag(event
, GetDragInfo()->start_pt
,
2225 ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE
);
2227 if (OnMouseDragged(event
))
2229 // Fall through to return value based on context menu controller.
2231 // WARNING: we may have been deleted.
2232 return (context_menu_controller
!= NULL
) || possible_drag
;
2235 void View::ProcessMouseReleased(const ui::MouseEvent
& event
) {
2236 if (!kContextMenuOnMousePress
&& context_menu_controller_
&&
2237 event
.IsOnlyRightMouseButton()) {
2238 // Assume that if there is a context menu controller we won't be deleted
2239 // from mouse released.
2240 gfx::Point
location(event
.location());
2241 OnMouseReleased(event
);
2242 if (HitTestPoint(location
)) {
2243 ConvertPointToScreen(this, &location
);
2244 ShowContextMenu(location
, ui::MENU_SOURCE_MOUSE
);
2247 OnMouseReleased(event
);
2249 // WARNING: we may have been deleted.
2252 // Accelerators ----------------------------------------------------------------
2254 void View::RegisterPendingAccelerators() {
2255 if (!accelerators_
.get() ||
2256 registered_accelerator_count_
== accelerators_
->size()) {
2257 // No accelerators are waiting for registration.
2262 // The view is not yet attached to a widget, defer registration until then.
2266 accelerator_focus_manager_
= GetFocusManager();
2267 if (!accelerator_focus_manager_
) {
2268 // Some crash reports seem to show that we may get cases where we have no
2269 // focus manager (see bug #1291225). This should never be the case, just
2270 // making sure we don't crash.
2274 for (std::vector
<ui::Accelerator
>::const_iterator
i(
2275 accelerators_
->begin() + registered_accelerator_count_
);
2276 i
!= accelerators_
->end(); ++i
) {
2277 accelerator_focus_manager_
->RegisterAccelerator(
2278 *i
, ui::AcceleratorManager::kNormalPriority
, this);
2280 registered_accelerator_count_
= accelerators_
->size();
2283 void View::UnregisterAccelerators(bool leave_data_intact
) {
2284 if (!accelerators_
.get())
2288 if (accelerator_focus_manager_
) {
2289 accelerator_focus_manager_
->UnregisterAccelerators(this);
2290 accelerator_focus_manager_
= NULL
;
2292 if (!leave_data_intact
) {
2293 accelerators_
->clear();
2294 accelerators_
.reset();
2296 registered_accelerator_count_
= 0;
2300 // Focus -----------------------------------------------------------------------
2302 void View::InitFocusSiblings(View
* v
, int index
) {
2303 int count
= child_count();
2306 v
->next_focusable_view_
= NULL
;
2307 v
->previous_focusable_view_
= NULL
;
2309 if (index
== count
) {
2310 // We are inserting at the end, but the end of the child list may not be
2311 // the last focusable element. Let's try to find an element with no next
2312 // focusable element to link to.
2313 View
* last_focusable_view
= NULL
;
2314 for (Views::iterator
i(children_
.begin()); i
!= children_
.end(); ++i
) {
2315 if (!(*i
)->next_focusable_view_
) {
2316 last_focusable_view
= *i
;
2320 if (last_focusable_view
== NULL
) {
2321 // Hum... there is a cycle in the focus list. Let's just insert ourself
2322 // after the last child.
2323 View
* prev
= children_
[index
- 1];
2324 v
->previous_focusable_view_
= prev
;
2325 v
->next_focusable_view_
= prev
->next_focusable_view_
;
2326 prev
->next_focusable_view_
->previous_focusable_view_
= v
;
2327 prev
->next_focusable_view_
= v
;
2329 last_focusable_view
->next_focusable_view_
= v
;
2330 v
->next_focusable_view_
= NULL
;
2331 v
->previous_focusable_view_
= last_focusable_view
;
2334 View
* prev
= children_
[index
]->GetPreviousFocusableView();
2335 v
->previous_focusable_view_
= prev
;
2336 v
->next_focusable_view_
= children_
[index
];
2338 prev
->next_focusable_view_
= v
;
2339 children_
[index
]->previous_focusable_view_
= v
;
2344 // System events ---------------------------------------------------------------
2346 void View::PropagateThemeChanged() {
2347 for (int i
= child_count() - 1; i
>= 0; --i
)
2348 child_at(i
)->PropagateThemeChanged();
2352 void View::PropagateLocaleChanged() {
2353 for (int i
= child_count() - 1; i
>= 0; --i
)
2354 child_at(i
)->PropagateLocaleChanged();
2358 // Tooltips --------------------------------------------------------------------
2360 void View::UpdateTooltip() {
2361 Widget
* widget
= GetWidget();
2362 // TODO(beng): The TooltipManager NULL check can be removed when we
2363 // consolidate Init() methods and make views_unittests Init() all
2364 // Widgets that it uses.
2365 if (widget
&& widget
->GetTooltipManager())
2366 widget
->GetTooltipManager()->UpdateTooltip();
2369 // Drag and drop ---------------------------------------------------------------
2371 bool View::DoDrag(const ui::LocatedEvent
& event
,
2372 const gfx::Point
& press_pt
,
2373 ui::DragDropTypes::DragEventSource source
) {
2374 int drag_operations
= GetDragOperations(press_pt
);
2375 if (drag_operations
== ui::DragDropTypes::DRAG_NONE
)
2378 Widget
* widget
= GetWidget();
2379 // We should only start a drag from an event, implying we have a widget.
2382 // Don't attempt to start a drag while in the process of dragging. This is
2383 // especially important on X where we can get multiple mouse move events when
2384 // we start the drag.
2385 if (widget
->dragged_view())
2388 OSExchangeData data
;
2389 WriteDragData(press_pt
, &data
);
2391 // Message the RootView to do the drag and drop. That way if we're removed
2392 // the RootView can detect it and avoid calling us back.
2393 gfx::Point
widget_location(event
.location());
2394 ConvertPointToWidget(this, &widget_location
);
2395 widget
->RunShellDrag(this, data
, widget_location
, drag_operations
, source
);
2396 // WARNING: we may have been deleted.
2400 } // namespace views