| 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 #include "ui/views/view.h" | 5 #include "ui/views/view.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 #include "ui/gfx/canvas.h" | 21 #include "ui/gfx/canvas.h" |
| 22 #include "ui/gfx/interpolated_transform.h" | 22 #include "ui/gfx/interpolated_transform.h" |
| 23 #include "ui/gfx/path.h" | 23 #include "ui/gfx/path.h" |
| 24 #include "ui/gfx/point3.h" | 24 #include "ui/gfx/point3.h" |
| 25 #include "ui/gfx/skia_util.h" | 25 #include "ui/gfx/skia_util.h" |
| 26 #include "ui/gfx/transform.h" | 26 #include "ui/gfx/transform.h" |
| 27 #include "ui/views/background.h" | 27 #include "ui/views/background.h" |
| 28 #include "ui/views/context_menu_controller.h" | 28 #include "ui/views/context_menu_controller.h" |
| 29 #include "ui/views/drag_controller.h" | 29 #include "ui/views/drag_controller.h" |
| 30 #include "ui/views/layout/layout_manager.h" | 30 #include "ui/views/layout/layout_manager.h" |
| 31 #include "ui/views/view_constants.h" |
| 31 #include "ui/views/views_delegate.h" | 32 #include "ui/views/views_delegate.h" |
| 32 #include "ui/views/widget/native_widget_private.h" | 33 #include "ui/views/widget/native_widget_private.h" |
| 33 #include "ui/views/widget/root_view.h" | 34 #include "ui/views/widget/root_view.h" |
| 34 #include "ui/views/widget/tooltip_manager.h" | 35 #include "ui/views/widget/tooltip_manager.h" |
| 35 #include "ui/views/widget/widget.h" | 36 #include "ui/views/widget/widget.h" |
| 36 | 37 |
| 37 #if defined(OS_WIN) | 38 #if defined(OS_WIN) |
| 38 #include "base/win/scoped_gdi_object.h" | 39 #include "base/win/scoped_gdi_object.h" |
| 39 #include "ui/views/accessibility/native_view_accessibility_win.h" | 40 #include "ui/views/accessibility/native_view_accessibility_win.h" |
| 40 #endif | 41 #endif |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 74 }; | 75 }; |
| 75 | 76 |
| 76 // Returns the top view in |view|'s hierarchy. | 77 // Returns the top view in |view|'s hierarchy. |
| 77 const views::View* GetHierarchyRoot(const views::View* view) { | 78 const views::View* GetHierarchyRoot(const views::View* view) { |
| 78 const views::View* root = view; | 79 const views::View* root = view; |
| 79 while (root && root->parent()) | 80 while (root && root->parent()) |
| 80 root = root->parent(); | 81 root = root->parent(); |
| 81 return root; | 82 return root; |
| 82 } | 83 } |
| 83 | 84 |
| 85 // Returns a ratio of the area of intersection compared to the smaller of |
| 86 // the two rectangles. |
| 87 double OverlapProportion(const gfx::Rect& rect_one, |
| 88 const gfx::Rect& rect_two) { |
| 89 gfx::Rect intersection = rect_one.Intersect(rect_two); |
| 90 double rect_one_area = rect_one.size().GetArea();; |
| 91 double rect_two_area = rect_two.size().GetArea();; |
| 92 double intersection_area = intersection.size().GetArea();; |
| 93 if ((rect_one_area <= 0) || (rect_two_area <= 0)) |
| 94 return 0.0; |
| 95 if (rect_one_area > rect_two_area) |
| 96 return intersection_area / rect_two_area; |
| 97 else |
| 98 return intersection_area / rect_one_area; |
| 99 } |
| 100 |
| 101 // The positive distance from |pos| to the nearest endpoint of the interval |
| 102 // [start, end] is returned if |pos| lies within the interval, otherwise |
| 103 // 0 is returned. |
| 104 int DistanceToInterval(int pos, int start, int end) { |
| 105 if (pos < start) |
| 106 return start - pos; |
| 107 if (pos > end) |
| 108 return pos - end; |
| 109 return 0; |
| 110 } |
| 111 |
| 112 // Returns the square of the distance from |point| to the center line of |
| 113 // |target_rect|. The center line of a rectangle is obtained by repeatedly |
| 114 // stripping away 1px borders around the rectangle until a line remains. |
| 115 int DistanceSquaredFromCenterLineToPoint(const gfx::Point& point, |
| 116 const gfx::Rect& target_rect) { |
| 117 gfx::Point center_point = target_rect.CenterPoint(); |
| 118 int dx = center_point.x() - point.x(); |
| 119 int dy = center_point.y() - point.y(); |
| 120 |
| 121 if (target_rect.width() > target_rect.height()) { |
| 122 dx = DistanceToInterval(point.x(), |
| 123 target_rect.x() + (target_rect.height() / 2), |
| 124 target_rect.right() - (target_rect.height() / 2)); |
| 125 } else { |
| 126 dy = DistanceToInterval(point.y(), |
| 127 target_rect.y() + (target_rect.width() / 2), |
| 128 target_rect.bottom() - (target_rect.width() / 2)); |
| 129 } |
| 130 return (dx * dx) + (dy * dy); |
| 131 } |
| 132 |
| 84 } // namespace | 133 } // namespace |
| 85 | 134 |
| 86 namespace views { | 135 namespace views { |
| 87 | 136 |
| 88 // static | 137 // static |
| 89 ViewsDelegate* ViewsDelegate::views_delegate = NULL; | 138 ViewsDelegate* ViewsDelegate::views_delegate = NULL; |
| 90 | 139 |
| 91 // static | 140 // static |
| 92 const char View::kViewClassName[] = "views/View"; | 141 const char View::kViewClassName[] = "views/View"; |
| 93 | 142 |
| (...skipping 526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 620 target->ConvertPointFromAncestor(root, point); | 669 target->ConvertPointFromAncestor(root, point); |
| 621 | 670 |
| 622 // API defines NULL |source| as returning the point in screen coordinates. | 671 // API defines NULL |source| as returning the point in screen coordinates. |
| 623 if (!source) { | 672 if (!source) { |
| 624 *point = point->Subtract( | 673 *point = point->Subtract( |
| 625 root->GetWidget()->GetClientAreaBoundsInScreen().origin()); | 674 root->GetWidget()->GetClientAreaBoundsInScreen().origin()); |
| 626 } | 675 } |
| 627 } | 676 } |
| 628 | 677 |
| 629 // static | 678 // static |
| 679 void View::ConvertRectToTarget(const View* source, |
| 680 const View* target, |
| 681 gfx::Rect* rect) { |
| 682 gfx::Point rect_location(rect->x(), rect->y()); |
| 683 View::ConvertPointToTarget(source, target, &rect_location); |
| 684 rect->set_origin(rect_location); |
| 685 } |
| 686 |
| 687 // static |
| 630 void View::ConvertPointToWidget(const View* src, gfx::Point* p) { | 688 void View::ConvertPointToWidget(const View* src, gfx::Point* p) { |
| 631 DCHECK(src); | 689 DCHECK(src); |
| 632 DCHECK(p); | 690 DCHECK(p); |
| 633 | 691 |
| 634 src->ConvertPointForAncestor(NULL, p); | 692 src->ConvertPointForAncestor(NULL, p); |
| 635 } | 693 } |
| 636 | 694 |
| 637 // static | 695 // static |
| 638 void View::ConvertPointFromWidget(const View* dest, gfx::Point* p) { | 696 void View::ConvertPointFromWidget(const View* dest, gfx::Point* p) { |
| 639 DCHECK(dest); | 697 DCHECK(dest); |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 742 } | 800 } |
| 743 | 801 |
| 744 // static | 802 // static |
| 745 bool View::get_use_acceleration_when_possible() { | 803 bool View::get_use_acceleration_when_possible() { |
| 746 return use_acceleration_when_possible; | 804 return use_acceleration_when_possible; |
| 747 } | 805 } |
| 748 | 806 |
| 749 // Input ----------------------------------------------------------------------- | 807 // Input ----------------------------------------------------------------------- |
| 750 | 808 |
| 751 View* View::GetEventHandlerForPoint(const gfx::Point& point) { | 809 View* View::GetEventHandlerForPoint(const gfx::Point& point) { |
| 752 // Walk the child Views recursively looking for the View that most | 810 return GetEventHandler(gfx::Rect(point, gfx::Size(1, 1)), |
| 753 // tightly encloses the specified point. | 811 EVENT_HANDLER_TYPE_MOUSE); |
| 812 } |
| 813 |
| 814 View* View::GetEventHandlerForRect(const gfx::Rect& rect) { |
| 815 // TODO: Consider expanding small (single point) rectangles. |
| 816 return GetEventHandler(rect, EVENT_HANDLER_TYPE_TOUCH); |
| 817 } |
| 818 |
| 819 View* View::GetEventHandler(const gfx::Rect& rect, EventType type) { |
| 820 View* closest_view = NULL; |
| 821 View* closest_untouched_view = NULL; |
| 822 double max_proportion = 0; |
| 823 int closest_distance = INT_MAX; |
| 754 for (int i = child_count() - 1; i >= 0; --i) { | 824 for (int i = child_count() - 1; i >= 0; --i) { |
| 755 View* child = child_at(i); | 825 View* child = child_at(i); |
| 756 if (!child->visible()) | 826 if (!child->visible()) |
| 757 continue; | 827 continue; |
| 758 | 828 |
| 759 gfx::Point point_in_child_coords(point); | 829 gfx::Rect child_rect(child->bounds()); |
| 760 ConvertPointToTarget(this, child, &point_in_child_coords); | 830 |
| 761 if (child->HitTestPoint(point_in_child_coords)) | 831 if (!child_rect.Intersects(rect)) |
| 762 return child->GetEventHandlerForPoint(point_in_child_coords); | 832 continue; |
| 833 |
| 834 gfx::Rect rect_in_child_coords(rect); |
| 835 View::ConvertRectToTarget(this, child, &rect_in_child_coords); |
| 836 View* cur_view = child->GetEventHandler(rect_in_child_coords, type); |
| 837 if (!cur_view) |
| 838 continue; |
| 839 |
| 840 if (type == EVENT_HANDLER_TYPE_MOUSE) |
| 841 return cur_view; |
| 842 |
| 843 gfx::Point touch_center(rect.CenterPoint()); |
| 844 gfx::Rect cur_rect(cur_view->GetLocalBounds()); |
| 845 View::ConvertRectToTarget(cur_view, this, &cur_rect); |
| 846 int distance = DistanceSquaredFromCenterLineToPoint(touch_center, |
| 847 cur_rect); |
| 848 double proportion = OverlapProportion(cur_rect, rect); |
| 849 if (proportion == 0) { |
| 850 if (distance < closest_distance) { |
| 851 closest_untouched_view = cur_view; |
| 852 closest_distance = distance; |
| 853 } |
| 854 } else if (!closest_view || proportion > max_proportion) { |
| 855 closest_view = cur_view; |
| 856 max_proportion = proportion; |
| 857 } |
| 763 } | 858 } |
| 764 return this; | 859 |
| 860 if (closest_view) |
| 861 return closest_view; |
| 862 |
| 863 gfx::Rect view_rect(GetLocalBounds()); |
| 864 double proportion = OverlapProportion(view_rect, rect); |
| 865 if (proportion > max_proportion) |
| 866 return this; |
| 867 if (closest_untouched_view) |
| 868 return closest_untouched_view; |
| 869 return type == EVENT_HANDLER_TYPE_MOUSE ? this : NULL; |
| 765 } | 870 } |
| 766 | 871 |
| 767 gfx::NativeCursor View::GetCursor(const ui::MouseEvent& event) { | 872 gfx::NativeCursor View::GetCursor(const ui::MouseEvent& event) { |
| 768 #if defined(OS_WIN) | 873 #if defined(OS_WIN) |
| 769 #if defined(USE_AURA) | 874 #if defined(USE_AURA) |
| 770 static ui::Cursor arrow; | 875 static ui::Cursor arrow; |
| 771 if (!arrow.platform()) | 876 if (!arrow.platform()) |
| 772 arrow.SetPlatformCursor(LoadCursor(NULL, IDC_ARROW)); | 877 arrow.SetPlatformCursor(LoadCursor(NULL, IDC_ARROW)); |
| 773 return arrow; | 878 return arrow; |
| 774 #else | 879 #else |
| (...skipping 1345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2120 gfx::Point widget_location(event.location()); | 2225 gfx::Point widget_location(event.location()); |
| 2121 ConvertPointToWidget(this, &widget_location); | 2226 ConvertPointToWidget(this, &widget_location); |
| 2122 GetWidget()->RunShellDrag(this, data, widget_location, drag_operations); | 2227 GetWidget()->RunShellDrag(this, data, widget_location, drag_operations); |
| 2123 return true; | 2228 return true; |
| 2124 #else | 2229 #else |
| 2125 return false; | 2230 return false; |
| 2126 #endif // !defined(OS_MACOSX) | 2231 #endif // !defined(OS_MACOSX) |
| 2127 } | 2232 } |
| 2128 | 2233 |
| 2129 } // namespace views | 2234 } // namespace views |
| OLD | NEW |