コード例 #1
0
bool CursorRing::setup()
{
    m_node->localCursorRings(m_frame, &m_rings);
    if (!m_rings.size()) {
        DBG_NAV_LOG("!rings.size()");
        m_viewImpl->m_hasCursorBounds = false;
        return false;
    }
    m_isButton = false;
    m_viewImpl->gButtonMutex.lock();
    // If this is a button drawn by us (rather than webkit) do not draw the
    // cursor ring, since its cursor will be shown by a change in what we draw.
    // Should be in sync with recordButtons, since that will be called
    // before this.
    if (m_viewImpl->m_buttons.size() > 0) {
        WebCore::Node* cursorPointer = (WebCore::Node*) m_node->nodePointer();
        Container* end = m_viewImpl->m_buttons.end();
        for (Container* ptr = m_viewImpl->m_buttons.begin(); ptr != end; ptr++) {
            if (ptr->matches(cursorPointer)) {
                m_isButton = true;
                break;
            }
        }
    }
    m_viewImpl->gButtonMutex.unlock();
    m_bounds = m_node->localBounds(m_frame);
    m_viewImpl->updateCursorBounds(m_root, m_frame, m_node);

    bool useHitBounds = m_node->useHitBounds();
    if (useHitBounds)
        m_bounds = m_node->localHitBounds(m_frame);
    if (useHitBounds || m_node->useBounds()) {
        m_rings.clear();
        m_rings.append(m_bounds);
    }
    m_bounds.inflate(SkScalarCeil(CURSOR_RING_OUTER_DIAMETER));
    if (!m_node->hasCursorRing() || (m_node->isPlugin() && m_node->isFocus()))
        return false;
    m_flavor = NORMAL_FLAVOR;
    if (!m_isButton) {
        m_flavor = m_node->isSyntheticLink() ? FAKE_FLAVOR : NORMAL_FLAVOR;
        if (m_followedLink) {
            m_flavor = static_cast<Flavor>(m_flavor + NORMAL_ANIMATING);
        }
#if DEBUG_NAV_UI
        const WebCore::IntRect& ring = m_rings[0];
        DBG_NAV_LOGD("cursorNode=%d (nodePointer=%p) flavor=%s rings=%d"
            " (%d, %d, %d, %d) isPlugin=%s",
            m_node->index(), m_node->nodePointer(),
            m_flavor == FAKE_FLAVOR ? "FAKE_FLAVOR" :
            m_flavor == NORMAL_ANIMATING ? "NORMAL_ANIMATING" :
            m_flavor == FAKE_ANIMATING ? "FAKE_ANIMATING" : "NORMAL_FLAVOR",
            m_rings.size(), ring.x(), ring.y(), ring.width(), ring.height(),
            m_node->isPlugin() ? "true" : "false");
#endif
    }
    return true;
}
コード例 #2
0
 void doRect()
 {
     /* Record the outer bounds of the lines of text that intersect the
        touch coordinates, given some slop */
     if (SkIRect::Intersects(mPartial, mHit)) {
         if (mHitLeft > mPartial.fLeft)
             mHitLeft = mPartial.fLeft;
         DBG_NAV_LOGD("LeftCheck mHitLeft=%d", mHitLeft);
     } else if (mHitLeft == INT_MAX)
         return; // wait for intersect success
     /* If text is too far away vertically, don't consider it */
     if (!mBounds.isEmpty() && (mPartial.fTop > mBounds.fBottom + SLOP
             || mPartial.fBottom < mBounds.fTop - SLOP)) {
         DBG_NAV_LOGD("LeftCheck stop mPartial=(%d, %d, %d, %d)"
             " mBounds=(%d, %d, %d, %d)",
             mPartial.fLeft, mPartial.fTop, mPartial.fRight, mPartial.fBottom,
             mBounds.fLeft, mBounds.fTop, mBounds.fRight, mBounds.fBottom);
         mHitLeft = INT_MAX; // and disable future comparisons
         return;
     }
     /* If the considered text is completely to the left or right of the
        touch coordinates, skip it, turn off further detection */
     if (mPartial.fLeft > mX || mPartial.fRight < mX) {
         DBG_NAV_LOGD("LeftCheck stop mX=%d mPartial=(%d, %d, %d, %d)", mX,
             mPartial.fLeft, mPartial.fTop, mPartial.fRight, mPartial.fBottom);
         mHitLeft = INT_MAX;
         return;
     }
     /* record the smallest margins on the left and right */
     if (mMostLeft > mPartial.fLeft) {
         DBG_NAV_LOGD("LeftCheck new mMostLeft=%d (old=%d)", mPartial.fLeft,
             mMostLeft);
         mMostLeft = mPartial.fLeft;
     }
     if (mBounds.isEmpty())
         mBounds = mPartial;
     else if (mPartial.fBottom > mBounds.fBottom) {
         DBG_NAV_LOGD("LeftCheck new bottom=%d (old=%d)", mPartial.fBottom,
             mBounds.fBottom);
         mBounds.fBottom = mPartial.fBottom;
     }
 }
