Пример #1
0
// intersectingRegions and remainingFingerRegion are all in main frame contents coordinates,
// even on recursive calls of ::findIntersectingRegions.
bool FatFingers::findIntersectingRegions(Document* document,
                                         Vector<IntersectingRegion>& intersectingRegions, Platform::IntRectRegion& remainingFingerRegion)
{
    if (!document || !document->frame()->view())
        return false;

    // The layout needs to be up-to-date to determine if a node is focusable.
    document->updateLayoutIgnorePendingStylesheets();

    // Create fingerRect.
    IntPoint frameContentPos(document->frame()->view()->windowToContents(m_webPage->m_mainFrame->view()->contentsToWindow(m_contentPos)));

#if DEBUG_FAT_FINGERS
    IntRect fingerRect(fingerRectForPoint(frameContentPos));
    IntRect screenFingerRect = m_webPage->mapToTransformed(fingerRect);
    log(LogLevelInfo, "fat finger rect now %d, %d, %d, %d", screenFingerRect.x(), screenFingerRect.y(), screenFingerRect.width(), screenFingerRect.height());

    // only record the first finger rect
    if (document == m_webPage->m_mainFrame->document())
        m_debugFatFingerRect = m_webPage->mapToTransformed(m_webPage->mapFromContentsToViewport(fingerRect));
#endif

    bool foundOne = false;

    RenderLayer* lowestPositionedEnclosingLayerSoFar = 0;

    // Iterate over the list of nodes (and subrects of nodes where possible), for each saving the
    // intersection of the bounding box with the finger rect.
    ListHashSet<RefPtr<Node> > intersectedNodes;
    getNodesFromRect(document, frameContentPos, intersectedNodes);

    ListHashSet<RefPtr<Node> >::const_iterator it = intersectedNodes.begin();
    ListHashSet<RefPtr<Node> >::const_iterator end = intersectedNodes.end();
    for ( ; it != end; ++it) {
        Node* curNode = (*it).get();
        if (!curNode || !curNode->renderer())
            continue;

        if (remainingFingerRegion.isEmpty())
            break;

        bool isElement = curNode->isElementNode();
        if (isElement && isValidFrameOwner(toElement(curNode))) {

            HTMLFrameOwnerElement* owner = static_cast<HTMLFrameOwnerElement*>(curNode);
            Document* childDocument = owner && owner->contentFrame() ? owner->contentFrame()->document() : 0;
            if (!childDocument)
                continue;

            ASSERT(childDocument->frame()->view());

            foundOne |= findIntersectingRegions(childDocument, intersectingRegions, remainingFingerRegion);
        } else if (isElement && m_targetType == ClickableElement) {
            foundOne |= checkForClickableElement(toElement(curNode), intersectingRegions, remainingFingerRegion, lowestPositionedEnclosingLayerSoFar);
        } else if (m_targetType == Text)
            foundOne |= checkForText(curNode, intersectingRegions, remainingFingerRegion);
    }

    return foundOne;
}
Пример #2
0
const FatFingersResult FatFingers::findBestPoint()
{
    ASSERT(m_webPage);
    ASSERT(m_webPage->m_mainFrame);

    m_cachedRectHitTestResults.clear();

    FatFingersResult result(m_contentPos);
    m_matchingApproach = ClickableByDefault;

    // Lets set nodeUnderFatFinger to the result of a point based hit test here. If something
    // targable is actually found by ::findIntersectingRegions, then we might replace what we just set below later on.
    Element* elementUnderPoint;
    Element* clickableElementUnderPoint;
    getRelevantInfoFromPoint(m_webPage->m_mainFrame->document(), m_contentPos, elementUnderPoint, clickableElementUnderPoint);

    if (elementUnderPoint) {
        result.m_nodeUnderFatFinger = elementUnderPoint;

        // If we are looking for a Clickable Element and we found one, we can quit early.
        if (m_targetType == ClickableElement) {
            if (clickableElementUnderPoint) {
                setSuccessfulFatFingersResult(result, clickableElementUnderPoint, m_contentPos /*adjustedPosition*/);
                return result;
            }

            if (isElementClickable(elementUnderPoint)) {
                setSuccessfulFatFingersResult(result, elementUnderPoint, m_contentPos /*adjustedPosition*/);
                return result;
            }
        }
    }

#if DEBUG_FAT_FINGERS
    // Force blit to make the fat fingers rects show up.
    if (!m_debugFatFingerRect.isEmpty())
        m_webPage->m_backingStore->repaint(0, 0, m_webPage->transformedViewportSize().width(), m_webPage->transformedViewportSize().height(), true, true);
#endif

    Vector<IntersectingRegion> intersectingRegions;
    Platform::IntRectRegion remainingFingerRegion = Platform::IntRectRegion(fingerRectForPoint(m_contentPos));

    bool foundOne = findIntersectingRegions(m_webPage->m_mainFrame->document(), intersectingRegions, remainingFingerRegion);
    if (!foundOne) {
        m_matchingApproach = MadeClickableByTheWebpage;
        remainingFingerRegion = Platform::IntRectRegion(fingerRectForPoint(m_contentPos));
        foundOne = findIntersectingRegions(m_webPage->m_mainFrame->document(), intersectingRegions, remainingFingerRegion);
    }

    m_matchingApproach = Done;
    m_cachedRectHitTestResults.clear();

    if (!foundOne)
        return result;

    Node* bestNode = 0;
    Platform::IntRectRegion largestIntersectionRegion;
    IntPoint bestPoint;
    int largestIntersectionRegionArea = 0;

    Vector<IntersectingRegion>::const_iterator endIt = intersectingRegions.end();
    for (Vector<IntersectingRegion>::const_iterator it = intersectingRegions.begin(); it != endIt; ++it) {
        Node* currentNode = it->first;
        Platform::IntRectRegion currentIntersectionRegion = it->second;

        int currentIntersectionRegionArea = currentIntersectionRegion.area();
        if (currentIntersectionRegionArea > largestIntersectionRegionArea
            || (currentIntersectionRegionArea == largestIntersectionRegionArea
            && compareDistanceBetweenPoints(m_contentPos, currentIntersectionRegion, largestIntersectionRegion))) {
            bestNode = currentNode;
            largestIntersectionRegion = currentIntersectionRegion;
            largestIntersectionRegionArea = currentIntersectionRegionArea;
        }
    }

    if (!bestNode || largestIntersectionRegion.isEmpty())
        return result;

#if DEBUG_FAT_FINGERS
    m_debugFatFingerAdjustedPosition = m_webPage->mapToTransformed(m_webPage->mapFromContentsToViewport(largestIntersectionRegion.rects()[0].center()));
#endif

    setSuccessfulFatFingersResult(result, bestNode, largestIntersectionRegion.rects()[0].center() /*adjustedPosition*/);

    return result;
}
Пример #3
0
const FatFingersResult FatFingers::findBestPoint()
{
    ASSERT(m_webPage);
    ASSERT(m_webPage->m_mainFrame);

    // Even though we have clamped the point in libwebview to viewport, but there might be a rounding difference for viewport rect.
    // Clamp position to viewport to ensure we are inside viewport.
    IntRect viewportRect = m_webPage->mainFrame()->view()->visibleContentRect();
    m_contentPos = Platform::pointClampedToRect(m_contentPos, viewportRect);

    m_cachedRectHitTestResults.clear();

    FatFingersResult result(m_contentPos);

    // Lets set nodeUnderFatFinger to the result of a point based hit test here. If something
    // targable is actually found by ::findIntersectingRegions, then we might replace what we just set below later on.
    const HitTestResult& hitResult = m_webPage->hitTestResult(m_contentPos);
    Node* node = hitResult.innerNode();
    while (node && !node->isElementNode())
        node = node->parentNode();

    Element* elementUnderPoint = static_cast<Element*>(node);

    if (elementUnderPoint) {
        result.m_nodeUnderFatFinger = elementUnderPoint;

        // If we are looking for a Clickable Element and we found one, we can quit early.
        if (m_targetType == ClickableElement) {
            if (isElementClickable(elementUnderPoint)) {
                setSuccessfulFatFingersResult(result, elementUnderPoint, m_contentPos /*adjustedPosition*/);
                return result;
            }
            if (hitResult.URLElement()) {
                setSuccessfulFatFingersResult(result, hitResult.URLElement(), m_contentPos /*adjustedPosition*/);
                return result;
            }
        }
    }

#if DEBUG_FAT_FINGERS
    // Force blit to make the fat fingers rects show up.
    if (!m_debugFatFingerRect.isEmpty())
        m_webPage->m_backingStore->repaint(0, 0, m_webPage->transformedViewportSize().width(), m_webPage->transformedViewportSize().height(), true, true);
#endif

    Vector<IntersectingRegion> intersectingRegions;
    IntRectRegion remainingFingerRegion = IntRectRegion(fingerRectForPoint(m_contentPos));

    bool foundOne = findIntersectingRegions(m_webPage->m_mainFrame->document(), intersectingRegions, remainingFingerRegion);

    m_cachedRectHitTestResults.clear();

    if (!foundOne)
        return result;

    Node* bestNode = 0;
    IntRectRegion largestIntersectionRegion;
    int largestIntersectionRegionArea = 0;

    Vector<IntersectingRegion>::const_iterator endIt = intersectingRegions.end();
    for (Vector<IntersectingRegion>::const_iterator it = intersectingRegions.begin(); it != endIt; ++it) {
        Node* currentNode = it->first;
        IntRectRegion currentIntersectionRegion = it->second;

        int currentIntersectionRegionArea = currentIntersectionRegion.area();
        if (currentIntersectionRegionArea > largestIntersectionRegionArea
            || (currentIntersectionRegionArea == largestIntersectionRegionArea
            && compareDistanceBetweenPoints(m_contentPos, currentIntersectionRegion, largestIntersectionRegion))) {
            bestNode = currentNode;
            largestIntersectionRegion = currentIntersectionRegion;
            largestIntersectionRegionArea = currentIntersectionRegionArea;
        }
    }

    if (!bestNode || largestIntersectionRegion.isEmpty())
        return result;

#if DEBUG_FAT_FINGERS
    const Platform::ViewportAccessor* viewportAccessor = m_webPage->m_webkitThreadViewportAccessor;

    m_debugFatFingerAdjustedPosition = viewportAccessor->pixelViewportFromContents(
        viewportAccessor->roundToPixelFromDocumentContents(largestIntersectionRegion.rects()[0].center()));
#endif

    setSuccessfulFatFingersResult(result, bestNode, largestIntersectionRegion.rects()[0].center() /*adjustedPosition*/);

    return result;
}