Changeset 122970 in webkit
- Timestamp:
- Jul 18, 2012 7:47:40 AM (12 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r122968 r122970 1 2012-07-18 Kevin Ellis <kevers@chromium.org> 2 3 TOUCH_ADJUSTMENT is too aggressive when snapping to large elements. 4 https://bugs.webkit.org/show_bug.cgi?id=91262 5 6 Reviewed by Antonio Gomes. 7 8 Adding a test case to ensure that the adjusted touch position is 9 within the bounds of the target element and the touch area. 10 Previously, the target position snapped to the center of the target 11 element, which can be far removed from the touch area. 12 13 The second test is for non-rectilinear elements, and verifies that 14 the touch area must overlap the true bounds of the element for an 15 adjustment to occur. 16 17 * touchadjustment/big-div-expected.txt: Added. 18 * touchadjustment/big-div.html: Added. 19 * touchadjustment/rotated-node-expected.txt: Added. 20 * touchadjustment/rotated-node.html: Added. 21 1 22 2012-07-18 Vsevolod Vlasov <vsevik@chromium.org> 2 23 -
trunk/Source/WebCore/ChangeLog
r122966 r122970 1 2012-07-18 Kevin Ellis <kevers@chromium.org> 2 3 TOUCH_ADJUSTMENT is too aggressive when snapping to large elements. 4 https://bugs.webkit.org/show_bug.cgi?id=91262 5 6 Reviewed by Antonio Gomes. 7 8 Constrains the extent to which the touch point can be adjusted when 9 generating synthetic mouse events when TOUCH_ADJUSTEMNT is enabled. 10 Previously, the target position snapped to the center of the target 11 element, which can be far removed from the touch position when tapping 12 on or near a large element. The refined strategy is to leave the 13 adjusted position unchanged if tapping within the element or to snap 14 to the center of the overlap region if the touch point lies outside the 15 bounds of the element, but the touch area and element bounds overlap. 16 For non-rectilineary bounds, a point lying outside the element boundary 17 is pulled towards the center of the element, by an amount limited by 18 the radius of the touch area. 19 20 Tests: touchadjustment/big-div.html 21 touchadjustment/rotated-node.html 22 23 * page/TouchAdjustment.cpp: 24 (WebCore::TouchAdjustment::contentsToWindow): 25 (TouchAdjustment): 26 (WebCore::TouchAdjustment::snapTo): 27 (WebCore::TouchAdjustment::findNodeWithLowestDistanceMetric): 28 1 29 2012-07-18 Sergey Rogulenko <rogulenko@google.com> 2 30 -
trunk/Source/WebCore/page/TouchAdjustment.cpp
r117128 r122970 240 240 } 241 241 242 FloatPoint contentsToWindow(FrameView *view, FloatPoint pt) 243 { 244 int x = static_cast<int>(pt.x() + 0.5f); 245 int y = static_cast<int>(pt.y() + 0.5f); 246 IntPoint adjusted = view->contentsToWindow(IntPoint(x, y)); 247 return FloatPoint(adjusted.x(), adjusted.y()); 248 } 249 250 bool snapTo(const SubtargetGeometry& geom, const IntPoint& touchPoint, const IntRect& touchArea, IntPoint& adjustedPoint) 251 { 252 FrameView* view = geom.node()->document()->view(); 253 FloatQuad quad = geom.quad(); 254 255 if (quad.isRectilinear()) { 256 IntRect contentBounds = geom.boundingBox(); 257 // Convert from frame coordinates to window coordinates. 258 IntRect bounds = view->contentsToWindow(contentBounds); 259 if (bounds.contains(touchPoint)) { 260 adjustedPoint = touchPoint; 261 return true; 262 } 263 if (bounds.intersects(touchArea)) { 264 bounds.intersect(touchArea); 265 adjustedPoint = bounds.center(); 266 return true; 267 } 268 return false; 269 } 270 271 // Non-rectilinear element. 272 // Convert quad from content to window coordinates. 273 FloatPoint p1 = contentsToWindow(view, quad.p1()); 274 FloatPoint p2 = contentsToWindow(view, quad.p2()); 275 FloatPoint p3 = contentsToWindow(view, quad.p3()); 276 FloatPoint p4 = contentsToWindow(view, quad.p4()); 277 quad = FloatQuad(p1, p2, p3, p4); 278 279 if (quad.containsPoint(touchPoint)) { 280 adjustedPoint = touchPoint; 281 return true; 282 } 283 284 // Pull point towards the center of the element. 285 float cx = 0.25 * (p1.x() + p2.x() + p3.x() + p4.x()); 286 float cy = 0.25 * (p1.y() + p2.y() + p3.y() + p4.y()); 287 FloatPoint center = FloatPoint(cx, cy); 288 289 FloatSize pullDirection = center - touchPoint; 290 float distanceToCenter = pullDirection.diagonalLength(); 291 292 // Use distance from center to corner of touch area to limit adjustment distance. 293 float dx = 0.5f * touchArea.width(); 294 float dy = 0.5f * touchArea.height(); 295 float touchRadius = sqrt(dx * dx + dy * dy); 296 297 float scaleFactor = touchRadius / distanceToCenter; 298 if (scaleFactor > 1) 299 scaleFactor = 1; 300 pullDirection.scale(scaleFactor); 301 302 int x = static_cast<int>(touchPoint.x() + pullDirection.width()); 303 int y = static_cast<int>(touchPoint.y() + pullDirection.height()); 304 IntPoint point(x, y); 305 306 if (quad.containsPoint(point)) { 307 adjustedPoint = point; 308 return true; 309 } 310 return false; 311 } 242 312 243 313 // A generic function for finding the target node with the lowest distance metric. A distance metric here is the result … … 250 320 SubtargetGeometryList::const_iterator it = subtargets.begin(); 251 321 const SubtargetGeometryList::const_iterator end = subtargets.end(); 322 IntPoint adjustedPoint; 252 323 for (; it != end; ++it) { 253 324 Node* node = it->node(); 254 325 float distanceMetric = distanceFunction(touchHotspot, touchArea, *it); 255 326 if (distanceMetric < bestDistanceMetric) { 256 targetPoint = roundedIntPoint(it->quad().center()); 257 targetArea = it->boundingBox(); 258 targetNode = node; 259 bestDistanceMetric = distanceMetric; 327 if (snapTo(*it, touchHotspot, touchArea, adjustedPoint)) { 328 targetPoint = adjustedPoint; 329 targetArea = it->boundingBox(); 330 targetNode = node; 331 bestDistanceMetric = distanceMetric; 332 } 260 333 } else if (distanceMetric == bestDistanceMetric) { 261 334 // Try to always return the inner-most element. 262 if (node->isDescendantOf(targetNode)) { 335 if (node->isDescendantOf(targetNode) && snapTo(*it, touchHotspot, touchArea, adjustedPoint)) { 336 targetPoint = adjustedPoint; 263 337 targetNode = node; 264 338 targetArea = it->boundingBox(); … … 268 342 if (targetNode) { 269 343 targetArea = targetNode->document()->view()->contentsToWindow(targetArea); 270 targetPoint = targetNode->document()->view()->contentsToWindow(targetPoint); 271 } 272 344 } 273 345 return (targetNode); 274 346 }
Note: See TracChangeset
for help on using the changeset viewer.