コード例 #3
0
void CursorRing::draw(SkCanvas* canvas, LayerAndroid* layer)
{
#if USE(ACCELERATED_COMPOSITING)
    int layerId = m_node->isInLayer() ? m_frame->layer(m_node)->uniqueId() : -1;
    if (layer->uniqueId() != layerId)
        return;
#endif
    if (canvas->quickReject(m_bounds, SkCanvas::kAA_EdgeType)) {
        DBG_NAV_LOGD("canvas->quickReject cursorNode=%d (nodePointer=%p)"
            " bounds=(%d,%d,w=%d,h=%d)", m_node->index(), m_node->nodePointer(),
            m_bounds.x(), m_bounds.y(), m_bounds.width(), m_bounds.height());
        m_followedLink = false;
        return;
    }
    unsigned rectCount = m_rings.size();
    SkRegion rgn;
    SkPath path;
    for (unsigned i = 0; i < rectCount; i++)
    {
        SkRect  r(m_rings[i]);
        SkIRect ir;

        r.round(&ir);
        ir.inset(-CURSOR_RING_OUTER_OUTSET, -CURSOR_RING_OUTER_OUTSET);
        rgn.op(ir, SkRegion::kUnion_Op);
    }
    rgn.getBoundaryPath(&path);

    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setPathEffect(new SkCornerPathEffect(CURSOR_RING_ROUNDEDNESS))->unref();
    if (m_flavor >= NORMAL_ANIMATING) { // pressed
        paint.setColor(cursorPressedColors[m_flavor - NORMAL_ANIMATING]);
        canvas->drawPath(path, paint);
    }
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(CURSOR_RING_OUTER_DIAMETER);
    paint.setColor(cursorOuterColors[m_flavor]);
    canvas->drawPath(path, paint);
    paint.setStrokeWidth(CURSOR_RING_INNER_DIAMETER);
    paint.setColor(cursorInnerColors[m_flavor]);
    canvas->drawPath(path, paint);
}
コード例 #4
0
ファイル: CachedNode.cpp プロジェクト: 325116067/semc-qsd8x50
void CachedNode::fixUpCursorRects(const CachedFrame* frame)
{
    if (mFixedUpCursorRects)
        return;
    mFixedUpCursorRects = true;
    // if the hit-test rect doesn't intersect any other rect, use it
    if (mHitBounds != mBounds && mHitBounds.contains(mBounds) &&
            frame->checkRings(this, mCursorRing, mHitBounds)) {
        DBG_NAV_LOGD("use mHitBounds (%d,%d,%d,%d)", mHitBounds.x(),
            mHitBounds.y(), mHitBounds.width(), mHitBounds.height());
        mUseHitBounds = true;
        return;
    }
    if (mNavableRects <= 1)
        return;
    // if there is more than 1 rect, and the bounds doesn't intersect
    // any other cursor ring bounds, use it
    if (frame->checkRings(this, mCursorRing, mBounds)) {
        DBG_NAV_LOGD("use mBounds (%d,%d,%d,%d)", mBounds.x(),
            mBounds.y(), mBounds.width(), mBounds.height());
        mUseBounds = true;
        return;
    }
#if DEBUG_NAV_UI
    {
        WebCore::IntRect* boundsPtr = mCursorRing.begin() - 1;
        const WebCore::IntRect* const boundsEnd = mCursorRing.begin() + mCursorRing.size();
        while (++boundsPtr < boundsEnd)
            LOGD("%s %d:(%d, %d, %d, %d)\n", __FUNCTION__, boundsPtr - mCursorRing.begin(),
                boundsPtr->x(), boundsPtr->y(), boundsPtr->width(), boundsPtr->height());
    }
#endif
    // q: need to know when rects are for drawing and hit-testing, but not mouse down calcs?
    bool again;
    do {
        again = false;
        size_t size = mCursorRing.size();
        WebCore::IntRect* unitBoundsPtr = mCursorRing.begin() - 1;
        const WebCore::IntRect* const unitBoundsEnd = mCursorRing.begin() + size;
        while (++unitBoundsPtr < unitBoundsEnd) {
            // any other unitBounds to the left or right of this one?
            int unitTop = unitBoundsPtr->y();
            int unitBottom = unitBoundsPtr->bottom();
            int unitLeft = unitBoundsPtr->x();
            int unitRight = unitBoundsPtr->right();
            WebCore::IntRect* testBoundsPtr = mCursorRing.begin() - 1;
            while (++testBoundsPtr < unitBoundsEnd) {
                if (unitBoundsPtr == testBoundsPtr)
                    continue;
                int testTop = testBoundsPtr->y();
                int testBottom = testBoundsPtr->bottom();
                int testLeft = testBoundsPtr->x();
                int testRight = testBoundsPtr->right();
                int candidateTop = unitTop > testTop ? unitTop : testTop;
                int candidateBottom = unitBottom < testBottom ? unitBottom : testBottom;
                int candidateLeft = unitRight < testLeft ? unitRight : testRight;
                int candidateRight = unitRight > testLeft ? unitLeft : testLeft;
                bool leftRight = true;
                if (candidateTop + OVERLAP >= candidateBottom ||
                        candidateLeft + OVERLAP >= candidateRight) {
                    candidateTop = unitBottom < testTop ? unitBottom : testBottom;
                    candidateBottom = unitBottom > testTop ? unitTop : testTop;
                    candidateLeft = unitLeft > testLeft ? unitLeft : testLeft;
                    candidateRight = unitRight < testRight ? unitRight : testRight;
                    if (candidateTop + OVERLAP >= candidateBottom ||
                            candidateLeft + OVERLAP >= candidateRight)
                        continue;
                    leftRight = false;
                }
                // construct candidate to add
                WebCore::IntRect candidate = WebCore::IntRect(candidateLeft, candidateTop, 
                    candidateRight - candidateLeft, candidateBottom - candidateTop);
                // does a different unit bounds intersect the candidate? if so, don't add
                WebCore::IntRect* checkBoundsPtr = mCursorRing.begin() - 1;
                while (++checkBoundsPtr < unitBoundsEnd) {
                    if (checkBoundsPtr->intersects(candidate) == false)
                        continue;
                    if (leftRight) {
                        if (candidateTop >= checkBoundsPtr->y() &&
                                candidateBottom > checkBoundsPtr->bottom())
                            candidateTop = checkBoundsPtr->bottom(); 
                        else if (candidateTop < checkBoundsPtr->y() &&
                                candidateBottom <= checkBoundsPtr->bottom())
                            candidateBottom = checkBoundsPtr->y();
                        else
                            goto nextCheck;
                    } else {
                        if (candidateLeft >= checkBoundsPtr->x() &&
                                candidateRight > checkBoundsPtr->right())
                            candidateLeft = checkBoundsPtr->right(); 
                        else if (candidateLeft < checkBoundsPtr->x() &&
                                candidateRight <= checkBoundsPtr->right())
                            candidateRight = checkBoundsPtr->x();
                        else
                            goto nextCheck;
                    }
                 } 
                 candidate = WebCore::IntRect(candidateLeft, candidateTop, 
                    candidateRight - candidateLeft, candidateBottom - candidateTop);
                 ASSERT(candidate.isEmpty() == false);
#if DEBUG_NAV_UI
                LOGD("%s %d:(%d, %d, %d, %d)\n", __FUNCTION__, mCursorRing.size(),
                    candidate.x(), candidate.y(), candidate.width(), candidate.height());
#endif
                mCursorRing.append(candidate);
                again = true;
                goto tryAgain;
        nextCheck:
                continue;
            }
        }
tryAgain:
        ;
    } while (again);
}