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