diff options
author | Leon Scroggins <scroggo@google.com> | 2009-07-30 16:29:30 -0400 |
---|---|---|
committer | Leon Scroggins <scroggo@google.com> | 2009-07-31 11:33:01 -0400 |
commit | e3635bdd4530eeff44657cb1423a0572482381ce (patch) | |
tree | 10560cd9ed79aaa8d4faac770518e7cf3982f938 /WebKit | |
parent | 7ed73b9c2878d611c2c6954665d21aa6f162d5cc (diff) | |
download | external_webkit-e3635bdd4530eeff44657cb1423a0572482381ce.zip external_webkit-e3635bdd4530eeff44657cb1423a0572482381ce.tar.gz external_webkit-e3635bdd4530eeff44657cb1423a0572482381ce.tar.bz2 |
Allow user to jump to the next textfield.
In CachedFrame, add methods to find the next textfield and to
determine which ImeAction should be associated with a given textfield.
In WebView, uses these apis to determine the ImeAction and jump
to the next textfield and scroll it on screen. Requires a change to
frameworks/base.
Diffstat (limited to 'WebKit')
-rw-r--r-- | WebKit/android/nav/CachedFrame.cpp | 28 | ||||
-rw-r--r-- | WebKit/android/nav/CachedFrame.h | 12 | ||||
-rw-r--r-- | WebKit/android/nav/CachedRoot.cpp | 26 | ||||
-rw-r--r-- | WebKit/android/nav/CachedRoot.h | 10 | ||||
-rw-r--r-- | WebKit/android/nav/WebView.cpp | 84 |
5 files changed, 139 insertions, 21 deletions
diff --git a/WebKit/android/nav/CachedFrame.cpp b/WebKit/android/nav/CachedFrame.cpp index 4bf9805..416e880 100644 --- a/WebKit/android/nav/CachedFrame.cpp +++ b/WebKit/android/nav/CachedFrame.cpp @@ -891,6 +891,34 @@ int CachedFrame::maxWorkingVertical() const return history()->maxWorkingVertical(); } +const CachedNode* CachedFrame::nextTextField(const CachedNode* start, + const CachedFrame** framePtr, bool includeTextAreas) const +{ + CachedNode* test; + if (start) { + test = const_cast<CachedNode*>(start); + test++; + } else { + test = const_cast<CachedNode*>(mCachedNodes.begin()); + } + while (test != mCachedNodes.end()) { + CachedFrame* frame = const_cast<CachedFrame*>(hasFrame(test)); + if (frame) { + const CachedNode* node + = frame->nextTextField(0, framePtr, includeTextAreas); + if (node) + return node; + } else if (test->isTextField() + || (includeTextAreas && test->isTextArea())) { + if (framePtr) + *framePtr = this; + return test; + } + test++; + } + return 0; +} + bool CachedFrame::moveInFrame(MoveInDirection moveInDirection, const CachedNode* test, BestData* bestData, const CachedNode* cursor) const diff --git a/WebKit/android/nav/CachedFrame.h b/WebKit/android/nav/CachedFrame.h index 0df5489..fcfddb8 100644 --- a/WebKit/android/nav/CachedFrame.h +++ b/WebKit/android/nav/CachedFrame.h @@ -97,6 +97,18 @@ public: const CachedFrame* lastChild() const { return &mCachedFrames.last(); } CachedNode* lastNode() { return &mCachedNodes.last(); } CachedFrame* lastChild() { return &mCachedFrames.last(); } + /** + * Find the next textfield/textarea + * @param start Must be a CachedNode in this CachedFrame's tree, or + * null, in which case we start from the beginning. + * @param framePtr If not null, and a textfield/textarea is found, its + * CachedFrame will be pointed to by this pointer. + * @param includeTextAreas If true, will return the next textfield or area. + * Otherwise it only considers textfields. + * @return CachedNode* Next textfield (or area) + */ + const CachedNode* nextTextField(const CachedNode* start, + const CachedFrame** framePtr, bool includeTextAreas) const; const CachedFrame* parent() const { return mParent; } CachedFrame* parent() { return mParent; } bool sameFrame(const CachedFrame* ) const; diff --git a/WebKit/android/nav/CachedRoot.cpp b/WebKit/android/nav/CachedRoot.cpp index 93b4179..cf029c2 100644 --- a/WebKit/android/nav/CachedRoot.cpp +++ b/WebKit/android/nav/CachedRoot.cpp @@ -738,6 +738,32 @@ bool CachedRoot::checkRings(const WTF::Vector<WebCore::IntRect>& rings, return ringCheck.success(); } +CachedRoot::ImeAction CachedRoot::cursorTextFieldAction() const +{ + const CachedFrame* cursorFrame; + const CachedNode* cursor = currentCursor(&cursorFrame); + if (!cursor) { + // Error case. The cursor has no action, because there is no node under + // the cursor + return FAILURE; + } + const CachedNode* firstTextfield = nextTextField(0, 0, false); + if (!firstTextfield) { + // Error case. There are no textfields in this tree. + return FAILURE; + } + // Now find the next textfield/area starting with the cursor + if (nextTextField(cursor, 0, true)) { + // There is a textfield/area after the cursor, so the textfield under + // the cursor should have the NEXT action + return NEXT; + } + // If this line is reached, we know that the textfield under the cursor is + // the last one. If it is also the first, then it is the only one, so make + // the action GO. Otherwise, the action is DONE. + return (firstTextfield == cursor) ? GO : DONE; +} + const CachedNode* CachedRoot::findAt(const WebCore::IntRect& rect, const CachedFrame** framePtr, int* x, int* y, bool checkForHidden) const { diff --git a/WebKit/android/nav/CachedRoot.h b/WebKit/android/nav/CachedRoot.h index a64fa22..23cc126 100644 --- a/WebKit/android/nav/CachedRoot.h +++ b/WebKit/android/nav/CachedRoot.h @@ -40,6 +40,12 @@ class CachedNode; class CachedRoot : public CachedFrame { public: + enum ImeAction { + FAILURE = -1, + NEXT = 0, + GO = 1, + DONE = 2 + }; bool adjustForScroll(BestData* , Direction , WebCore::IntPoint* scrollPtr, bool findClosest); int checkForCenter(int x, int y) const; @@ -47,6 +53,10 @@ public: bool checkRings(const WTF::Vector<WebCore::IntRect>& rings, const WebCore::IntRect& bounds) const; WebCore::IntPoint cursorLocation() const; + // This method returns the desired ImeAction for the textfield where the + // mouse cursor currently is. If the mouse cursor is not on a textfield, + // it will return FAILURE + ImeAction cursorTextFieldAction() const; int documentHeight() { return mContents.height(); } int documentWidth() { return mContents.width(); } const CachedNode* findAt(const WebCore::IntRect& , const CachedFrame** , diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp index 37e4608..cbc91ae 100644 --- a/WebKit/android/nav/WebView.cpp +++ b/WebKit/android/nav/WebView.cpp @@ -339,29 +339,10 @@ void drawMatch(const SkRegion& region, SkCanvas* canvas, bool focused) canvas->drawPath(matchPath, m_findPaint); } -// Put a cap on the number of matches to draw. If the current page has more -// matches than this, only draw the focused match. -#define MAX_NUMBER_OF_MATCHES_TO_DRAW 101 - -void drawMatches(SkCanvas* canvas) +bool scrollRectOnScreen(int left, int top, int right, int bottom) { - if (!m_matches || !m_matches->size()) { - return; - } - if (m_findIndex >= m_matches->size()) { - m_findIndex = 0; - } - const MatchInfo& matchInfo = (*m_matches)[m_findIndex]; - const SkRegion& currentMatchRegion = matchInfo.getLocation(); - const SkIRect& currentMatchBounds = currentMatchRegion.getBounds(); - int left = currentMatchBounds.fLeft; - int top = currentMatchBounds.fTop; - int right = currentMatchBounds.fRight; - int bottom = currentMatchBounds.fBottom; WebCore::IntRect visible; getVisibleRect(&visible); - // Check to make sure that the highlighted match is on screen. If not, - // scroll it onscreen and return. int dx = 0; if (left < visible.x()) { dx = left - visible.x(); @@ -379,8 +360,28 @@ void drawMatches(SkCanvas* canvas) if ((dx|dy)) { scrollBy(dx, dy); viewInvalidate(); - return; + return true; } + return false; +} + +// Put a cap on the number of matches to draw. If the current page has more +// matches than this, only draw the focused match. +#define MAX_NUMBER_OF_MATCHES_TO_DRAW 101 + +void drawMatches(SkCanvas* canvas) +{ + if (!m_matches || !m_matches->size()) + return; + if (m_findIndex >= m_matches->size()) + m_findIndex = 0; + const MatchInfo& matchInfo = (*m_matches)[m_findIndex]; + const SkRegion& currentMatchRegion = matchInfo.getLocation(); + const SkIRect& currentMatchBounds = currentMatchRegion.getBounds(); + if (scrollRectOnScreen(currentMatchBounds.fLeft, currentMatchBounds.fTop, + currentMatchBounds.fRight, currentMatchBounds.fBottom)) + return; + // Set up the paints used for drawing the matches if (!m_isFindPaintSetUp) setUpFindPaint(); @@ -394,6 +395,8 @@ void drawMatches(SkCanvas* canvas) unsigned numberOfMatches = m_matches->size(); if (numberOfMatches > 1 && numberOfMatches < MAX_NUMBER_OF_MATCHES_TO_DRAW) { + WebCore::IntRect visible; + getVisibleRect(&visible); SkIRect visibleIRect(visible); for(unsigned i = 0; i < numberOfMatches; i++) { // The current match has already been drawn @@ -1871,6 +1874,41 @@ static void nativeDestroy(JNIEnv *env, jobject obj) delete view; } +static void nativeMoveCursorToNextTextInput(JNIEnv *env, jobject obj) +{ + WebView* view = GET_NATIVE_VIEW(env, obj); + CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer); + if (!root) + return; + const CachedNode* cursor = root->currentCursor(); + if (!cursor) + return; + const CachedFrame* frame; + const CachedNode* next = root->nextTextField(cursor, &frame, true); + if (!next) + return; + const WebCore::IntRect& bounds = next->bounds(); + root->rootHistory()->setMouseBounds(bounds); + view->updateCursorBounds(root, frame, next); + root->setCursor(const_cast<CachedFrame*>(frame), + const_cast<CachedNode*>(next)); + WebCore::IntPoint pos; + root->getSimulatedMousePosition(&pos); + view->sendMoveMouse(static_cast<WebCore::Frame*>(frame->framePointer()), + static_cast<WebCore::Node*>(next->nodePointer()), pos.x(), pos.y()); + view->scrollRectOnScreen(bounds.x(), bounds.y(), bounds.right(), + bounds.bottom()); +} + +static jint nativeTextFieldAction(JNIEnv *env, jobject obj) +{ + WebView* view = GET_NATIVE_VIEW(env, obj); + CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer); + if (!root) + return static_cast<jint>(CachedRoot::FAILURE); + return static_cast<jint>(root->cursorTextFieldAction()); +} + static int nativeMoveGeneration(JNIEnv *env, jobject obj) { WebView* view = GET_NATIVE_VIEW(env, obj); @@ -2023,6 +2061,8 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeMotionUp }, { "nativeMoveCursor", "(IIZ)Z", (void*) nativeMoveCursor }, + { "nativeMoveCursorToNextTextInput", "()V", + (void*) nativeMoveCursorToNextTextInput }, { "nativeMoveGeneration", "()I", (void*) nativeMoveGeneration }, { "nativeMoveSelection", "(IIZ)V", @@ -2039,6 +2079,8 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeSetFollowedLink }, { "nativeSetHeightCanMeasure", "(Z)V", (void*) nativeSetHeightCanMeasure }, + { "nativeTextFieldAction", "()I", + (void*) nativeTextFieldAction }, { "nativeTextGeneration", "()I", (void*) nativeTextGeneration }, { "nativeUpdateCachedTextfield", "(Ljava/lang/String;I)V", |