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 #include "ui/views/view.h"
6 
7 #include <algorithm>
8 #include <memory>
9 #include <utility>
10 
11 #include "base/check_op.h"
12 #include "base/command_line.h"
13 #include "base/containers/adapters.h"
14 #include "base/feature_list.h"
15 #include "base/i18n/rtl.h"
16 #include "base/macros.h"
17 #include "base/notreached.h"
18 #include "base/scoped_observer.h"
19 #include "base/stl_util.h"
20 #include "base/strings/stringprintf.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/trace_event/trace_event.h"
23 #include "build/build_config.h"
24 #include "third_party/skia/include/core/SkRect.h"
25 #include "ui/accessibility/ax_action_data.h"
26 #include "ui/accessibility/ax_enums.mojom.h"
27 #include "ui/base/cursor/cursor.h"
28 #include "ui/base/dragdrop/drag_drop_types.h"
29 #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
30 #include "ui/base/ime/input_method.h"
31 #include "ui/compositor/clip_recorder.h"
32 #include "ui/compositor/compositor.h"
33 #include "ui/compositor/layer.h"
34 #include "ui/compositor/layer_animator.h"
35 #include "ui/compositor/paint_context.h"
36 #include "ui/compositor/paint_recorder.h"
37 #include "ui/compositor/transform_recorder.h"
38 #include "ui/display/screen.h"
39 #include "ui/events/base_event_utils.h"
40 #include "ui/events/event_target_iterator.h"
41 #include "ui/gfx/canvas.h"
42 #include "ui/gfx/geometry/angle_conversions.h"
43 #include "ui/gfx/geometry/point3_f.h"
44 #include "ui/gfx/geometry/point_conversions.h"
45 #include "ui/gfx/interpolated_transform.h"
46 #include "ui/gfx/scoped_canvas.h"
47 #include "ui/gfx/transform.h"
48 #include "ui/native_theme/native_theme.h"
49 #include "ui/views/accessibility/ax_event_manager.h"
50 #include "ui/views/accessibility/view_accessibility.h"
51 #include "ui/views/background.h"
52 #include "ui/views/border.h"
53 #include "ui/views/buildflags.h"
54 #include "ui/views/context_menu_controller.h"
55 #include "ui/views/controls/scroll_view.h"
56 #include "ui/views/drag_controller.h"
57 #include "ui/views/layout/layout_manager.h"
58 #include "ui/views/metadata/metadata_impl_macros.h"
59 #include "ui/views/view_observer.h"
60 #include "ui/views/view_tracker.h"
61 #include "ui/views/views_features.h"
62 #include "ui/views/views_switches.h"
63 #include "ui/views/widget/native_widget_private.h"
64 #include "ui/views/widget/root_view.h"
65 #include "ui/views/widget/tooltip_manager.h"
66 #include "ui/views/widget/widget.h"
67 
68 #if defined(OS_WIN)
69 #include "base/win/scoped_gdi_object.h"
70 #include "ui/native_theme/native_theme_win.h"
71 #endif
72 
73 namespace views {
74 
75 namespace {
76 
77 #if defined(OS_WIN)
78 constexpr bool kContextMenuOnMousePress = false;
79 #else
80 constexpr bool kContextMenuOnMousePress = true;
81 #endif
82 
83 // Default horizontal drag threshold in pixels.
84 // Same as what gtk uses.
85 constexpr int kDefaultHorizontalDragThreshold = 8;
86 
87 // Default vertical drag threshold in pixels.
88 // Same as what gtk uses.
89 constexpr int kDefaultVerticalDragThreshold = 8;
90 
91 // Returns the top view in |view|'s hierarchy.
GetHierarchyRoot(const View * view)92 const View* GetHierarchyRoot(const View* view) {
93   const View* root = view;
94   while (root && root->parent())
95     root = root->parent();
96   return root;
97 }
98 
99 }  // namespace
100 
101 namespace internal {
102 
103 #if DCHECK_IS_ON()
104 class ScopedChildrenLock {
105  public:
ScopedChildrenLock(const View * view)106   explicit ScopedChildrenLock(const View* view)
107       : reset_(&view->iterating_, true) {}
108   ~ScopedChildrenLock() = default;
109 
110  private:
111   base::AutoReset<bool> reset_;
112   DISALLOW_COPY_AND_ASSIGN(ScopedChildrenLock);
113 };
114 #else
115 class ScopedChildrenLock {
116  public:
117   explicit ScopedChildrenLock(const View* view) {}
118   ~ScopedChildrenLock() {}
119 };
120 #endif
121 
122 }  // namespace internal
123 
124 ////////////////////////////////////////////////////////////////////////////////
125 // ViewMaskLayer
126 // This class is responsible for creating a masking layer for a view that paints
127 // to a layer. It tracks the size of the layer it is masking.
128 class VIEWS_EXPORT ViewMaskLayer : public ui::LayerDelegate,
129                                    public ViewObserver {
130  public:
131   // Note that |observed_view| must outlive the ViewMaskLayer instance.
132   ViewMaskLayer(const SkPath& path, View* observed_view);
133   ViewMaskLayer(const ViewMaskLayer& mask_layer) = delete;
134   ViewMaskLayer& operator=(const ViewMaskLayer& mask_layer) = delete;
135   ~ViewMaskLayer() override;
136 
layer()137   ui::Layer* layer() { return &layer_; }
138 
139  private:
140   // ui::LayerDelegate:
141   void OnDeviceScaleFactorChanged(float old_device_scale_factor,
142                                   float new_device_scale_factor) override;
143   void OnPaintLayer(const ui::PaintContext& context) override;
144 
145   // views::ViewObserver:
146   void OnViewBoundsChanged(View* observed_view) override;
147 
148   ScopedObserver<View, ViewObserver> observed_view_{this};
149 
150   SkPath path_;
151   ui::Layer layer_;
152 };
153 
ViewMaskLayer(const SkPath & path,View * observed_view)154 ViewMaskLayer::ViewMaskLayer(const SkPath& path, View* observed_view)
155     : path_{path} {
156   layer_.set_delegate(this);
157   layer_.SetFillsBoundsOpaquely(false);
158   layer_.SetName("ViewMaskLayer");
159   observed_view_.Add(observed_view);
160   OnViewBoundsChanged(observed_view);
161 }
162 
~ViewMaskLayer()163 ViewMaskLayer::~ViewMaskLayer() {
164   layer_.set_delegate(nullptr);
165 }
166 
OnDeviceScaleFactorChanged(float old_device_scale_factor,float new_device_scale_factor)167 void ViewMaskLayer::OnDeviceScaleFactorChanged(float old_device_scale_factor,
168                                                float new_device_scale_factor) {}
169 
OnPaintLayer(const ui::PaintContext & context)170 void ViewMaskLayer::OnPaintLayer(const ui::PaintContext& context) {
171   cc::PaintFlags flags;
172   flags.setAlpha(255);
173   flags.setStyle(cc::PaintFlags::kFill_Style);
174   flags.setAntiAlias(true);
175 
176   ui::PaintRecorder recorder(context, layer()->size());
177   recorder.canvas()->DrawPath(path_, flags);
178 }
179 
OnViewBoundsChanged(View * observed_view)180 void ViewMaskLayer::OnViewBoundsChanged(View* observed_view) {
181   layer_.SetBounds(observed_view->GetLocalBounds());
182 }
183 
184 ////////////////////////////////////////////////////////////////////////////////
185 // View, public:
186 
187 // Creation and lifetime -------------------------------------------------------
188 
View()189 View::View() {
190   SetTargetHandler(this);
191 }
192 
~View()193 View::~View() {
194   if (parent_)
195     parent_->RemoveChildView(this);
196 
197   // This view should have been removed from the focus list by now.
198   DCHECK_EQ(next_focusable_view_, nullptr);
199   DCHECK_EQ(previous_focusable_view_, nullptr);
200 
201   // Need to remove layout manager before deleting children because if we do not
202   // it is possible for layout-related calls (e.g. CalculatePreferredSize()) to
203   // be called on this view during one of the callbacks below. Since most
204   // layout managers access child view properties, this would result in a
205   // use-after-free error.
206   layout_manager_.reset();
207 
208   {
209     internal::ScopedChildrenLock lock(this);
210     for (auto* child : children_) {
211       child->parent_ = nullptr;
212 
213       // Since all children are removed here, it is safe to set
214       // |child|'s focus list pointers to null and expect any references
215       // to |child| will be removed subsequently.
216       child->next_focusable_view_ = nullptr;
217       child->previous_focusable_view_ = nullptr;
218 
219       if (!child->owned_by_client_)
220         delete child;
221     }
222   }
223 
224   for (ViewObserver& observer : observers_)
225     observer.OnViewIsDeleting(this);
226 
227   for (ui::Layer* layer_beneath : layers_beneath_)
228     layer_beneath->RemoveObserver(this);
229 
230   // Clearing properties explicitly here lets us guarantee that properties
231   // outlive |this| (at least the View part of |this|). This is intentionally
232   // called at the end so observers can examine properties inside
233   // OnViewIsDeleting(), for instance.
234   ClearProperties();
235 }
236 
237 // Tree operations -------------------------------------------------------------
238 
GetWidget() const239 const Widget* View::GetWidget() const {
240   // The root view holds a reference to this view hierarchy's Widget.
241   return parent_ ? parent_->GetWidget() : nullptr;
242 }
243 
GetWidget()244 Widget* View::GetWidget() {
245   return const_cast<Widget*>(const_cast<const View*>(this)->GetWidget());
246 }
247 
ReorderChildView(View * view,int index)248 void View::ReorderChildView(View* view, int index) {
249   DCHECK_EQ(view->parent_, this);
250   const auto i = std::find(children_.begin(), children_.end(), view);
251   DCHECK(i != children_.end());
252 
253   // If |view| is already at the desired position, there's nothing to do.
254   const bool move_to_end = (index < 0) || (size_t{index} >= children_.size());
255   const auto pos = move_to_end ? std::prev(children_.end())
256                                : std::next(children_.begin(), index);
257   if (i == pos)
258     return;
259 
260     // Rotate |view| to be at the desired position.
261 #if DCHECK_IS_ON()
262   DCHECK(!iterating_);
263 #endif
264   if (pos < i)
265     std::rotate(pos, i, std::next(i));
266   else
267     std::rotate(i, std::next(i), std::next(pos));
268 
269   // Update focus siblings.  Unhook |view| from the focus cycle first so
270   // SetFocusSiblings() won't traverse through it.
271   view->RemoveFromFocusList();
272   SetFocusSiblings(view, pos);
273 
274   for (ViewObserver& observer : observers_)
275     observer.OnChildViewReordered(this, view);
276 
277   ReorderLayers();
278   InvalidateLayout();
279 }
280 
RemoveChildView(View * view)281 void View::RemoveChildView(View* view) {
282   DoRemoveChildView(view, true, false, nullptr);
283 }
284 
RemoveAllChildViews(bool delete_children)285 void View::RemoveAllChildViews(bool delete_children) {
286   while (!children_.empty())
287     DoRemoveChildView(children_.front(), false, delete_children, nullptr);
288   UpdateTooltip();
289 }
290 
Contains(const View * view) const291 bool View::Contains(const View* view) const {
292   for (const View* v = view; v; v = v->parent_) {
293     if (v == this)
294       return true;
295   }
296   return false;
297 }
298 
FindChild(const View * view) const299 View::Views::const_iterator View::FindChild(const View* view) const {
300   return std::find(children_.cbegin(), children_.cend(), view);
301 }
302 
GetIndexOf(const View * view) const303 int View::GetIndexOf(const View* view) const {
304   const auto i = FindChild(view);
305   return i == children_.cend()
306              ? -1
307              : static_cast<int>(std::distance(children_.cbegin(), i));
308 }
309 
310 // Size and disposition --------------------------------------------------------
311 
SetBounds(int x,int y,int width,int height)312 void View::SetBounds(int x, int y, int width, int height) {
313   SetBoundsRect(gfx::Rect(x, y, std::max(0, width), std::max(0, height)));
314 }
315 
SetBoundsRect(const gfx::Rect & bounds)316 void View::SetBoundsRect(const gfx::Rect& bounds) {
317   if (bounds == bounds_) {
318     if (needs_layout_) {
319       needs_layout_ = false;
320       TRACE_EVENT1("views", "View::Layout(set_bounds)", "class",
321                    GetClassName());
322       Layout();
323     }
324     return;
325   }
326 
327   bool is_size_changed = bounds_.size() != bounds.size();
328   // Paint where the view is currently.
329   SchedulePaintBoundsChanged(is_size_changed);
330 
331   gfx::Rect prev = bounds_;
332   bounds_ = bounds;
333 
334   // Paint the new bounds.
335   SchedulePaintBoundsChanged(is_size_changed);
336 
337   if (layer()) {
338     if (parent_) {
339       LayerOffsetData offset_data(
340           parent_->CalculateOffsetToAncestorWithLayer(nullptr));
341       offset_data += GetMirroredPosition().OffsetFromOrigin();
342       SetLayerBounds(size(), offset_data);
343     } else {
344       SetLayerBounds(bounds_.size(),
345                      LayerOffsetData() + bounds_.OffsetFromOrigin());
346     }
347 
348     // In RTL mode, if our width has changed, our children's mirrored bounds
349     // will have changed. Update the child's layer bounds, or if it is not a
350     // layer, the bounds of any layers inside the child.
351     if (GetMirrored() && bounds_.width() != prev.width()) {
352       for (View* child : children_) {
353         child->UpdateChildLayerBounds(
354             LayerOffsetData(layer()->device_scale_factor(),
355                             child->GetMirroredPosition().OffsetFromOrigin()));
356       }
357     }
358   } else {
359     // If our bounds have changed, then any descendant layer bounds may have
360     // changed. Update them accordingly.
361     UpdateChildLayerBounds(CalculateOffsetToAncestorWithLayer(nullptr));
362   }
363 
364   OnBoundsChanged(prev);
365   if (bounds_ != prev)
366     NotifyAccessibilityEvent(ax::mojom::Event::kLocationChanged, false);
367 
368   if (needs_layout_ || is_size_changed) {
369     needs_layout_ = false;
370     TRACE_EVENT1("views", "View::Layout(bounds_changed)", "class",
371                  GetClassName());
372     Layout();
373   }
374 
375   if (GetNeedsNotificationWhenVisibleBoundsChange())
376     OnVisibleBoundsChanged();
377 
378   // Notify interested Views that visible bounds within the root view may have
379   // changed.
380   if (descendants_to_notify_) {
381     for (auto* i : *descendants_to_notify_) {
382       i->OnVisibleBoundsChanged();
383     }
384   }
385 
386   for (ViewObserver& observer : observers_)
387     observer.OnViewBoundsChanged(this);
388 }
389 
SetSize(const gfx::Size & size)390 void View::SetSize(const gfx::Size& size) {
391   SetBounds(x(), y(), size.width(), size.height());
392 }
393 
SetPosition(const gfx::Point & position)394 void View::SetPosition(const gfx::Point& position) {
395   SetBounds(position.x(), position.y(), width(), height());
396 }
397 
SetX(int x)398 void View::SetX(int x) {
399   SetBounds(x, y(), width(), height());
400 }
401 
SetY(int y)402 void View::SetY(int y) {
403   SetBounds(x(), y, width(), height());
404 }
405 
GetContentsBounds() const406 gfx::Rect View::GetContentsBounds() const {
407   gfx::Rect contents_bounds(GetLocalBounds());
408   contents_bounds.Inset(GetInsets());
409   return contents_bounds;
410 }
411 
GetLocalBounds() const412 gfx::Rect View::GetLocalBounds() const {
413   return gfx::Rect(size());
414 }
415 
GetInsets() const416 gfx::Insets View::GetInsets() const {
417   return border_ ? border_->GetInsets() : gfx::Insets();
418 }
419 
GetVisibleBounds() const420 gfx::Rect View::GetVisibleBounds() const {
421   if (!IsDrawn())
422     return gfx::Rect();
423   gfx::Rect vis_bounds(GetLocalBounds());
424   gfx::Rect ancestor_bounds;
425   const View* view = this;
426   gfx::Transform transform;
427 
428   while (view != nullptr && !vis_bounds.IsEmpty()) {
429     transform.ConcatTransform(view->GetTransform());
430     gfx::Transform translation;
431     translation.Translate(static_cast<float>(view->GetMirroredX()),
432                           static_cast<float>(view->y()));
433     transform.ConcatTransform(translation);
434 
435     vis_bounds = view->ConvertRectToParent(vis_bounds);
436     const View* ancestor = view->parent_;
437     if (ancestor != nullptr) {
438       ancestor_bounds.SetRect(0, 0, ancestor->width(), ancestor->height());
439       vis_bounds.Intersect(ancestor_bounds);
440     } else if (!view->GetWidget()) {
441       // If the view has no Widget, we're not visible. Return an empty rect.
442       return gfx::Rect();
443     }
444     view = ancestor;
445   }
446   if (vis_bounds.IsEmpty())
447     return vis_bounds;
448   // Convert back to this views coordinate system.
449   gfx::RectF views_vis_bounds(vis_bounds);
450   transform.TransformRectReverse(&views_vis_bounds);
451   // Partially visible pixels should be considered visible.
452   return gfx::ToEnclosingRect(views_vis_bounds);
453 }
454 
GetBoundsInScreen() const455 gfx::Rect View::GetBoundsInScreen() const {
456   gfx::Point origin;
457   View::ConvertPointToScreen(this, &origin);
458   return gfx::Rect(origin, size());
459 }
460 
GetAnchorBoundsInScreen() const461 gfx::Rect View::GetAnchorBoundsInScreen() const {
462   return GetBoundsInScreen();
463 }
464 
GetPreferredSize() const465 gfx::Size View::GetPreferredSize() const {
466   if (preferred_size_)
467     return *preferred_size_;
468   return CalculatePreferredSize();
469 }
470 
GetBaseline() const471 int View::GetBaseline() const {
472   return -1;
473 }
474 
SetPreferredSize(const gfx::Size & size)475 void View::SetPreferredSize(const gfx::Size& size) {
476   if (preferred_size_ && *preferred_size_ == size)
477     return;
478 
479   preferred_size_ = size;
480   PreferredSizeChanged();
481 }
482 
SizeToPreferredSize()483 void View::SizeToPreferredSize() {
484   SetSize(GetPreferredSize());
485 }
486 
GetMinimumSize() const487 gfx::Size View::GetMinimumSize() const {
488   if (layout_manager_)
489     return layout_manager_->GetMinimumSize(this);
490 
491   return GetPreferredSize();
492 }
493 
GetMaximumSize() const494 gfx::Size View::GetMaximumSize() const {
495   return gfx::Size();
496 }
497 
GetHeightForWidth(int w) const498 int View::GetHeightForWidth(int w) const {
499   if (layout_manager_)
500     return layout_manager_->GetPreferredHeightForWidth(this, w);
501   return GetPreferredSize().height();
502 }
503 
GetAvailableSize(const View * child) const504 SizeBounds View::GetAvailableSize(const View* child) const {
505   if (layout_manager_)
506     return layout_manager_->GetAvailableSize(this, child);
507   return SizeBounds();
508 }
509 
GetVisible() const510 bool View::GetVisible() const {
511   return visible_;
512 }
513 
SetVisible(bool visible)514 void View::SetVisible(bool visible) {
515   const bool was_visible = visible_;
516   if (was_visible != visible) {
517     // If the View was visible, schedule paint to refresh parent.
518     // TODO(beng): not sure we should be doing this if we have a layer.
519     if (was_visible)
520       SchedulePaint();
521 
522     visible_ = visible;
523     AdvanceFocusIfNecessary();
524 
525     // Notify the parent.
526     if (parent_) {
527       parent_->ChildVisibilityChanged(this);
528       if (!view_accessibility_ || !view_accessibility_->IsIgnored()) {
529         parent_->NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged,
530                                           true);
531       }
532     }
533 
534     // This notifies all sub-views recursively.
535     PropagateVisibilityNotifications(this, visible_);
536     UpdateLayerVisibility();
537 
538     // Notify all other subscriptions of the change.
539     OnPropertyChanged(&visible_, kPropertyEffectsPaint);
540   }
541 
542   if (parent_) {
543     LayoutManager* const layout_manager = parent_->GetLayoutManager();
544     if (layout_manager && layout_manager->view_setting_visibility_on_ != this)
545       layout_manager->ViewVisibilitySet(parent_, this, was_visible, visible);
546   }
547 }
548 
AddVisibleChangedCallback(PropertyChangedCallback callback)549 PropertyChangedSubscription View::AddVisibleChangedCallback(
550     PropertyChangedCallback callback) {
551   return AddPropertyChangedCallback(&visible_, std::move(callback));
552 }
553 
IsDrawn() const554 bool View::IsDrawn() const {
555   return visible_ && parent_ ? parent_->IsDrawn() : false;
556 }
557 
GetEnabled() const558 bool View::GetEnabled() const {
559   return enabled_;
560 }
561 
SetEnabled(bool enabled)562 void View::SetEnabled(bool enabled) {
563   if (enabled_ == enabled)
564     return;
565 
566   enabled_ = enabled;
567   AdvanceFocusIfNecessary();
568   NotifyAccessibilityEvent(ax::mojom::Event::kStateChanged, true);
569   OnPropertyChanged(&enabled_, kPropertyEffectsPaint);
570 }
571 
AddEnabledChangedCallback(PropertyChangedCallback callback)572 PropertyChangedSubscription View::AddEnabledChangedCallback(
573     PropertyChangedCallback callback) {
574   return AddPropertyChangedCallback(&enabled_, std::move(callback));
575 }
576 
GetChildrenInZOrder()577 View::Views View::GetChildrenInZOrder() {
578   if (layout_manager_) {
579     const auto result = layout_manager_->GetChildViewsInPaintOrder(this);
580     DCHECK_EQ(children_.size(), result.size());
581     return result;
582   }
583   return children_;
584 }
585 
586 // Transformations -------------------------------------------------------------
587 
GetTransform() const588 gfx::Transform View::GetTransform() const {
589   if (!layer())
590     return gfx::Transform();
591 
592   gfx::Transform transform = layer()->transform();
593   gfx::ScrollOffset scroll_offset = layer()->CurrentScrollOffset();
594   // Offsets for layer-based scrolling are never negative, but the horizontal
595   // scroll direction is reversed in RTL via canvas flipping.
596   transform.Translate((GetMirrored() ? 1 : -1) * scroll_offset.x(),
597                       -scroll_offset.y());
598   return transform;
599 }
600 
SetClipPath(const SkPath & path)601 void View::SetClipPath(const SkPath& path) {
602   clip_path_ = path;
603   if (layer())
604     CreateMaskLayer();
605 }
606 
SetTransform(const gfx::Transform & transform)607 void View::SetTransform(const gfx::Transform& transform) {
608   if (transform.IsIdentity()) {
609     if (layer())
610       layer()->SetTransform(transform);
611     paint_to_layer_for_transform_ = false;
612     CreateOrDestroyLayer();
613   } else {
614     paint_to_layer_for_transform_ = true;
615     CreateOrDestroyLayer();
616     DCHECK_NE(layer(), nullptr);
617     layer()->SetTransform(transform);
618     layer()->ScheduleDraw();
619   }
620 
621   for (ui::Layer* layer_beneath : layers_beneath_)
622     layer_beneath->SetTransform(transform);
623 }
624 
SetPaintToLayer(ui::LayerType layer_type)625 void View::SetPaintToLayer(ui::LayerType layer_type) {
626   // Avoid re-creating the layer if unnecessary.
627   if (paint_to_layer_explicitly_set_) {
628     DCHECK_NE(layer(), nullptr);
629     if (layer()->type() == layer_type)
630       return;
631   }
632 
633   DestroyLayerImpl(LayerChangeNotifyBehavior::DONT_NOTIFY);
634   paint_to_layer_explicitly_set_ = true;
635 
636   // We directly call |CreateLayer()| here to pass |layer_type|. A call to
637   // |CreateOrDestroyLayer()| is therefore not necessary.
638   CreateLayer(layer_type);
639 
640   if (!clip_path_.isEmpty() && !mask_layer_)
641     CreateMaskLayer();
642 
643   // Notify the parent chain about the layer change.
644   NotifyParentsOfLayerChange();
645 }
646 
DestroyLayer()647 void View::DestroyLayer() {
648   paint_to_layer_explicitly_set_ = false;
649   CreateOrDestroyLayer();
650 }
651 
AddLayerBeneathView(ui::Layer * new_layer)652 void View::AddLayerBeneathView(ui::Layer* new_layer) {
653   DCHECK(new_layer);
654   DCHECK(!base::Contains(layers_beneath_, new_layer)) << "Layer already added.";
655 
656   new_layer->AddObserver(this);
657   new_layer->SetVisible(GetVisible());
658   layers_beneath_.push_back(new_layer);
659 
660   // If painting to a layer already, ensure |new_layer| gets added and stacked
661   // correctly. If not, this will happen on layer creation.
662   if (layer()) {
663     ui::Layer* parent_layer = layer()->parent();
664     // Note that |new_layer| may have already been added to the parent, for
665     // example when the layer of a LayerOwner is recreated.
666     if (parent_layer && parent_layer != new_layer->parent())
667       parent_layer->Add(new_layer);
668     new_layer->SetBounds(gfx::Rect(new_layer->size()) +
669                          layer()->bounds().OffsetFromOrigin());
670     if (parent())
671       parent()->ReorderLayers();
672   }
673 
674   CreateOrDestroyLayer();
675 
676   layer()->SetFillsBoundsOpaquely(false);
677 }
678 
RemoveLayerBeneathView(ui::Layer * old_layer)679 void View::RemoveLayerBeneathView(ui::Layer* old_layer) {
680   RemoveLayerBeneathViewKeepInLayerTree(old_layer);
681 
682   // Note that |old_layer| may have already been removed from its parent.
683   ui::Layer* parent_layer = layer()->parent();
684   if (parent_layer && parent_layer == old_layer->parent())
685     parent_layer->Remove(old_layer);
686 
687   CreateOrDestroyLayer();
688 }
689 
RemoveLayerBeneathViewKeepInLayerTree(ui::Layer * old_layer)690 void View::RemoveLayerBeneathViewKeepInLayerTree(ui::Layer* old_layer) {
691   auto layer_pos =
692       std::find(layers_beneath_.begin(), layers_beneath_.end(), old_layer);
693   DCHECK(layer_pos != layers_beneath_.end())
694       << "Attempted to remove a layer that was never added.";
695   layers_beneath_.erase(layer_pos);
696   old_layer->RemoveObserver(this);
697 }
698 
GetLayersInOrder()699 std::vector<ui::Layer*> View::GetLayersInOrder() {
700   // If not painting to a layer, there are no layers immediately related to this
701   // view.
702   if (!layer())
703     return {};
704 
705   std::vector<ui::Layer*> result;
706   for (ui::Layer* layer_beneath : layers_beneath_)
707     result.push_back(layer_beneath);
708   result.push_back(layer());
709 
710   return result;
711 }
712 
LayerDestroyed(ui::Layer * layer)713 void View::LayerDestroyed(ui::Layer* layer) {
714   // Only layers added with |AddLayerBeneathView()| are observed so |layer| can
715   // safely be removed.
716   RemoveLayerBeneathView(layer);
717 }
718 
RecreateLayer()719 std::unique_ptr<ui::Layer> View::RecreateLayer() {
720   std::unique_ptr<ui::Layer> old_layer = LayerOwner::RecreateLayer();
721   Widget* widget = GetWidget();
722   if (widget)
723     widget->LayerTreeChanged();
724   return old_layer;
725 }
726 
727 // RTL positioning -------------------------------------------------------------
728 
GetMirroredBounds() const729 gfx::Rect View::GetMirroredBounds() const {
730   gfx::Rect bounds(bounds_);
731   bounds.set_x(GetMirroredX());
732   return bounds;
733 }
734 
GetMirroredContentsBounds() const735 gfx::Rect View::GetMirroredContentsBounds() const {
736   gfx::Rect bounds(bounds_);
737   bounds.Inset(GetInsets());
738   bounds.set_x(GetMirroredX());
739   return bounds;
740 }
741 
GetMirroredPosition() const742 gfx::Point View::GetMirroredPosition() const {
743   return gfx::Point(GetMirroredX(), y());
744 }
745 
GetMirroredX() const746 int View::GetMirroredX() const {
747   return parent_ ? parent_->GetMirroredXForRect(bounds_) : x();
748 }
749 
GetMirroredXForRect(const gfx::Rect & rect) const750 int View::GetMirroredXForRect(const gfx::Rect& rect) const {
751   return GetMirrored() ? (width() - rect.x() - rect.width()) : rect.x();
752 }
753 
GetMirroredRect(const gfx::Rect & rect) const754 gfx::Rect View::GetMirroredRect(const gfx::Rect& rect) const {
755   gfx::Rect mirrored_rect = rect;
756   mirrored_rect.set_x(GetMirroredXForRect(rect));
757   return mirrored_rect;
758 }
759 
GetMirroredXInView(int x) const760 int View::GetMirroredXInView(int x) const {
761   return GetMirrored() ? width() - x : x;
762 }
763 
GetMirroredXWithWidthInView(int x,int w) const764 int View::GetMirroredXWithWidthInView(int x, int w) const {
765   return GetMirrored() ? width() - x - w : x;
766 }
767 
768 // Layout ----------------------------------------------------------------------
769 
Layout()770 void View::Layout() {
771   needs_layout_ = false;
772 
773   // If we have a layout manager, let it handle the layout for us.
774   if (layout_manager_)
775     layout_manager_->Layout(this);
776 
777   // Make sure to propagate the Layout() call to any children that haven't
778   // received it yet through the layout manager and need to be laid out. This
779   // is needed for the case when the child requires a layout but its bounds
780   // weren't changed by the layout manager. If there is no layout manager, we
781   // just propagate the Layout() call down the hierarchy, so whoever receives
782   // the call can take appropriate action.
783   internal::ScopedChildrenLock lock(this);
784   for (auto* child : children_) {
785     if (child->needs_layout_ || !layout_manager_) {
786       TRACE_EVENT1("views", "View::Layout", "class", child->GetClassName());
787       child->needs_layout_ = false;
788       child->Layout();
789     }
790   }
791 }
792 
InvalidateLayout()793 void View::InvalidateLayout() {
794   // Always invalidate up. This is needed to handle the case of us already being
795   // valid, but not our parent.
796   needs_layout_ = true;
797   if (layout_manager_)
798     layout_manager_->InvalidateLayout();
799 
800   if (parent_) {
801     parent_->InvalidateLayout();
802   } else {
803     Widget* widget = GetWidget();
804     if (widget)
805       widget->ScheduleLayout();
806   }
807 }
808 
GetLayoutManager() const809 LayoutManager* View::GetLayoutManager() const {
810   return layout_manager_.get();
811 }
812 
SetLayoutManager(std::nullptr_t)813 void View::SetLayoutManager(std::nullptr_t) {
814   SetLayoutManagerImpl(nullptr);
815 }
816 
817 // Attributes ------------------------------------------------------------------
818 
GetViewByID(int id) const819 const View* View::GetViewByID(int id) const {
820   if (id == id_)
821     return const_cast<View*>(this);
822 
823   internal::ScopedChildrenLock lock(this);
824   for (auto* child : children_) {
825     const View* view = child->GetViewByID(id);
826     if (view)
827       return view;
828   }
829   return nullptr;
830 }
831 
GetViewByID(int id)832 View* View::GetViewByID(int id) {
833   return const_cast<View*>(const_cast<const View*>(this)->GetViewByID(id));
834 }
835 
SetID(int id)836 void View::SetID(int id) {
837   if (id == id_)
838     return;
839 
840   id_ = id;
841 
842   OnPropertyChanged(&id_, kPropertyEffectsNone);
843 }
844 
AddIDChangedCallback(PropertyChangedCallback callback)845 PropertyChangedSubscription View::AddIDChangedCallback(
846     PropertyChangedCallback callback) {
847   return AddPropertyChangedCallback(&id_, callback);
848 }
849 
SetGroup(int gid)850 void View::SetGroup(int gid) {
851   // Don't change the group id once it's set.
852   DCHECK(group_ == -1 || group_ == gid);
853   if (group_ != gid) {
854     group_ = gid;
855     OnPropertyChanged(&group_, kPropertyEffectsNone);
856   }
857 }
858 
GetGroup() const859 int View::GetGroup() const {
860   return group_;
861 }
862 
AddGroupChangedCallback(PropertyChangedCallback callback)863 PropertyChangedSubscription View::AddGroupChangedCallback(
864     PropertyChangedCallback callback) {
865   return AddPropertyChangedCallback(&group_, callback);
866 }
867 
IsGroupFocusTraversable() const868 bool View::IsGroupFocusTraversable() const {
869   return true;
870 }
871 
GetViewsInGroup(int group,Views * views)872 void View::GetViewsInGroup(int group, Views* views) {
873   if (group_ == group)
874     views->push_back(this);
875 
876   internal::ScopedChildrenLock lock(this);
877   for (auto* child : children_)
878     child->GetViewsInGroup(group, views);
879 }
880 
GetSelectedViewForGroup(int group)881 View* View::GetSelectedViewForGroup(int group) {
882   Views views;
883   GetWidget()->GetRootView()->GetViewsInGroup(group, &views);
884   return views.empty() ? nullptr : views[0];
885 }
886 
887 // Coordinate conversion -------------------------------------------------------
888 
889 // static
ConvertPointToTarget(const View * source,const View * target,gfx::Point * point)890 void View::ConvertPointToTarget(const View* source,
891                                 const View* target,
892                                 gfx::Point* point) {
893   DCHECK(source);
894   DCHECK(target);
895   if (source == target)
896     return;
897 
898   const View* root = GetHierarchyRoot(target);
899   CHECK_EQ(GetHierarchyRoot(source), root);
900 
901   if (source != root)
902     source->ConvertPointForAncestor(root, point);
903 
904   if (target != root)
905     target->ConvertPointFromAncestor(root, point);
906 }
907 
908 // static
ConvertRectToTarget(const View * source,const View * target,gfx::RectF * rect)909 void View::ConvertRectToTarget(const View* source,
910                                const View* target,
911                                gfx::RectF* rect) {
912   DCHECK(source);
913   DCHECK(target);
914   if (source == target)
915     return;
916 
917   const View* root = GetHierarchyRoot(target);
918   CHECK_EQ(GetHierarchyRoot(source), root);
919 
920   if (source != root)
921     source->ConvertRectForAncestor(root, rect);
922 
923   if (target != root)
924     target->ConvertRectFromAncestor(root, rect);
925 }
926 
927 // static
ConvertPointToWidget(const View * src,gfx::Point * p)928 void View::ConvertPointToWidget(const View* src, gfx::Point* p) {
929   DCHECK(src);
930   DCHECK(p);
931 
932   src->ConvertPointForAncestor(nullptr, p);
933 }
934 
935 // static
ConvertPointFromWidget(const View * dest,gfx::Point * p)936 void View::ConvertPointFromWidget(const View* dest, gfx::Point* p) {
937   DCHECK(dest);
938   DCHECK(p);
939 
940   dest->ConvertPointFromAncestor(nullptr, p);
941 }
942 
943 // static
ConvertPointToScreen(const View * src,gfx::Point * p)944 void View::ConvertPointToScreen(const View* src, gfx::Point* p) {
945   DCHECK(src);
946   DCHECK(p);
947 
948   // If the view is not connected to a tree, there's nothing we can do.
949   const Widget* widget = src->GetWidget();
950   if (widget) {
951     ConvertPointToWidget(src, p);
952     *p += widget->GetClientAreaBoundsInScreen().OffsetFromOrigin();
953   }
954 }
955 
956 // static
ConvertPointFromScreen(const View * dst,gfx::Point * p)957 void View::ConvertPointFromScreen(const View* dst, gfx::Point* p) {
958   DCHECK(dst);
959   DCHECK(p);
960 
961   const views::Widget* widget = dst->GetWidget();
962   if (!widget)
963     return;
964   *p -= widget->GetClientAreaBoundsInScreen().OffsetFromOrigin();
965   ConvertPointFromWidget(dst, p);
966 }
967 
968 // static
ConvertRectToScreen(const View * src,gfx::Rect * rect)969 void View::ConvertRectToScreen(const View* src, gfx::Rect* rect) {
970   DCHECK(src);
971   DCHECK(rect);
972 
973   gfx::Point new_origin = rect->origin();
974   views::View::ConvertPointToScreen(src, &new_origin);
975   rect->set_origin(new_origin);
976 }
977 
ConvertRectToParent(const gfx::Rect & rect) const978 gfx::Rect View::ConvertRectToParent(const gfx::Rect& rect) const {
979   gfx::RectF x_rect = gfx::RectF(rect);
980   GetTransform().TransformRect(&x_rect);
981   x_rect.Offset(GetMirroredPosition().OffsetFromOrigin());
982   // Pixels we partially occupy in the parent should be included.
983   return gfx::ToEnclosingRect(x_rect);
984 }
985 
ConvertRectToWidget(const gfx::Rect & rect) const986 gfx::Rect View::ConvertRectToWidget(const gfx::Rect& rect) const {
987   gfx::Rect x_rect = rect;
988   for (const View* v = this; v; v = v->parent_)
989     x_rect = v->ConvertRectToParent(x_rect);
990   return x_rect;
991 }
992 
993 // Painting --------------------------------------------------------------------
994 
SchedulePaint()995 void View::SchedulePaint() {
996   SchedulePaintInRect(GetLocalBounds());
997 }
998 
SchedulePaintInRect(const gfx::Rect & rect)999 void View::SchedulePaintInRect(const gfx::Rect& rect) {
1000   needs_paint_ = true;
1001   SchedulePaintInRectImpl(rect);
1002 }
1003 
Paint(const PaintInfo & parent_paint_info)1004 void View::Paint(const PaintInfo& parent_paint_info) {
1005   if (!ShouldPaint())
1006     return;
1007 
1008   const gfx::Rect& parent_bounds =
1009       !parent() ? GetMirroredBounds() : parent()->GetMirroredBounds();
1010 
1011   PaintInfo paint_info = PaintInfo::CreateChildPaintInfo(
1012       parent_paint_info, GetMirroredBounds(), parent_bounds.size(),
1013       GetPaintScaleType(), !!layer(), needs_paint_);
1014 
1015   needs_paint_ = false;
1016 
1017   const ui::PaintContext& context = paint_info.context();
1018   bool is_invalidated = true;
1019   if (paint_info.context().CanCheckInvalid() ||
1020       base::FeatureList::IsEnabled(features::kEnableViewPaintOptimization)) {
1021     // For View paint optimization, do not default to repainting every View in
1022     // the View hierarchy if the invalidation rect is empty. Repainting does not
1023     // depend on the invalidation rect for View paint optimization.
1024 #if DCHECK_IS_ON()
1025     if (!context.is_pixel_canvas()) {
1026       gfx::Vector2d offset;
1027       context.Visited(this);
1028       View* view = this;
1029       while (view->parent() && !view->layer()) {
1030         DCHECK(view->GetTransform().IsIdentity());
1031         offset += view->GetMirroredPosition().OffsetFromOrigin();
1032         view = view->parent();
1033       }
1034       // The offset in the PaintContext should be the offset up to the paint
1035       // root, which we compute and verify here.
1036       DCHECK_EQ(context.PaintOffset().x(), offset.x());
1037       DCHECK_EQ(context.PaintOffset().y(), offset.y());
1038       // The above loop will stop when |view| is the paint root, which should be
1039       // the root of the current paint walk, as verified by storing the root in
1040       // the PaintContext.
1041       DCHECK_EQ(context.RootVisited(), view);
1042     }
1043 #endif
1044 
1045     // If the View wasn't invalidated, don't waste time painting it, the output
1046     // would be culled.
1047     is_invalidated = paint_info.ShouldPaint();
1048   }
1049 
1050   TRACE_EVENT1("views", "View::Paint", "class", GetClassName());
1051 
1052   // If the view is backed by a layer, it should paint with itself as the origin
1053   // rather than relative to its parent.
1054   // TODO(danakj): Rework clip and transform recorder usage here to use
1055   // std::optional once we can do so.
1056   ui::ClipRecorder clip_recorder(parent_paint_info.context());
1057   if (!layer()) {
1058     // Set the clip rect to the bounds of this View, or |clip_path_| if it's
1059     // been set. Note that the X (or left) position we pass to ClipRect takes
1060     // into consideration whether or not the View uses a right-to-left layout so
1061     // that we paint the View in its mirrored position if need be.
1062     if (clip_path_.isEmpty()) {
1063       clip_recorder.ClipRect(gfx::Rect(paint_info.paint_recording_size()) +
1064                              paint_info.offset_from_parent());
1065     } else {
1066       SkPath clip_path_in_parent = clip_path_;
1067 
1068       // Transform |clip_path_| from local space to parent recording space.
1069       gfx::Transform to_parent_recording_space;
1070 
1071       to_parent_recording_space.Translate(paint_info.offset_from_parent());
1072       to_parent_recording_space.Scale(
1073           SkFloatToScalar(paint_info.paint_recording_scale_x()),
1074           SkFloatToScalar(paint_info.paint_recording_scale_y()));
1075 
1076       clip_path_in_parent.transform(
1077           SkMatrix(to_parent_recording_space.matrix()));
1078       clip_recorder.ClipPathWithAntiAliasing(clip_path_in_parent);
1079     }
1080   }
1081 
1082   ui::TransformRecorder transform_recorder(context);
1083   SetUpTransformRecorderForPainting(paint_info.offset_from_parent(),
1084                                     &transform_recorder);
1085 
1086   // Note that the cache is not aware of the offset of the view
1087   // relative to the parent since painting is always done relative to
1088   // the top left of the individual view.
1089   if (is_invalidated ||
1090       !paint_cache_.UseCache(context, paint_info.paint_recording_size())) {
1091     ui::PaintRecorder recorder(context, paint_info.paint_recording_size(),
1092                                paint_info.paint_recording_scale_x(),
1093                                paint_info.paint_recording_scale_y(),
1094                                &paint_cache_);
1095     gfx::Canvas* canvas = recorder.canvas();
1096     gfx::ScopedCanvas scoped_canvas(canvas);
1097     if (flip_canvas_on_paint_for_rtl_ui_)
1098       scoped_canvas.FlipIfRTL(width());
1099 
1100     // Delegate painting the contents of the View to the virtual OnPaint method.
1101     OnPaint(canvas);
1102   }
1103 
1104   // View::Paint() recursion over the subtree.
1105   PaintChildren(paint_info);
1106 }
1107 
SetBackground(std::unique_ptr<Background> b)1108 void View::SetBackground(std::unique_ptr<Background> b) {
1109   background_ = std::move(b);
1110   SchedulePaint();
1111 }
1112 
SetBorder(std::unique_ptr<Border> b)1113 void View::SetBorder(std::unique_ptr<Border> b) {
1114   const gfx::Rect old_contents_bounds = GetContentsBounds();
1115   border_ = std::move(b);
1116 
1117   // Conceptually, this should be PreferredSizeChanged(), but for some view
1118   // hierarchies that triggers synchronous add/remove operations that are unsafe
1119   // in some contexts where SetBorder is called.
1120   //
1121   // InvalidateLayout() still triggers a re-layout of the view, which should
1122   // include re-querying its preferred size so in practice this is both safe and
1123   // has the intended effect.
1124   if (old_contents_bounds != GetContentsBounds())
1125     InvalidateLayout();
1126 
1127   SchedulePaint();
1128 }
1129 
GetThemeProvider() const1130 const ui::ThemeProvider* View::GetThemeProvider() const {
1131   const Widget* widget = GetWidget();
1132   return widget ? widget->GetThemeProvider() : nullptr;
1133 }
1134 
GetNativeTheme() const1135 const ui::NativeTheme* View::GetNativeTheme() const {
1136   if (native_theme_)
1137     return native_theme_;
1138 
1139   if (parent())
1140     return parent()->GetNativeTheme();
1141 
1142   const Widget* widget = GetWidget();
1143   if (widget)
1144     return widget->GetNativeTheme();
1145 
1146   return ui::NativeTheme::GetInstanceForNativeUi();
1147 }
1148 
SetNativeThemeForTesting(ui::NativeTheme * theme)1149 void View::SetNativeThemeForTesting(ui::NativeTheme* theme) {
1150   ui::NativeTheme* original_native_theme = GetNativeTheme();
1151   native_theme_ = theme;
1152   if (native_theme_ != original_native_theme)
1153     PropagateThemeChanged();
1154 }
1155 
1156 // RTL painting ----------------------------------------------------------------
1157 
GetFlipCanvasOnPaintForRTLUI() const1158 bool View::GetFlipCanvasOnPaintForRTLUI() const {
1159   return flip_canvas_on_paint_for_rtl_ui_;
1160 }
1161 
SetFlipCanvasOnPaintForRTLUI(bool enable)1162 void View::SetFlipCanvasOnPaintForRTLUI(bool enable) {
1163   if (enable == flip_canvas_on_paint_for_rtl_ui_)
1164     return;
1165   flip_canvas_on_paint_for_rtl_ui_ = enable;
1166 
1167   OnPropertyChanged(&flip_canvas_on_paint_for_rtl_ui_, kPropertyEffectsPaint);
1168 }
1169 
AddFlipCanvasOnPaintForRTLUIChangedCallback(PropertyChangedCallback callback)1170 PropertyChangedSubscription View::AddFlipCanvasOnPaintForRTLUIChangedCallback(
1171     PropertyChangedCallback callback) {
1172   return AddPropertyChangedCallback(&flip_canvas_on_paint_for_rtl_ui_,
1173                                     std::move(callback));
1174 }
1175 
SetMirrored(bool is_mirrored)1176 void View::SetMirrored(bool is_mirrored) {
1177   if (is_mirrored_ && is_mirrored_.value() == is_mirrored)
1178     return;
1179   is_mirrored_ = is_mirrored;
1180 
1181   OnPropertyChanged(&is_mirrored_, kPropertyEffectsPaint);
1182 }
1183 
GetMirrored() const1184 bool View::GetMirrored() const {
1185   return is_mirrored_.value_or(base::i18n::IsRTL());
1186 }
1187 
1188 // Input -----------------------------------------------------------------------
1189 
GetEventHandlerForPoint(const gfx::Point & point)1190 View* View::GetEventHandlerForPoint(const gfx::Point& point) {
1191   return GetEventHandlerForRect(gfx::Rect(point, gfx::Size(1, 1)));
1192 }
1193 
GetEventHandlerForRect(const gfx::Rect & rect)1194 View* View::GetEventHandlerForRect(const gfx::Rect& rect) {
1195   return GetEffectiveViewTargeter()->TargetForRect(this, rect);
1196 }
1197 
GetCanProcessEventsWithinSubtree() const1198 bool View::GetCanProcessEventsWithinSubtree() const {
1199   return can_process_events_within_subtree_;
1200 }
1201 
SetCanProcessEventsWithinSubtree(bool can_process)1202 void View::SetCanProcessEventsWithinSubtree(bool can_process) {
1203   if (can_process_events_within_subtree_ == can_process)
1204     return;
1205   can_process_events_within_subtree_ = can_process;
1206   OnPropertyChanged(&can_process_events_within_subtree_, kPropertyEffectsNone);
1207 }
1208 
GetTooltipHandlerForPoint(const gfx::Point & point)1209 View* View::GetTooltipHandlerForPoint(const gfx::Point& point) {
1210   // TODO(tdanderson): Move this implementation into ViewTargetDelegate.
1211   if (!HitTestPoint(point) || !GetCanProcessEventsWithinSubtree())
1212     return nullptr;
1213 
1214   // Walk the child Views recursively looking for the View that most
1215   // tightly encloses the specified point.
1216   View::Views children = GetChildrenInZOrder();
1217   DCHECK_EQ(children_.size(), children.size());
1218   for (auto* child : base::Reversed(children)) {
1219     if (!child->GetVisible())
1220       continue;
1221 
1222     gfx::Point point_in_child_coords(point);
1223     ConvertPointToTarget(this, child, &point_in_child_coords);
1224     View* handler = child->GetTooltipHandlerForPoint(point_in_child_coords);
1225     if (handler)
1226       return handler;
1227   }
1228   return this;
1229 }
1230 
GetCursor(const ui::MouseEvent & event)1231 gfx::NativeCursor View::GetCursor(const ui::MouseEvent& event) {
1232 #if defined(OS_WIN)
1233   static ui::Cursor arrow;
1234   if (!arrow.platform())
1235     arrow.SetPlatformCursor(LoadCursor(nullptr, IDC_ARROW));
1236   return arrow;
1237 #else
1238   return gfx::kNullCursor;
1239 #endif
1240 }
1241 
HitTestPoint(const gfx::Point & point) const1242 bool View::HitTestPoint(const gfx::Point& point) const {
1243   return HitTestRect(gfx::Rect(point, gfx::Size(1, 1)));
1244 }
1245 
HitTestRect(const gfx::Rect & rect) const1246 bool View::HitTestRect(const gfx::Rect& rect) const {
1247   return GetEffectiveViewTargeter()->DoesIntersectRect(this, rect);
1248 }
1249 
IsMouseHovered() const1250 bool View::IsMouseHovered() const {
1251   // If we haven't yet been placed in an onscreen view hierarchy, we can't be
1252   // hovered.
1253   if (!GetWidget())
1254     return false;
1255 
1256   // If mouse events are disabled, then the mouse cursor is invisible and
1257   // is therefore not hovering over this button.
1258   if (!GetWidget()->IsMouseEventsEnabled())
1259     return false;
1260 
1261   gfx::Point cursor_pos(display::Screen::GetScreen()->GetCursorScreenPoint());
1262   ConvertPointFromScreen(this, &cursor_pos);
1263   return HitTestPoint(cursor_pos);
1264 }
1265 
OnMousePressed(const ui::MouseEvent & event)1266 bool View::OnMousePressed(const ui::MouseEvent& event) {
1267   return false;
1268 }
1269 
OnMouseDragged(const ui::MouseEvent & event)1270 bool View::OnMouseDragged(const ui::MouseEvent& event) {
1271   return false;
1272 }
1273 
OnMouseReleased(const ui::MouseEvent & event)1274 void View::OnMouseReleased(const ui::MouseEvent& event) {}
1275 
OnMouseCaptureLost()1276 void View::OnMouseCaptureLost() {}
1277 
OnMouseMoved(const ui::MouseEvent & event)1278 void View::OnMouseMoved(const ui::MouseEvent& event) {}
1279 
OnMouseEntered(const ui::MouseEvent & event)1280 void View::OnMouseEntered(const ui::MouseEvent& event) {}
1281 
OnMouseExited(const ui::MouseEvent & event)1282 void View::OnMouseExited(const ui::MouseEvent& event) {}
1283 
SetMouseHandler(View * new_mouse_handler)1284 void View::SetMouseHandler(View* new_mouse_handler) {
1285   // |new_mouse_handler| may be nullptr.
1286   if (parent_)
1287     parent_->SetMouseHandler(new_mouse_handler);
1288 }
1289 
OnKeyPressed(const ui::KeyEvent & event)1290 bool View::OnKeyPressed(const ui::KeyEvent& event) {
1291   return false;
1292 }
1293 
OnKeyReleased(const ui::KeyEvent & event)1294 bool View::OnKeyReleased(const ui::KeyEvent& event) {
1295   return false;
1296 }
1297 
OnMouseWheel(const ui::MouseWheelEvent & event)1298 bool View::OnMouseWheel(const ui::MouseWheelEvent& event) {
1299   return false;
1300 }
1301 
OnKeyEvent(ui::KeyEvent * event)1302 void View::OnKeyEvent(ui::KeyEvent* event) {
1303   bool consumed = (event->type() == ui::ET_KEY_PRESSED) ? OnKeyPressed(*event)
1304                                                         : OnKeyReleased(*event);
1305   if (consumed)
1306     event->StopPropagation();
1307 }
1308 
OnMouseEvent(ui::MouseEvent * event)1309 void View::OnMouseEvent(ui::MouseEvent* event) {
1310   switch (event->type()) {
1311     case ui::ET_MOUSE_PRESSED:
1312       if (ProcessMousePressed(*event))
1313         event->SetHandled();
1314       return;
1315 
1316     case ui::ET_MOUSE_MOVED:
1317       if ((event->flags() &
1318            (ui::EF_LEFT_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON |
1319             ui::EF_MIDDLE_MOUSE_BUTTON)) == 0) {
1320         OnMouseMoved(*event);
1321         return;
1322       }
1323       FALLTHROUGH;
1324     case ui::ET_MOUSE_DRAGGED:
1325       ProcessMouseDragged(event);
1326       return;
1327 
1328     case ui::ET_MOUSE_RELEASED:
1329       ProcessMouseReleased(*event);
1330       return;
1331 
1332     case ui::ET_MOUSEWHEEL:
1333       if (OnMouseWheel(*event->AsMouseWheelEvent()))
1334         event->SetHandled();
1335       break;
1336 
1337     case ui::ET_MOUSE_ENTERED:
1338       if (event->flags() & ui::EF_TOUCH_ACCESSIBILITY)
1339         NotifyAccessibilityEvent(ax::mojom::Event::kHover, true);
1340       OnMouseEntered(*event);
1341       break;
1342 
1343     case ui::ET_MOUSE_EXITED:
1344       OnMouseExited(*event);
1345       break;
1346 
1347     default:
1348       return;
1349   }
1350 }
1351 
OnScrollEvent(ui::ScrollEvent * event)1352 void View::OnScrollEvent(ui::ScrollEvent* event) {}
1353 
OnTouchEvent(ui::TouchEvent * event)1354 void View::OnTouchEvent(ui::TouchEvent* event) {
1355   NOTREACHED() << "Views should not receive touch events.";
1356 }
1357 
OnGestureEvent(ui::GestureEvent * event)1358 void View::OnGestureEvent(ui::GestureEvent* event) {}
1359 
SetNotifyEnterExitOnChild(bool notify)1360 void View::SetNotifyEnterExitOnChild(bool notify) {
1361   notify_enter_exit_on_child_ = notify;
1362 }
1363 
GetNotifyEnterExitOnChild() const1364 bool View::GetNotifyEnterExitOnChild() const {
1365   return notify_enter_exit_on_child_;
1366 }
1367 
GetInputMethod() const1368 const ui::InputMethod* View::GetInputMethod() const {
1369   Widget* widget = const_cast<Widget*>(GetWidget());
1370   return widget ? const_cast<const ui::InputMethod*>(widget->GetInputMethod())
1371                 : nullptr;
1372 }
1373 
SetEventTargeter(std::unique_ptr<ViewTargeter> targeter)1374 std::unique_ptr<ViewTargeter> View::SetEventTargeter(
1375     std::unique_ptr<ViewTargeter> targeter) {
1376   std::unique_ptr<ViewTargeter> old_targeter = std::move(targeter_);
1377   targeter_ = std::move(targeter);
1378   return old_targeter;
1379 }
1380 
GetEffectiveViewTargeter() const1381 ViewTargeter* View::GetEffectiveViewTargeter() const {
1382   DCHECK(GetWidget());
1383   ViewTargeter* view_targeter = targeter();
1384   if (!view_targeter)
1385     view_targeter = GetWidget()->GetRootView()->targeter();
1386   CHECK(view_targeter);
1387   return view_targeter;
1388 }
1389 
GetWordLookupClient()1390 WordLookupClient* View::GetWordLookupClient() {
1391   return nullptr;
1392 }
1393 
CanAcceptEvent(const ui::Event & event)1394 bool View::CanAcceptEvent(const ui::Event& event) {
1395   return IsDrawn();
1396 }
1397 
GetParentTarget()1398 ui::EventTarget* View::GetParentTarget() {
1399   return parent_;
1400 }
1401 
GetChildIterator() const1402 std::unique_ptr<ui::EventTargetIterator> View::GetChildIterator() const {
1403   return std::make_unique<ui::EventTargetIteratorPtrImpl<View>>(children_);
1404 }
1405 
GetEventTargeter()1406 ui::EventTargeter* View::GetEventTargeter() {
1407   return targeter_.get();
1408 }
1409 
ConvertEventToTarget(const ui::EventTarget * target,ui::LocatedEvent * event) const1410 void View::ConvertEventToTarget(const ui::EventTarget* target,
1411                                 ui::LocatedEvent* event) const {
1412   event->ConvertLocationToTarget(this, static_cast<const View*>(target));
1413 }
1414 
GetScreenLocationF(const ui::LocatedEvent & event) const1415 gfx::PointF View::GetScreenLocationF(const ui::LocatedEvent& event) const {
1416   DCHECK_EQ(this, event.target());
1417   gfx::Point screen_location(event.location());
1418   ConvertPointToScreen(this, &screen_location);
1419   return gfx::PointF(screen_location);
1420 }
1421 
1422 // Accelerators ----------------------------------------------------------------
1423 
AddAccelerator(const ui::Accelerator & accelerator)1424 void View::AddAccelerator(const ui::Accelerator& accelerator) {
1425   if (!accelerators_)
1426     accelerators_ = std::make_unique<std::vector<ui::Accelerator>>();
1427 
1428   if (!base::Contains(*accelerators_, accelerator))
1429     accelerators_->push_back(accelerator);
1430 
1431   RegisterPendingAccelerators();
1432 }
1433 
RemoveAccelerator(const ui::Accelerator & accelerator)1434 void View::RemoveAccelerator(const ui::Accelerator& accelerator) {
1435   if (!accelerators_) {
1436     NOTREACHED() << "Removing non-existing accelerator";
1437     return;
1438   }
1439 
1440   auto i(std::find(accelerators_->begin(), accelerators_->end(), accelerator));
1441   if (i == accelerators_->end()) {
1442     NOTREACHED() << "Removing non-existing accelerator";
1443     return;
1444   }
1445 
1446   size_t index = i - accelerators_->begin();
1447   accelerators_->erase(i);
1448   if (index >= registered_accelerator_count_) {
1449     // The accelerator is not registered to FocusManager.
1450     return;
1451   }
1452   --registered_accelerator_count_;
1453 
1454   // Providing we are attached to a Widget and registered with a focus manager,
1455   // we should de-register from that focus manager now.
1456   if (GetWidget() && accelerator_focus_manager_)
1457     accelerator_focus_manager_->UnregisterAccelerator(accelerator, this);
1458 }
1459 
ResetAccelerators()1460 void View::ResetAccelerators() {
1461   if (accelerators_)
1462     UnregisterAccelerators(false);
1463 }
1464 
AcceleratorPressed(const ui::Accelerator & accelerator)1465 bool View::AcceleratorPressed(const ui::Accelerator& accelerator) {
1466   return false;
1467 }
1468 
CanHandleAccelerators() const1469 bool View::CanHandleAccelerators() const {
1470   const Widget* widget = GetWidget();
1471   if (!GetEnabled() || !IsDrawn() || !widget || !widget->IsVisible())
1472     return false;
1473 #if BUILDFLAG(ENABLE_DESKTOP_AURA)
1474   // Non-ChromeOS aura windows have an associated FocusManagerEventHandler which
1475   // adds currently focused view as an event PreTarget (see
1476   // DesktopNativeWidgetAura::InitNativeWidget). However, the focused view isn't
1477   // always the right view to handle accelerators: It should only handle them
1478   // when active. Only top level widgets can be active, so for child widgets
1479   // check if they are focused instead. ChromeOS also behaves different than
1480   // Linux when an extension popup is about to handle the accelerator.
1481   bool child = widget && widget->GetTopLevelWidget() != widget;
1482   bool focus_in_child = widget && widget->GetRootView()->Contains(
1483                                       GetFocusManager()->GetFocusedView());
1484   if ((child && !focus_in_child) || (!child && !widget->IsActive()))
1485     return false;
1486 #endif
1487   return true;
1488 }
1489 
1490 // Focus -----------------------------------------------------------------------
1491 
HasFocus() const1492 bool View::HasFocus() const {
1493   const FocusManager* focus_manager = GetFocusManager();
1494   return focus_manager && (focus_manager->GetFocusedView() == this);
1495 }
1496 
GetNextFocusableView()1497 View* View::GetNextFocusableView() {
1498   return next_focusable_view_;
1499 }
1500 
GetNextFocusableView() const1501 const View* View::GetNextFocusableView() const {
1502   return next_focusable_view_;
1503 }
1504 
GetPreviousFocusableView()1505 View* View::GetPreviousFocusableView() {
1506   return previous_focusable_view_;
1507 }
1508 
RemoveFromFocusList()1509 void View::RemoveFromFocusList() {
1510   View* const old_prev = previous_focusable_view_;
1511   View* const old_next = next_focusable_view_;
1512 
1513   previous_focusable_view_ = nullptr;
1514   next_focusable_view_ = nullptr;
1515 
1516   if (old_prev)
1517     old_prev->next_focusable_view_ = old_next;
1518 
1519   if (old_next)
1520     old_next->previous_focusable_view_ = old_prev;
1521 }
1522 
InsertBeforeInFocusList(View * view)1523 void View::InsertBeforeInFocusList(View* view) {
1524   DCHECK(view);
1525   DCHECK_EQ(parent_, view->parent_);
1526 
1527   if (view == next_focusable_view_)
1528     return;
1529 
1530   RemoveFromFocusList();
1531 
1532   next_focusable_view_ = view;
1533   previous_focusable_view_ = view->previous_focusable_view_;
1534 
1535   if (previous_focusable_view_)
1536     previous_focusable_view_->next_focusable_view_ = this;
1537 
1538   next_focusable_view_->previous_focusable_view_ = this;
1539 }
1540 
InsertAfterInFocusList(View * view)1541 void View::InsertAfterInFocusList(View* view) {
1542   DCHECK(view);
1543   DCHECK_EQ(parent_, view->parent_);
1544 
1545   if (view == previous_focusable_view_)
1546     return;
1547 
1548   RemoveFromFocusList();
1549 
1550   if (view->next_focusable_view_) {
1551     InsertBeforeInFocusList(view->next_focusable_view_);
1552     return;
1553   }
1554 
1555   view->next_focusable_view_ = this;
1556   previous_focusable_view_ = view;
1557 }
1558 
GetFocusBehavior() const1559 View::FocusBehavior View::GetFocusBehavior() const {
1560   return focus_behavior_;
1561 }
1562 
SetFocusBehavior(FocusBehavior focus_behavior)1563 void View::SetFocusBehavior(FocusBehavior focus_behavior) {
1564   if (focus_behavior_ == focus_behavior)
1565     return;
1566 
1567   focus_behavior_ = focus_behavior;
1568   AdvanceFocusIfNecessary();
1569 
1570   OnPropertyChanged(&focus_behavior_, kPropertyEffectsNone);
1571 }
1572 
IsFocusable() const1573 bool View::IsFocusable() const {
1574   return focus_behavior_ == FocusBehavior::ALWAYS && GetEnabled() && IsDrawn();
1575 }
1576 
IsAccessibilityFocusable() const1577 bool View::IsAccessibilityFocusable() const {
1578   return focus_behavior_ != FocusBehavior::NEVER && GetEnabled() && IsDrawn();
1579 }
1580 
GetFocusManager()1581 FocusManager* View::GetFocusManager() {
1582   Widget* widget = GetWidget();
1583   return widget ? widget->GetFocusManager() : nullptr;
1584 }
1585 
GetFocusManager() const1586 const FocusManager* View::GetFocusManager() const {
1587   const Widget* widget = GetWidget();
1588   return widget ? widget->GetFocusManager() : nullptr;
1589 }
1590 
RequestFocus()1591 void View::RequestFocus() {
1592   FocusManager* focus_manager = GetFocusManager();
1593   if (focus_manager) {
1594     bool focusable = focus_manager->keyboard_accessible()
1595                          ? IsAccessibilityFocusable()
1596                          : IsFocusable();
1597     if (focusable)
1598       focus_manager->SetFocusedView(this);
1599   }
1600 }
1601 
SkipDefaultKeyEventProcessing(const ui::KeyEvent & event)1602 bool View::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
1603   return false;
1604 }
1605 
GetFocusTraversable()1606 FocusTraversable* View::GetFocusTraversable() {
1607   return nullptr;
1608 }
1609 
GetPaneFocusTraversable()1610 FocusTraversable* View::GetPaneFocusTraversable() {
1611   return nullptr;
1612 }
1613 
1614 // Tooltips --------------------------------------------------------------------
1615 
GetTooltipText(const gfx::Point & p) const1616 base::string16 View::GetTooltipText(const gfx::Point& p) const {
1617   return base::string16();
1618 }
1619 
1620 // Context menus ---------------------------------------------------------------
1621 
ShowContextMenu(const gfx::Point & p,ui::MenuSourceType source_type)1622 void View::ShowContextMenu(const gfx::Point& p,
1623                            ui::MenuSourceType source_type) {
1624   if (!context_menu_controller_)
1625     return;
1626 
1627   context_menu_controller_->ShowContextMenuForView(this, p, source_type);
1628 }
1629 
GetKeyboardContextMenuLocation()1630 gfx::Point View::GetKeyboardContextMenuLocation() {
1631   gfx::Rect vis_bounds = GetVisibleBounds();
1632   gfx::Point screen_point(vis_bounds.x() + vis_bounds.width() / 2,
1633                           vis_bounds.y() + vis_bounds.height() / 2);
1634   ConvertPointToScreen(this, &screen_point);
1635   return screen_point;
1636 }
1637 
1638 // Drag and drop ---------------------------------------------------------------
1639 
GetDropFormats(int * formats,std::set<ui::ClipboardFormatType> * format_types)1640 bool View::GetDropFormats(int* formats,
1641                           std::set<ui::ClipboardFormatType>* format_types) {
1642   return false;
1643 }
1644 
AreDropTypesRequired()1645 bool View::AreDropTypesRequired() {
1646   return false;
1647 }
1648 
CanDrop(const OSExchangeData & data)1649 bool View::CanDrop(const OSExchangeData& data) {
1650   // TODO(sky): when I finish up migration, this should default to true.
1651   return false;
1652 }
1653 
OnDragEntered(const ui::DropTargetEvent & event)1654 void View::OnDragEntered(const ui::DropTargetEvent& event) {}
1655 
OnDragUpdated(const ui::DropTargetEvent & event)1656 int View::OnDragUpdated(const ui::DropTargetEvent& event) {
1657   return ui::DragDropTypes::DRAG_NONE;
1658 }
1659 
OnDragExited()1660 void View::OnDragExited() {}
1661 
OnPerformDrop(const ui::DropTargetEvent & event)1662 int View::OnPerformDrop(const ui::DropTargetEvent& event) {
1663   return ui::DragDropTypes::DRAG_NONE;
1664 }
1665 
OnDragDone()1666 void View::OnDragDone() {}
1667 
1668 // static
ExceededDragThreshold(const gfx::Vector2d & delta)1669 bool View::ExceededDragThreshold(const gfx::Vector2d& delta) {
1670   return (abs(delta.x()) > GetHorizontalDragThreshold() ||
1671           abs(delta.y()) > GetVerticalDragThreshold());
1672 }
1673 
1674 // Accessibility----------------------------------------------------------------
1675 
GetViewAccessibility()1676 ViewAccessibility& View::GetViewAccessibility() {
1677   if (!view_accessibility_)
1678     view_accessibility_ = ViewAccessibility::Create(this);
1679   return *view_accessibility_;
1680 }
1681 
HandleAccessibleAction(const ui::AXActionData & action_data)1682 bool View::HandleAccessibleAction(const ui::AXActionData& action_data) {
1683   switch (action_data.action) {
1684     case ax::mojom::Action::kBlur:
1685       if (HasFocus()) {
1686         GetFocusManager()->ClearFocus();
1687         return true;
1688       }
1689       break;
1690     case ax::mojom::Action::kDoDefault: {
1691       const gfx::Point center = GetLocalBounds().CenterPoint();
1692       ui::MouseEvent press(ui::ET_MOUSE_PRESSED, center, center,
1693                            ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1694                            ui::EF_LEFT_MOUSE_BUTTON);
1695       OnEvent(&press);
1696       ui::MouseEvent release(ui::ET_MOUSE_RELEASED, center, center,
1697                              ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
1698                              ui::EF_LEFT_MOUSE_BUTTON);
1699       OnEvent(&release);
1700       return true;
1701     }
1702     case ax::mojom::Action::kFocus:
1703       if (IsAccessibilityFocusable()) {
1704         RequestFocus();
1705         return true;
1706       }
1707       break;
1708     case ax::mojom::Action::kScrollToMakeVisible:
1709       ScrollRectToVisible(GetLocalBounds());
1710       return true;
1711     case ax::mojom::Action::kShowContextMenu:
1712       ShowContextMenu(GetBoundsInScreen().CenterPoint(),
1713                       ui::MENU_SOURCE_KEYBOARD);
1714       return true;
1715     default:
1716       // Some actions are handled by subclasses of View.
1717       break;
1718   }
1719 
1720   return false;
1721 }
1722 
GetNativeViewAccessible()1723 gfx::NativeViewAccessible View::GetNativeViewAccessible() {
1724   return GetViewAccessibility().GetNativeObject();
1725 }
1726 
NotifyAccessibilityEvent(ax::mojom::Event event_type,bool send_native_event)1727 void View::NotifyAccessibilityEvent(ax::mojom::Event event_type,
1728                                     bool send_native_event) {
1729   AXEventManager::Get()->NotifyViewEvent(this, event_type);
1730 
1731   if (send_native_event && GetWidget())
1732     GetViewAccessibility().NotifyAccessibilityEvent(event_type);
1733 
1734   OnAccessibilityEvent(event_type);
1735 }
1736 
OnAccessibilityEvent(ax::mojom::Event event_type)1737 void View::OnAccessibilityEvent(ax::mojom::Event event_type) {}
1738 
1739 // Scrolling -------------------------------------------------------------------
1740 
ScrollRectToVisible(const gfx::Rect & rect)1741 void View::ScrollRectToVisible(const gfx::Rect& rect) {
1742   if (parent_)
1743     parent_->ScrollRectToVisible(rect + bounds().OffsetFromOrigin());
1744 }
1745 
ScrollViewToVisible()1746 void View::ScrollViewToVisible() {
1747   ScrollRectToVisible(GetLocalBounds());
1748 }
1749 
AddObserver(ViewObserver * observer)1750 void View::AddObserver(ViewObserver* observer) {
1751   CHECK(observer);
1752   observers_.AddObserver(observer);
1753 }
1754 
RemoveObserver(ViewObserver * observer)1755 void View::RemoveObserver(ViewObserver* observer) {
1756   observers_.RemoveObserver(observer);
1757 }
1758 
HasObserver(const ViewObserver * observer) const1759 bool View::HasObserver(const ViewObserver* observer) const {
1760   return observers_.HasObserver(observer);
1761 }
1762 
1763 ////////////////////////////////////////////////////////////////////////////////
1764 // View, protected:
1765 
1766 // Size and disposition --------------------------------------------------------
1767 
CalculatePreferredSize() const1768 gfx::Size View::CalculatePreferredSize() const {
1769   if (layout_manager_)
1770     return layout_manager_->GetPreferredSize(this);
1771   return gfx::Size();
1772 }
1773 
PreferredSizeChanged()1774 void View::PreferredSizeChanged() {
1775   if (parent_)
1776     parent_->ChildPreferredSizeChanged(this);
1777   // Since some layout managers (specifically AnimatingLayoutManager) can react
1778   // to InvalidateLayout() by doing calculations and since the parent can
1779   // potentially change preferred size, etc. as a result of calling
1780   // ChildPreferredSizeChanged(), postpone invalidation until the events have
1781   // run all the way up the hierarchy.
1782   InvalidateLayout();
1783   for (ViewObserver& observer : observers_)
1784     observer.OnViewPreferredSizeChanged(this);
1785 }
1786 
GetNeedsNotificationWhenVisibleBoundsChange() const1787 bool View::GetNeedsNotificationWhenVisibleBoundsChange() const {
1788   return false;
1789 }
1790 
OnVisibleBoundsChanged()1791 void View::OnVisibleBoundsChanged() {}
1792 
1793 // Tree operations -------------------------------------------------------------
1794 
ViewHierarchyChanged(const ViewHierarchyChangedDetails & details)1795 void View::ViewHierarchyChanged(const ViewHierarchyChangedDetails& details) {}
1796 
VisibilityChanged(View * starting_from,bool is_visible)1797 void View::VisibilityChanged(View* starting_from, bool is_visible) {}
1798 
NativeViewHierarchyChanged()1799 void View::NativeViewHierarchyChanged() {
1800   FocusManager* focus_manager = GetFocusManager();
1801   if (accelerator_focus_manager_ != focus_manager) {
1802     UnregisterAccelerators(true);
1803 
1804     if (focus_manager)
1805       RegisterPendingAccelerators();
1806   }
1807 }
1808 
AddedToWidget()1809 void View::AddedToWidget() {}
1810 
RemovedFromWidget()1811 void View::RemovedFromWidget() {}
1812 
1813 // Painting --------------------------------------------------------------------
1814 
OnDidSchedulePaint(const gfx::Rect & rect)1815 void View::OnDidSchedulePaint(const gfx::Rect& rect) {}
1816 
PaintChildren(const PaintInfo & paint_info)1817 void View::PaintChildren(const PaintInfo& paint_info) {
1818   TRACE_EVENT1("views", "View::PaintChildren", "class", GetClassName());
1819   RecursivePaintHelper(&View::Paint, paint_info);
1820 }
1821 
OnPaint(gfx::Canvas * canvas)1822 void View::OnPaint(gfx::Canvas* canvas) {
1823   TRACE_EVENT1("views", "View::OnPaint", "class", GetClassName());
1824   OnPaintBackground(canvas);
1825   OnPaintBorder(canvas);
1826 }
1827 
OnPaintBackground(gfx::Canvas * canvas)1828 void View::OnPaintBackground(gfx::Canvas* canvas) {
1829   if (background_) {
1830     TRACE_EVENT0("views", "View::OnPaintBackground");
1831     background_->Paint(canvas, this);
1832   }
1833 }
1834 
OnPaintBorder(gfx::Canvas * canvas)1835 void View::OnPaintBorder(gfx::Canvas* canvas) {
1836   if (border_) {
1837     TRACE_EVENT0("views", "View::OnPaintBorder");
1838     border_->Paint(*this, canvas);
1839   }
1840 }
1841 
1842 // Accelerated Painting --------------------------------------------------------
1843 
CalculateOffsetToAncestorWithLayer(ui::Layer ** layer_parent)1844 View::LayerOffsetData View::CalculateOffsetToAncestorWithLayer(
1845     ui::Layer** layer_parent) {
1846   if (layer()) {
1847     if (layer_parent)
1848       *layer_parent = layer();
1849     return LayerOffsetData(layer()->device_scale_factor());
1850   }
1851   if (!parent_)
1852     return LayerOffsetData();
1853 
1854   LayerOffsetData offset_data =
1855       parent_->CalculateOffsetToAncestorWithLayer(layer_parent);
1856 
1857   return offset_data + GetMirroredPosition().OffsetFromOrigin();
1858 }
1859 
UpdateParentLayer()1860 void View::UpdateParentLayer() {
1861   if (!layer())
1862     return;
1863 
1864   ui::Layer* parent_layer = nullptr;
1865 
1866   if (parent_)
1867     parent_->CalculateOffsetToAncestorWithLayer(&parent_layer);
1868 
1869   ReparentLayer(parent_layer);
1870 }
1871 
MoveLayerToParent(ui::Layer * parent_layer,const LayerOffsetData & offset_data)1872 void View::MoveLayerToParent(ui::Layer* parent_layer,
1873                              const LayerOffsetData& offset_data) {
1874   LayerOffsetData local_offset_data(offset_data);
1875   if (parent_layer != layer())
1876     local_offset_data += GetMirroredPosition().OffsetFromOrigin();
1877 
1878   if (layer() && parent_layer != layer()) {
1879     // Adding the main layer can trigger a call to |SnapLayerToPixelBoundary()|.
1880     // That method assumes layers beneath have already been added. Therefore
1881     // layers beneath must be added first here. See crbug.com/961212.
1882     for (ui::Layer* layer_beneath : layers_beneath_)
1883       parent_layer->Add(layer_beneath);
1884     parent_layer->Add(layer());
1885 
1886     SetLayerBounds(size(), local_offset_data);
1887   } else {
1888     internal::ScopedChildrenLock lock(this);
1889     for (auto* child : GetChildrenInZOrder())
1890       child->MoveLayerToParent(parent_layer, local_offset_data);
1891   }
1892 }
1893 
UpdateLayerVisibility()1894 void View::UpdateLayerVisibility() {
1895   bool visible = visible_;
1896   for (const View* v = parent_; visible && v && !v->layer(); v = v->parent_)
1897     visible = v->GetVisible();
1898 
1899   UpdateChildLayerVisibility(visible);
1900 }
1901 
UpdateChildLayerVisibility(bool ancestor_visible)1902 void View::UpdateChildLayerVisibility(bool ancestor_visible) {
1903   const bool layers_visible = ancestor_visible && visible_;
1904   if (layer()) {
1905     layer()->SetVisible(layers_visible);
1906     for (ui::Layer* layer_beneath : layers_beneath_)
1907       layer_beneath->SetVisible(layers_visible);
1908   }
1909   {
1910     internal::ScopedChildrenLock lock(this);
1911     for (auto* child : children_)
1912       child->UpdateChildLayerVisibility(layers_visible);
1913   }
1914 }
1915 
DestroyLayerImpl(LayerChangeNotifyBehavior notify_parents)1916 void View::DestroyLayerImpl(LayerChangeNotifyBehavior notify_parents) {
1917   // Normally, adding layers beneath will trigger painting to a layer. It would
1918   // leave this view in an inconsistent state if its layer were destroyed while
1919   // layers beneath were still present. So, assume this doesn't happen.
1920   DCHECK(layers_beneath_.empty());
1921 
1922   if (!layer())
1923     return;
1924 
1925   // Copy children(), since the loop below will mutate its result.
1926   std::vector<ui::Layer*> children = layer()->children();
1927   ui::Layer* new_parent = layer()->parent();
1928   for (auto* child : children) {
1929     layer()->Remove(child);
1930     if (new_parent)
1931       new_parent->Add(child);
1932   }
1933 
1934   mask_layer_.reset();
1935 
1936   LayerOwner::DestroyLayer();
1937 
1938   if (new_parent)
1939     ReorderLayers();
1940 
1941   UpdateChildLayerBounds(CalculateOffsetToAncestorWithLayer(nullptr));
1942 
1943   SchedulePaint();
1944 
1945   // Notify the parent chain about the layer change.
1946   if (notify_parents == LayerChangeNotifyBehavior::NOTIFY)
1947     NotifyParentsOfLayerChange();
1948 
1949   Widget* widget = GetWidget();
1950   if (widget)
1951     widget->LayerTreeChanged();
1952 }
1953 
NotifyParentsOfLayerChange()1954 void View::NotifyParentsOfLayerChange() {
1955   // Notify the parent chain about the layer change.
1956   View* view_parent = parent();
1957   while (view_parent) {
1958     view_parent->OnChildLayerChanged(this);
1959     view_parent = view_parent->parent();
1960   }
1961 }
1962 
UpdateChildLayerBounds(const LayerOffsetData & offset_data)1963 void View::UpdateChildLayerBounds(const LayerOffsetData& offset_data) {
1964   if (layer()) {
1965     SetLayerBounds(size(), offset_data);
1966   } else {
1967     internal::ScopedChildrenLock lock(this);
1968     for (auto* child : children_) {
1969       child->UpdateChildLayerBounds(
1970           offset_data + child->GetMirroredPosition().OffsetFromOrigin());
1971     }
1972   }
1973 }
1974 
OnPaintLayer(const ui::PaintContext & context)1975 void View::OnPaintLayer(const ui::PaintContext& context) {
1976   PaintFromPaintRoot(context);
1977 }
1978 
OnLayerTransformed(const gfx::Transform & old_transform,ui::PropertyChangeReason reason)1979 void View::OnLayerTransformed(const gfx::Transform& old_transform,
1980                               ui::PropertyChangeReason reason) {
1981   NotifyAccessibilityEvent(ax::mojom::Event::kLocationChanged, false);
1982 }
1983 
OnDeviceScaleFactorChanged(float old_device_scale_factor,float new_device_scale_factor)1984 void View::OnDeviceScaleFactorChanged(float old_device_scale_factor,
1985                                       float new_device_scale_factor) {
1986   snap_layer_to_pixel_boundary_ =
1987       (new_device_scale_factor - std::floor(new_device_scale_factor)) != 0.0f;
1988 
1989   if (!layer())
1990     return;
1991 
1992   // There can be no subpixel offset if the layer has no parent.
1993   if (!parent() || !layer()->parent())
1994     return;
1995 
1996   if (layer()->parent() && layer()->GetCompositor() &&
1997       layer()->GetCompositor()->is_pixel_canvas()) {
1998     LayerOffsetData offset_data(
1999         parent()->CalculateOffsetToAncestorWithLayer(nullptr));
2000     offset_data += GetMirroredPosition().OffsetFromOrigin();
2001     SnapLayerToPixelBoundary(offset_data);
2002   } else {
2003     SnapLayerToPixelBoundary(LayerOffsetData());
2004   }
2005 }
2006 
CreateOrDestroyLayer()2007 void View::CreateOrDestroyLayer() {
2008   if (paint_to_layer_explicitly_set_ || paint_to_layer_for_transform_ ||
2009       !layers_beneath_.empty()) {
2010     // If we need to paint to a layer, make sure we have one.
2011     if (!layer())
2012       CreateLayer(ui::LAYER_TEXTURED);
2013   } else if (layer()) {
2014     // If we don't, make sure we delete our layer.
2015     DestroyLayerImpl(LayerChangeNotifyBehavior::NOTIFY);
2016   }
2017 }
2018 
ReorderLayers()2019 void View::ReorderLayers() {
2020   View* v = this;
2021   while (v && !v->layer())
2022     v = v->parent();
2023 
2024   Widget* widget = GetWidget();
2025   if (!v) {
2026     if (widget) {
2027       ui::Layer* layer = widget->GetLayer();
2028       if (layer)
2029         widget->GetRootView()->ReorderChildLayers(layer);
2030     }
2031   } else {
2032     v->ReorderChildLayers(v->layer());
2033   }
2034 
2035   if (widget) {
2036     // Reorder the widget's child NativeViews in case a child NativeView is
2037     // associated with a view (e.g. via a NativeViewHost). Always do the
2038     // reordering because the associated NativeView's layer (if it has one)
2039     // is parented to the widget's layer regardless of whether the host view has
2040     // an ancestor with a layer.
2041     widget->ReorderNativeViews();
2042   }
2043 }
2044 
ReorderChildLayers(ui::Layer * parent_layer)2045 void View::ReorderChildLayers(ui::Layer* parent_layer) {
2046   if (layer() && layer() != parent_layer) {
2047     DCHECK_EQ(parent_layer, layer()->parent());
2048     parent_layer->StackAtBottom(layer());
2049     for (ui::Layer* layer_beneath : layers_beneath_)
2050       parent_layer->StackAtBottom(layer_beneath);
2051   } else {
2052     // Iterate backwards through the children so that a child with a layer
2053     // which is further to the back is stacked above one which is further to
2054     // the front.
2055     View::Views children = GetChildrenInZOrder();
2056     DCHECK_EQ(children_.size(), children.size());
2057     for (auto* child : base::Reversed(children))
2058       child->ReorderChildLayers(parent_layer);
2059   }
2060 }
2061 
OnChildLayerChanged(View * child)2062 void View::OnChildLayerChanged(View* child) {}
2063 
2064 // Input -----------------------------------------------------------------------
2065 
GetDragInfo()2066 View::DragInfo* View::GetDragInfo() {
2067   return parent_ ? parent_->GetDragInfo() : nullptr;
2068 }
2069 
2070 // Focus -----------------------------------------------------------------------
2071 
OnFocus()2072 void View::OnFocus() {
2073   // TODO(beng): Investigate whether it's possible for us to move this to
2074   //             Focus().
2075   // By default, we clear the native focus. This ensures that no visible native
2076   // view as the focus and that we still receive keyboard inputs.
2077   FocusManager* focus_manager = GetFocusManager();
2078   if (focus_manager)
2079     focus_manager->ClearNativeFocus();
2080 
2081   // TODO(beng): Investigate whether it's possible for us to move this to
2082   //             Focus().
2083   // Notify assistive technologies of the focus change.
2084   AXVirtualView* focused_virtual_child =
2085       view_accessibility_ ? view_accessibility_->FocusedVirtualChild()
2086                           : nullptr;
2087   if (focused_virtual_child)
2088     focused_virtual_child->NotifyAccessibilityEvent(ax::mojom::Event::kFocus);
2089   else
2090     NotifyAccessibilityEvent(ax::mojom::Event::kFocus, true);
2091 }
2092 
OnBlur()2093 void View::OnBlur() {}
2094 
Focus()2095 void View::Focus() {
2096   OnFocus();
2097 
2098   // If this is the contents root of a |ScrollView|, focus should bring the
2099   // |ScrollView| to visible rather than resetting its content scroll position.
2100   ScrollView* scroll_view = ScrollView::GetScrollViewForContents(this);
2101   if (scroll_view)
2102     scroll_view->ScrollViewToVisible();
2103   else
2104     ScrollViewToVisible();
2105 
2106   for (ViewObserver& observer : observers_)
2107     observer.OnViewFocused(this);
2108 }
2109 
Blur()2110 void View::Blur() {
2111   ViewTracker tracker(this);
2112   OnBlur();
2113 
2114   if (tracker.view()) {
2115     for (ViewObserver& observer : observers_)
2116       observer.OnViewBlurred(this);
2117   }
2118 }
2119 
2120 // System events ---------------------------------------------------------------
2121 
OnThemeChanged()2122 void View::OnThemeChanged() {
2123 #if DCHECK_IS_ON()
2124   on_theme_changed_called_ = true;
2125 #endif
2126 }
2127 
2128 // Tooltips --------------------------------------------------------------------
2129 
TooltipTextChanged()2130 void View::TooltipTextChanged() {
2131   Widget* widget = GetWidget();
2132   // TooltipManager may be null if there is a problem creating it.
2133   if (widget && widget->GetTooltipManager())
2134     widget->GetTooltipManager()->TooltipTextChanged(this);
2135 }
2136 
2137 // Drag and drop ---------------------------------------------------------------
2138 
GetDragOperations(const gfx::Point & press_pt)2139 int View::GetDragOperations(const gfx::Point& press_pt) {
2140   return drag_controller_
2141              ? drag_controller_->GetDragOperationsForView(this, press_pt)
2142              : ui::DragDropTypes::DRAG_NONE;
2143 }
2144 
WriteDragData(const gfx::Point & press_pt,OSExchangeData * data)2145 void View::WriteDragData(const gfx::Point& press_pt, OSExchangeData* data) {
2146   DCHECK(drag_controller_);
2147   drag_controller_->WriteDragDataForView(this, press_pt, data);
2148 }
2149 
InDrag() const2150 bool View::InDrag() const {
2151   const Widget* widget = GetWidget();
2152   return widget ? widget->dragged_view() == this : false;
2153 }
2154 
GetHorizontalDragThreshold()2155 int View::GetHorizontalDragThreshold() {
2156   // TODO(jennyz): This value may need to be adjusted for different platforms
2157   // and for different display density.
2158   return kDefaultHorizontalDragThreshold;
2159 }
2160 
GetVerticalDragThreshold()2161 int View::GetVerticalDragThreshold() {
2162   // TODO(jennyz): This value may need to be adjusted for different platforms
2163   // and for different display density.
2164   return kDefaultVerticalDragThreshold;
2165 }
2166 
GetPaintScaleType() const2167 PaintInfo::ScaleType View::GetPaintScaleType() const {
2168   return PaintInfo::ScaleType::kScaleWithEdgeSnapping;
2169 }
2170 
HandlePropertyChangeEffects(PropertyEffects effects)2171 void View::HandlePropertyChangeEffects(PropertyEffects effects) {
2172   if (effects & kPropertyEffectsPreferredSizeChanged)
2173     PreferredSizeChanged();
2174   if (effects & kPropertyEffectsLayout)
2175     InvalidateLayout();
2176   if (effects & kPropertyEffectsPaint)
2177     SchedulePaint();
2178 }
2179 
AddPropertyChangedCallback(PropertyKey property,PropertyChangedCallback callback)2180 PropertyChangedSubscription View::AddPropertyChangedCallback(
2181     PropertyKey property,
2182     PropertyChangedCallback callback) {
2183   auto entry = property_changed_vectors_.find(property);
2184   if (entry == property_changed_vectors_.end()) {
2185     entry = property_changed_vectors_
2186                 .emplace(property, std::make_unique<PropertyChangedCallbacks>())
2187                 .first;
2188   }
2189   PropertyChangedCallbacks* property_changed_callbacks = entry->second.get();
2190 
2191   return property_changed_callbacks->Add(std::move(callback));
2192 }
2193 
OnPropertyChanged(PropertyKey property,PropertyEffects property_effects)2194 void View::OnPropertyChanged(PropertyKey property,
2195                              PropertyEffects property_effects) {
2196   if (property_effects != kPropertyEffectsNone)
2197     HandlePropertyChangeEffects(property_effects);
2198 
2199   auto entry = property_changed_vectors_.find(property);
2200   if (entry == property_changed_vectors_.end())
2201     return;
2202 
2203   PropertyChangedCallbacks* property_changed_callbacks = entry->second.get();
2204   property_changed_callbacks->Notify();
2205 }
2206 
2207 ////////////////////////////////////////////////////////////////////////////////
2208 // View, private:
2209 
2210 // DropInfo --------------------------------------------------------------------
2211 
Reset()2212 void View::DragInfo::Reset() {
2213   possible_drag = false;
2214   start_pt = gfx::Point();
2215 }
2216 
PossibleDrag(const gfx::Point & p)2217 void View::DragInfo::PossibleDrag(const gfx::Point& p) {
2218   possible_drag = true;
2219   start_pt = p;
2220 }
2221 
2222 // Painting --------------------------------------------------------------------
2223 
SchedulePaintInRectImpl(const gfx::Rect & rect)2224 void View::SchedulePaintInRectImpl(const gfx::Rect& rect) {
2225   OnDidSchedulePaint(rect);
2226   if (!visible_)
2227     return;
2228   if (layer()) {
2229     layer()->SchedulePaint(rect);
2230   } else if (parent_) {
2231     // Translate the requested paint rect to the parent's coordinate system
2232     // then pass this notification up to the parent.
2233     parent_->SchedulePaintInRectImpl(ConvertRectToParent(rect));
2234   }
2235 }
2236 
SchedulePaintBoundsChanged(bool size_changed)2237 void View::SchedulePaintBoundsChanged(bool size_changed) {
2238   if (!visible_)
2239     return;
2240 
2241   // If we have a layer and the View's size did not change, we do not need to
2242   // schedule any paints since the layer will be redrawn at its new location
2243   // during the next Draw() cycle in the compositor.
2244   if (!layer() || size_changed) {
2245     // Otherwise, if the size changes or we don't have a layer then we need to
2246     // use SchedulePaint to invalidate the area occupied by the View.
2247     SchedulePaint();
2248   } else {
2249     // The compositor doesn't Draw() until something on screen changes, so
2250     // if our position changes but nothing is being animated on screen, then
2251     // tell the compositor to redraw the scene. We know layer() exists due to
2252     // the above if clause.
2253     layer()->ScheduleDraw();
2254   }
2255 }
2256 
SchedulePaintOnParent()2257 void View::SchedulePaintOnParent() {
2258   if (parent_) {
2259     // Translate the requested paint rect to the parent's coordinate system
2260     // then pass this notification up to the parent.
2261     parent_->SchedulePaintInRect(ConvertRectToParent(GetLocalBounds()));
2262   }
2263 }
2264 
ShouldPaint() const2265 bool View::ShouldPaint() const {
2266   return visible_ && !size().IsEmpty();
2267 }
2268 
SetUpTransformRecorderForPainting(const gfx::Vector2d & offset_from_parent,ui::TransformRecorder * recorder) const2269 void View::SetUpTransformRecorderForPainting(
2270     const gfx::Vector2d& offset_from_parent,
2271     ui::TransformRecorder* recorder) const {
2272   // If the view is backed by a layer, it should paint with itself as the origin
2273   // rather than relative to its parent.
2274   if (layer())
2275     return;
2276 
2277   // Translate the graphics such that 0,0 corresponds to where this View is
2278   // located relative to its parent.
2279   gfx::Transform transform_from_parent;
2280   transform_from_parent.Translate(offset_from_parent.x(),
2281                                   offset_from_parent.y());
2282   recorder->Transform(transform_from_parent);
2283 }
2284 
RecursivePaintHelper(void (View::* func)(const PaintInfo &),const PaintInfo & info)2285 void View::RecursivePaintHelper(void (View::*func)(const PaintInfo&),
2286                                 const PaintInfo& info) {
2287   View::Views children = GetChildrenInZOrder();
2288   DCHECK_EQ(children_.size(), children.size());
2289   for (auto* child : children) {
2290     if (!child->layer())
2291       (child->*func)(info);
2292   }
2293 }
2294 
PaintFromPaintRoot(const ui::PaintContext & parent_context)2295 void View::PaintFromPaintRoot(const ui::PaintContext& parent_context) {
2296   PaintInfo paint_info = PaintInfo::CreateRootPaintInfo(
2297       parent_context, layer() ? layer()->size() : size());
2298   Paint(paint_info);
2299   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
2300           switches::kDrawViewBoundsRects))
2301     PaintDebugRects(paint_info);
2302 }
2303 
PaintDebugRects(const PaintInfo & parent_paint_info)2304 void View::PaintDebugRects(const PaintInfo& parent_paint_info) {
2305   if (!ShouldPaint())
2306     return;
2307 
2308   const gfx::Rect& parent_bounds = (layer() || !parent())
2309                                        ? GetMirroredBounds()
2310                                        : parent()->GetMirroredBounds();
2311   PaintInfo paint_info = PaintInfo::CreateChildPaintInfo(
2312       parent_paint_info, GetMirroredBounds(), parent_bounds.size(),
2313       GetPaintScaleType(), !!layer());
2314 
2315   const ui::PaintContext& context = paint_info.context();
2316 
2317   ui::TransformRecorder transform_recorder(context);
2318   SetUpTransformRecorderForPainting(paint_info.offset_from_parent(),
2319                                     &transform_recorder);
2320 
2321   RecursivePaintHelper(&View::PaintDebugRects, paint_info);
2322 
2323   // Draw outline rects for debugging.
2324   ui::PaintRecorder recorder(context, paint_info.paint_recording_size(),
2325                              paint_info.paint_recording_scale_x(),
2326                              paint_info.paint_recording_scale_y(),
2327                              &paint_cache_);
2328   gfx::Canvas* canvas = recorder.canvas();
2329   const float scale = canvas->UndoDeviceScaleFactor();
2330   gfx::RectF outline_rect(ScaleToEnclosedRect(GetLocalBounds(), scale));
2331   gfx::RectF content_outline_rect(
2332       ScaleToEnclosedRect(GetContentsBounds(), scale));
2333   if (content_outline_rect != outline_rect) {
2334     content_outline_rect.Inset(0.5f, 0.5f);
2335     const SkColor content_color = SkColorSetARGB(0x30, 0, 0, 0xff);
2336     canvas->DrawRect(content_outline_rect, content_color);
2337   }
2338   outline_rect.Inset(0.5f, 0.5f);
2339   const SkColor color = SkColorSetARGB(0x30, 0xff, 0, 0);
2340   canvas->DrawRect(outline_rect, color);
2341 }
2342 
2343 // Tree operations -------------------------------------------------------------
2344 
AddChildViewAtImpl(View * view,int index)2345 void View::AddChildViewAtImpl(View* view, int index) {
2346   CHECK_NE(view, this) << "You cannot add a view as its own child";
2347   DCHECK_GE(index, 0);
2348   DCHECK_LE(size_t{index}, children_.size());
2349 
2350   // TODO(https://crbug.com/942298): Should just DCHECK(!view->parent_);.
2351   View* parent = view->parent_;
2352   if (parent == this) {
2353     ReorderChildView(view, index);
2354     return;
2355   }
2356 
2357   // Remove |view| from its parent, if any.
2358   ui::NativeTheme* old_theme = nullptr;
2359   Widget* old_widget = nullptr;
2360   if (parent) {
2361     old_theme = view->GetNativeTheme();
2362     old_widget = view->GetWidget();
2363     parent->DoRemoveChildView(view, true, false, this);
2364   }
2365 
2366   view->parent_ = this;
2367 #if DCHECK_IS_ON()
2368   DCHECK(!iterating_);
2369 #endif
2370   const auto pos = children_.insert(std::next(children_.cbegin(), index), view);
2371 
2372   view->RemoveFromFocusList();
2373   SetFocusSiblings(view, pos);
2374 
2375   // Ensure the layer tree matches the view tree before calling to any client
2376   // code. This way if client code further modifies the view tree we are in a
2377   // sane state.
2378   const bool did_reparent_any_layers = view->UpdateParentLayers();
2379   Widget* widget = GetWidget();
2380   if (did_reparent_any_layers && widget)
2381     widget->LayerTreeChanged();
2382 
2383   ReorderLayers();
2384 
2385   // Make sure the visibility of the child layers are correct.
2386   // If any of the parent View is hidden, then the layers of the subtree
2387   // rooted at |this| should be hidden. Otherwise, all the child layers should
2388   // inherit the visibility of the owner View.
2389   view->UpdateLayerVisibility();
2390 
2391   if (widget) {
2392     const ui::NativeTheme* new_theme = view->GetNativeTheme();
2393     if (new_theme != old_theme)
2394       view->PropagateThemeChanged();
2395   }
2396 
2397   // Need to notify the layout manager because one of the callbacks below might
2398   // want to know the view's new preferred size, minimum size, etc.
2399   if (layout_manager_)
2400     layout_manager_->ViewAdded(this, view);
2401 
2402   ViewHierarchyChangedDetails details(true, this, view, parent);
2403 
2404   for (View* v = this; v; v = v->parent_)
2405     v->ViewHierarchyChangedImpl(details);
2406 
2407   view->PropagateAddNotifications(details, widget && widget != old_widget);
2408 
2409   UpdateTooltip();
2410 
2411   if (widget) {
2412     RegisterChildrenForVisibleBoundsNotification(view);
2413 
2414     if (view->GetVisible())
2415       view->SchedulePaint();
2416   }
2417 
2418   for (ViewObserver& observer : observers_)
2419     observer.OnChildViewAdded(this, view);
2420 }
2421 
DoRemoveChildView(View * view,bool update_tool_tip,bool delete_removed_view,View * new_parent)2422 void View::DoRemoveChildView(View* view,
2423                              bool update_tool_tip,
2424                              bool delete_removed_view,
2425                              View* new_parent) {
2426   DCHECK(view);
2427 
2428   const auto i = std::find(children_.cbegin(), children_.cend(), view);
2429   if (i == children_.cend())
2430     return;
2431 
2432   std::unique_ptr<View> view_to_be_deleted;
2433   view->RemoveFromFocusList();
2434 
2435   Widget* widget = GetWidget();
2436   bool is_removed_from_widget = false;
2437   if (widget) {
2438     UnregisterChildrenForVisibleBoundsNotification(view);
2439     if (view->GetVisible())
2440       view->SchedulePaint();
2441 
2442     is_removed_from_widget = !new_parent || new_parent->GetWidget() != widget;
2443     if (is_removed_from_widget)
2444       widget->NotifyWillRemoveView(view);
2445   }
2446 
2447   // Make sure the layers belonging to the subtree rooted at |view| get
2448   // removed.
2449   view->OrphanLayers();
2450   if (widget)
2451     widget->LayerTreeChanged();
2452 
2453   // Need to notify the layout manager because one of the callbacks below might
2454   // want to know the view's new preferred size, minimum size, etc.
2455   if (layout_manager_)
2456     layout_manager_->ViewRemoved(this, view);
2457 
2458   view->PropagateRemoveNotifications(this, new_parent, is_removed_from_widget);
2459   view->parent_ = nullptr;
2460 
2461   if (delete_removed_view && !view->owned_by_client_)
2462     view_to_be_deleted.reset(view);
2463 
2464 #if DCHECK_IS_ON()
2465   DCHECK(!iterating_);
2466 #endif
2467   children_.erase(i);
2468 
2469   if (update_tool_tip)
2470     UpdateTooltip();
2471 
2472   for (ViewObserver& observer : observers_)
2473     observer.OnChildViewRemoved(this, view);
2474 }
2475 
PropagateRemoveNotifications(View * old_parent,View * new_parent,bool is_removed_from_widget)2476 void View::PropagateRemoveNotifications(View* old_parent,
2477                                         View* new_parent,
2478                                         bool is_removed_from_widget) {
2479   {
2480     internal::ScopedChildrenLock lock(this);
2481     for (auto* child : children_) {
2482       child->PropagateRemoveNotifications(old_parent, new_parent,
2483                                           is_removed_from_widget);
2484     }
2485   }
2486 
2487   // When a view is removed from a hierarchy, UnregisterAccelerators() is called
2488   // for the removed view and all descendant views in post-order.
2489   UnregisterAccelerators(true);
2490 
2491   ViewHierarchyChangedDetails details(false, old_parent, this, new_parent);
2492   for (View* v = this; v; v = v->parent_)
2493     v->ViewHierarchyChangedImpl(details);
2494 
2495   if (is_removed_from_widget) {
2496     RemovedFromWidget();
2497     for (ViewObserver& observer : observers_)
2498       observer.OnViewRemovedFromWidget(this);
2499   }
2500 }
2501 
PropagateAddNotifications(const ViewHierarchyChangedDetails & details,bool is_added_to_widget)2502 void View::PropagateAddNotifications(const ViewHierarchyChangedDetails& details,
2503                                      bool is_added_to_widget) {
2504   // When a view is added to a Widget hierarchy, RegisterPendingAccelerators()
2505   // will be called for the added view and all its descendants in pre-order.
2506   // This means that descendant views will register their accelerators after
2507   // their parents. This allows children to override accelerators registered by
2508   // their parents as accelerators registered later take priority over those
2509   // registered earlier.
2510   if (GetFocusManager())
2511     RegisterPendingAccelerators();
2512 
2513   {
2514     internal::ScopedChildrenLock lock(this);
2515     for (auto* child : children_)
2516       child->PropagateAddNotifications(details, is_added_to_widget);
2517   }
2518 
2519   ViewHierarchyChangedImpl(details);
2520   if (is_added_to_widget) {
2521     AddedToWidget();
2522     for (ViewObserver& observer : observers_)
2523       observer.OnViewAddedToWidget(this);
2524   }
2525 }
2526 
PropagateNativeViewHierarchyChanged()2527 void View::PropagateNativeViewHierarchyChanged() {
2528   {
2529     internal::ScopedChildrenLock lock(this);
2530     for (auto* child : children_)
2531       child->PropagateNativeViewHierarchyChanged();
2532   }
2533   NativeViewHierarchyChanged();
2534 }
2535 
ViewHierarchyChangedImpl(const ViewHierarchyChangedDetails & details)2536 void View::ViewHierarchyChangedImpl(
2537     const ViewHierarchyChangedDetails& details) {
2538   ViewHierarchyChanged(details);
2539 
2540   for (ViewObserver& observer : observers_)
2541     observer.OnViewHierarchyChanged(this, details);
2542 
2543   details.parent->needs_layout_ = true;
2544 }
2545 
2546 // Size and disposition --------------------------------------------------------
2547 
PropagateVisibilityNotifications(View * start,bool is_visible)2548 void View::PropagateVisibilityNotifications(View* start, bool is_visible) {
2549   {
2550     internal::ScopedChildrenLock lock(this);
2551     for (auto* child : children_)
2552       child->PropagateVisibilityNotifications(start, is_visible);
2553   }
2554   VisibilityChangedImpl(start, is_visible);
2555 }
2556 
VisibilityChangedImpl(View * starting_from,bool is_visible)2557 void View::VisibilityChangedImpl(View* starting_from, bool is_visible) {
2558   VisibilityChanged(starting_from, is_visible);
2559   for (ViewObserver& observer : observers_)
2560     observer.OnViewVisibilityChanged(this, starting_from);
2561 }
2562 
SnapLayerToPixelBoundary(const LayerOffsetData & offset_data)2563 void View::SnapLayerToPixelBoundary(const LayerOffsetData& offset_data) {
2564   if (!layer())
2565     return;
2566 
2567 #if DCHECK_IS_ON()
2568   // We rely on our layers beneath being parented correctly at this point.
2569   for (ui::Layer* layer_beneath : layers_beneath_)
2570     DCHECK_EQ(layer()->parent(), layer_beneath->parent());
2571 #endif  // DCHECK_IS_ON()
2572 
2573   if (layer()->GetCompositor() && layer()->GetCompositor()->is_pixel_canvas()) {
2574     gfx::Vector2dF offset = snap_layer_to_pixel_boundary_ && layer()->parent()
2575                                 ? offset_data.GetSubpixelOffset()
2576                                 : gfx::Vector2dF();
2577     layer()->SetSubpixelPositionOffset(offset);
2578     for (ui::Layer* layer_beneath : layers_beneath_)
2579       layer_beneath->SetSubpixelPositionOffset(offset);
2580   }
2581 }
2582 
2583 // static
RegisterChildrenForVisibleBoundsNotification(View * view)2584 void View::RegisterChildrenForVisibleBoundsNotification(View* view) {
2585   if (view->GetNeedsNotificationWhenVisibleBoundsChange())
2586     view->RegisterForVisibleBoundsNotification();
2587   for (View* child : view->children_)
2588     RegisterChildrenForVisibleBoundsNotification(child);
2589 }
2590 
2591 // static
UnregisterChildrenForVisibleBoundsNotification(View * view)2592 void View::UnregisterChildrenForVisibleBoundsNotification(View* view) {
2593   if (view->GetNeedsNotificationWhenVisibleBoundsChange())
2594     view->UnregisterForVisibleBoundsNotification();
2595   for (View* child : view->children_)
2596     UnregisterChildrenForVisibleBoundsNotification(child);
2597 }
2598 
RegisterForVisibleBoundsNotification()2599 void View::RegisterForVisibleBoundsNotification() {
2600   if (registered_for_visible_bounds_notification_)
2601     return;
2602 
2603   registered_for_visible_bounds_notification_ = true;
2604   for (View* ancestor = parent_; ancestor; ancestor = ancestor->parent_)
2605     ancestor->AddDescendantToNotify(this);
2606 }
2607 
UnregisterForVisibleBoundsNotification()2608 void View::UnregisterForVisibleBoundsNotification() {
2609   if (!registered_for_visible_bounds_notification_)
2610     return;
2611 
2612   registered_for_visible_bounds_notification_ = false;
2613   for (View* ancestor = parent_; ancestor; ancestor = ancestor->parent_)
2614     ancestor->RemoveDescendantToNotify(this);
2615 }
2616 
AddDescendantToNotify(View * view)2617 void View::AddDescendantToNotify(View* view) {
2618   DCHECK(view);
2619   if (!descendants_to_notify_)
2620     descendants_to_notify_ = std::make_unique<Views>();
2621   descendants_to_notify_->push_back(view);
2622 }
2623 
RemoveDescendantToNotify(View * view)2624 void View::RemoveDescendantToNotify(View* view) {
2625   DCHECK(view && descendants_to_notify_);
2626   auto i(std::find(descendants_to_notify_->begin(),
2627                    descendants_to_notify_->end(), view));
2628   DCHECK(i != descendants_to_notify_->end());
2629   descendants_to_notify_->erase(i);
2630   if (descendants_to_notify_->empty())
2631     descendants_to_notify_.reset();
2632 }
2633 
SetLayoutManagerImpl(std::unique_ptr<LayoutManager> layout_manager)2634 void View::SetLayoutManagerImpl(std::unique_ptr<LayoutManager> layout_manager) {
2635   // Some code keeps a bare pointer to the layout manager for calling
2636   // derived-class-specific-functions. It's an easy mistake to create a new
2637   // unique_ptr and re-set the layout manager with a new unique_ptr, which
2638   // will cause a crash. Re-setting to nullptr is OK.
2639   CHECK(!layout_manager || layout_manager_ != layout_manager);
2640 
2641   layout_manager_ = std::move(layout_manager);
2642   if (layout_manager_)
2643     layout_manager_->Installed(this);
2644 }
2645 
SetLayerBounds(const gfx::Size & size,const LayerOffsetData & offset_data)2646 void View::SetLayerBounds(const gfx::Size& size,
2647                           const LayerOffsetData& offset_data) {
2648   const gfx::Rect bounds = gfx::Rect(size) + offset_data.offset();
2649   const bool bounds_changed = (bounds != layer()->GetTargetBounds());
2650   layer()->SetBounds(bounds);
2651   for (ui::Layer* layer_beneath : layers_beneath_) {
2652     layer_beneath->SetBounds(gfx::Rect(layer_beneath->size()) +
2653                              bounds.OffsetFromOrigin());
2654   }
2655   SnapLayerToPixelBoundary(offset_data);
2656   if (bounds_changed) {
2657     for (ViewObserver& observer : observers_)
2658       observer.OnLayerTargetBoundsChanged(this);
2659   }
2660 }
2661 
2662 // Transformations -------------------------------------------------------------
2663 
GetTransformRelativeTo(const View * ancestor,gfx::Transform * transform) const2664 bool View::GetTransformRelativeTo(const View* ancestor,
2665                                   gfx::Transform* transform) const {
2666   const View* p = this;
2667 
2668   while (p && p != ancestor) {
2669     transform->ConcatTransform(p->GetTransform());
2670     gfx::Transform translation;
2671     translation.Translate(static_cast<float>(p->GetMirroredX()),
2672                           static_cast<float>(p->y()));
2673     transform->ConcatTransform(translation);
2674 
2675     p = p->parent_;
2676   }
2677 
2678   return p == ancestor;
2679 }
2680 
2681 // Coordinate conversion -------------------------------------------------------
2682 
ConvertPointForAncestor(const View * ancestor,gfx::Point * point) const2683 bool View::ConvertPointForAncestor(const View* ancestor,
2684                                    gfx::Point* point) const {
2685   gfx::Transform trans;
2686   // TODO(sad): Have some way of caching the transformation results.
2687   bool result = GetTransformRelativeTo(ancestor, &trans);
2688   auto p = gfx::Point3F(gfx::PointF(*point));
2689   trans.TransformPoint(&p);
2690   *point = gfx::ToFlooredPoint(p.AsPointF());
2691   return result;
2692 }
2693 
ConvertPointFromAncestor(const View * ancestor,gfx::Point * point) const2694 bool View::ConvertPointFromAncestor(const View* ancestor,
2695                                     gfx::Point* point) const {
2696   gfx::Transform trans;
2697   bool result = GetTransformRelativeTo(ancestor, &trans);
2698   auto p = gfx::Point3F(gfx::PointF(*point));
2699   trans.TransformPointReverse(&p);
2700   *point = gfx::ToFlooredPoint(p.AsPointF());
2701   return result;
2702 }
2703 
ConvertRectForAncestor(const View * ancestor,gfx::RectF * rect) const2704 bool View::ConvertRectForAncestor(const View* ancestor,
2705                                   gfx::RectF* rect) const {
2706   gfx::Transform trans;
2707   // TODO(sad): Have some way of caching the transformation results.
2708   bool result = GetTransformRelativeTo(ancestor, &trans);
2709   trans.TransformRect(rect);
2710   return result;
2711 }
2712 
ConvertRectFromAncestor(const View * ancestor,gfx::RectF * rect) const2713 bool View::ConvertRectFromAncestor(const View* ancestor,
2714                                    gfx::RectF* rect) const {
2715   gfx::Transform trans;
2716   bool result = GetTransformRelativeTo(ancestor, &trans);
2717   trans.TransformRectReverse(rect);
2718   return result;
2719 }
2720 
2721 // Accelerated painting --------------------------------------------------------
2722 
CreateLayer(ui::LayerType layer_type)2723 void View::CreateLayer(ui::LayerType layer_type) {
2724   // A new layer is being created for the view. So all the layers of the
2725   // sub-tree can inherit the visibility of the corresponding view.
2726   {
2727     internal::ScopedChildrenLock lock(this);
2728     for (auto* child : children_)
2729       child->UpdateChildLayerVisibility(true);
2730   }
2731 
2732   SetLayer(std::make_unique<ui::Layer>(layer_type));
2733   layer()->set_delegate(this);
2734   layer()->SetName(GetClassName());
2735 
2736   UpdateParentLayers();
2737   UpdateLayerVisibility();
2738 
2739   // The new layer needs to be ordered in the layer tree according
2740   // to the view tree. Children of this layer were added in order
2741   // in UpdateParentLayers().
2742   if (parent())
2743     parent()->ReorderLayers();
2744 
2745   Widget* widget = GetWidget();
2746   if (widget)
2747     widget->LayerTreeChanged();
2748 
2749   // Before having its own Layer, this View may have painted in to a Layer owned
2750   // by an ancestor View. Scheduling a paint on the parent View will erase this
2751   // View's painting effects on the ancestor View's Layer.
2752   // (See crbug.com/551492)
2753   SchedulePaintOnParent();
2754 }
2755 
UpdateParentLayers()2756 bool View::UpdateParentLayers() {
2757   // Attach all top-level un-parented layers.
2758   if (layer()) {
2759     if (!layer()->parent()) {
2760       UpdateParentLayer();
2761       return true;
2762     }
2763     // The layers of any child views are already in place, so we can stop
2764     // iterating here.
2765     return false;
2766   }
2767   bool result = false;
2768   internal::ScopedChildrenLock lock(this);
2769   for (auto* child : children_) {
2770     if (child->UpdateParentLayers())
2771       result = true;
2772   }
2773   return result;
2774 }
2775 
OrphanLayers()2776 void View::OrphanLayers() {
2777   if (layer()) {
2778     ui::Layer* parent = layer()->parent();
2779     if (parent) {
2780       parent->Remove(layer());
2781       for (ui::Layer* layer_beneath : layers_beneath_)
2782         parent->Remove(layer_beneath);
2783     }
2784 
2785     // The layer belonging to this View has already been orphaned. It is not
2786     // necessary to orphan the child layers.
2787     return;
2788   }
2789   internal::ScopedChildrenLock lock(this);
2790   for (auto* child : children_)
2791     child->OrphanLayers();
2792 }
2793 
ReparentLayer(ui::Layer * parent_layer)2794 void View::ReparentLayer(ui::Layer* parent_layer) {
2795   DCHECK_NE(layer(), parent_layer);
2796   if (parent_layer) {
2797     // Adding the main layer can trigger a call to |SnapLayerToPixelBoundary()|.
2798     // That method assumes layers beneath have already been added. Therefore
2799     // layers beneath must be added first here. See crbug.com/961212.
2800     for (ui::Layer* layer_beneath : layers_beneath_)
2801       parent_layer->Add(layer_beneath);
2802     parent_layer->Add(layer());
2803   }
2804   // Update the layer bounds; this needs to be called after this layer is added
2805   // to the new parent layer since snapping to pixel boundary will be affected
2806   // by the layer hierarchy.
2807   LayerOffsetData offset =
2808       parent_ ? parent_->CalculateOffsetToAncestorWithLayer(nullptr)
2809               : LayerOffsetData(layer()->device_scale_factor());
2810   SetLayerBounds(size(), offset + GetMirroredBounds().OffsetFromOrigin());
2811   layer()->SchedulePaint(GetLocalBounds());
2812   MoveLayerToParent(layer(), LayerOffsetData(layer()->device_scale_factor()));
2813 }
2814 
CreateMaskLayer()2815 void View::CreateMaskLayer() {
2816   DCHECK(layer());
2817   mask_layer_ = std::make_unique<views::ViewMaskLayer>(clip_path_, this);
2818   layer()->SetMaskLayer(mask_layer_->layer());
2819 }
2820 
2821 // Input -----------------------------------------------------------------------
2822 
ProcessMousePressed(const ui::MouseEvent & event)2823 bool View::ProcessMousePressed(const ui::MouseEvent& event) {
2824   int drag_operations = (enabled_ && event.IsOnlyLeftMouseButton() &&
2825                          HitTestPoint(event.location()))
2826                             ? GetDragOperations(event.location())
2827                             : 0;
2828   ContextMenuController* context_menu_controller =
2829       event.IsRightMouseButton() ? context_menu_controller_ : nullptr;
2830   View::DragInfo* drag_info = GetDragInfo();
2831 
2832   const bool was_enabled = GetEnabled();
2833   const bool result = OnMousePressed(event);
2834 
2835   if (!was_enabled)
2836     return result;
2837 
2838   if (event.IsOnlyRightMouseButton() && context_menu_controller &&
2839       kContextMenuOnMousePress) {
2840     // Assume that if there is a context menu controller we won't be deleted
2841     // from mouse pressed.
2842     if (HitTestPoint(event.location())) {
2843       gfx::Point location(event.location());
2844       ConvertPointToScreen(this, &location);
2845       ShowContextMenu(location, ui::MENU_SOURCE_MOUSE);
2846       return true;
2847     }
2848   }
2849 
2850   // WARNING: we may have been deleted, don't use any View variables.
2851   if (drag_operations != ui::DragDropTypes::DRAG_NONE) {
2852     drag_info->PossibleDrag(event.location());
2853     return true;
2854   }
2855   return !!context_menu_controller || result;
2856 }
2857 
ProcessMouseDragged(ui::MouseEvent * event)2858 void View::ProcessMouseDragged(ui::MouseEvent* event) {
2859   // Copy the field, that way if we're deleted after drag and drop no harm is
2860   // done.
2861   ContextMenuController* context_menu_controller = context_menu_controller_;
2862   const bool possible_drag = GetDragInfo()->possible_drag;
2863   if (possible_drag &&
2864       ExceededDragThreshold(GetDragInfo()->start_pt - event->location()) &&
2865       (!drag_controller_ ||
2866        drag_controller_->CanStartDragForView(this, GetDragInfo()->start_pt,
2867                                              event->location()))) {
2868     if (DoDrag(*event, GetDragInfo()->start_pt,
2869                ui::mojom::DragEventSource::kMouse)) {
2870       event->StopPropagation();
2871       return;
2872     }
2873   } else {
2874     if (OnMouseDragged(*event)) {
2875       event->SetHandled();
2876       return;
2877     }
2878     // Fall through to return value based on context menu controller.
2879   }
2880   // WARNING: we may have been deleted.
2881   if ((context_menu_controller != nullptr) || possible_drag)
2882     event->SetHandled();
2883 }
2884 
ProcessMouseReleased(const ui::MouseEvent & event)2885 void View::ProcessMouseReleased(const ui::MouseEvent& event) {
2886   if (!kContextMenuOnMousePress && context_menu_controller_ &&
2887       event.IsOnlyRightMouseButton()) {
2888     // Assume that if there is a context menu controller we won't be deleted
2889     // from mouse released.
2890     gfx::Point location(event.location());
2891     OnMouseReleased(event);
2892     if (HitTestPoint(location)) {
2893       ConvertPointToScreen(this, &location);
2894       ShowContextMenu(location, ui::MENU_SOURCE_MOUSE);
2895     }
2896   } else {
2897     OnMouseReleased(event);
2898   }
2899   // WARNING: we may have been deleted.
2900 }
2901 
2902 // Accelerators ----------------------------------------------------------------
2903 
RegisterPendingAccelerators()2904 void View::RegisterPendingAccelerators() {
2905   if (!accelerators_ ||
2906       registered_accelerator_count_ == accelerators_->size()) {
2907     // No accelerators are waiting for registration.
2908     return;
2909   }
2910 
2911   if (!GetWidget()) {
2912     // The view is not yet attached to a widget, defer registration until then.
2913     return;
2914   }
2915 
2916   accelerator_focus_manager_ = GetFocusManager();
2917   if (!accelerator_focus_manager_) {
2918     // Some crash reports seem to show that we may get cases where we have no
2919     // focus manager (see bug #1291225).  This should never be the case, just
2920     // making sure we don't crash.
2921     NOTREACHED();
2922     return;
2923   }
2924   for (std::vector<ui::Accelerator>::const_iterator i(
2925            accelerators_->begin() + registered_accelerator_count_);
2926        i != accelerators_->end(); ++i) {
2927     accelerator_focus_manager_->RegisterAccelerator(
2928         *i, ui::AcceleratorManager::kNormalPriority, this);
2929   }
2930   registered_accelerator_count_ = accelerators_->size();
2931 }
2932 
UnregisterAccelerators(bool leave_data_intact)2933 void View::UnregisterAccelerators(bool leave_data_intact) {
2934   if (!accelerators_)
2935     return;
2936 
2937   if (GetWidget()) {
2938     if (accelerator_focus_manager_) {
2939       accelerator_focus_manager_->UnregisterAccelerators(this);
2940       accelerator_focus_manager_ = nullptr;
2941     }
2942     if (!leave_data_intact) {
2943       accelerators_->clear();
2944       accelerators_.reset();
2945     }
2946     registered_accelerator_count_ = 0;
2947   }
2948 }
2949 
2950 // Focus -----------------------------------------------------------------------
2951 
SetFocusSiblings(View * view,Views::const_iterator pos)2952 void View::SetFocusSiblings(View* view, Views::const_iterator pos) {
2953   // |view| was just inserted at |pos|, so all of these conditions must hold.
2954   DCHECK(!children_.empty());
2955   DCHECK(pos != children_.cend());
2956   DCHECK_EQ(view, *pos);
2957 
2958   if (children_.size() > 1) {
2959     if (std::next(pos) == children_.cend()) {
2960       // |view| was inserted at the end, but the end of the child list may not
2961       // be the last focusable element. Try to hook in after the last focusable
2962       // child.
2963       View* const old_last =
2964           *std::find_if(children_.cbegin(), pos,
2965                         [](View* v) { return !v->next_focusable_view_; });
2966       DCHECK_NE(old_last, view);
2967       view->InsertAfterInFocusList(old_last);
2968     } else {
2969       // |view| was inserted somewhere other than the end.  Hook in before the
2970       // subsequent child.
2971       view->InsertBeforeInFocusList(*std::next(pos));
2972     }
2973   }
2974 }
2975 
AdvanceFocusIfNecessary()2976 void View::AdvanceFocusIfNecessary() {
2977   // Focus should only be advanced if this is the focused view and has become
2978   // unfocusable. If the view is still focusable or is not focused, we can
2979   // return early avoiding further unnecessary checks. Focusability check is
2980   // performed first as it tends to be faster.
2981   if (IsAccessibilityFocusable() || !HasFocus())
2982     return;
2983 
2984   FocusManager* focus_manager = GetFocusManager();
2985   if (focus_manager)
2986     focus_manager->AdvanceFocusIfNecessary();
2987 }
2988 
2989 // System events ---------------------------------------------------------------
2990 
PropagateThemeChanged()2991 void View::PropagateThemeChanged() {
2992   {
2993     internal::ScopedChildrenLock lock(this);
2994     for (auto* child : base::Reversed(children_))
2995       child->PropagateThemeChanged();
2996   }
2997   OnThemeChanged();
2998 #if DCHECK_IS_ON()
2999   DCHECK(on_theme_changed_called_)
3000       << "views::View::OnThemeChanged() has not been called. This means that "
3001          "some class in the hierarchy is not calling their direct parent's "
3002          "OnThemeChanged(). Please fix this by adding the missing call. Do not "
3003          "call views::View::OnThemeChanged() directly unless views::View is "
3004          "the direct parent class.";
3005   on_theme_changed_called_ = false;
3006 #endif
3007   for (ViewObserver& observer : observers_)
3008     observer.OnViewThemeChanged(this);
3009 }
3010 
PropagateDeviceScaleFactorChanged(float old_device_scale_factor,float new_device_scale_factor)3011 void View::PropagateDeviceScaleFactorChanged(float old_device_scale_factor,
3012                                              float new_device_scale_factor) {
3013   {
3014     internal::ScopedChildrenLock lock(this);
3015     for (auto* child : base::Reversed(children_)) {
3016       child->PropagateDeviceScaleFactorChanged(old_device_scale_factor,
3017                                                new_device_scale_factor);
3018     }
3019   }
3020 
3021   // If the view is drawing to the layer, OnDeviceScaleFactorChanged() is called
3022   // through LayerDelegate callback.
3023   if (!layer())
3024     OnDeviceScaleFactorChanged(old_device_scale_factor,
3025                                new_device_scale_factor);
3026 }
3027 
3028 // Tooltips --------------------------------------------------------------------
3029 
UpdateTooltip()3030 void View::UpdateTooltip() {
3031   Widget* widget = GetWidget();
3032   // TODO(beng): The TooltipManager nullptr check can be removed when we
3033   //             consolidate Init() methods and make views_unittests Init() all
3034   //             Widgets that it uses.
3035   if (widget && widget->GetTooltipManager())
3036     widget->GetTooltipManager()->UpdateTooltip();
3037 }
3038 
3039 // Drag and drop ---------------------------------------------------------------
3040 
DoDrag(const ui::LocatedEvent & event,const gfx::Point & press_pt,ui::mojom::DragEventSource source)3041 bool View::DoDrag(const ui::LocatedEvent& event,
3042                   const gfx::Point& press_pt,
3043                   ui::mojom::DragEventSource source) {
3044   int drag_operations = GetDragOperations(press_pt);
3045   if (drag_operations == ui::DragDropTypes::DRAG_NONE)
3046     return false;
3047 
3048   Widget* widget = GetWidget();
3049   // We should only start a drag from an event, implying we have a widget.
3050   DCHECK(widget);
3051 
3052   // Don't attempt to start a drag while in the process of dragging. This is
3053   // especially important on X where we can get multiple mouse move events when
3054   // we start the drag.
3055   if (widget->dragged_view())
3056     return false;
3057 
3058   std::unique_ptr<OSExchangeData> data(std::make_unique<OSExchangeData>());
3059   WriteDragData(press_pt, data.get());
3060 
3061   // Message the RootView to do the drag and drop. That way if we're removed
3062   // the RootView can detect it and avoid calling us back.
3063   gfx::Point widget_location(event.location());
3064   ConvertPointToWidget(this, &widget_location);
3065   widget->RunShellDrag(this, std::move(data), widget_location, drag_operations,
3066                        source);
3067   // WARNING: we may have been deleted.
3068   return true;
3069 }
3070 
3071 DEFINE_ENUM_CONVERTERS(View::FocusBehavior,
3072                        {View::FocusBehavior::ACCESSIBLE_ONLY,
3073                         base::ASCIIToUTF16("ACCESSIBLE_ONLY")},
3074                        {View::FocusBehavior::ALWAYS,
3075                         base::ASCIIToUTF16("ALWAYS")},
3076                        {View::FocusBehavior::NEVER,
3077                         base::ASCIIToUTF16("NEVER")})
3078 
3079 // This block requires the existence of METADATA_HEADER(View) in the class
3080 // declaration for View.
3081 BEGIN_METADATA_BASE(View)
3082 ADD_READONLY_PROPERTY_METADATA(const char*, ClassName)
3083 ADD_PROPERTY_METADATA(bool, Enabled)
3084 ADD_PROPERTY_METADATA(View::FocusBehavior, FocusBehavior)
3085 ADD_PROPERTY_METADATA(bool, FlipCanvasOnPaintForRTLUI)
3086 ADD_PROPERTY_METADATA(int, Group)
3087 ADD_PROPERTY_METADATA(int, ID)
3088 ADD_READONLY_PROPERTY_METADATA(gfx::Size, MaximumSize)
3089 ADD_READONLY_PROPERTY_METADATA(gfx::Size, MinimumSize)
3090 ADD_PROPERTY_METADATA(bool, Mirrored)
3091 ADD_PROPERTY_METADATA(bool, NotifyEnterExitOnChild)
3092 ADD_PROPERTY_METADATA(bool, Visible)
3093 ADD_PROPERTY_METADATA(bool, CanProcessEventsWithinSubtree)
3094 END_METADATA
3095 
3096 }  // namespace views
3097