From 95fa6e99128685c55e9be6f4362e67c288482a74 Mon Sep 17 00:00:00 2001 From: Leon Scroggins Date: Tue, 15 Dec 2009 16:33:28 -0500 Subject: If the DOM changes textfield focus, make the IME work properly. Fix for http://b/issue?id=2219166 Requires a change to frameworks/base Remove the old change to update the WebTextView when a key is pressed, since the IME does not generate key events. Instead, when the focus changes, and the IME is serving the WebTextView, immediately clear the cursor and update the WebTextView, so the user can continue typing. Also, allow "Next" to work on the currently focused textfield, even if it's not the cursor. Further, check for a new action if there is a focus but not a cursor. --- WebKit/android/nav/CachedRoot.cpp | 21 ++++++++++++--------- WebKit/android/nav/CachedRoot.h | 7 ++++--- WebKit/android/nav/WebView.cpp | 38 +++++++++++++++++++++++++------------- 3 files changed, 41 insertions(+), 25 deletions(-) (limited to 'WebKit/android/nav') diff --git a/WebKit/android/nav/CachedRoot.cpp b/WebKit/android/nav/CachedRoot.cpp index 2354ebc..5c1def5 100644 --- a/WebKit/android/nav/CachedRoot.cpp +++ b/WebKit/android/nav/CachedRoot.cpp @@ -756,14 +756,17 @@ bool CachedRoot::checkRings(const WTF::Vector& rings, return ringCheck.success(); } -CachedRoot::ImeAction CachedRoot::cursorTextFieldAction() const +CachedRoot::ImeAction CachedRoot::currentTextFieldAction() 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 CachedFrame* currentFrame; + const CachedNode* current = currentCursor(¤tFrame); + if (!current) { + // Although the cursor is not on a textfield, a textfield may have + // focus. Find the action for that textfield. + current = currentFocus(¤tFrame); + if (!current) + // Error case. No cursor and no focus. + return FAILURE; } const CachedNode* firstTextfield = nextTextField(0, 0, false); if (!firstTextfield) { @@ -773,8 +776,8 @@ CachedRoot::ImeAction CachedRoot::cursorTextFieldAction() const // Now find the next textfield/area starting with the cursor const CachedFrame* potentialFrame; const CachedNode* potentialNext - = cursorFrame->nextTextField(cursor, &potentialFrame, true); - if (potentialNext && cursorFrame->textInput(cursor)->formPointer() + = currentFrame->nextTextField(current, &potentialFrame, true); + if (potentialNext && currentFrame->textInput(current)->formPointer() == potentialFrame->textInput(potentialNext)->formPointer()) { // There is a textfield/area after the cursor in the same form, // so the textfield under the cursor should have the NEXT action diff --git a/WebKit/android/nav/CachedRoot.h b/WebKit/android/nav/CachedRoot.h index 435937a..5fdf8df 100644 --- a/WebKit/android/nav/CachedRoot.h +++ b/WebKit/android/nav/CachedRoot.h @@ -52,11 +52,12 @@ public: void checkForJiggle(int* ) const; bool checkRings(const WTF::Vector& 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, + // mouse cursor currently is, or where the focus is if there is no mouse + // cursor. If the mouse cursor is not on a textfield, // it will return FAILURE - ImeAction cursorTextFieldAction() const; + ImeAction currentTextFieldAction() const; + WebCore::IntPoint cursorLocation() 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 c29cb22..d1d5e86 100644 --- a/WebKit/android/nav/WebView.cpp +++ b/WebKit/android/nav/WebView.cpp @@ -104,11 +104,11 @@ struct JavaGlue { jmethodID m_sendMoveMouse; jmethodID m_sendMoveMouseIfLatest; jmethodID m_sendMotionUp; + jmethodID m_domChangedFocus; jmethodID m_getScaledMaxXScroll; jmethodID m_getScaledMaxYScroll; jmethodID m_getVisibleRect; jmethodID m_rebuildWebTextView; - jmethodID m_setOkayToNotMatch; jmethodID m_displaySoftKeyboard; jmethodID m_viewInvalidate; jmethodID m_viewInvalidateRect; @@ -134,11 +134,11 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) m_javaGlue.m_sendMoveMouse = GetJMethod(env, clazz, "sendMoveMouse", "(IIII)V"); m_javaGlue.m_sendMoveMouseIfLatest = GetJMethod(env, clazz, "sendMoveMouseIfLatest", "(Z)V"); m_javaGlue.m_sendMotionUp = GetJMethod(env, clazz, "sendMotionUp", "(IIIII)V"); + m_javaGlue.m_domChangedFocus = GetJMethod(env, clazz, "domChangedFocus", "()V"); m_javaGlue.m_getScaledMaxXScroll = GetJMethod(env, clazz, "getScaledMaxXScroll", "()I"); m_javaGlue.m_getScaledMaxYScroll = GetJMethod(env, clazz, "getScaledMaxYScroll", "()I"); m_javaGlue.m_getVisibleRect = GetJMethod(env, clazz, "sendOurVisibleRect", "()Landroid/graphics/Rect;"); m_javaGlue.m_rebuildWebTextView = GetJMethod(env, clazz, "rebuildWebTextView", "()V"); - m_javaGlue.m_setOkayToNotMatch = GetJMethod(env, clazz, "setOkayNotToMatch", "()V"); m_javaGlue.m_displaySoftKeyboard = GetJMethod(env, clazz, "displaySoftKeyboard", "(Z)V"); m_javaGlue.m_viewInvalidate = GetJMethod(env, clazz, "viewInvalidate", "()V"); m_javaGlue.m_viewInvalidateRect = GetJMethod(env, clazz, "viewInvalidate", "(IIII)V"); @@ -613,6 +613,7 @@ CachedRoot* getFrameCache(FrameCachePermission allowNewer) } DBG_NAV_LOGD("%s", "m_viewImpl->m_updatedFrameCache == true"); bool hadCursor = m_frameCacheUI && m_frameCacheUI->currentCursor(); + const CachedNode* oldFocus = m_frameCacheUI ? m_frameCacheUI->currentFocus() : 0; m_viewImpl->gFrameCacheMutex.lock(); delete m_frameCacheUI; delete m_navPictureUI; @@ -623,6 +624,19 @@ CachedRoot* getFrameCache(FrameCachePermission allowNewer) m_viewImpl->m_navPictureKit = 0; m_viewImpl->gFrameCacheMutex.unlock(); fixCursor(); + if (oldFocus && m_frameCacheUI) { + const CachedNode* newFocus = m_frameCacheUI->currentFocus(); + if (newFocus && oldFocus != newFocus && newFocus->isTextInput() + && oldFocus->isTextInput() + && newFocus != m_frameCacheUI->currentCursor()) { + // The focus has changed. We may need to update things. + LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->CallVoidMethod(m_javaGlue.object(env).get(), + m_javaGlue.m_domChangedFocus); + checkException(env); + } + } if (hadCursor && (!m_frameCacheUI || !m_frameCacheUI->currentCursor())) viewInvalidate(); // redraw in case cursor ring is still visible return m_frameCacheUI; @@ -839,7 +853,7 @@ bool moveCursor(int keyCode, int count, bool ignoreScroll) void notifyProgressFinished() { DBG_NAV_LOGD("cursorIsTextInput=%d", cursorIsTextInput(DontAllowNewer)); - rebuildWebTextView(false); + rebuildWebTextView(); #if DEBUG_NAV_UI if (m_frameCacheUI) { const CachedNode* focus = m_frameCacheUI->currentFocus(); @@ -964,7 +978,7 @@ bool motionUp(int x, int y, int slop) viewInvalidate(); if (result->isTextInput()) { bool isReadOnly = frame->textInput(result)->isReadOnly(); - rebuildWebTextView(true); + rebuildWebTextView(); if (!isReadOnly) displaySoftKeyboard(true); } else { @@ -1277,7 +1291,7 @@ bool hasFocusNode() return focusNode; } -void rebuildWebTextView(bool needNotMatchFocus) +void rebuildWebTextView() { JNIEnv* env = JSC::Bindings::getJNIEnv(); AutoJObject obj = m_javaGlue.object(env); @@ -1287,10 +1301,6 @@ void rebuildWebTextView(bool needNotMatchFocus) return; env->CallVoidMethod(obj.get(), m_javaGlue.m_rebuildWebTextView); checkException(env); - if (needNotMatchFocus) { - env->CallVoidMethod(obj.get(), m_javaGlue.m_setOkayToNotMatch); - checkException(env); - } } void displaySoftKeyboard(bool isTextView) @@ -2002,11 +2012,13 @@ static void nativeMoveCursorToNextTextInput(JNIEnv *env, jobject obj) CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer); if (!root) return; - const CachedNode* cursor = root->currentCursor(); - if (!cursor) + const CachedNode* current = root->currentCursor(); + if (!current) + current = root->currentFocus(); + if (!current) return; const CachedFrame* frame; - const CachedNode* next = root->nextTextField(cursor, &frame, true); + const CachedNode* next = root->nextTextField(current, &frame, true); if (!next) return; const WebCore::IntRect& bounds = next->bounds(); @@ -2027,7 +2039,7 @@ static jint nativeTextFieldAction(JNIEnv *env, jobject obj) CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer); if (!root) return static_cast(CachedRoot::FAILURE); - return static_cast(root->cursorTextFieldAction()); + return static_cast(root->currentTextFieldAction()); } static int nativeMoveGeneration(JNIEnv *env, jobject obj) -- cgit v1.1