| 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> |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 #include "ui/gfx/scoped_canvas.h" | 31 #include "ui/gfx/scoped_canvas.h" |
| 32 #include "ui/gfx/screen.h" | 32 #include "ui/gfx/screen.h" |
| 33 #include "ui/gfx/skia_util.h" | 33 #include "ui/gfx/skia_util.h" |
| 34 #include "ui/gfx/transform.h" | 34 #include "ui/gfx/transform.h" |
| 35 #include "ui/native_theme/native_theme.h" | 35 #include "ui/native_theme/native_theme.h" |
| 36 #include "ui/views/accessibility/native_view_accessibility.h" | 36 #include "ui/views/accessibility/native_view_accessibility.h" |
| 37 #include "ui/views/background.h" | 37 #include "ui/views/background.h" |
| 38 #include "ui/views/context_menu_controller.h" | 38 #include "ui/views/context_menu_controller.h" |
| 39 #include "ui/views/drag_controller.h" | 39 #include "ui/views/drag_controller.h" |
| 40 #include "ui/views/layout/layout_manager.h" | 40 #include "ui/views/layout/layout_manager.h" |
| 41 #include "ui/views/rect_based_targeting_utils.h" |
| 41 #include "ui/views/views_delegate.h" | 42 #include "ui/views/views_delegate.h" |
| 42 #include "ui/views/widget/native_widget_private.h" | 43 #include "ui/views/widget/native_widget_private.h" |
| 43 #include "ui/views/widget/root_view.h" | 44 #include "ui/views/widget/root_view.h" |
| 44 #include "ui/views/widget/tooltip_manager.h" | 45 #include "ui/views/widget/tooltip_manager.h" |
| 45 #include "ui/views/widget/widget.h" | 46 #include "ui/views/widget/widget.h" |
| 46 | 47 |
| 47 #if defined(USE_AURA) | 48 #if defined(USE_AURA) |
| 48 #include "ui/base/cursor/cursor.h" | 49 #include "ui/base/cursor/cursor.h" |
| 49 #endif | 50 #endif |
| 50 | 51 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 61 #else | 62 #else |
| 62 bool use_acceleration_when_possible = false; | 63 bool use_acceleration_when_possible = false; |
| 63 #endif | 64 #endif |
| 64 | 65 |
| 65 #if defined(OS_WIN) | 66 #if defined(OS_WIN) |
| 66 const bool kContextMenuOnMousePress = false; | 67 const bool kContextMenuOnMousePress = false; |
| 67 #else | 68 #else |
| 68 const bool kContextMenuOnMousePress = true; | 69 const bool kContextMenuOnMousePress = true; |
| 69 #endif | 70 #endif |
| 70 | 71 |
| 72 // The minimum percentage of a view's area that needs to be covered by a rect |
| 73 // representing a touch region in order for that view to be considered by the |
| 74 // rect-based targeting algorithm. |
| 75 static const float kRectTargetOverlap = 0.6; |
| 76 |
| 71 // Returns the top view in |view|'s hierarchy. | 77 // Returns the top view in |view|'s hierarchy. |
| 72 const views::View* GetHierarchyRoot(const views::View* view) { | 78 const views::View* GetHierarchyRoot(const views::View* view) { |
| 73 const views::View* root = view; | 79 const views::View* root = view; |
| 74 while (root && root->parent()) | 80 while (root && root->parent()) |
| 75 root = root->parent(); | 81 root = root->parent(); |
| 76 return root; | 82 return root; |
| 77 } | 83 } |
| 78 | 84 |
| 79 } // namespace | 85 } // namespace |
| 80 | 86 |
| (...skipping 593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 674 target->ConvertPointFromAncestor(root, point); | 680 target->ConvertPointFromAncestor(root, point); |
| 675 | 681 |
| 676 // API defines NULL |source| as returning the point in screen coordinates. | 682 // API defines NULL |source| as returning the point in screen coordinates. |
| 677 if (!source) { | 683 if (!source) { |
| 678 *point -= | 684 *point -= |
| 679 root->GetWidget()->GetClientAreaBoundsInScreen().OffsetFromOrigin(); | 685 root->GetWidget()->GetClientAreaBoundsInScreen().OffsetFromOrigin(); |
| 680 } | 686 } |
| 681 } | 687 } |
| 682 | 688 |
| 683 // static | 689 // static |
| 690 void View::ConvertRectToTarget(const View* source, |
| 691 const View* target, |
| 692 gfx::Rect* rect) { |
| 693 if (source == target) |
| 694 return; |
| 695 |
| 696 // |source| can be NULL. |
| 697 const View* root = GetHierarchyRoot(target); |
| 698 if (source) { |
| 699 CHECK_EQ(GetHierarchyRoot(source), root); |
| 700 |
| 701 if (source != root) |
| 702 source->ConvertRectForAncestor(root, rect); |
| 703 } |
| 704 |
| 705 if (target != root) |
| 706 target->ConvertRectFromAncestor(root, rect); |
| 707 |
| 708 // API defines NULL |source| as returning the point in screen coordinates. |
| 709 if (!source) { |
| 710 rect->set_origin(rect->origin() - |
| 711 root->GetWidget()->GetClientAreaBoundsInScreen().OffsetFromOrigin()); |
| 712 } |
| 713 } |
| 714 |
| 715 // static |
| 684 void View::ConvertPointToWidget(const View* src, gfx::Point* p) { | 716 void View::ConvertPointToWidget(const View* src, gfx::Point* p) { |
| 685 DCHECK(src); | 717 DCHECK(src); |
| 686 DCHECK(p); | 718 DCHECK(p); |
| 687 | 719 |
| 688 src->ConvertPointForAncestor(NULL, p); | 720 src->ConvertPointForAncestor(NULL, p); |
| 689 } | 721 } |
| 690 | 722 |
| 691 // static | 723 // static |
| 692 void View::ConvertPointFromWidget(const View* dest, gfx::Point* p) { | 724 void View::ConvertPointFromWidget(const View* dest, gfx::Point* p) { |
| 693 DCHECK(dest); | 725 DCHECK(dest); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 800 } | 832 } |
| 801 | 833 |
| 802 // static | 834 // static |
| 803 bool View::get_use_acceleration_when_possible() { | 835 bool View::get_use_acceleration_when_possible() { |
| 804 return use_acceleration_when_possible; | 836 return use_acceleration_when_possible; |
| 805 } | 837 } |
| 806 | 838 |
| 807 // Input ----------------------------------------------------------------------- | 839 // Input ----------------------------------------------------------------------- |
| 808 | 840 |
| 809 View* View::GetEventHandlerForPoint(const gfx::Point& point) { | 841 View* View::GetEventHandlerForPoint(const gfx::Point& point) { |
| 810 // Walk the child Views recursively looking for the View that most | 842 return GetEventHandlerForRect(gfx::Rect(point, gfx::Size(1, 1))); |
| 811 // tightly encloses the specified point. | 843 } |
| 844 |
| 845 View* View::GetEventHandlerForRect(const gfx::Rect& rect) { |
| 846 // |rect_view| represents the current best candidate to return |
| 847 // if rect-based targeting (i.e., fuzzing) is used. |
| 848 // |rect_view_distance| is used to keep track of the distance |
| 849 // between the center point of |rect_view| and the center |
| 850 // point of |rect|. |
| 851 View* rect_view = NULL; |
| 852 int rect_view_distance = INT_MAX; |
| 853 |
| 854 // |point_view| represents the view that would have been returned |
| 855 // from this function call if point-based targeting were used. |
| 856 View* point_view = NULL; |
| 857 |
| 812 for (int i = child_count() - 1; i >= 0; --i) { | 858 for (int i = child_count() - 1; i >= 0; --i) { |
| 813 View* child = child_at(i); | 859 View* child = child_at(i); |
| 860 |
| 861 // Ignore any children which are invisible or do not intersect |rect|. |
| 814 if (!child->visible()) | 862 if (!child->visible()) |
| 815 continue; | 863 continue; |
| 864 gfx::Rect rect_in_child_coords(rect); |
| 865 ConvertRectToTarget(this, child, &rect_in_child_coords); |
| 866 if (!child->HitTestRect(rect_in_child_coords)) |
| 867 continue; |
| 816 | 868 |
| 817 gfx::Point point_in_child_coords(point); | 869 View* cur_view = child->GetEventHandlerForRect(rect_in_child_coords); |
| 818 ConvertPointToTarget(this, child, &point_in_child_coords); | 870 |
| 819 if (child->HitTestPoint(point_in_child_coords)) | 871 if (views::UsePointBasedTargeting(rect)) |
| 820 return child->GetEventHandlerForPoint(point_in_child_coords); | 872 return cur_view; |
| 873 |
| 874 gfx::Rect cur_view_bounds(cur_view->GetLocalBounds()); |
| 875 ConvertRectToTarget(cur_view, this, &cur_view_bounds); |
| 876 if (views::PercentCoveredBy(cur_view_bounds, rect) >= kRectTargetOverlap) { |
| 877 // |cur_view| is a suitable candidate for rect-based targeting. |
| 878 // Check to see if it is the closest suitable candidate so far. |
| 879 gfx::Point touch_center(rect.CenterPoint()); |
| 880 int cur_dist = views::DistanceSquaredFromCenterLineToPoint( |
| 881 touch_center, cur_view_bounds); |
| 882 if (!rect_view || cur_dist < rect_view_distance) { |
| 883 rect_view = cur_view; |
| 884 rect_view_distance = cur_dist; |
| 885 } |
| 886 } else if (!rect_view && !point_view) { |
| 887 // Rect-based targeting has not yielded any candidates so far. Check |
| 888 // if point-based targeting would have selected |cur_view|. |
| 889 gfx::Point point_in_child_coords(rect_in_child_coords.CenterPoint()); |
| 890 if (child->HitTestPoint(point_in_child_coords)) |
| 891 point_view = child->GetEventHandlerForPoint(point_in_child_coords); |
| 892 } |
| 821 } | 893 } |
| 822 return this; | 894 |
| 895 if (views::UsePointBasedTargeting(rect) || (!rect_view && !point_view)) |
| 896 return this; |
| 897 |
| 898 return rect_view ? rect_view : point_view; |
| 823 } | 899 } |
| 824 | 900 |
| 825 View* View::GetTooltipHandlerForPoint(const gfx::Point& point) { | 901 View* View::GetTooltipHandlerForPoint(const gfx::Point& point) { |
| 826 if (!HitTestPoint(point)) | 902 if (!HitTestPoint(point)) |
| 827 return NULL; | 903 return NULL; |
| 828 | 904 |
| 829 // Walk the child Views recursively looking for the View that most | 905 // Walk the child Views recursively looking for the View that most |
| 830 // tightly encloses the specified point. | 906 // tightly encloses the specified point. |
| 831 for (int i = child_count() - 1; i >= 0; --i) { | 907 for (int i = child_count() - 1; i >= 0; --i) { |
| 832 View* child = child_at(i); | 908 View* child = child_at(i); |
| (...skipping 1138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1971 bool View::ConvertPointFromAncestor(const View* ancestor, | 2047 bool View::ConvertPointFromAncestor(const View* ancestor, |
| 1972 gfx::Point* point) const { | 2048 gfx::Point* point) const { |
| 1973 gfx::Transform trans; | 2049 gfx::Transform trans; |
| 1974 bool result = GetTransformRelativeTo(ancestor, &trans); | 2050 bool result = GetTransformRelativeTo(ancestor, &trans); |
| 1975 gfx::Point3F p(*point); | 2051 gfx::Point3F p(*point); |
| 1976 trans.TransformPointReverse(&p); | 2052 trans.TransformPointReverse(&p); |
| 1977 *point = gfx::ToFlooredPoint(p.AsPointF()); | 2053 *point = gfx::ToFlooredPoint(p.AsPointF()); |
| 1978 return result; | 2054 return result; |
| 1979 } | 2055 } |
| 1980 | 2056 |
| 2057 bool View::ConvertRectForAncestor(const View* ancestor, |
| 2058 gfx::Rect* rect) const { |
| 2059 gfx::Transform trans; |
| 2060 // TODO(sad): Have some way of caching the transformation results. |
| 2061 bool result = GetTransformRelativeTo(ancestor, &trans); |
| 2062 gfx::RectF r(*rect); |
| 2063 trans.TransformRect(&r); |
| 2064 *rect = gfx::ToEnclosingRect(r); |
| 2065 return result; |
| 2066 } |
| 2067 |
| 2068 bool View::ConvertRectFromAncestor(const View* ancestor, |
| 2069 gfx::Rect* rect) const { |
| 2070 gfx::Transform trans; |
| 2071 bool result = GetTransformRelativeTo(ancestor, &trans); |
| 2072 gfx::RectF r(*rect); |
| 2073 trans.TransformRectReverse(&r); |
| 2074 *rect = gfx::ToEnclosingRect(r); |
| 2075 return result; |
| 2076 } |
| 2077 |
| 1981 // Accelerated painting -------------------------------------------------------- | 2078 // Accelerated painting -------------------------------------------------------- |
| 1982 | 2079 |
| 1983 void View::CreateLayer() { | 2080 void View::CreateLayer() { |
| 1984 // A new layer is being created for the view. So all the layers of the | 2081 // A new layer is being created for the view. So all the layers of the |
| 1985 // sub-tree can inherit the visibility of the corresponding view. | 2082 // sub-tree can inherit the visibility of the corresponding view. |
| 1986 for (int i = 0, count = child_count(); i < count; ++i) | 2083 for (int i = 0, count = child_count(); i < count; ++i) |
| 1987 child_at(i)->UpdateChildLayerVisibility(true); | 2084 child_at(i)->UpdateChildLayerVisibility(true); |
| 1988 | 2085 |
| 1989 layer_ = new ui::Layer(); | 2086 layer_ = new ui::Layer(); |
| 1990 layer_owner_.reset(layer_); | 2087 layer_owner_.reset(layer_); |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2280 // Message the RootView to do the drag and drop. That way if we're removed | 2377 // Message the RootView to do the drag and drop. That way if we're removed |
| 2281 // the RootView can detect it and avoid calling us back. | 2378 // the RootView can detect it and avoid calling us back. |
| 2282 gfx::Point widget_location(event.location()); | 2379 gfx::Point widget_location(event.location()); |
| 2283 ConvertPointToWidget(this, &widget_location); | 2380 ConvertPointToWidget(this, &widget_location); |
| 2284 widget->RunShellDrag(this, data, widget_location, drag_operations, source); | 2381 widget->RunShellDrag(this, data, widget_location, drag_operations, source); |
| 2285 // WARNING: we may have been deleted. | 2382 // WARNING: we may have been deleted. |
| 2286 return true; | 2383 return true; |
| 2287 } | 2384 } |
| 2288 | 2385 |
| 2289 } // namespace views | 2386 } // namespace views |
| OLD | NEW |