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