diff options
Diffstat (limited to 'WebKit/android/nav')
-rw-r--r-- | WebKit/android/nav/CacheBuilder.cpp | 94 | ||||
-rw-r--r-- | WebKit/android/nav/CacheBuilder.h | 17 | ||||
-rw-r--r-- | WebKit/android/nav/CachedFrame.cpp | 11 | ||||
-rw-r--r-- | WebKit/android/nav/CachedFrame.h | 7 | ||||
-rw-r--r-- | WebKit/android/nav/CachedInput.cpp | 62 | ||||
-rw-r--r-- | WebKit/android/nav/CachedInput.h | 78 | ||||
-rw-r--r-- | WebKit/android/nav/CachedNode.cpp | 54 | ||||
-rw-r--r-- | WebKit/android/nav/CachedNode.h | 60 | ||||
-rw-r--r-- | WebKit/android/nav/CachedNodeType.h | 23 | ||||
-rw-r--r-- | WebKit/android/nav/CachedRoot.cpp | 4 | ||||
-rw-r--r-- | WebKit/android/nav/WebView.cpp | 82 |
11 files changed, 318 insertions, 174 deletions
diff --git a/WebKit/android/nav/CacheBuilder.cpp b/WebKit/android/nav/CacheBuilder.cpp index c77f7fc..c9adb53 100644 --- a/WebKit/android/nav/CacheBuilder.cpp +++ b/WebKit/android/nav/CacheBuilder.cpp @@ -725,7 +725,7 @@ void CacheBuilder::Debug::wideString(const String& str) { CacheBuilder::CacheBuilder() { - mAllowableTypes = ALL_CACHEDNODETYPES; + mAllowableTypes = ALL_CACHEDNODE_BITS; #ifdef DUMP_NAV_CACHE_USING_PRINTF gNavCacheLogFile = NULL; #endif @@ -909,6 +909,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, cachedFrame->add(cachedParentNode); Node* node = parent; int cacheIndex = 1; + int textInputIndex = 0; Node* focused = doc->focusedNode(); if (focused) cachedRoot->setFocusBounds(focused->getRect()); @@ -953,7 +954,8 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, cachedFrame->addFrame(cachedChild); cachedNode.init(node); cachedNode.setIndex(cacheIndex++); - cachedNode.setChildFrameIndex(childFrameIndex); + cachedNode.setDataIndex(childFrameIndex); + cachedNode.setType(FRAME_CACHEDNODETYPE); #if DUMP_NAV_CACHE cachedNode.mDebug.mNodeIndex = nodeIndex; cachedNode.mDebug.mParentGroupIndex = Debug::ParentIndex( @@ -993,28 +995,19 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, bool computeCursorRings = false; bool hasClip = false; bool hasMouseOver = false; - bool isAnchor = false; - bool isArea = node->hasTagName(HTMLNames::areaTag); - bool isPassword = false; - bool isTextArea = false; - bool isTextField = false; - bool isReadOnly = false; - bool isRtlText = false; bool isUnclipped = false; bool isFocus = node == focused; bool takesFocus = false; - bool wantsKeyEvents = false; - int maxLength = -1; - int textSize = 12; int columnGap = 0; TextDirection direction = LTR; - String name; String exported; CachedNodeType type = NORMAL_CACHEDNODETYPE; + CachedInput cachedInput; IntRect bounds; IntRect absBounds; WTF::Vector<IntRect>* columns = NULL; - if (isArea) { + if (node->hasTagName(HTMLNames::areaTag)) { + type = AREA_CACHEDNODETYPE; HTMLAreaElement* area = static_cast<HTMLAreaElement*>(node); bounds = getAreaRect(area); bounds.move(globalOffsetX, globalOffsetY); @@ -1036,7 +1029,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, bounds = absBounds; isUnclipped = true; takesFocus = true; - wantsKeyEvents = true; + type = PLUGIN_CACHEDNODETYPE; goto keepNode; } if (nodeRenderer->isRenderBlock()) { @@ -1064,7 +1057,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, clip.mBounds.move(oRect.x(), oRect.y()); } } - if (node->isTextNode() && mAllowableTypes != NORMAL_CACHEDNODETYPE) { + if (node->isTextNode() && mAllowableTypes != NORMAL_CACHEDNODE_BITS) { if (last->mSomeParentTakesFocus) // don't look at text inside focusable node continue; CachedNodeType checkType; @@ -1080,7 +1073,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, DUMP_NAV_LOGD("%s\n", buffer); } #endif - type = (CachedNodeType) checkType; + type = checkType; // !!! test ! is the following line correctly needed for frames to work? cachedNode.init(node); const ClipColumnTracker& clipTrack = clipTracker.last(); @@ -1104,23 +1097,26 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, } if (node->hasTagName(WebCore::HTMLNames::inputTag)) { HTMLInputElement* input = (HTMLInputElement*) node; - - isTextField = input->isTextField(); - if (isTextField) { - wantsKeyEvents = true; - isReadOnly = input->readOnly(); + if (input->isTextField()) { + type = TEXT_INPUT_CACHEDNODETYPE; + cachedInput.init(); + cachedInput.setIsTextField(true); + cachedInput.setIsReadOnly(input->readOnly()); exported = input->value().threadsafeCopy(); + cachedInput.setIsPassword(input->inputType() == + HTMLInputElement::PASSWORD); + cachedInput.setMaxLength(input->maxLength()); + // If this does not need to be threadsafe, we can use crossThreadString(). + // See http://trac.webkit.org/changeset/49160. + cachedInput.setName(input->name().string().threadsafeCopy()); + // can't detect if this is drawn on top (example: deviant.com login parts) + isUnclipped = isTransparent; } - isPassword = input->inputType() == HTMLInputElement::PASSWORD; - maxLength = input->maxLength(); - // If this does not need to be threadsafe, we can use crossThreadString(). - // See http://trac.webkit.org/changeset/49160. - name = input->name().string().threadsafeCopy(); - isUnclipped = isTransparent; // can't detect if this is drawn on top (example: deviant.com login parts) } else if (node->hasTagName(HTMLNames::textareaTag)) { - isTextArea = wantsKeyEvents = true; + cachedInput.init(); + type = TEXT_INPUT_CACHEDNODETYPE; HTMLTextAreaElement* area = static_cast<HTMLTextAreaElement*>(node); - isReadOnly = area->readOnly(); + cachedInput.setIsReadOnly(area->readOnly()); exported = area->value().threadsafeCopy(); } else if (node->hasTagName(HTMLNames::aTag)) { const HTMLAnchorElement* anchorNode = @@ -1130,13 +1126,13 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, if (node->disabled()) continue; hasMouseOver = NodeHasEventListeners(node, &eventNames().mouseoverEvent, 1); - isAnchor = true; + type = ANCHOR_CACHEDNODETYPE; KURL href = anchorNode->href(); if (!href.isEmpty() && !WebCore::protocolIsJavaScript(href.string())) // Set the exported string for all non-javascript anchors. exported = href.string().threadsafeCopy(); } - if (isTextField || isTextArea) { + if (type == TEXT_INPUT_CACHEDNODETYPE) { RenderTextControl* renderText = static_cast<RenderTextControl*>(nodeRenderer); if (isFocus) @@ -1146,15 +1142,15 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, RenderStyle* style = nodeRenderer->style(); if (style) { isUnclipped |= !style->hasAppearance(); - textSize = style->fontSize(); - isRtlText = style->direction() == RTL || - style->textAlign() == WebCore::RIGHT || - style->textAlign() == WebCore::WEBKIT_RIGHT; + cachedInput.setTextSize(style->fontSize()); + cachedInput.setIsRtlText(style->direction() == RTL + || style->textAlign() == WebCore::RIGHT + || style->textAlign() == WebCore::WEBKIT_RIGHT); } } takesFocus = true; bounds = absBounds; - if (!isAnchor) { + if (type != ANCHOR_CACHEDNODETYPE) { bool isFocusable = node->isKeyboardFocusable(NULL) || node->isMouseFocusable() || node->isFocusable(); if (isFocusable == false) { @@ -1188,7 +1184,7 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, continue; } const IntRect& parentClip = clipTrack.mBounds; - if (hasClip == false && isAnchor) + if (hasClip == false && type == ANCHOR_CACHEDNODETYPE) clip = parentClip; else clip.intersect(parentClip); @@ -1204,30 +1200,24 @@ void CacheBuilder::BuildFrame(Frame* root, Frame* frame, } } cachedNode.setNavableRects(); - cachedNode.setChildFrameIndex(-1); cachedNode.setExport(exported); cachedNode.setHasCursorRing(hasCursorRing); cachedNode.setHasMouseOver(hasMouseOver); cachedNode.setHitBounds(absBounds); cachedNode.setIndex(cacheIndex); - cachedNode.setIsAnchor(isAnchor); - cachedNode.setIsArea(isArea); cachedNode.setIsFocus(isFocus); - cachedNode.setIsPassword(isPassword); - cachedNode.setIsReadOnly(isReadOnly); - cachedNode.setIsRtlText(isRtlText); - cachedNode.setIsTextArea(isTextArea); - cachedNode.setIsTextField(isTextField); cachedNode.setIsTransparent(isTransparent); cachedNode.setIsUnclipped(isUnclipped); - cachedNode.setMaxLength(maxLength); - cachedNode.setName(name); cachedNode.setParentIndex(last->mCachedNodeIndex); cachedNode.setParentGroup(ParentWithChildren(node)); cachedNode.setTabIndex(tabIndex); - cachedNode.setTextSize(textSize); cachedNode.setType(type); - cachedNode.setWantsKeyEvents(wantsKeyEvents); + if (type == TEXT_INPUT_CACHEDNODETYPE) { + cachedFrame->add(cachedInput); + cachedNode.setDataIndex(textInputIndex); + textInputIndex++; + } else + cachedNode.setDataIndex(-1); #if DUMP_NAV_CACHE cachedNode.mDebug.mNodeIndex = nodeIndex; cachedNode.mDebug.mParentGroupIndex = Debug::ParentIndex( @@ -2467,9 +2457,9 @@ bool CacheBuilder::isFocusableText(NodeWalk* walk, bool more, Node* node, baseStart = start; for (CachedNodeType checkType = ADDRESS_CACHEDNODETYPE; checkType <= PHONE_CACHEDNODETYPE; - checkType = (CachedNodeType) (checkType << 1)) + checkType = static_cast<CachedNodeType>(checkType + 1)) { - if ((checkType & mAllowableTypes) == 0) + if ((1 << (checkType - 1) & mAllowableTypes) == 0) continue; InlineTextBox* inlineTextBox = baseInline; FindState findState; diff --git a/WebKit/android/nav/CacheBuilder.h b/WebKit/android/nav/CacheBuilder.h index 0c12699..6cf1817 100644 --- a/WebKit/android/nav/CacheBuilder.h +++ b/WebKit/android/nav/CacheBuilder.h @@ -77,17 +77,17 @@ public: FOUND_COMPLETE }; CacheBuilder(); - void allowAllTextDetection() { mAllowableTypes = ALL_CACHEDNODETYPES; } + void allowAllTextDetection() { mAllowableTypes = ALL_CACHEDNODE_BITS; } void buildCache(CachedRoot* root); static bool ConstructPartRects(Node* node, const IntRect& bounds, IntRect* focusBounds, int x, int y, WTF::Vector<IntRect>* result); Node* currentFocus() const; - void disallowAddressDetection() { mAllowableTypes = (CachedNodeType) ( - mAllowableTypes & ~ADDRESS_CACHEDNODETYPE); } - void disallowEmailDetection() { mAllowableTypes = (CachedNodeType) ( - mAllowableTypes & ~EMAIL_CACHEDNODETYPE); } - void disallowPhoneDetection() { mAllowableTypes = (CachedNodeType) ( - mAllowableTypes & ~PHONE_CACHEDNODETYPE); } + void disallowAddressDetection() { mAllowableTypes = (CachedNodeBits) ( + mAllowableTypes & ~ADDRESS_CACHEDNODE_BIT); } + void disallowEmailDetection() { mAllowableTypes = (CachedNodeBits) ( + mAllowableTypes & ~EMAIL_CACHEDNODE_BIT); } + void disallowPhoneDetection() { mAllowableTypes = (CachedNodeBits) ( + mAllowableTypes & ~PHONE_CACHEDNODE_BIT); } static FoundState FindAddress(const UChar* , unsigned length, int* start, int* end, bool caseInsensitive); static void GetGlobalOffset(Frame* , int* x, int * y); @@ -126,7 +126,6 @@ private: BoundsPart mPart; WTF::Vector<BoundsPart> mParts; char mStore[NAVIGATION_MAX_PHONE_LENGTH + 1]; - CachedNodeType mStoreType; int mPartIndex; Node* mNode; Node* mFinalNode; @@ -241,7 +240,7 @@ private: bool setData(CachedFrame* ); Node* tryFocus(Direction direction); Node* trySegment(Direction direction, int mainStart, int mainEnd); - CachedNodeType mAllowableTypes; + CachedNodeBits mAllowableTypes; #if DUMP_NAV_CACHE public: class Debug { diff --git a/WebKit/android/nav/CachedFrame.cpp b/WebKit/android/nav/CachedFrame.cpp index 8a05cd6..cce5e4c 100644 --- a/WebKit/android/nav/CachedFrame.cpp +++ b/WebKit/android/nav/CachedFrame.cpp @@ -911,8 +911,8 @@ const CachedNode* CachedFrame::nextTextField(const CachedNode* start, = frame->nextTextField(0, framePtr, includeTextAreas); if (node) return node; - } else if (test->isTextField() - || (includeTextAreas && test->isTextArea())) { + } else if (test->isTextField(this) + || (includeTextAreas && test->isTextInput())) { if (framePtr) *framePtr = this; return test; @@ -1332,8 +1332,13 @@ void CachedFrame::Debug::print() const DEBUG_PRINT_RECT("//", VIEW, mViewBounds); DUMP_NAV_LOGD("// CachedNode mCachedNodes={ // count=%d\n", b->mCachedNodes.size()); for (CachedNode* node = b->mCachedNodes.begin(); - node != b->mCachedNodes.end(); node++) + node != b->mCachedNodes.end(); node++) { node->mDebug.print(); + if (node->isTextInput()) { + const CachedInput& input = b->input(node); + input.mDebug.print(); + } + } DUMP_NAV_LOGD("// }; // end of nodes\n"); DUMP_NAV_LOGD("// CachedFrame mCachedFrames={ // count=%d\n", b->mCachedFrames.size()); for (CachedFrame* child = b->mCachedFrames.begin(); diff --git a/WebKit/android/nav/CachedFrame.h b/WebKit/android/nav/CachedFrame.h index 0062424..f0996f7 100644 --- a/WebKit/android/nav/CachedFrame.h +++ b/WebKit/android/nav/CachedFrame.h @@ -26,6 +26,7 @@ #ifndef CachedFrame_H #define CachedFrame_H +#include "CachedInput.h" #include "CachedNode.h" #include "IntRect.h" #include "SkFixed.h" @@ -66,6 +67,7 @@ public: CURSOR_SET = 0 }; CachedFrame() {} + void add(CachedInput& input) { mCachedTextInputs.append(input); } void add(CachedNode& node) { mCachedNodes.append(node); } void addFrame(CachedFrame& child) { mCachedFrames.append(child); } bool checkVisited(const CachedNode* , CachedFrame::Direction ) const; @@ -123,6 +125,10 @@ public: void setFocusIndex(int index) { mFocusIndex = index; } void setLocalViewBounds(const WebCore::IntRect& bounds) { mLocalViewBounds = bounds; } int size() { return mCachedNodes.size(); } + const CachedInput* textInput(const CachedNode* node) const { + return node->isTextInput() ? &mCachedTextInputs[node->textInputIndex()] + : 0; + } const CachedNode* validDocument() const; protected: struct BestData { @@ -206,6 +212,7 @@ protected: WebCore::IntRect mViewBounds; WTF::Vector<CachedNode> mCachedNodes; WTF::Vector<CachedFrame> mCachedFrames; + WTF::Vector<CachedInput> mCachedTextInputs; void* mFrame; // WebCore::Frame*, used only to compare pointers CachedFrame* mParent; int mCursorIndex; diff --git a/WebKit/android/nav/CachedInput.cpp b/WebKit/android/nav/CachedInput.cpp new file mode 100644 index 0000000..0625ab8 --- /dev/null +++ b/WebKit/android/nav/CachedInput.cpp @@ -0,0 +1,62 @@ +/* + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "CachedPrefix.h" +#include "CachedInput.h" + +namespace android { + +#if DUMP_NAV_CACHE + +#define DEBUG_PRINT_BOOL(field) \ + DUMP_NAV_LOGD("// bool " #field "=%s;\n", b->field ? "true" : "false") + +CachedInput* CachedInput::Debug::base() const { + CachedInput* nav = (CachedInput*) ((char*) this - OFFSETOF(CachedInput, mDebug)); + return nav; +} + +void CachedInput::Debug::print() const +{ + CachedInput* b = base(); + char scratch[256]; + size_t index = snprintf(scratch, sizeof(scratch), "// char* mName=\""); + const UChar* ch = b->mName.characters(); + while (ch && *ch && index < sizeof(scratch)) { + UChar c = *ch++; + if (c < ' ' || c >= 0x7f) c = ' '; + scratch[index++] = c; + } + DUMP_NAV_LOGD("%.*s\"\n", index, scratch); + DUMP_NAV_LOGD("// int mMaxLength=%d;\n", b->mMaxLength); + DUMP_NAV_LOGD("// int mTextSize=%d;\n", b->mTextSize); + DEBUG_PRINT_BOOL(mIsPassword); + DEBUG_PRINT_BOOL(mIsRtlText); + DEBUG_PRINT_BOOL(mIsTextField); +} + +#endif + +} diff --git a/WebKit/android/nav/CachedInput.h b/WebKit/android/nav/CachedInput.h new file mode 100644 index 0000000..3b00b52 --- /dev/null +++ b/WebKit/android/nav/CachedInput.h @@ -0,0 +1,78 @@ +/* + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CachedInput_H +#define CachedInput_H + +#include "CachedDebug.h" +#include "PlatformString.h" + +namespace android { + +class CachedInput { +public: + CachedInput() { + // Initiaized to 0 in its array, so nothing to do in the + // constructor + } + void init() { + bzero(this, sizeof(CachedInput)); + mName = WebCore::String(); + } + bool isPassword() const { return mIsPassword; } + bool isReadOnly() const { return mIsReadOnly; } + bool isRtlText() const { return mIsRtlText; } + bool isTextField() const { return mIsTextField; } + int maxLength() const { return mMaxLength; }; + const WebCore::String& name() const { return mName; } + void setIsPassword(bool isPassword) { mIsPassword = isPassword; } + void setIsReadOnly(bool isReadOnly) { mIsReadOnly = isReadOnly; } + void setIsRtlText(bool isRtlText) { mIsRtlText = isRtlText; } + void setIsTextField(bool isTextField) { mIsTextField = isTextField; } + void setMaxLength(int maxLength) { mMaxLength = maxLength; } + void setName(const WebCore::String& name) { mName = name; } + void setTextSize(int textSize) { mTextSize = textSize; } + int textSize() const { return mTextSize; } +private: + WebCore::String mName; + int mMaxLength; + int mTextSize; + bool mIsPassword : 1; + bool mIsReadOnly : 1; + bool mIsRtlText : 1; + bool mIsTextField : 1; +#if DUMP_NAV_CACHE +public: + class Debug { +public: + CachedInput* base() const; + void print() const; + } mDebug; +#endif +}; + +} + +#endif diff --git a/WebKit/android/nav/CachedNode.cpp b/WebKit/android/nav/CachedNode.cpp index 7ac39ea..58ada58 100644 --- a/WebKit/android/nav/CachedNode.cpp +++ b/WebKit/android/nav/CachedNode.cpp @@ -76,6 +76,16 @@ bool CachedNode::clip(const WebCore::IntRect& bounds) return Clip(bounds, &mBounds, &mCursorRing); } +void CachedNode::cursorRingBounds(WebCore::IntRect* bounds) const +{ + int partMax = mNavableRects; + ASSERT(partMax > 0); + *bounds = mCursorRing[0]; + for (int partIndex = 1; partIndex < partMax; partIndex++) + bounds->unite(mCursorRing[partIndex]); + bounds->inflate(CURSOR_RING_HIT_TEST_RADIUS); +} + #define OVERLAP 3 void CachedNode::fixUpCursorRects(const CachedRoot* root) @@ -194,17 +204,6 @@ tryAgain: } while (again); } - -void CachedNode::cursorRingBounds(WebCore::IntRect* bounds) const -{ - int partMax = mNavableRects; - ASSERT(partMax > 0); - *bounds = mCursorRing[0]; - for (int partIndex = 1; partIndex < partMax; partIndex++) - bounds->unite(mCursorRing[partIndex]); - bounds->inflate(CURSOR_RING_HIT_TEST_RADIUS); -} - void CachedNode::hideCursor(CachedFrame* parent) { if (isFrame()) { @@ -218,12 +217,17 @@ void CachedNode::init(WebCore::Node* node) { bzero(this, sizeof(CachedNode)); mExport = WebCore::String(); - mName = WebCore::String(); mNode = node; - mParentIndex = mChildFrameIndex = -1; + mParentIndex = mDataIndex = -1; mType = android::NORMAL_CACHEDNODETYPE; } +bool CachedNode::isTextField(const CachedFrame* frame) const +{ + const CachedInput* input = frame->textInput(this); + return input ? input->isTextField() : false; +} + void CachedNode::move(int x, int y) { mBounds.move(x, y); @@ -306,6 +310,11 @@ const char* CachedNode::Debug::type(android::CachedNodeType t) const case ADDRESS_CACHEDNODETYPE: return "ADDRESS"; break; case EMAIL_CACHEDNODETYPE: return "EMAIL"; break; case PHONE_CACHEDNODETYPE: return "PHONE"; break; + case ANCHOR_CACHEDNODETYPE: return "ANCHOR"; break; + case AREA_CACHEDNODETYPE: return "AREA"; break; + case FRAME_CACHEDNODETYPE: return "FRAME"; break; + case PLUGIN_CACHEDNODETYPE: return "PLUGIN"; break; + case TEXT_INPUT_CACHEDNODETYPE: return "INPUT"; break; default: return "???"; } } @@ -322,14 +331,6 @@ void CachedNode::Debug::print() const scratch[index++] = c; } DUMP_NAV_LOGD("%.*s\"\n", index, scratch); - index = snprintf(scratch, sizeof(scratch), "// char* mName=\""); - ch = b->mName.characters(); - while (ch && *ch && index < sizeof(scratch)) { - UChar c = *ch++; - if (c < ' ' || c >= 0x7f) c = ' '; - scratch[index++] = c; - } - DUMP_NAV_LOGD("%.*s\"\n", index, scratch); DEBUG_PRINT_RECT(mBounds); DEBUG_PRINT_RECT(mHitBounds); const WTF::Vector<WebCore::IntRect>& rects = b->cursorRings(); @@ -341,12 +342,10 @@ void CachedNode::Debug::print() const DUMP_NAV_LOGD("// };\n"); DUMP_NAV_LOGD("// void* mNode=%p; // (%d) \n", b->mNode, mNodeIndex); DUMP_NAV_LOGD("// void* mParentGroup=%p; // (%d) \n", b->mParentGroup, mParentGroupIndex); - DUMP_NAV_LOGD("// int mChildFrameIndex=%d;\n", b->mChildFrameIndex); + DUMP_NAV_LOGD("// int mDataIndex=%d;\n", b->mDataIndex); DUMP_NAV_LOGD("// int mIndex=%d;\n", b->mIndex); - DUMP_NAV_LOGD("// int mMaxLength=%d;\n", b->mMaxLength); DUMP_NAV_LOGD("// int mNavableRects=%d;\n", b->mNavableRects); DUMP_NAV_LOGD("// int mParentIndex=%d;\n", b->mParentIndex); - DUMP_NAV_LOGD("// int mTextSize=%d;\n", b->mTextSize); DUMP_NAV_LOGD("// int mTabIndex=%d;\n", b->mTabIndex); DUMP_NAV_LOGD("// Condition mCondition=%s;\n", condition(b->mCondition)); DUMP_NAV_LOGD("// Type mType=%s;\n", type(b->mType)); @@ -355,22 +354,15 @@ void CachedNode::Debug::print() const DEBUG_PRINT_BOOL(mFixedUpCursorRects); DEBUG_PRINT_BOOL(mHasCursorRing); DEBUG_PRINT_BOOL(mHasMouseOver); - DEBUG_PRINT_BOOL(mIsAnchor); - DEBUG_PRINT_BOOL(mIsArea); DEBUG_PRINT_BOOL(mIsCursor); DEBUG_PRINT_BOOL(mIsFocus); DEBUG_PRINT_BOOL(mIsHidden); DEBUG_PRINT_BOOL(mIsParentAnchor); - DEBUG_PRINT_BOOL(mIsPassword); - DEBUG_PRINT_BOOL(mIsRtlText); - DEBUG_PRINT_BOOL(mIsTextArea); - DEBUG_PRINT_BOOL(mIsTextField); DEBUG_PRINT_BOOL(mIsTransparent); DEBUG_PRINT_BOOL(mIsUnclipped); DEBUG_PRINT_BOOL(mLast); DEBUG_PRINT_BOOL(mUseBounds); DEBUG_PRINT_BOOL(mUseHitBounds); - DEBUG_PRINT_BOOL(mWantsKeyEvents); DUMP_NAV_LOGD("\n"); } diff --git a/WebKit/android/nav/CachedNode.h b/WebKit/android/nav/CachedNode.h index bfc2107..a2e1f39 100644 --- a/WebKit/android/nav/CachedNode.h +++ b/WebKit/android/nav/CachedNode.h @@ -86,7 +86,7 @@ public: const WebCore::IntRect& bounds() const { return mBounds; } WebCore::IntRect* boundsPtr() { return &mBounds; } - int childFrameIndex() const { return mChildFrameIndex; } + int childFrameIndex() const { return isFrame() ? mDataIndex : -1; } void clearCondition() const { mCondition = NOT_REJECTED; } void clearCursor(CachedFrame* ); static bool Clip(const WebCore::IntRect& outer, WebCore::IntRect* inner, @@ -94,11 +94,11 @@ public: bool clip(const WebCore::IntRect& ); bool clippedOut() { return mClippedOut; } void cursorRingBounds(WebCore::IntRect* ) const; + WTF::Vector<WebCore::IntRect>& cursorRings() { return mCursorRing; } + const WTF::Vector<WebCore::IntRect>& cursorRings() const { return mCursorRing; } bool disabled() const { return mDisabled; } const CachedNode* document() const { return &this[-mIndex]; } void fixUpCursorRects(const CachedRoot* root); - WTF::Vector<WebCore::IntRect>& cursorRings() { return mCursorRing; } - const WTF::Vector<WebCore::IntRect>& cursorRings() const { return mCursorRing; } const WebCore::IntRect& getBounds() const { return mBounds; } void getBounds(WebCore::IntRect* bounds) const { *bounds = mBounds; } const WebCore::String& getExport() const { return mExport; } @@ -108,28 +108,24 @@ public: const WebCore::IntRect& hitBounds() const { return mHitBounds; } int index() const { return mIndex; } void init(WebCore::Node* node); - bool isAnchor() const { return mIsAnchor; } + bool isAnchor() const { return mType == ANCHOR_CACHEDNODETYPE; } bool isCursor() const { return mIsCursor; } - bool isArea() const { return mIsArea; } + bool isArea() const { return mType == AREA_CACHEDNODETYPE; } bool isFocus() const { return mIsFocus; } - bool isFrame() const { return mChildFrameIndex >= 0 ; } + bool isFrame() const { return mType == FRAME_CACHEDNODETYPE; } bool isHidden() const { return mIsHidden; } bool isNavable(const WebCore::IntRect& clip) const { return clip.intersects(mBounds); } - bool isPassword() const { return mIsPassword; } - bool isPlugin() const { - return mWantsKeyEvents && !mIsTextArea && !mIsTextField; + bool isPlugin() const { return mType == PLUGIN_CACHEDNODETYPE; } + bool isSyntheticLink() const { + return mType >= ADDRESS_CACHEDNODETYPE && mType <= PHONE_CACHEDNODETYPE; } - bool isReadOnly() const { return mIsReadOnly; } - bool isRtlText() const { return mIsRtlText; } - bool isTextArea() const { return mIsTextArea; } - bool isTextField() const { return mIsTextField; } + bool isTextField(const CachedFrame*) const; + bool isTextInput() const { return mType == TEXT_INPUT_CACHEDNODETYPE; } bool isTransparent() const { return mIsTransparent; } bool isUnclipped() const { return mIsUnclipped; } - int maxLength() const { return mMaxLength; }; void move(int x, int y); - const WebCore::String& name() const { return mName; } int navableRects() const { return mNavableRects; } void* nodePointer() const { return mNode; } bool noSecondChance() const { return mCondition > SECOND_CHANCE_END; } @@ -139,90 +135,66 @@ public: bool partRectsContains(const CachedNode* other) const; void reset(); void setBounds(const WebCore::IntRect& bounds) { mBounds = bounds; } - void setChildFrameIndex(int index) { mChildFrameIndex = index; } void setClippedOut(bool clipped) { mClippedOut = clipped; } void setCondition(Condition condition) const { mCondition = condition; } + void setDataIndex(int index) { mDataIndex = index; } void setDisabled(bool disabled) { mDisabled = disabled; } void setExport(const WebCore::String& exported) { mExport = exported; } void setHasCursorRing(bool hasRing) { mHasCursorRing = hasRing; } void setHasMouseOver(bool hasMouseOver) { mHasMouseOver = hasMouseOver; } void setHitBounds(const WebCore::IntRect& bounds) { mHitBounds = bounds; } void setIndex(int index) { mIndex = index; } - void setIsAnchor(bool isAnchor) { mIsAnchor = isAnchor; } - void setIsArea(bool isArea) { mIsArea = isArea; } void setIsCursor(bool isCursor) { mIsCursor = isCursor; } void setIsFocus(bool isFocus) { mIsFocus = isFocus; } void setIsParentAnchor(bool isAnchor) { mIsParentAnchor = isAnchor; } - void setIsPassword(bool isPassword) { mIsPassword = isPassword; } - void setIsReadOnly(bool isReadOnly) { mIsReadOnly = isReadOnly; } - void setIsRtlText(bool isRtlText) { mIsRtlText = isRtlText; } - void setIsTextArea(bool isTextArea) { mIsTextArea = isTextArea; } - void setIsTextField(bool isTextField) { mIsTextField = isTextField; } void setIsTransparent(bool isTransparent) { mIsTransparent = isTransparent; } void setIsUnclipped(bool unclipped) { mIsUnclipped = unclipped; } void setLast() { mLast = true; } - void setMaxLength(int maxLength) { mMaxLength = maxLength; } - void setName(const WebCore::String& name) { mName = name; } void setNavableRects() { mNavableRects = mCursorRing.size(); } void setParentGroup(void* group) { mParentGroup = group; } void setParentIndex(int parent) { mParentIndex = parent; } void setTabIndex(int index) { mTabIndex = index; } - void setTextSize(int textSize) { mTextSize = textSize; } void setType(CachedNodeType type) { mType = type; } - void setWantsKeyEvents(bool wantsKeys) { mWantsKeyEvents = wantsKeys; } void show() { mIsHidden = false; } int tabIndex() const { return mTabIndex; } + int textInputIndex() const { return isTextInput() ? mDataIndex : -1; } const CachedNode* traverseNextNode() const { return mLast ? NULL : &this[1]; } - int textSize() const { return mTextSize; } - CachedNodeType type() const { return mType; } bool useBounds() const { return mUseBounds; } bool useHitBounds() const { return mUseHitBounds; } - bool wantsKeyEvents() const { return mWantsKeyEvents; } + bool wantsKeyEvents() const { return isTextInput() || isPlugin(); } private: WebCore::String mExport; - WebCore::String mName; WebCore::IntRect mBounds; WebCore::IntRect mHitBounds; WTF::Vector<WebCore::IntRect> mCursorRing; void* mNode; // WebCore::Node*, only used to match pointers void* mParentGroup; // WebCore::Node*, only used to match pointers - int mChildFrameIndex; // set to -1 if node is not a frame + int mDataIndex; // child frame if a frame; input data index; or -1 int mIndex; // index of itself, to find first in array (document) - int mMaxLength; int mNavableRects; // FIXME: could be bitfield once I limit max number of rects int mParentIndex; - int mTextSize; int mTabIndex; mutable Condition mCondition : 5; // why the node was not chosen on the first pass - CachedNodeType mType : 3; + CachedNodeType mType : 4; bool mClippedOut : 1; bool mDisabled : 1; bool mFixedUpCursorRects : 1; bool mHasCursorRing : 1; bool mHasMouseOver : 1; - bool mIsAnchor : 1; - bool mIsArea : 1; bool mIsCursor : 1; bool mIsFocus : 1; bool mIsHidden : 1; bool mIsParentAnchor : 1; - bool mIsPassword : 1; - bool mIsReadOnly : 1; - bool mIsRtlText : 1; - bool mIsTextArea : 1; - bool mIsTextField : 1; bool mIsTransparent : 1; bool mIsUnclipped : 1; bool mLast : 1; // true if this is the last node in a group bool mUseBounds : 1; bool mUseHitBounds : 1; - bool mWantsKeyEvents : 1; // true for nodes like plugins #ifdef BROWSER_DEBUG public: WebCore::Node* webCoreNode() const { return (WebCore::Node*) mNode; } bool mDisplayMeasure; mutable bool mInCompare; - // mutable int mCondition; int mSideDistance; int mSecondSide; #endif diff --git a/WebKit/android/nav/CachedNodeType.h b/WebKit/android/nav/CachedNodeType.h index 75449da..21e2d40 100644 --- a/WebKit/android/nav/CachedNodeType.h +++ b/WebKit/android/nav/CachedNodeType.h @@ -29,11 +29,24 @@ namespace android { enum CachedNodeType { - NORMAL_CACHEDNODETYPE = 0, - ADDRESS_CACHEDNODETYPE = 1, - EMAIL_CACHEDNODETYPE = 2, - PHONE_CACHEDNODETYPE = 4, - ALL_CACHEDNODETYPES = 7 + NORMAL_CACHEDNODETYPE, + ADDRESS_CACHEDNODETYPE, + EMAIL_CACHEDNODETYPE, + PHONE_CACHEDNODETYPE, + ANCHOR_CACHEDNODETYPE, + AREA_CACHEDNODETYPE, + FRAME_CACHEDNODETYPE, + PLUGIN_CACHEDNODETYPE, + TEXT_INPUT_CACHEDNODETYPE +}; + +enum CachedNodeBits { + NORMAL_CACHEDNODE_BITS = 0, + ADDRESS_CACHEDNODE_BIT = 1 << (ADDRESS_CACHEDNODETYPE - 1), + EMAIL_CACHEDNODE_BIT = 1 << (EMAIL_CACHEDNODETYPE - 1), + PHONE_CACHEDNODE_BIT = 1 << (PHONE_CACHEDNODETYPE - 1), + ALL_CACHEDNODE_BITS = ADDRESS_CACHEDNODE_BIT | EMAIL_CACHEDNODE_BIT + | PHONE_CACHEDNODE_BIT }; } diff --git a/WebKit/android/nav/CachedRoot.cpp b/WebKit/android/nav/CachedRoot.cpp index 5bb2b19..83e2ab6 100644 --- a/WebKit/android/nav/CachedRoot.cpp +++ b/WebKit/android/nav/CachedRoot.cpp @@ -844,9 +844,9 @@ int CachedRoot::getBlockLeftEdge(int x, int y, float scale) const const CachedFrame* frame; int fx, fy; const CachedNode* node = findAt(rect, &frame, &fx, &fy, true); - if (node && (node->isTextArea() || node->isTextField() || node->isPlugin())) { + if (node && node->wantsKeyEvents()) { DBG_NAV_LOGD("x=%d (%s)", node->bounds().x(), - node->isTextArea() || node->isTextField() ? "text" : "plugin"); + node->isTextInput() ? "text" : "plugin"); return node->bounds().x(); } int halfW = (int) (mViewBounds.width() * scale * 0.5f); diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp index 4939637..f47b7f0 100644 --- a/WebKit/android/nav/WebView.cpp +++ b/WebKit/android/nav/WebView.cpp @@ -485,8 +485,8 @@ void drawCursorRing(SkCanvas* canvas) return; CursorRing::Flavor flavor = CursorRing::NORMAL_FLAVOR; if (!isButton) { - flavor = node->type() != NORMAL_CACHEDNODETYPE ? - CursorRing::FAKE_FLAVOR : CursorRing::NORMAL_FLAVOR; + flavor = node->isSyntheticLink() + ? CursorRing::FAKE_FLAVOR : CursorRing::NORMAL_FLAVOR; if (m_followedLink) { flavor = static_cast<CursorRing::Flavor> (flavor + CursorRing::NORMAL_ANIMATING); @@ -533,9 +533,8 @@ bool cursorIsTextInput(FrameCachePermission allowNewer) DBG_NAV_LOG("!cursor"); return false; } - DBG_NAV_LOGD("%s", - cursor->isTextArea() || cursor->isTextField() ? "true" : "false"); - return cursor->isTextArea() || cursor->isTextField(); + DBG_NAV_LOGD("%s", cursor->isTextInput() ? "true" : "false"); + return cursor->isTextInput(); } void cursorRingBounds(WebCore::IntRect* bounds) @@ -938,22 +937,22 @@ bool motionUp(int x, int y, int slop) updateCursorBounds(root, frame, result); root->setCursor(const_cast<CachedFrame*>(frame), const_cast<CachedNode*>(result)); - CachedNodeType type = result->type(); - if (type == NORMAL_CACHEDNODETYPE) { + bool syntheticLink = result->isSyntheticLink(); + if (!syntheticLink) { sendMotionUp( frame ? (WebCore::Frame*) frame->framePointer() : 0, result ? (WebCore::Node*) result->nodePointer() : 0, rx, ry); } viewInvalidate(); - if (result->isTextField() || result->isTextArea()) { + if (result->isTextInput()) { rebuildWebTextView(true); - if (!result->isReadOnly()) { + if (!frame->textInput(result)->isReadOnly()) { displaySoftKeyboard(true); } } else { clearTextEntry(); setFollowedLink(true); - if (type != NORMAL_CACHEDNODETYPE) + if (syntheticLink) overrideUrlLoading(result->getExport()); } return pageScrolled; @@ -1388,6 +1387,14 @@ static const CachedNode* getCursorNode(JNIEnv *env, jobject obj) return root ? root->currentCursor() : 0; } +static const CachedNode* getCursorNode(JNIEnv *env, jobject obj, + const CachedFrame** frame) +{ + WebView* view = GET_NATIVE_VIEW(env, obj); + CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer); + return root ? root->currentCursor(frame) : 0; +} + static const CachedNode* getFocusCandidate(JNIEnv *env, jobject obj) { WebView* view = GET_NATIVE_VIEW(env, obj); @@ -1407,6 +1414,19 @@ static const CachedNode* getFocusNode(JNIEnv *env, jobject obj) return root ? root->currentFocus() : 0; } +static const CachedInput* getInputCandidate(JNIEnv *env, jobject obj) +{ + WebView* view = GET_NATIVE_VIEW(env, obj); + CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer); + if (!root) + return 0; + const CachedFrame* frame; + const CachedNode* cursor = root->currentCursor(&frame); + if (!cursor || !cursor->wantsKeyEvents()) + cursor = root->currentFocus(&frame); + return cursor ? frame->textInput(cursor) : 0; +} + static jboolean nativeCursorMatchesFocus(JNIEnv *env, jobject obj) { const CachedNode* cursor = getCursorNode(env, obj); @@ -1467,14 +1487,20 @@ static bool nativeCursorIsAnchor(JNIEnv *env, jobject obj) static bool nativeCursorIsReadOnly(JNIEnv *env, jobject obj) { - const CachedNode* node = getCursorNode(env, obj); - return node ? node->isReadOnly() : false; + const CachedFrame* frame; + const CachedNode* node = getCursorNode(env, obj, &frame); + if (!node) + return false; + const CachedInput* input = frame->textInput(node); + if (!input) + return false; + return input->isReadOnly(); } static bool nativeCursorIsTextInput(JNIEnv *env, jobject obj) { const CachedNode* node = getCursorNode(env, obj); - return node ? node->isTextField() || node->isTextArea() : false; + return node ? node->isTextInput() : false; } static jobject nativeCursorText(JNIEnv *env, jobject obj) @@ -1586,40 +1612,40 @@ static jint nativeFocusCandidateFramePointer(JNIEnv *env, jobject obj) static bool nativeFocusCandidateIsPassword(JNIEnv *env, jobject obj) { - const CachedNode* node = getFocusCandidate(env, obj); - return node ? node->isPassword() : false; + const CachedInput* input = getInputCandidate(env, obj); + return input ? input->isPassword() : false; } static bool nativeFocusCandidateIsRtlText(JNIEnv *env, jobject obj) { - const CachedNode* node = getFocusCandidate(env, obj); - return node ? node->isRtlText() : false; + const CachedInput* input = getInputCandidate(env, obj); + return input ? input->isRtlText() : false; } static bool nativeFocusCandidateIsTextField(JNIEnv *env, jobject obj) { - const CachedNode* node = getFocusCandidate(env, obj); - return node ? node->isTextField() : false; + const CachedInput* input = getInputCandidate(env, obj); + return input ? input->isTextField() : false; } static bool nativeFocusCandidateIsTextInput(JNIEnv *env, jobject obj) { const CachedNode* node = getFocusCandidate(env, obj); - return node ? node->isTextField() || node->isTextArea() : false; + return node ? node->isTextInput() : false; } static jint nativeFocusCandidateMaxLength(JNIEnv *env, jobject obj) { - const CachedNode* node = getFocusCandidate(env, obj); - return node ? node->maxLength() : false; + const CachedInput* input = getInputCandidate(env, obj); + return input ? input->maxLength() : false; } static jobject nativeFocusCandidateName(JNIEnv *env, jobject obj) { - const CachedNode* node = getFocusCandidate(env, obj); - if (!node) + const CachedInput* input = getInputCandidate(env, obj); + if (!input) return 0; - const WebCore::String& name = node->name(); + const WebCore::String& name = input->name(); return env->NewString((jchar*)name.characters(), name.length()); } @@ -1653,8 +1679,8 @@ static jobject nativeFocusCandidateText(JNIEnv *env, jobject obj) static jint nativeFocusCandidateTextSize(JNIEnv *env, jobject obj) { - const CachedNode* node = getFocusCandidate(env, obj); - return node ? node->textSize() : 0; + const CachedInput* input = getInputCandidate(env, obj); + return input ? input->textSize() : 0; } static bool nativeFocusCandidateIsPlugin(JNIEnv *env, jobject obj) @@ -1854,7 +1880,7 @@ static void nativeUpdateCachedTextfield(JNIEnv *env, jobject obj, jstring update if (!root) return; const CachedNode* cachedFocusNode = root->currentFocus(); - if (!cachedFocusNode || (!cachedFocusNode->isTextField() && !cachedFocusNode->isTextArea())) + if (!cachedFocusNode || !cachedFocusNode->isTextInput()) return; WebCore::String webcoreString = to_string(env, updatedText); (const_cast<CachedNode*>(cachedFocusNode))->setExport(webcoreString); |