Home | History | Annotate | Download | only in nav
      1 /*
      2  * Copyright 2007, The Android Open Source Project
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *  * Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  *  * Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "CachedPrefix.h"
     27 #include "CachedFrame.h"
     28 #include "CachedNode.h"
     29 #if DUMP_NAV_CACHE
     30 #include "CachedRoot.h"
     31 #endif
     32 
     33 #include "CachedHistory.h"
     34 
     35 namespace android {
     36 
     37 CachedHistory::CachedHistory() {
     38     memset(this, 0, sizeof(CachedHistory)); // this assume the class has no virtuals
     39     mLastMove = CachedFrame::UNINITIALIZED;
     40     mPriorMove = CachedFrame::UNINITIALIZED;
     41 }
     42 
     43 
     44 void CachedHistory::addToVisited(const CachedNode* node, CachedFrame::Direction direction)
     45 {
     46     memmove(&mVisited[1], &mVisited[0], sizeof(mVisited) - sizeof(mVisited[0]));
     47     mVisited[0].mNode = node;
     48     mVisited[0].mDirection = direction;
     49 }
     50 
     51 bool CachedHistory::checkVisited(const CachedNode* node, CachedFrame::Direction direction) const
     52 {
     53     // if the direction is unchanged and we've already visited this node, don't visit it again
     54     int index = 0;
     55     while (index < NAVIGATION_VISIT_DEPTH - 1) {
     56         if (direction != mVisited[index].mDirection)
     57             break;
     58         index++; // compare with last direction, previous to last node (where the arrow took us from)
     59         if (node == mVisited[index].mNode)
     60             return false;
     61     }
     62     return true;
     63 }
     64 
     65 void CachedHistory::pinMaxMin(const WebCore::IntRect& viewBounds)
     66 {
     67     if (mMinWorkingHorizontal < viewBounds.y() ||
     68             mMinWorkingHorizontal >= viewBounds.bottom())
     69         mMinWorkingHorizontal = viewBounds.y();
     70     if (mMaxWorkingHorizontal > viewBounds.bottom() ||
     71             mMaxWorkingHorizontal <= viewBounds.y())
     72         mMaxWorkingHorizontal = viewBounds.bottom();
     73     if (mMinWorkingVertical < viewBounds.x() ||
     74             mMinWorkingVertical >= viewBounds.right())
     75         mMinWorkingVertical = viewBounds.x();
     76     if (mMaxWorkingVertical > viewBounds.right() ||
     77             mMaxWorkingVertical <= viewBounds.x())
     78         mMaxWorkingVertical = viewBounds.right();
     79 }
     80 
     81 void CachedHistory::reset()
     82 {
     83     memset(mVisited, 0, sizeof(mVisited));
     84 //    mLastScroll = 0;
     85     mPriorBounds = WebCore::IntRect(0, 0, 0, 0);
     86     mDirectionChange = false;
     87     mDidFirstLayout = false;
     88     mPriorMove = mLastMove = CachedFrame::UNINITIALIZED;
     89     mMinWorkingHorizontal = mMinWorkingVertical = INT_MIN;
     90     mMaxWorkingHorizontal = mMaxWorkingVertical = INT_MAX;
     91 }
     92 
     93 void CachedHistory::setWorking(CachedFrame::Direction newMove,
     94     const CachedFrame* cursorFrame, const CachedNode* cursor,
     95     const WebCore::IntRect& viewBounds)
     96 {
     97     CachedFrame::Direction lastAxis = (CachedFrame::Direction) (mLastMove & ~CachedFrame::RIGHT_DOWN); // up, left or uninitialized
     98     CachedFrame::Direction newAxis = (CachedFrame::Direction) (newMove & ~CachedFrame::RIGHT_DOWN);
     99     bool change = newAxis != lastAxis;
    100     mDirectionChange = change && mLastMove != CachedFrame::UNINITIALIZED;
    101     if (cursor != NULL || mLastMove != CachedFrame::UNINITIALIZED) {
    102         mPriorMove = mLastMove;
    103         mLastMove = newMove;
    104     }
    105     const WebCore::IntRect* navBounds = &mNavBounds;
    106     if (cursor != NULL) {
    107         WebCore::IntRect cursorBounds = cursor->bounds(cursorFrame);
    108         if (cursorBounds.isEmpty() == false)
    109             mNavBounds = cursorBounds;
    110     }
    111     if (change) {   // uninitialized or change in direction
    112         if (lastAxis != CachedFrame::LEFT && navBounds->height() > 0) {
    113             mMinWorkingHorizontal = navBounds->y();
    114             mMaxWorkingHorizontal = navBounds->bottom();
    115         }
    116         if (lastAxis != CachedFrame::UP && navBounds->width() > 0) {
    117             mMinWorkingVertical = navBounds->x();
    118             mMaxWorkingVertical = navBounds->right();
    119         }
    120     }
    121     pinMaxMin(viewBounds);
    122 }
    123 
    124 #if DUMP_NAV_CACHE
    125 
    126 #define DEBUG_PRINT_BOOL(field) \
    127     DUMP_NAV_LOGD("// bool " #field "=%s;\n", b->field ? "true" : "false")
    128 
    129 #define DEBUG_PRINT_RECT(field) \
    130     { const WebCore::IntRect& r = b->field; \
    131     DUMP_NAV_LOGD("// IntRect " #field "={%d, %d, %d, %d};\n", \
    132         r.x(), r.y(), r.width(), r.height()); }
    133 
    134 CachedHistory* CachedHistory::Debug::base() const {
    135     CachedHistory* nav = (CachedHistory*) ((char*) this - OFFSETOF(CachedHistory, mDebug));
    136     return nav;
    137 }
    138 
    139 const char* CachedHistory::Debug::direction(CachedFrame::Direction d) const
    140 {
    141     switch (d) {
    142         case CachedFrame::LEFT: return "LEFT"; break;
    143         case CachedFrame::RIGHT: return "RIGHT"; break;
    144         case CachedFrame::UP: return "UP"; break;
    145         case CachedFrame::DOWN: return "DOWN"; break;
    146         default: return "UNINITIALIZED";
    147     }
    148 }
    149 
    150 void CachedHistory::Debug::print(CachedRoot* root) const
    151 {
    152     CachedHistory* b = base();
    153     DUMP_NAV_LOGD("// Visited mVisited[]={\n");
    154     for (size_t i = 0; i < NAVIGATION_VISIT_DEPTH; i++) {
    155         const Visited& visit = b->mVisited[i];
    156         const CachedNode* node = visit.mNode;
    157         int index = root != NULL && root->CachedFrame::mDebug.validate(node) ?
    158             node->index() : -1;
    159         DUMP_NAV_LOGD("    // { 0x%p (%d), %s },\n", node, index, direction(visit.mDirection));
    160     }
    161     DUMP_NAV_LOGD("// };\n");
    162 //    DUMP_NAV_LOGD("// int mLastScroll=%d;\n", b->mLastScroll);
    163     DEBUG_PRINT_RECT(mMouseBounds);
    164     DEBUG_PRINT_RECT(mNavBounds);
    165     DEBUG_PRINT_RECT(mPriorBounds);
    166     DEBUG_PRINT_BOOL(mDirectionChange);
    167     DEBUG_PRINT_BOOL(mDidFirstLayout);
    168     DUMP_NAV_LOGD("// CachedFrame::Direction mLastMove=%s, mPriorMove=%s;\n",
    169         direction(b->mLastMove), direction(b->mPriorMove));
    170     int max = b->mMaxWorkingHorizontal;
    171     DUMP_NAV_LOGD("static int TEST_MAX_H = %d;\n",  max);
    172     int min = b->mMinWorkingHorizontal;
    173     if (min == INT_MIN)
    174         min++;
    175     DUMP_NAV_LOGD("static int TEST_MIN_H = %d;\n",  min);
    176     max = b->mMaxWorkingVertical;
    177     DUMP_NAV_LOGD("static int TEST_MAX_V = %d;\n",  max);
    178     min = b->mMinWorkingVertical;
    179     if (min == INT_MIN)
    180         min++;
    181     DUMP_NAV_LOGD("static int TEST_MIN_V = %d;\n",  min);
    182     DUMP_NAV_LOGD("\n");
    183 }
    184 
    185 #endif
    186 
    187 }
    188