| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #define _USE_MATH_DEFINES // For VC++ to get M_PI. This has to be first. | 5 #define _USE_MATH_DEFINES // For VC++ to get M_PI. This has to be first. |
| 6 | 6 |
| 7 #include "ui/views/view.h" | 7 #include "ui/views/view.h" |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <cmath> | 10 #include <cmath> |
| 11 #include <memory> | 11 #include <memory> |
| 12 #include <utility> | 12 #include <utility> |
| 13 | 13 |
| 14 #include "base/command_line.h" |
| 14 #include "base/containers/adapters.h" | 15 #include "base/containers/adapters.h" |
| 15 #include "base/logging.h" | 16 #include "base/logging.h" |
| 16 #include "base/macros.h" | 17 #include "base/macros.h" |
| 17 #include "base/memory/ptr_util.h" | 18 #include "base/memory/ptr_util.h" |
| 18 #include "base/message_loop/message_loop.h" | 19 #include "base/message_loop/message_loop.h" |
| 19 #include "base/stl_util.h" | 20 #include "base/stl_util.h" |
| 20 #include "base/strings/stringprintf.h" | 21 #include "base/strings/stringprintf.h" |
| 21 #include "base/strings/utf_string_conversions.h" | 22 #include "base/strings/utf_string_conversions.h" |
| 22 #include "base/trace_event/trace_event.h" | 23 #include "base/trace_event/trace_event.h" |
| 23 #include "build/build_config.h" | 24 #include "build/build_config.h" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 47 #include "ui/native_theme/native_theme.h" | 48 #include "ui/native_theme/native_theme.h" |
| 48 #include "ui/views/accessibility/native_view_accessibility.h" | 49 #include "ui/views/accessibility/native_view_accessibility.h" |
| 49 #include "ui/views/background.h" | 50 #include "ui/views/background.h" |
| 50 #include "ui/views/border.h" | 51 #include "ui/views/border.h" |
| 51 #include "ui/views/context_menu_controller.h" | 52 #include "ui/views/context_menu_controller.h" |
| 52 #include "ui/views/drag_controller.h" | 53 #include "ui/views/drag_controller.h" |
| 53 #include "ui/views/focus/view_storage.h" | 54 #include "ui/views/focus/view_storage.h" |
| 54 #include "ui/views/layout/layout_manager.h" | 55 #include "ui/views/layout/layout_manager.h" |
| 55 #include "ui/views/view_observer.h" | 56 #include "ui/views/view_observer.h" |
| 56 #include "ui/views/views_delegate.h" | 57 #include "ui/views/views_delegate.h" |
| 58 #include "ui/views/views_switches.h" |
| 57 #include "ui/views/widget/native_widget_private.h" | 59 #include "ui/views/widget/native_widget_private.h" |
| 58 #include "ui/views/widget/root_view.h" | 60 #include "ui/views/widget/root_view.h" |
| 59 #include "ui/views/widget/tooltip_manager.h" | 61 #include "ui/views/widget/tooltip_manager.h" |
| 60 #include "ui/views/widget/widget.h" | 62 #include "ui/views/widget/widget.h" |
| 61 | 63 |
| 62 #if defined(OS_WIN) | 64 #if defined(OS_WIN) |
| 63 #include "base/win/scoped_gdi_object.h" | 65 #include "base/win/scoped_gdi_object.h" |
| 64 #include "ui/native_theme/native_theme_win.h" | 66 #include "ui/native_theme/native_theme_win.h" |
| 65 #endif | 67 #endif |
| 66 | 68 |
| (...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 835 if (layer()) { | 837 if (layer()) { |
| 836 layer()->SchedulePaint(rect); | 838 layer()->SchedulePaint(rect); |
| 837 } else if (parent_) { | 839 } else if (parent_) { |
| 838 // Translate the requested paint rect to the parent's coordinate system | 840 // Translate the requested paint rect to the parent's coordinate system |
| 839 // then pass this notification up to the parent. | 841 // then pass this notification up to the parent. |
| 840 parent_->SchedulePaintInRect(ConvertRectToParent(rect)); | 842 parent_->SchedulePaintInRect(ConvertRectToParent(rect)); |
| 841 } | 843 } |
| 842 } | 844 } |
| 843 | 845 |
| 844 void View::Paint(const ui::PaintContext& parent_context) { | 846 void View::Paint(const ui::PaintContext& parent_context) { |
| 845 if (!visible_) | 847 if (!ShouldPaint()) |
| 846 return; | |
| 847 if (size().IsEmpty()) | |
| 848 return; | 848 return; |
| 849 | 849 |
| 850 gfx::Vector2d offset_to_parent; | 850 ui::PaintContext context(parent_context, GetPaintContextOffset()); |
| 851 if (!layer()) { | |
| 852 // If the View has a layer() then it is a paint root. Otherwise, we need to | |
| 853 // add the offset from the parent into the total offset from the paint root. | |
| 854 DCHECK(parent() || origin() == gfx::Point()); | |
| 855 offset_to_parent = GetMirroredPosition().OffsetFromOrigin(); | |
| 856 } | |
| 857 ui::PaintContext context(parent_context, offset_to_parent); | |
| 858 | 851 |
| 859 bool is_invalidated = true; | 852 bool is_invalidated = true; |
| 860 if (context.CanCheckInvalid()) { | 853 if (context.CanCheckInvalid()) { |
| 861 #if DCHECK_IS_ON() | 854 #if DCHECK_IS_ON() |
| 862 gfx::Vector2d offset; | 855 gfx::Vector2d offset; |
| 863 context.Visited(this); | 856 context.Visited(this); |
| 864 View* view = this; | 857 View* view = this; |
| 865 while (view->parent() && !view->layer()) { | 858 while (view->parent() && !view->layer()) { |
| 866 DCHECK(view->GetTransform().IsIdentity()); | 859 DCHECK(view->GetTransform().IsIdentity()); |
| 867 offset += view->GetMirroredPosition().OffsetFromOrigin(); | 860 offset += view->GetMirroredPosition().OffsetFromOrigin(); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 879 | 872 |
| 880 // If the View wasn't invalidated, don't waste time painting it, the output | 873 // If the View wasn't invalidated, don't waste time painting it, the output |
| 881 // would be culled. | 874 // would be culled. |
| 882 is_invalidated = context.IsRectInvalid(GetLocalBounds()); | 875 is_invalidated = context.IsRectInvalid(GetLocalBounds()); |
| 883 } | 876 } |
| 884 | 877 |
| 885 TRACE_EVENT1("views", "View::Paint", "class", GetClassName()); | 878 TRACE_EVENT1("views", "View::Paint", "class", GetClassName()); |
| 886 | 879 |
| 887 // If the view is backed by a layer, it should paint with itself as the origin | 880 // If the view is backed by a layer, it should paint with itself as the origin |
| 888 // rather than relative to its parent. | 881 // rather than relative to its parent. |
| 889 bool paint_relative_to_parent = !layer(); | |
| 890 | |
| 891 // TODO(danakj): Rework clip and transform recorder usage here to use | 882 // TODO(danakj): Rework clip and transform recorder usage here to use |
| 892 // std::optional once we can do so. | 883 // std::optional once we can do so. |
| 893 ui::ClipRecorder clip_recorder(parent_context); | 884 ui::ClipRecorder clip_recorder(parent_context); |
| 894 if (paint_relative_to_parent) { | 885 if (!layer()) { |
| 895 // Set the clip rect to the bounds of this View, or |clip_path_| if it's | 886 // Set the clip rect to the bounds of this View, or |clip_path_| if it's |
| 896 // been set. Note that the X (or left) position we pass to ClipRect takes | 887 // been set. Note that the X (or left) position we pass to ClipRect takes |
| 897 // into consideration whether or not the View uses a right-to-left layout so | 888 // into consideration whether or not the View uses a right-to-left layout so |
| 898 // that we paint the View in its mirrored position if need be. | 889 // that we paint the View in its mirrored position if need be. |
| 899 if (clip_path_.isEmpty()) { | 890 if (clip_path_.isEmpty()) { |
| 900 clip_recorder.ClipRect(GetMirroredBounds()); | 891 clip_recorder.ClipRect(GetMirroredBounds()); |
| 901 } else { | 892 } else { |
| 902 gfx::Path clip_path_in_parent = clip_path_; | 893 gfx::Path clip_path_in_parent = clip_path_; |
| 903 clip_path_in_parent.offset(GetMirroredX(), y()); | 894 clip_path_in_parent.offset(GetMirroredX(), y()); |
| 904 clip_recorder.ClipPathWithAntiAliasing(clip_path_in_parent); | 895 clip_recorder.ClipPathWithAntiAliasing(clip_path_in_parent); |
| 905 } | 896 } |
| 906 } | 897 } |
| 907 | 898 |
| 908 ui::TransformRecorder transform_recorder(context); | 899 ui::TransformRecorder transform_recorder(context); |
| 909 if (paint_relative_to_parent) { | 900 SetupTransformRecorderForPainting(&transform_recorder); |
| 910 // Translate the graphics such that 0,0 corresponds to where | |
| 911 // this View is located relative to its parent. | |
| 912 gfx::Transform transform_from_parent; | |
| 913 gfx::Vector2d offset_from_parent = GetMirroredPosition().OffsetFromOrigin(); | |
| 914 transform_from_parent.Translate(offset_from_parent.x(), | |
| 915 offset_from_parent.y()); | |
| 916 transform_from_parent.PreconcatTransform(GetTransform()); | |
| 917 transform_recorder.Transform(transform_from_parent); | |
| 918 } | |
| 919 | 901 |
| 920 // Note that the cache is not aware of the offset of the view | 902 // Note that the cache is not aware of the offset of the view |
| 921 // relative to the parent since painting is always done relative to | 903 // relative to the parent since painting is always done relative to |
| 922 // the top left of the individual view. | 904 // the top left of the individual view. |
| 923 if (is_invalidated || !paint_cache_.UseCache(context, size())) { | 905 if (is_invalidated || !paint_cache_.UseCache(context, size())) { |
| 924 ui::PaintRecorder recorder(context, size(), &paint_cache_); | 906 ui::PaintRecorder recorder(context, size(), &paint_cache_); |
| 925 gfx::Canvas* canvas = recorder.canvas(); | 907 gfx::Canvas* canvas = recorder.canvas(); |
| 926 gfx::ScopedRTLFlipCanvas scoped_canvas(canvas, width(), | 908 gfx::ScopedRTLFlipCanvas scoped_canvas(canvas, width(), |
| 927 flip_canvas_on_paint_for_rtl_ui_); | 909 flip_canvas_on_paint_for_rtl_ui_); |
| 928 | 910 |
| (...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1513 } | 1495 } |
| 1514 | 1496 |
| 1515 void View::AddedToWidget() {} | 1497 void View::AddedToWidget() {} |
| 1516 | 1498 |
| 1517 void View::RemovedFromWidget() {} | 1499 void View::RemovedFromWidget() {} |
| 1518 | 1500 |
| 1519 // Painting -------------------------------------------------------------------- | 1501 // Painting -------------------------------------------------------------------- |
| 1520 | 1502 |
| 1521 void View::PaintChildren(const ui::PaintContext& context) { | 1503 void View::PaintChildren(const ui::PaintContext& context) { |
| 1522 TRACE_EVENT1("views", "View::PaintChildren", "class", GetClassName()); | 1504 TRACE_EVENT1("views", "View::PaintChildren", "class", GetClassName()); |
| 1523 View::Views children = GetChildrenInZOrder(); | 1505 RecursivePaintHelper(&View::Paint, context); |
| 1524 DCHECK_EQ(child_count(), static_cast<int>(children.size())); | |
| 1525 for (auto* child : children) { | |
| 1526 if (!child->layer()) | |
| 1527 child->Paint(context); | |
| 1528 } | |
| 1529 } | 1506 } |
| 1530 | 1507 |
| 1531 void View::OnPaint(gfx::Canvas* canvas) { | 1508 void View::OnPaint(gfx::Canvas* canvas) { |
| 1532 TRACE_EVENT1("views", "View::OnPaint", "class", GetClassName()); | 1509 TRACE_EVENT1("views", "View::OnPaint", "class", GetClassName()); |
| 1533 OnPaintBackground(canvas); | 1510 OnPaintBackground(canvas); |
| 1534 OnPaintBorder(canvas); | 1511 OnPaintBorder(canvas); |
| 1535 } | 1512 } |
| 1536 | 1513 |
| 1537 void View::OnPaintBackground(gfx::Canvas* canvas) { | 1514 void View::OnPaintBackground(gfx::Canvas* canvas) { |
| 1538 if (background_.get()) { | 1515 if (background_.get()) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1621 } else { | 1598 } else { |
| 1622 internal::ScopedChildrenLock lock(this); | 1599 internal::ScopedChildrenLock lock(this); |
| 1623 for (auto* child : children_) { | 1600 for (auto* child : children_) { |
| 1624 child->UpdateChildLayerBounds( | 1601 child->UpdateChildLayerBounds( |
| 1625 offset + gfx::Vector2d(child->GetMirroredX(), child->y())); | 1602 offset + gfx::Vector2d(child->GetMirroredX(), child->y())); |
| 1626 } | 1603 } |
| 1627 } | 1604 } |
| 1628 } | 1605 } |
| 1629 | 1606 |
| 1630 void View::OnPaintLayer(const ui::PaintContext& context) { | 1607 void View::OnPaintLayer(const ui::PaintContext& context) { |
| 1631 Paint(context); | 1608 PaintRoot(context); |
| 1632 } | 1609 } |
| 1633 | 1610 |
| 1634 void View::OnDelegatedFrameDamage( | 1611 void View::OnDelegatedFrameDamage( |
| 1635 const gfx::Rect& damage_rect_in_dip) { | 1612 const gfx::Rect& damage_rect_in_dip) { |
| 1636 } | 1613 } |
| 1637 | 1614 |
| 1638 void View::OnDeviceScaleFactorChanged(float device_scale_factor) { | 1615 void View::OnDeviceScaleFactorChanged(float device_scale_factor) { |
| 1639 snap_layer_to_pixel_boundary_ = | 1616 snap_layer_to_pixel_boundary_ = |
| 1640 (device_scale_factor - std::floor(device_scale_factor)) != 0.0f; | 1617 (device_scale_factor - std::floor(device_scale_factor)) != 0.0f; |
| 1641 SnapLayerToPixelBoundary(); | 1618 SnapLayerToPixelBoundary(); |
| (...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2214 } | 2191 } |
| 2215 | 2192 |
| 2216 bool View::ConvertRectFromAncestor(const View* ancestor, | 2193 bool View::ConvertRectFromAncestor(const View* ancestor, |
| 2217 gfx::RectF* rect) const { | 2194 gfx::RectF* rect) const { |
| 2218 gfx::Transform trans; | 2195 gfx::Transform trans; |
| 2219 bool result = GetTransformRelativeTo(ancestor, &trans); | 2196 bool result = GetTransformRelativeTo(ancestor, &trans); |
| 2220 trans.TransformRectReverse(rect); | 2197 trans.TransformRectReverse(rect); |
| 2221 return result; | 2198 return result; |
| 2222 } | 2199 } |
| 2223 | 2200 |
| 2201 // Painting -------------------------------------------------------------------- |
| 2202 |
| 2203 bool View::ShouldPaint() const { |
| 2204 return visible_ && !size().IsEmpty(); |
| 2205 } |
| 2206 |
| 2207 gfx::Vector2d View::GetPaintContextOffset() const { |
| 2208 // If the View has a layer() then it is a paint root. Otherwise, we need to |
| 2209 // add the offset from the parent into the total offset from the paint root. |
| 2210 DCHECK(layer() || parent() || origin() == gfx::Point()); |
| 2211 return layer() ? gfx::Vector2d() : GetMirroredPosition().OffsetFromOrigin(); |
| 2212 } |
| 2213 |
| 2214 void View::SetupTransformRecorderForPainting( |
| 2215 ui::TransformRecorder* recorder) const { |
| 2216 // If the view is backed by a layer, it should paint with itself as the origin |
| 2217 // rather than relative to its parent. |
| 2218 if (layer()) |
| 2219 return; |
| 2220 |
| 2221 // Translate the graphics such that 0,0 corresponds to where this View is |
| 2222 // located relative to its parent. |
| 2223 gfx::Transform transform_from_parent; |
| 2224 gfx::Vector2d offset_from_parent = GetMirroredPosition().OffsetFromOrigin(); |
| 2225 transform_from_parent.Translate(offset_from_parent.x(), |
| 2226 offset_from_parent.y()); |
| 2227 transform_from_parent.PreconcatTransform(GetTransform()); |
| 2228 recorder->Transform(transform_from_parent); |
| 2229 } |
| 2230 |
| 2231 void View::RecursivePaintHelper(void (View::*func)(const ui::PaintContext&), |
| 2232 const ui::PaintContext& context) { |
| 2233 View::Views children = GetChildrenInZOrder(); |
| 2234 DCHECK_EQ(child_count(), static_cast<int>(children.size())); |
| 2235 for (auto* child : children) { |
| 2236 if (!child->layer()) |
| 2237 (child->*func)(context); |
| 2238 } |
| 2239 } |
| 2240 |
| 2241 void View::PaintRoot(const ui::PaintContext& parent_context) { |
| 2242 Paint(parent_context); |
| 2243 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 2244 switches::kDrawViewBoundsRects)) |
| 2245 PaintDebugRects(parent_context); |
| 2246 } |
| 2247 |
| 2248 void View::PaintDebugRects(const ui::PaintContext& parent_context) { |
| 2249 if (!ShouldPaint()) |
| 2250 return; |
| 2251 |
| 2252 ui::PaintContext context(parent_context, GetPaintContextOffset()); |
| 2253 ui::TransformRecorder transform_recorder(context); |
| 2254 SetupTransformRecorderForPainting(&transform_recorder); |
| 2255 |
| 2256 RecursivePaintHelper(&View::PaintDebugRects, context); |
| 2257 |
| 2258 // Draw outline rects for debugging. |
| 2259 ui::PaintRecorder recorder(context, size()); |
| 2260 gfx::Canvas* canvas = recorder.canvas(); |
| 2261 const float scale = canvas->UndoDeviceScaleFactor(); |
| 2262 gfx::RectF outline_rect(ScaleToEnclosedRect(GetLocalBounds(), scale)); |
| 2263 outline_rect.Inset(0.5f, 0.5f); |
| 2264 const SkColor color = SkColorSetARGB(0x30, 0xff, 0, 0); |
| 2265 canvas->DrawRect(outline_rect, color); |
| 2266 } |
| 2267 |
| 2224 // Accelerated painting -------------------------------------------------------- | 2268 // Accelerated painting -------------------------------------------------------- |
| 2225 | 2269 |
| 2226 void View::CreateLayer(ui::LayerType layer_type) { | 2270 void View::CreateLayer(ui::LayerType layer_type) { |
| 2227 // A new layer is being created for the view. So all the layers of the | 2271 // A new layer is being created for the view. So all the layers of the |
| 2228 // sub-tree can inherit the visibility of the corresponding view. | 2272 // sub-tree can inherit the visibility of the corresponding view. |
| 2229 { | 2273 { |
| 2230 internal::ScopedChildrenLock lock(this); | 2274 internal::ScopedChildrenLock lock(this); |
| 2231 for (auto* child : children_) | 2275 for (auto* child : children_) |
| 2232 child->UpdateChildLayerVisibility(true); | 2276 child->UpdateChildLayerVisibility(true); |
| 2233 } | 2277 } |
| (...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2562 // Message the RootView to do the drag and drop. That way if we're removed | 2606 // Message the RootView to do the drag and drop. That way if we're removed |
| 2563 // the RootView can detect it and avoid calling us back. | 2607 // the RootView can detect it and avoid calling us back. |
| 2564 gfx::Point widget_location(event.location()); | 2608 gfx::Point widget_location(event.location()); |
| 2565 ConvertPointToWidget(this, &widget_location); | 2609 ConvertPointToWidget(this, &widget_location); |
| 2566 widget->RunShellDrag(this, data, widget_location, drag_operations, source); | 2610 widget->RunShellDrag(this, data, widget_location, drag_operations, source); |
| 2567 // WARNING: we may have been deleted. | 2611 // WARNING: we may have been deleted. |
| 2568 return true; | 2612 return true; |
| 2569 } | 2613 } |
| 2570 | 2614 |
| 2571 } // namespace views | 2615 } // namespace views |
| OLD | NEW |