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 #ifndef CachedFrame_H 27 #define CachedFrame_H 28 29 #include "CachedInput.h" 30 #include "CachedLayer.h" 31 #include "CachedNode.h" 32 #include "IntRect.h" 33 #include "SkFixed.h" 34 #include "wtf/Vector.h" 35 36 class SkPicture; 37 38 namespace WebCore { 39 class Frame; 40 class Node; 41 } 42 43 namespace android { 44 45 class CachedHistory; 46 class CachedRoot; 47 48 // first node referenced by cache is always document 49 class CachedFrame { 50 public: 51 enum Direction { 52 UNINITIALIZED = -1, 53 LEFT, 54 RIGHT, 55 UP, 56 DOWN, 57 DIRECTION_COUNT, 58 DIRECTION_MASK = DIRECTION_COUNT - 1, 59 UP_DOWN = UP & DOWN, // mask and result 60 RIGHT_DOWN = RIGHT & DOWN, // mask and result 61 }; 62 enum Compare { 63 UNDECIDED = -1, 64 TEST_IS_BEST, 65 REJECT_TEST 66 }; 67 enum CursorInit { 68 CURSOR_UNINITIALIZED = -2, 69 CURSOR_CLEARED = -1, 70 CURSOR_SET = 0 71 }; CachedFrame()72 CachedFrame() {} add(CachedInput & input)73 void add(CachedInput& input) { mCachedTextInputs.append(input); } 74 #if USE(ACCELERATED_COMPOSITING) add(CachedLayer & layer)75 void add(CachedLayer& layer) { mCachedLayers.append(layer); } 76 #endif add(CachedNode & node)77 void add(CachedNode& node) { mCachedNodes.append(node); } addFrame(CachedFrame & child)78 void addFrame(CachedFrame& child) { mCachedFrames.append(child); } 79 WebCore::IntRect adjustBounds(const CachedNode* , 80 const WebCore::IntRect& ) const; 81 bool checkRings(const CachedNode* node, 82 const WTF::Vector<WebCore::IntRect>& rings, 83 const WebCore::IntRect& bounds) const; 84 bool checkVisited(const CachedNode* , CachedFrame::Direction ) const; childCount()85 size_t childCount() { return mCachedFrames.size(); } 86 void clearCursor(); currentCursor()87 const CachedNode* currentCursor() const { return currentCursor(NULL); } 88 const CachedNode* currentCursor(const CachedFrame** ) const; currentFocus()89 const CachedNode* currentFocus() const { return currentFocus(NULL); } 90 const CachedNode* currentFocus(const CachedFrame** ) const; 91 bool directionChange() const; document()92 const CachedNode* document() const { return mCachedNodes.begin(); } empty()93 bool empty() const { return mCachedNodes.size() < 2; } // must have 1 past doc 94 const CachedNode* findBestAt(const WebCore::IntRect& , int* best, 95 bool* inside, const CachedNode** , const CachedFrame** directFrame, 96 const CachedFrame** resultFrame, int* x, 97 int* y, bool checkForHidden) const; 98 const CachedFrame* findBestFrameAt(int x, int y) const; 99 const CachedNode* findBestHitAt(const WebCore::IntRect& , 100 const CachedFrame** , int* x, int* y) const; 101 void finishInit(); firstChild()102 CachedFrame* firstChild() { return mCachedFrames.begin(); } firstChild()103 const CachedFrame* firstChild() const { return mCachedFrames.begin(); } framePointer()104 void* framePointer() const { return mFrame; } getIndex(int index)105 CachedNode* getIndex(int index) { return index >= 0 ? 106 &mCachedNodes[index] : NULL; } 107 const CachedFrame* hasFrame(const CachedNode* node) const; 108 void hideCursor(); indexInParent()109 int indexInParent() const { return mIndexInParent; } 110 void init(const CachedRoot* root, int index, WebCore::Frame* frame); lastChild()111 const CachedFrame* lastChild() const { return &mCachedFrames.last(); } 112 #if USE(ACCELERATED_COMPOSITING) lastLayer()113 const CachedLayer* lastLayer() const { return &mCachedLayers.last(); } 114 #endif lastNode()115 CachedNode* lastNode() { return &mCachedNodes.last(); } lastChild()116 CachedFrame* lastChild() { return &mCachedFrames.last(); } 117 #if USE(ACCELERATED_COMPOSITING) 118 const CachedLayer* layer(const CachedNode* ) const; layerCount()119 size_t layerCount() const { return mCachedLayers.size(); } 120 #endif 121 WebCore::IntRect localBounds(const CachedNode* , 122 const WebCore::IntRect& ) const; parent()123 const CachedFrame* parent() const { return mParent; } parent()124 CachedFrame* parent() { return mParent; } 125 SkPicture* picture(const CachedNode* ) const; 126 void resetLayers(); 127 bool sameFrame(const CachedFrame* ) const; removeLast()128 void removeLast() { mCachedNodes.removeLast(); } 129 void resetClippedOut(); setContentsSize(int width,int height)130 void setContentsSize(int width, int height) { mContents.setWidth(width); 131 mContents.setHeight(height); } 132 bool setCursor(WebCore::Frame* , WebCore::Node* , int x, int y); setCursorIndex(int index)133 void setCursorIndex(int index) { mCursorIndex = index; } 134 void setData(); 135 bool setFocus(WebCore::Frame* , WebCore::Node* , int x, int y); setFocusIndex(int index)136 void setFocusIndex(int index) { mFocusIndex = index; } setLocalViewBounds(const WebCore::IntRect & bounds)137 void setLocalViewBounds(const WebCore::IntRect& bounds) { mLocalViewBounds = bounds; } size()138 int size() { return mCachedNodes.size(); } textInput(const CachedNode * node)139 const CachedInput* textInput(const CachedNode* node) const { 140 return node->isTextInput() ? &mCachedTextInputs[node->textInputIndex()] 141 : 0; 142 } 143 const CachedNode* validDocument() const; 144 protected: 145 const CachedNode* nextTextField(const CachedNode* start, 146 const CachedFrame** framePtr, bool* found) const; 147 struct BestData { 148 int mDistance; 149 int mSideDistance; 150 int mMajorDelta; // difference of center of object 151 // used only when leading and trailing edges contain another set of edges 152 int mMajorDelta2; // difference of leading edge (only used when center is same) 153 int mMajorButt; // checks for next cell butting up against or close to previous one 154 int mWorkingDelta; 155 int mWorkingDelta2; 156 int mNavDelta; 157 int mNavDelta2; 158 const CachedFrame* mFrame; 159 const CachedNode* mNode; 160 SkFixed mWorkingOverlap; // this and below are fuzzy answers instead of bools 161 SkFixed mNavOverlap; 162 SkFixed mPreferred; 163 bool mCursorChild; 164 bool mInNav; 165 bool mNavOutside; 166 bool mWorkingOutside; bottomBestData167 int bottom() const { return bounds().bottom(); } boundsBestData168 const WebCore::IntRect& bounds() const { return mNodeBounds; } 169 bool canBeReachedByAnotherDirection(); heightBestData170 int height() const { return bounds().height(); } inOrSubsumesNavBestData171 bool inOrSubsumesNav() const { return (mNavDelta ^ mNavDelta2) >= 0; } inOrSubsumesWorkingBestData172 bool inOrSubsumesWorking() const { return (mWorkingDelta ^ mWorkingDelta2) >= 0; } 173 int isContainer(BestData* ); mouseBoundsBestData174 const WebCore::IntRect& mouseBounds() const { return mMouseBounds; } 175 static SkFixed Overlap(int span, int left, int right); resetBestData176 void reset() { mNode = NULL; } rightBestData177 int right() const { return bounds().right(); } setMouseBoundsBestData178 void setMouseBounds(const WebCore::IntRect& b) { mMouseBounds = b; } setNodeBoundsBestData179 void setNodeBounds(const WebCore::IntRect& b) { mNodeBounds = b; } 180 void setDistances(); 181 bool setDownDirection(const CachedHistory* ); 182 bool setLeftDirection(const CachedHistory* ); 183 bool setRightDirection(const CachedHistory* ); 184 bool setUpDirection(const CachedHistory* ); 185 void setNavInclusion(int left, int right); 186 void setNavOverlap(int span, int left, int right); 187 void setWorkingInclusion(int left, int right); 188 void setWorkingOverlap(int span, int left, int right); widthBestData189 int width() const { return bounds().width(); } xBestData190 int x() const { return bounds().x(); } yBestData191 int y() const { return bounds().y(); } 192 private: // since computing these is complicated, protect them so that the 193 // are only written by appropriate helpers 194 WebCore::IntRect mMouseBounds; 195 WebCore::IntRect mNodeBounds; 196 }; 197 typedef const CachedNode* (CachedFrame::*MoveInDirection)( 198 const CachedNode* test, const CachedNode* limit, BestData* ) const; 199 void adjustToTextColumn(int* delta) const; 200 static bool CheckBetween(Direction , const WebCore::IntRect& bestRect, 201 const WebCore::IntRect& prior, WebCore::IntRect* result); 202 bool checkBetween(BestData* , Direction ); 203 int compare(BestData& testData, const BestData& bestData) const; 204 void findClosest(BestData* , Direction original, Direction test, 205 WebCore::IntRect* clip) const; 206 int frameNodeCommon(BestData& testData, const CachedNode* test, 207 BestData* bestData, BestData* originalData) const; 208 int framePartCommon(BestData& testData, const CachedNode* test, 209 BestData* ) const; 210 const CachedNode* frameDown(const CachedNode* test, const CachedNode* limit, 211 BestData* ) const; 212 const CachedNode* frameLeft(const CachedNode* test, const CachedNode* limit, 213 BestData* ) const; 214 const CachedNode* frameRight(const CachedNode* test, const CachedNode* limit, 215 BestData* ) const; 216 const CachedNode* frameUp(const CachedNode* test, const CachedNode* limit, 217 BestData* ) const; 218 int minWorkingHorizontal() const; 219 int minWorkingVertical() const; 220 int maxWorkingHorizontal() const; 221 int maxWorkingVertical() const; 222 bool moveInFrame(MoveInDirection , const CachedNode* test, BestData* ) const; 223 const WebCore::IntRect& _navBounds() const; 224 WebCore::IntRect mContents; 225 WebCore::IntRect mLocalViewBounds; 226 WebCore::IntRect mViewBounds; 227 WTF::Vector<CachedNode> mCachedNodes; 228 WTF::Vector<CachedFrame> mCachedFrames; 229 WTF::Vector<CachedInput> mCachedTextInputs; 230 #if USE(ACCELERATED_COMPOSITING) 231 WTF::Vector<CachedLayer> mCachedLayers; 232 #endif 233 void* mFrame; // WebCore::Frame*, used only to compare pointers 234 CachedFrame* mParent; 235 int mCursorIndex; 236 int mFocusIndex; 237 int mIndexInParent; // index within parent's array of children, or -1 if root 238 const CachedRoot* mRoot; 239 private: 240 CachedHistory* history() const; 241 #ifdef BROWSER_DEBUG 242 public: 243 CachedNode* find(WebCore::Node* ); // !!! probably debugging only 244 int mDebugIndex; 245 int mDebugLoopbackOffset; 246 #endif 247 #if !defined NDEBUG || DUMP_NAV_CACHE 248 public: 249 class Debug { 250 public: Debug()251 Debug() { 252 #if DUMP_NAV_CACHE 253 mFrameName[0] = '\0'; 254 #endif 255 #if !defined NDEBUG 256 mInUse = true; 257 #endif 258 } 259 #if !defined NDEBUG ~Debug()260 ~Debug() { mInUse = false; } 261 bool mInUse; 262 #endif 263 #if DUMP_NAV_CACHE 264 CachedFrame* base() const; 265 void print() const; 266 bool validate(const CachedNode* ) const; 267 char mFrameName[256]; 268 #endif 269 } mDebug; 270 #endif 271 }; 272 273 } 274 275 #endif 276