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 PaintFromPaintRoot(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 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1898 } | 1875 } |
1899 | 1876 |
1900 void View::SchedulePaintOnParent() { | 1877 void View::SchedulePaintOnParent() { |
1901 if (parent_) { | 1878 if (parent_) { |
1902 // Translate the requested paint rect to the parent's coordinate system | 1879 // Translate the requested paint rect to the parent's coordinate system |
1903 // then pass this notification up to the parent. | 1880 // then pass this notification up to the parent. |
1904 parent_->SchedulePaintInRect(ConvertRectToParent(GetLocalBounds())); | 1881 parent_->SchedulePaintInRect(ConvertRectToParent(GetLocalBounds())); |
1905 } | 1882 } |
1906 } | 1883 } |
1907 | 1884 |
| 1885 bool View::ShouldPaint() const { |
| 1886 return visible_ && !size().IsEmpty(); |
| 1887 } |
| 1888 |
| 1889 gfx::Vector2d View::GetPaintContextOffset() const { |
| 1890 // If the View has a layer() then it is a paint root. Otherwise, we need to |
| 1891 // add the offset from the parent into the total offset from the paint root. |
| 1892 DCHECK(layer() || parent() || origin() == gfx::Point()); |
| 1893 return layer() ? gfx::Vector2d() : GetMirroredPosition().OffsetFromOrigin(); |
| 1894 } |
| 1895 |
| 1896 void View::SetupTransformRecorderForPainting( |
| 1897 ui::TransformRecorder* recorder) const { |
| 1898 // If the view is backed by a layer, it should paint with itself as the origin |
| 1899 // rather than relative to its parent. |
| 1900 if (layer()) |
| 1901 return; |
| 1902 |
| 1903 // Translate the graphics such that 0,0 corresponds to where this View is |
| 1904 // located relative to its parent. |
| 1905 gfx::Transform transform_from_parent; |
| 1906 gfx::Vector2d offset_from_parent = GetMirroredPosition().OffsetFromOrigin(); |
| 1907 transform_from_parent.Translate(offset_from_parent.x(), |
| 1908 offset_from_parent.y()); |
| 1909 transform_from_parent.PreconcatTransform(GetTransform()); |
| 1910 recorder->Transform(transform_from_parent); |
| 1911 } |
| 1912 |
| 1913 void View::RecursivePaintHelper(void (View::*func)(const ui::PaintContext&), |
| 1914 const ui::PaintContext& context) { |
| 1915 View::Views children = GetChildrenInZOrder(); |
| 1916 DCHECK_EQ(child_count(), static_cast<int>(children.size())); |
| 1917 for (auto* child : children) { |
| 1918 if (!child->layer()) |
| 1919 (child->*func)(context); |
| 1920 } |
| 1921 } |
| 1922 |
| 1923 void View::PaintFromPaintRoot(const ui::PaintContext& parent_context) { |
| 1924 Paint(parent_context); |
| 1925 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 1926 switches::kDrawViewBoundsRects)) |
| 1927 PaintDebugRects(parent_context); |
| 1928 } |
| 1929 |
| 1930 void View::PaintDebugRects(const ui::PaintContext& parent_context) { |
| 1931 if (!ShouldPaint()) |
| 1932 return; |
| 1933 |
| 1934 ui::PaintContext context(parent_context, GetPaintContextOffset()); |
| 1935 ui::TransformRecorder transform_recorder(context); |
| 1936 SetupTransformRecorderForPainting(&transform_recorder); |
| 1937 |
| 1938 RecursivePaintHelper(&View::PaintDebugRects, context); |
| 1939 |
| 1940 // Draw outline rects for debugging. |
| 1941 ui::PaintRecorder recorder(context, size()); |
| 1942 gfx::Canvas* canvas = recorder.canvas(); |
| 1943 const float scale = canvas->UndoDeviceScaleFactor(); |
| 1944 gfx::RectF outline_rect(ScaleToEnclosedRect(GetLocalBounds(), scale)); |
| 1945 outline_rect.Inset(0.5f, 0.5f); |
| 1946 const SkColor color = SkColorSetARGB(0x30, 0xff, 0, 0); |
| 1947 canvas->DrawRect(outline_rect, color); |
| 1948 } |
| 1949 |
1908 // Tree operations ------------------------------------------------------------- | 1950 // Tree operations ------------------------------------------------------------- |
1909 | 1951 |
1910 void View::DoRemoveChildView(View* view, | 1952 void View::DoRemoveChildView(View* view, |
1911 bool update_focus_cycle, | 1953 bool update_focus_cycle, |
1912 bool update_tool_tip, | 1954 bool update_tool_tip, |
1913 bool delete_removed_view, | 1955 bool delete_removed_view, |
1914 View* new_parent) { | 1956 View* new_parent) { |
1915 DCHECK(view); | 1957 DCHECK(view); |
1916 | 1958 |
1917 const Views::iterator i(std::find(children_.begin(), children_.end(), view)); | 1959 const Views::iterator i(std::find(children_.begin(), children_.end(), view)); |
(...skipping 644 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 | 2604 // 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. | 2605 // the RootView can detect it and avoid calling us back. |
2564 gfx::Point widget_location(event.location()); | 2606 gfx::Point widget_location(event.location()); |
2565 ConvertPointToWidget(this, &widget_location); | 2607 ConvertPointToWidget(this, &widget_location); |
2566 widget->RunShellDrag(this, data, widget_location, drag_operations, source); | 2608 widget->RunShellDrag(this, data, widget_location, drag_operations, source); |
2567 // WARNING: we may have been deleted. | 2609 // WARNING: we may have been deleted. |
2568 return true; | 2610 return true; |
2569 } | 2611 } |
2570 | 2612 |
2571 } // namespace views | 2613 } // namespace views |
OLD | NEW |