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

Unified Diff: content/renderer/disambiguation_popup_helper.cc

Issue 10885004: Implement disambiguation popup (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Fixing visibility Created 8 years, 2 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/disambiguation_popup_helper.cc
diff --git a/content/renderer/disambiguation_popup_helper.cc b/content/renderer/disambiguation_popup_helper.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1a55414c03f698fd3396539980d2e30a3c7a2b84
--- /dev/null
+++ b/content/renderer/disambiguation_popup_helper.cc
@@ -0,0 +1,106 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/disambiguation_popup_helper.h"
+
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h"
+#include "ui/gfx/size_conversions.h"
+
+using WebKit::WebRect;
+using WebKit::WebVector;
+
+namespace {
+
+// The amount of padding to add to the disambiguation popup to show
+// content around the possible elements, adding some context.
+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.
+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.
+const int kDisambiguationPopupMinimumTouchSize = 40;
+const float kDisambiguationPopupMaxScale = 5.0;
+const float kDisambiguationPopupMinScale = 2.0;
+
+// Compute the scaling factor to ensure the smallest touch candidate reaches
+// a certain clickable size after zooming
+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));
+}
+
+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.
+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 = ToCeiledSize(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);
+}
+
+} // unnamed namespace
+
+namespace content {
+
+float DisambiguationPopupHelper::ComputeZoomAreaAndScaleFactor(
+ const gfx::Rect& tap_rect,
+ const WebVector<WebRect>& target_rects,
+ const gfx::Size& viewport_size,
+ gfx::Rect* zoom_rect) {
+ *zoom_rect = tap_rect;
+ 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(viewport_size));
+
+ float scale = FindOptimalScaleFactor(target_rects);
+ *zoom_rect = CropZoomArea(
+ *zoom_rect, viewport_size, tap_rect.CenterPoint(), scale);
+
+ return scale;
+}
+
+} // namespace content
« no previous file with comments | « content/renderer/disambiguation_popup_helper.h ('k') | content/renderer/disambiguation_popup_helper_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698