Bug 94936 - Improve touch-adjustment at an iframe boundary.
Summary: Improve touch-adjustment at an iframe boundary.
Status: RESOLVED DUPLICATE of bug 95204
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebCore Misc. (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Kevin Ellis
URL:
Keywords:
Depends on: 95204
Blocks:
  Show dependency treegraph
 
Reported: 2012-08-24 07:27 PDT by Kevin Ellis
Modified: 2012-08-29 07:05 PDT (History)
3 users (show)

See Also:


Attachments
testcasE? (1.69 KB, text/html)
2012-08-24 12:28 PDT, Antonio Gomes
no flags Details
Example where it is difficult to tap on a checkbox. (10.00 KB, application/x-tar)
2012-08-27 08:10 PDT, Kevin Ellis
no flags Details
Quick Patch (3.75 KB, patch)
2012-08-28 04:42 PDT, Allan Sandfeld Jensen
no flags Details | Formatted Diff | Diff
Patch (9.50 KB, patch)
2012-08-28 08:30 PDT, Kevin Ellis
no flags Details | Formatted Diff | Diff
Patch (7.58 KB, patch)
2012-08-28 13:35 PDT, Kevin Ellis
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Kevin Ellis 2012-08-24 07:27:55 PDT
Rect-based hit-tests largely follow the same logic as point based tests returning once a hit layer is found unless conditions are met for depth sorting descendants.  While this is entirely appropriate for point-based tests, it does not allow a rect-based test to consider all possible elements when layers at different z-orders partially overlap the hit-test area.

This limitation can be problematic for touch adjustment if a small control such as a checkbox is close to the edge of a navigation bar at a higher z-index.  A touch that covers the checkbox can easily clip the edge of the navigation bar, which would cause the hit test to only return elements on the navigation bar in the hit-test results even if the center of the touch lies outside the boundary of the navigation bar.
Comment 1 Allan Sandfeld Jensen 2012-08-24 07:54:31 PDT
I thought RenderLayer::hitTestLayer already handled that. A layer is only considered hit (and thus terminating the search) if an element fully encloses the hit-tested touch-point. 

This behaviour does create another bug of returning too many elements, since the areas that have been hit are not subtracted from the hit-test and can continue to hit elements in layers below.
Comment 2 Antonio Gomes 2012-08-24 08:33:44 PDT
See FatFingers.cpp 

354             
355 bool FatFingers::checkForClickableElement(Element* curElement,
356                                           Vector<IntersectingRegion>& intersectingRegions,
357                                           Platform::IntRectRegion& remainingFingerRegion,
358                                           RenderLayer*& lowestPositionedEnclosingLayerSoFar)

our intersection area is a region. Every time we have a higher zindex'ed layer, we subtract that layer's area from the "remaining intersection region", once we are done with it.
Comment 3 Kevin Ellis 2012-08-24 10:23:03 PDT
(In reply to comment #1)
> I thought RenderLayer::hitTestLayer already handled that. A layer is only considered hit (and thus terminating the search) if an element fully encloses the hit-tested touch-point. 
> 
> This behaviour does create another bug of returning too many elements, since the areas that have been hit are not subtracted from the hit-test and can continue to hit elements in layers below.

Will write up a test case demonstrating the problem.  Here is a brief description of the page layout.  Have a series of absolute positioned elements each covering the full page, but with the active page having a higher z-index.  Have a left side bar that overlaps the page with a higher z-index.  The active page contains checkboxes that are closely aligned to the navigation bar.

I misinterpreted some of the diagnostic output in my original test.  When the touch overlaps a checkbox but clips the navigation bar, we see the navigation bar and active page in the hit test results, but not the checkbox.  So the results are not restricted to the highest z-index element as I originally thought; however, the search is not picking up all of the elements that overlap the hit-test area.  The hit-test scores are pretty meaningless given the size of the elements involved and it is simply pulling to the smaller one (the navigation bar) based on the relative scores.
Comment 4 Antonio Gomes 2012-08-24 12:28:33 PDT
Created attachment 160473 [details]
testcasE?
Comment 5 Kevin Ellis 2012-08-27 08:10:39 PDT
Created attachment 160722 [details]
Example where it is difficult to tap on a checkbox.  

Attached an example that demonstrates a case where it is tough to tap on a checkbox even if touch adjustment is enabled.  The z-order issue initially reported might be a red-herring.  It turned out to also be important for the navigation bar and page to be in separate <iframe>s.

How does rect-based hit testing work when it spans multiple <iframe>s?
Comment 6 Antonio Gomes 2012-08-27 08:13:02 PDT
> How does rect-based hit testing work when it spans multiple <iframe>s?

it adds the <iframe> to the list of reached nodes, iirc.
Comment 7 Kevin Ellis 2012-08-27 08:22:33 PDT
That is consistent with what I'm seeing for the example.  The <iframe>s are detected but do not provide enough information for touch adjustment since smaller elements inside the <iframe>s are not picked up as candidates.

One solution may be to repeat the hit test on each of the <iframe>s from the first test.  Alternatively, could repeat the hit-test just for the <iframe> that contains the midpoint of the touch.
Comment 8 Antonio Gomes 2012-08-27 08:28:31 PDT
(In reply to comment #7)
> That is consistent with what I'm seeing for the example.  The <iframe>s are detected but do not provide enough information for touch adjustment since smaller elements inside the <iframe>s are not picked up as candidates.
> 
> One solution may be to repeat the hit test on each of the <iframe>s from the first test.  Alternatively, could repeat the hit-test just for the <iframe> that contains the midpoint of the touch.

Right. this is what we do for blackberry port.

FatFingers.cpp:
...
335         bool isElement = curNode->isElementNode();
336         if (isElement && isValidFrameOwner(toElement(curNode))) {
337 
338             HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(curNode);
339             Document* childDocument = owner && owner->contentFrame() ? owner->contentFrame()->document() : 0;
340             if (!childDocument)
341                 continue;
342 
343             ASSERT(childDocument->frame()->view());
344 
345             foundOne |= findIntersectingRegions(childDocument, intersectingRegions, remainingFingerRegion);
Comment 9 Allan Sandfeld Jensen 2012-08-27 08:32:27 PDT
(In reply to comment #7)
> That is consistent with what I'm seeing for the example.  The <iframe>s are detected but do not provide enough information for touch adjustment since smaller elements inside the <iframe>s are not picked up as candidates.
> 
> One solution may be to repeat the hit test on each of the <iframe>s from the first test.  Alternatively, could repeat the hit-test just for the <iframe> that contains the midpoint of the touch.

I think, though I am not entirely sure, that touch-adjustment is automatically performed in the frame that contains the midpoint, because it will be the frame receiving the event. Testing down into iframes contained in the result would help with the case where the hot-spot is in the top frame, but would probably still give problems when the hot-spot is in a lower frame.
Comment 10 Allan Sandfeld Jensen 2012-08-28 04:11:19 PDT
The problem is in EventHandler::hitTestResultAtPoint, it descends into inner frames if the frame is the HitTestResult::innerNode. 

Unfortunately the innerNode is rather useless with rect-based tests, and is often just the first intersected node.

The underlying problem is that EventHandler::hitTestResultAtPoint is not that suitable for rect-based tests. 

I think we should remove the padding argument from EventHandler::hitTestResultAtPoint, so it can't be used for area based tests, and provide a EventHandler::hitTestResultAtRect function to replace it.
Comment 11 Allan Sandfeld Jensen 2012-08-28 04:42:01 PDT
Created attachment 160953 [details]
Quick Patch

Here is a quick experimental patch that solves the test-case.

I am not sure it the right way to do it though. This won't handle iframes that have been transformed for instance. To handle that we need to let the hit-test descend into inner-documents during the normal hit-test recursion, and add a parameter similar to AllowShadowContent, AllowInnerDocumentContent, that controls whether it should go into inner documents.
Comment 12 Kevin Ellis 2012-08-28 08:30:06 PDT
Created attachment 160991 [details]
Patch
Comment 13 Kevin Ellis 2012-08-28 08:42:23 PDT
Still some failures in the test case to resolve.  The approach taken was to refine the scoring to favor the candidate containing the target hotspot in the event that all candidate scores are poor.  A poor score is denoted by a distance to center score being greater than 1 implying that the touch did not overlap the center-line even though the target is larger than the touch area (in which case a much stronger hit is expected).  

The strategy differs somewhat from the approach used in zoomableIntersectionQuotient which assigns an infinite score if the touch hotspot is not contained.  The rationale is that it is easy to get very good coverage but have the hotspot lie outside the candidate for a small target.  For large targets, there is still some merit in touch adjustment if none of the candidates contain the hotspot.
Comment 14 Allan Sandfeld Jensen 2012-08-28 08:58:45 PDT
(In reply to comment #12)
> Created an attachment (id=160991) [details]
> Patch

Does this require the patch I attached (or the one in bug #95204), and if not, how would it overcome the issue of only getting the elements of one of the frames?
Comment 15 Kevin Ellis 2012-08-28 10:49:17 PDT
(In reply to comment #14)
> (In reply to comment #12)
> > Created an attachment (id=160991) [details] [details]
> > Patch
> 
> Does this require the patch I attached (or the one in bug #95204), and if not, how would it overcome the issue of only getting the elements of one of the frames?

Yes, all test cases pass with the patch for #95204.  On its own, this patch only partially addresses the issue of getting elements from only one frame.  It ensures (with some reasonable level of confidence) that the correct iframe is selected when the hit adjustment candidates are iframes, but does not resume touch adjustment on the position in the child iframe.
Comment 16 Kevin Ellis 2012-08-28 13:35:22 PDT
Created attachment 161048 [details]
Patch
Comment 17 Kevin Ellis 2012-08-28 13:37:53 PDT
Backed out TouchAdjustment tweak and updated expected test results.  Test contains expected failures which are fixed by patch 95204.
Comment 18 Allan Sandfeld Jensen 2012-08-29 02:28:38 PDT
(In reply to comment #17)
> Backed out TouchAdjustment tweak and updated expected test results.  Test contains expected failures which are fixed by patch 95204.

Oh nice. I will merge the bugs then and include your test in my patch (with attribution of course!).
Comment 19 Allan Sandfeld Jensen 2012-08-29 02:29:33 PDT

*** This bug has been marked as a duplicate of bug 95204 ***