OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chrome/browser/ui/autofill/popup_controller_common.h" | 5 #include "chrome/browser/ui/autofill/popup_controller_common.h" |
6 | 6 |
7 #include <algorithm> | |
8 #include <utility> | |
9 | |
10 #include "content/public/browser/render_view_host.h" | 7 #include "content/public/browser/render_view_host.h" |
11 #include "content/public/browser/web_contents.h" | 8 #include "content/public/browser/web_contents.h" |
12 #include "ui/gfx/display.h" | |
13 #include "ui/gfx/geometry/rect_conversions.h" | |
14 #include "ui/gfx/geometry/vector2d.h" | |
15 #include "ui/gfx/screen.h" | |
16 | 9 |
17 namespace autofill { | 10 namespace autofill { |
18 | 11 |
19 PopupControllerCommon::PopupControllerCommon( | 12 PopupControllerCommon::PopupControllerCommon( |
20 const gfx::RectF& element_bounds, | 13 const gfx::RectF& element_bounds, |
21 base::i18n::TextDirection text_direction, | 14 base::i18n::TextDirection text_direction, |
22 const gfx::NativeView container_view, | 15 const gfx::NativeView container_view, |
23 content::WebContents* web_contents) | 16 content::WebContents* web_contents) |
24 : element_bounds_(element_bounds), | 17 : element_bounds_(element_bounds), |
25 text_direction_(text_direction), | 18 text_direction_(text_direction), |
(...skipping 20 matching lines...) Expand all Loading... |
46 void PopupControllerCommon::RemoveKeyPressCallback() { | 39 void PopupControllerCommon::RemoveKeyPressCallback() { |
47 if (web_contents_ && (!web_contents_->IsBeingDestroyed()) && | 40 if (web_contents_ && (!web_contents_->IsBeingDestroyed()) && |
48 key_press_event_target_ == web_contents_->GetRenderViewHost()) { | 41 key_press_event_target_ == web_contents_->GetRenderViewHost()) { |
49 web_contents_->GetRenderViewHost() | 42 web_contents_->GetRenderViewHost() |
50 ->GetWidget() | 43 ->GetWidget() |
51 ->RemoveKeyPressEventCallback(key_press_event_callback_); | 44 ->RemoveKeyPressEventCallback(key_press_event_callback_); |
52 } | 45 } |
53 key_press_event_target_ = NULL; | 46 key_press_event_target_ = NULL; |
54 } | 47 } |
55 | 48 |
56 gfx::Display PopupControllerCommon::GetDisplayNearestPoint( | |
57 const gfx::Point& point) const { | |
58 return gfx::Screen::GetScreenFor(container_view_)->GetDisplayNearestPoint( | |
59 point); | |
60 } | |
61 | |
62 const gfx::Rect PopupControllerCommon::RoundedElementBounds() const { | |
63 return gfx::ToEnclosingRect(element_bounds_); | |
64 } | |
65 | |
66 std::pair<int, int> PopupControllerCommon::CalculatePopupXAndWidth( | |
67 const gfx::Display& left_display, | |
68 const gfx::Display& right_display, | |
69 int popup_required_width) const { | |
70 int leftmost_display_x = left_display.bounds().x(); | |
71 int rightmost_display_x = | |
72 right_display.GetSizeInPixel().width() + right_display.bounds().x(); | |
73 | |
74 // Calculate the start coordinates for the popup if it is growing right or | |
75 // the end position if it is growing to the left, capped to screen space. | |
76 int right_growth_start = std::max(leftmost_display_x, | |
77 std::min(rightmost_display_x, | |
78 RoundedElementBounds().x())); | |
79 int left_growth_end = std::max(leftmost_display_x, | |
80 std::min(rightmost_display_x, | |
81 RoundedElementBounds().right())); | |
82 | |
83 int right_available = rightmost_display_x - right_growth_start; | |
84 int left_available = left_growth_end - leftmost_display_x; | |
85 | |
86 int popup_width = std::min(popup_required_width, | |
87 std::max(right_available, left_available)); | |
88 | |
89 std::pair<int, int> grow_right(right_growth_start, popup_width); | |
90 std::pair<int, int> grow_left(left_growth_end - popup_width, popup_width); | |
91 | |
92 // Prefer to grow towards the end (right for LTR, left for RTL). But if there | |
93 // is not enough space available in the desired direction and more space in | |
94 // the other direction, reverse it. | |
95 if (is_rtl()) { | |
96 return left_available >= popup_width || left_available >= right_available | |
97 ? grow_left | |
98 : grow_right; | |
99 } | |
100 return right_available >= popup_width || right_available >= left_available | |
101 ? grow_right | |
102 : grow_left; | |
103 } | |
104 | |
105 std::pair<int,int> PopupControllerCommon::CalculatePopupYAndHeight( | |
106 const gfx::Display& top_display, | |
107 const gfx::Display& bottom_display, | |
108 int popup_required_height) const { | |
109 int topmost_display_y = top_display.bounds().y(); | |
110 int bottommost_display_y = | |
111 bottom_display.GetSizeInPixel().height() + bottom_display.bounds().y(); | |
112 | |
113 // Calculate the start coordinates for the popup if it is growing down or | |
114 // the end position if it is growing up, capped to screen space. | |
115 int top_growth_end = std::max(topmost_display_y, | |
116 std::min(bottommost_display_y, | |
117 RoundedElementBounds().y())); | |
118 int bottom_growth_start = std::max(topmost_display_y, | |
119 std::min(bottommost_display_y, | |
120 RoundedElementBounds().bottom())); | |
121 | |
122 int top_available = bottom_growth_start - topmost_display_y; | |
123 int bottom_available = bottommost_display_y - top_growth_end; | |
124 | |
125 // TODO(csharp): Restrict the popup height to what is available. | |
126 if (bottom_available >= popup_required_height || | |
127 bottom_available >= top_available) { | |
128 // The popup can appear below the field. | |
129 return std::make_pair(bottom_growth_start, popup_required_height); | |
130 } else { | |
131 // The popup must appear above the field. | |
132 return std::make_pair(top_growth_end - popup_required_height, | |
133 popup_required_height); | |
134 } | |
135 } | |
136 | |
137 gfx::Rect PopupControllerCommon::GetPopupBounds(int desired_width, | |
138 int desired_height) const { | |
139 // This is the top left point of the popup if the popup is above the element | |
140 // and grows to the left (since that is the highest and furthest left the | |
141 // popup go could). | |
142 gfx::Point top_left_corner_of_popup = RoundedElementBounds().origin() + | |
143 gfx::Vector2d(RoundedElementBounds().width() - desired_width, | |
144 -desired_height); | |
145 | |
146 // This is the bottom right point of the popup if the popup is below the | |
147 // element and grows to the right (since the is the lowest and furthest right | |
148 // the popup could go). | |
149 gfx::Point bottom_right_corner_of_popup = RoundedElementBounds().origin() + | |
150 gfx::Vector2d(desired_width, | |
151 RoundedElementBounds().height() + desired_height); | |
152 | |
153 gfx::Display top_left_display = GetDisplayNearestPoint( | |
154 top_left_corner_of_popup); | |
155 gfx::Display bottom_right_display = GetDisplayNearestPoint( | |
156 bottom_right_corner_of_popup); | |
157 | |
158 std::pair<int, int> popup_x_and_width = | |
159 CalculatePopupXAndWidth(top_left_display, | |
160 bottom_right_display, | |
161 desired_width); | |
162 std::pair<int, int> popup_y_and_height = | |
163 CalculatePopupYAndHeight(top_left_display, | |
164 bottom_right_display, | |
165 desired_height); | |
166 | |
167 return gfx::Rect(popup_x_and_width.first, | |
168 popup_y_and_height.first, | |
169 popup_x_and_width.second, | |
170 popup_y_and_height.second); | |
171 } | |
172 | |
173 } // namespace autofill | 49 } // namespace autofill |
OLD | NEW |