Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1633)

Unified Diff: content/renderer/render_view_impl.cc

Issue 10885004: Implement disambiguation popup (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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);
+}

Powered by Google App Engine
This is Rietveld 408576698