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() || mMinWorkingHorizontal >= viewBounds.maxY())
     68         mMinWorkingHorizontal = viewBounds.y();
     69     if (mMaxWorkingHorizontal > viewBounds.maxY() || mMaxWorkingHorizontal <= viewBounds.y())
     70         mMaxWorkingHorizontal = viewBounds.maxY();
     71     if (mMinWorkingVertical < viewBounds.x() || mMinWorkingVertical >= viewBounds.maxX())
     72         mMinWorkingVertical = viewBounds.x();
     73     if (mMaxWorkingVertical > viewBounds.maxX() || mMaxWorkingVertical <= viewBounds.x())
     74         mMaxWorkingVertical = viewBounds.maxX();
     75 }
     76 
     77 void CachedHistory::reset()
     78 {
     79     memset(mVisited, 0, sizeof(mVisited));
     80 //    mLastScroll = 0;
     81     mPriorBounds = WebCore::IntRect(0, 0, 0, 0);
     82     mDirectionChange = false;
     83     mDidFirstLayout = false;
     84     mPriorMove = mLastMove = CachedFrame::UNINITIALIZED;
     85     mMinWorkingHorizontal = mMinWorkingVertical = INT_MIN;
     86     mMaxWorkingHorizontal = mMaxWorkingVertical = INT_MAX;
     87 }
     88 
     89 void CachedHistory::setWorking(CachedFrame::Direction newMove,
     90     const CachedFrame* cursorFrame, const CachedNode* cursor,
     91     const WebCore::IntRect& viewBounds)
     92 {
     93     CachedFrame::Direction lastAxis = (CachedFrame::Direction) (mLastMove & ~CachedFrame::RIGHT_DOWN); // up, left or uninitialized
     94     CachedFrame::Direction newAxis = (CachedFrame::Direction) (newMove & ~CachedFrame::RIGHT_DOWN);
     95     bool change = newAxis != lastAxis;
     96     mDirectionChange = change && mLastMove != CachedFrame::UNINITIALIZED;
     97     if (cursor != NULL || mLastMove != CachedFrame::UNINITIALIZED) {
     98         mPriorMove = mLastMove;
     99         mLastMove = newMove;
    100     }
    101     const WebCore::IntRect* navBounds = &mNavBounds;
    102     if (cursor != NULL) {
    103         WebCore::IntRect cursorBounds = cursor->bounds(cursorFrame);
    104         if (cursorBounds.isEmpty() == false)
    105             mNavBounds = cursorBounds;
    106     }
    107     if (change) {   // uninitialized or change in direction
    108         if (lastAxis != CachedFrame::LEFT && navBounds->height() > 0) {
    109             mMinWorkingHorizontal = navBounds->y();
    110             mMaxWorkingHorizontal = navBounds->maxY();
    111         }
    112         if (lastAxis != CachedFrame::UP && navBounds->width() > 0) {
    113             mMinWorkingVertical = navBounds->x();
    114             mMaxWorkingVertical = navBounds->maxX();
    115         }
    116     }
    117     pinMaxMin(viewBounds);
    118 }
    119 
    120 #if DUMP_NAV_CACHE
    121 
    122 #define DEBUG_PRINT_BOOL(field) \
    123     DUMP_NAV_LOGD("// bool " #field "=%s;\n", b->field ? "true" : "false")
    124 
    125 #define DEBUG_PRINT_RECT(field) \
    126     { const WebCore::IntRect& r = b->field; \
    127     DUMP_NAV_LOGD("// IntRect " #field "={%d, %d, %d, %d};\n", \
    128         r.x(), r.y(), r.width(), r.height()); }
    129 
    130 CachedHistory* CachedHistory::Debug::base() const {
    131     CachedHistory* nav = (CachedHistory*) ((char*) this - OFFSETOF(CachedHistory, mDebug));
    132     return nav;
    133 }
    134 
    135 const char* CachedHistory::Debug::direction(CachedFrame::Direction d) const
    136 {
    137     switch (d) {
    138         case CachedFrame::LEFT: return "LEFT"; break;
    139         case CachedFrame::RIGHT: return "RIGHT"; break;
    140         case CachedFrame::UP: return "UP"; break;
    141         case CachedFrame::DOWN: return "DOWN"; break;
    142         default: return "UNINITIALIZED";
    143     }
    144 }
    145 
    146 void CachedHistory::Debug::print(CachedRoot* root) const
    147 {
    148     CachedHistory* b = base();
    149     DUMP_NAV_LOGD("// Visited mVisited[]={\n");
    150     for (size_t i = 0; i < NAVIGATION_VISIT_DEPTH; i++) {
    151         const Visited& visit = b->mVisited[i];
    152         const CachedNode* node = visit.mNode;
    153         int index = root != NULL && root->CachedFrame::mDebug.validate(node) ?
    154             node->index() : -1;
    155         DUMP_NAV_LOGD("    // { 0x%p (%d), %s },\n", node, index, direction(visit.mDirection));
    156     }
    157     DUMP_NAV_LOGD("// };\n");
    158 //    DUMP_NAV_LOGD("// int mLastScroll=%d;\n", b->mLastScroll);
    159     DEBUG_PRINT_RECT(mMouseBounds);
    160     DEBUG_PRINT_RECT(mNavBounds);
    161     DEBUG_PRINT_RECT(mPriorBounds);
    162     DEBUG_PRINT_BOOL(mDirectionChange);
    163     DEBUG_PRINT_BOOL(mDidFirstLayout);
    164     DUMP_NAV_LOGD("// CachedFrame::Direction mLastMove=%s, mPriorMove=%s;\n",
    165         direction(b->mLastMove), direction(b->mPriorMove));
    166     int max = b->mMaxWorkingHorizontal;
    167     DUMP_NAV_LOGD("static int TEST_MAX_H = %d;\n",  max);
    168     int min = b->mMinWorkingHorizontal;
    169     if (min == INT_MIN)
    170         min++;
    171     DUMP_NAV_LOGD("static int TEST_MIN_H = %d;\n",  min);
    172     max = b->mMaxWorkingVertical;
    173     DUMP_NAV_LOGD("static int TEST_MAX_V = %d;\n",  max);
    174     min = b->mMinWorkingVertical;
    175     if (min == INT_MIN)
    176         min++;
    177     DUMP_NAV_LOGD("static int TEST_MIN_V = %d;\n",  min);
    178     DUMP_NAV_LOGD("\n");
    179 }
    180 
    181 #endif
    182 
    183 }
    184