Chromium Code Reviews| Index: content/renderer/render_view_impl.cc |
| diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc |
| index 4cf9502c982b22a15050cb76d59a1897072d0215..a17177b67249ac5cd14035b91733a5c1002884e9 100644 |
| --- a/content/renderer/render_view_impl.cc |
| +++ b/content/renderer/render_view_impl.cc |
| @@ -355,6 +355,21 @@ static const float kScalingIncrement = 0.1f; |
| static const float kScalingIncrementForGesture = 0.01f; |
| +// The amount of padding to add to the disambiguation popup to show |
| +// content around the possible elements, adding some context. |
| +static const int kDisambiguationPopupPadding = 8; |
| + |
| +// Constants used for fitting the disambiguation popup inside the bounds of |
| +// the view. Note that there are mirror constants in PopupZoomer.java. |
| +static const int kDisambiguationPopupBoundsMargin = 25; |
| + |
| +// The smallest allowable touch target used for disambiguation popup. |
| +// This value is used to determine the minimum amount we need to scale to |
| +// make all targets touchable. |
| +static const int kDisambiguationPopupMinimumTouchSize = 40; |
| +static const float kDisambiguationPopupMaxScale = 5.0; |
| +static const float kDisambiguationPopupMinScale = 2.0; |
| + |
| #if defined(OS_ANDROID) |
| // Delay between tapping in content and launching the associated android intent. |
| // Used to allow users see what has been recognized as content. |
| @@ -1007,6 +1022,8 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) { |
| IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode) |
| IPC_MESSAGE_HANDLER(JavaBridgeMsg_Init, OnJavaBridgeInit) |
| IPC_MESSAGE_HANDLER(ViewMsg_SetAccessibilityMode, OnSetAccessibilityMode) |
| + IPC_MESSAGE_HANDLER(ViewMsg_ReleaseDisambiguationPopupDIB, |
| + OnReleaseDisambiguationPopupDIB) |
| // Have the super handle all other messages. |
| IPC_MESSAGE_UNHANDLED(handled = RenderWidget::OnMessageReceived(message)) |
| @@ -5892,3 +5909,101 @@ void RenderViewImpl::OnJavaBridgeInit() { |
| java_bridge_dispatcher_ = new JavaBridgeDispatcher(this); |
| #endif |
| } |
| + |
| +// Compute the scaling factor to ensure the smallest touch candidate reaches |
|
darin (slow to review)
2012/08/30 17:39:23
render_view_impl.cc is already packed with code fo
trchen
2012/08/30 21:15:22
That sounds like a great idea. I think splitting i
|
| +// a certain clickable size after zooming |
| +static float FindOptimalScaleFactor(const WebVector<WebRect>& target_rects) { |
| + using std::min; |
| + using std::max; |
| + if (!target_rects.size()) // shall never reach |
| + return kDisambiguationPopupMinScale; |
| + int smallest_target = min(target_rects[0].width, target_rects[0].height); |
| + for (size_t i = 1; i < target_rects.size(); i++) { |
| + smallest_target = min(smallest_target, target_rects[i].width); |
| + smallest_target = min(smallest_target, target_rects[i].height); |
| + } |
| + smallest_target = max(smallest_target, 1); |
| + return min(kDisambiguationPopupMaxScale, max(kDisambiguationPopupMinScale, |
| + static_cast<float>(kDisambiguationPopupMinimumTouchSize) |
| + / smallest_target)); |
| +} |
| + |
| +static void TrimEdges(int *e1, int *e2, int max_combined) { |
| + if (*e1 + *e2 <= max_combined) |
| + return; |
| + |
| + if (std::min(*e1, *e2) * 2 >= max_combined) { |
| + *e1 = *e2 = max_combined / 2; |
| + } else if (*e1 > *e2) { |
| + *e1 = max_combined - *e2; |
| + } else |
| + *e2 = max_combined - *e1; |
| +} |
| + |
| +// Ensure the disambiguation popup fits inside the screen, |
| +// clip the edges farthest to the touch point if needed. |
| +static gfx::Rect CropZoomArea(const gfx::Rect& zoom_rect, |
| + const gfx::Size& viewport_size, |
| + const gfx::Point& touch_point, |
| + float scale) { |
| + gfx::Size max_size = viewport_size; |
| + max_size.Enlarge(-2 * kDisambiguationPopupBoundsMargin, |
| + -2 * kDisambiguationPopupBoundsMargin); |
| + max_size = max_size.Scale(1.0 / scale); |
| + |
| + int left = touch_point.x() - zoom_rect.x(); |
| + int right = zoom_rect.right() - touch_point.x(); |
| + int top = touch_point.y() - zoom_rect.y(); |
| + int bottom = zoom_rect.bottom() - touch_point.y(); |
| + TrimEdges(&left, &right, max_size.width()); |
| + TrimEdges(&top, &bottom, max_size.height()); |
| + |
| + return gfx::Rect(touch_point.x() - left, |
| + touch_point.y() - top, |
| + left + right, |
| + top + bottom); |
| +} |
| + |
| +bool RenderViewImpl::handleDisambiguationPopup( |
|
darin (slow to review)
2012/08/30 17:39:23
why is this function named "handleDisambiguationPo
trchen
2012/08/30 21:15:22
Yea... I agree the naming is confusing here.
Up t
|
| + const WebKit::WebGestureEvent& event, |
| + const WebVector<WebRect>& target_rects) { |
| + gfx::Rect zoom_rect = event.boundingBox; |
| + for (size_t i = 0; i < target_rects.size(); i++) |
| + zoom_rect = zoom_rect.Union(gfx::Rect(target_rects[i])); |
| + zoom_rect.Inset(-kDisambiguationPopupPadding, -kDisambiguationPopupPadding); |
| + zoom_rect = zoom_rect.Intersect(gfx::Rect(GetSize())); |
| + |
| + float scale = FindOptimalScaleFactor(target_rects); |
| + zoom_rect = CropZoomArea( |
| + zoom_rect, GetSize(), gfx::Point(event.x, event.y), scale); |
| + |
| + gfx::Size canvas_size = zoom_rect.size(); |
| + canvas_size = canvas_size.Scale(scale); |
| + |
| + TransportDIB* transport_dib = NULL; |
| + { |
| + scoped_ptr<skia::PlatformCanvas> canvas( |
| + RenderProcess::current()->GetDrawingCanvas(&transport_dib, |
| + gfx::Rect(canvas_size))); |
| + if (!canvas.get()) |
| + return false; |
| + |
| + canvas->scale(scale, scale); |
| + |
| + canvas->translate(-zoom_rect.x(), -zoom_rect.y()); |
| + webwidget_->paint(webkit_glue::ToWebCanvas(canvas.get()), zoom_rect, |
| + WebWidget::ForceSoftwareRenderingAndIgnoreGPUResidentContent); |
| + } |
| + Send(new ViewHostMsg_MultipleTargetsTouched(routing_id_, |
| + zoom_rect, |
| + canvas_size, |
| + transport_dib->id())); |
| + |
| + return true; |
| +} |
| + |
| +void RenderViewImpl::OnReleaseDisambiguationPopupDIB( |
| + TransportDIB::Handle dib_handle) { |
| + TransportDIB* dib = TransportDIB::CreateWithHandle(dib_handle); |
| + RenderProcess::current()->ReleaseTransportDIB(dib); |
| +} |