From 3e63d9b33b753ca86d0765d1b3d711114ba9e34f Mon Sep 17 00:00:00 2001 From: Leon Scroggins Date: Fri, 14 May 2010 15:38:53 -0400 Subject: Allow WebKit to scroll selection on screen. Requires a change to frameworks/base Bug 2679411 Bug 2659028 Change-Id: I482cefadc24c620c6d07cbce44acc216bdb9b8df --- WebCore/page/FrameView.cpp | 4 +- WebKit/android/WebCoreSupport/PlatformBridge.cpp | 2 +- WebKit/android/jni/WebCoreFrameBridge.cpp | 4 +- WebKit/android/jni/WebCoreFrameBridge.h | 10 ++--- WebKit/android/jni/WebViewCore.cpp | 57 ++++++++++++++++++++---- WebKit/android/jni/WebViewCore.h | 3 ++ 6 files changed, 62 insertions(+), 18 deletions(-) diff --git a/WebCore/page/FrameView.cpp b/WebCore/page/FrameView.cpp index 831ea86..f8a9418 100644 --- a/WebCore/page/FrameView.cpp +++ b/WebCore/page/FrameView.cpp @@ -1113,11 +1113,11 @@ bool FrameView::scrollToAnchor(const String& name) #ifdef ANDROID_SCROLL_ON_GOTO_ANCHOR // TODO(andreip): check with Grace if this is correct. - android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedClick(true); + android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedAction(true); #endif maintainScrollPositionAtAnchor(anchorNode ? static_cast(anchorNode) : m_frame->document()); #ifdef ANDROID_SCROLL_ON_GOTO_ANCHOR - android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedClick(false); + android::WebFrame::getWebFrame(m_frame.get())->setUserInitiatedAction(false); #endif return true; } diff --git a/WebKit/android/WebCoreSupport/PlatformBridge.cpp b/WebKit/android/WebCoreSupport/PlatformBridge.cpp index 754e4d9..f02f6b7 100644 --- a/WebKit/android/WebCoreSupport/PlatformBridge.cpp +++ b/WebKit/android/WebCoreSupport/PlatformBridge.cpp @@ -140,7 +140,7 @@ bool PlatformBridge::canScroll(const WebCore::FrameView* frameView) // we know how to do this ourselves in the UI thread. // An example of it being initiated by the user is if the user clicks // an anchor element which simply scrolls the page. - return android::WebFrame::getWebFrame(frameView->frame())->userInitiatedClick(); + return android::WebFrame::getWebFrame(frameView->frame())->userInitiatedAction(); } bool PlatformBridge::popupsAllowed(NPP) diff --git a/WebKit/android/jni/WebCoreFrameBridge.cpp b/WebKit/android/jni/WebCoreFrameBridge.cpp index f218cbb..d4d3bfe 100644 --- a/WebKit/android/jni/WebCoreFrameBridge.cpp +++ b/WebKit/android/jni/WebCoreFrameBridge.cpp @@ -288,7 +288,7 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page* LOG_ASSERT(mJavaFrame->mGetFile, "Could not find method getFile"); mUserAgent = WTF::String(); - mUserInitiatedClick = false; + mUserInitiatedAction = false; } WebFrame::~WebFrame() @@ -782,7 +782,7 @@ WebFrame::canHandleRequest(const WebCore::ResourceRequest& request) return true; WebCore::KURL requestUrl = request.url(); bool isUserGesture = UserGestureIndicator::processingUserGesture(); - if (!mUserInitiatedClick && !isUserGesture && + if (!mUserInitiatedAction && !isUserGesture && (requestUrl.protocolIs("http") || requestUrl.protocolIs("https") || requestUrl.protocolIs("file") || requestUrl.protocolIs("about") || WebCore::protocolIsJavaScript(requestUrl.string()))) diff --git a/WebKit/android/jni/WebCoreFrameBridge.h b/WebKit/android/jni/WebCoreFrameBridge.h index 07bdc41..2b323e1 100644 --- a/WebKit/android/jni/WebCoreFrameBridge.h +++ b/WebKit/android/jni/WebCoreFrameBridge.h @@ -110,16 +110,16 @@ class WebFrame : public WebCoreRefObject { float density() const; /** - * When the user initiates a click (via trackball, enter-press, or touch), - * we set mUserInitiatedClick to true. If a load happens due to this click, + * When the user initiates an action (via trackball, key-press, or touch), + * we set mUserInitiatedAction to true. If a load happens due to this click, * then we ask the application if it wants to override * the load. Otherwise, we attempt to load the resource internally. * We also check it to determine whether or not to allow webkit to request * a scroll. If it was user initated, the scroll is allowed. */ - void setUserInitiatedClick(bool userInitiatedClick) { mUserInitiatedClick = userInitiatedClick; } + void setUserInitiatedAction(bool userInitiatedAction) { mUserInitiatedAction = userInitiatedAction; } - bool userInitiatedClick() { return mUserInitiatedClick; } + bool userInitiatedAction() { return mUserInitiatedAction; } WebCore::Page* page() const { return mPage; } @@ -128,7 +128,7 @@ private: JavaBrowserFrame* mJavaFrame; WebCore::Page* mPage; WTF::String mUserAgent; - bool mUserInitiatedClick; + bool mUserInitiatedAction; }; } // namespace android diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp index 42aa718..87ef809 100644 --- a/WebKit/android/jni/WebViewCore.cpp +++ b/WebKit/android/jni/WebViewCore.cpp @@ -1286,6 +1286,22 @@ WTF::String WebViewCore::requestLabel(WebCore::Frame* frame, return WTF::String(); } +void WebViewCore::revealSelection() +{ + WebCore::Node* focus = currentFocus(); + if (!focus) + return; + WebCore::RenderObject* renderer = focus->renderer(); + if ((!renderer || (!renderer->isTextField() && !renderer->isTextArea())) + && !focus->isContentEditable()) + return; + WebCore::Frame* focusedFrame = focus->document()->frame(); + WebFrame* webFrame = WebFrame::getWebFrame(focusedFrame); + webFrame->setUserInitiatedAction(true); + focusedFrame->revealSelection(); + webFrame->setUserInitiatedAction(false); +} + void WebViewCore::updateCacheOnNodeChange() { gCursorBoundsMutex.lock(); @@ -1854,7 +1870,15 @@ void WebViewCore::setSelection(int start, int end) rtc->setSelectionRange(start, end); client->setUiGeneratedSelectionChange(false); WebCore::Frame* focusedFrame = focus->document()->frame(); - focusedFrame->revealSelection(); + if (renderer->isTextArea() + // For password fields, this is done in the UI side via + // bringPointIntoView, since the UI does the drawing. + || !static_cast(focus)->isPasswordField()) { + WebFrame* webFrame = WebFrame::getWebFrame(focusedFrame); + webFrame->setUserInitiatedAction(true); + focusedFrame->revealSelection(); + webFrame->setUserInitiatedAction(false); + } } String WebViewCore::modifySelection(const String& alter, const String& direction, const String& granularity) @@ -1939,6 +1963,7 @@ void WebViewCore::replaceTextfieldText(int oldStart, WebCore::TypingCommand::insertText(focus->document(), replace, false); client->setUiGeneratedSelectionChange(false); + // setSelection calls revealSelection, so there is no need to do it here. setSelection(start, end); m_textGeneration = textGeneration; } @@ -2217,16 +2242,26 @@ bool WebViewCore::key(const PlatformKeyboardEvent& event) event.keyIdentifier().utf8().data(), event.unichar(), focusNode); if (focusNode) { WebCore::Frame* frame = focusNode->document()->frame(); + WebFrame* webFrame = WebFrame::getWebFrame(frame); + if (focusNode->isContentEditable() || (focusNode->renderer() + && (focusNode->renderer()->isTextArea() + // For password fields, this is done in the UI side via + // bringPointIntoView, since the UI does the drawing. + || !static_cast(focusNode)->isPasswordField()))) { + webFrame->setUserInitiatedAction(true); + } eventHandler = frame->eventHandler(); + VisibleSelection old = frame->selection()->selection(); + bool handled = eventHandler->keyEvent(event); + webFrame->setUserInitiatedAction(false); if (focusNode->isContentEditable()) { // keyEvent will return true even if the contentEditable did not // change its selection. In the case that it does not, we want to // return false so that the key will be sent back to our navigation // system. - VisibleSelection old = frame->selection()->selection(); - eventHandler->keyEvent(event); - return frame->selection()->selection() != old; + handled = frame->selection()->selection() != old; } + return handled; } else { eventHandler = m_mainFrame->eventHandler(); } @@ -2414,9 +2449,9 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node // Need to special case area tags because an image map could have an area element in the middle // so when attempting to get the default, the point chosen would be follow the wrong link. if (nodePtr->hasTagName(WebCore::HTMLNames::areaTag)) { - webFrame->setUserInitiatedClick(true); + webFrame->setUserInitiatedAction(true); nodePtr->dispatchSimulatedClick(0, true, true); - webFrame->setUserInitiatedClick(false); + webFrame->setUserInitiatedAction(false); DBG_NAV_LOG("area"); return true; } @@ -2465,7 +2500,7 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node framePtr = m_mainFrame; if (nodePtr && valid) scrollLayer(nodePtr->renderer(), &m_mousePos); - webFrame->setUserInitiatedClick(true); + webFrame->setUserInitiatedAction(true); WebCore::PlatformMouseEvent mouseDown(m_mousePos, m_mousePos, WebCore::LeftButton, WebCore::MouseEventPressed, 1, false, false, false, false, WTF::currentTime()); @@ -2475,7 +2510,7 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node WebCore::MouseEventReleased, 1, false, false, false, false, WTF::currentTime()); bool handled = framePtr->eventHandler()->handleMouseReleaseEvent(mouseUp); - webFrame->setUserInitiatedClick(false); + webFrame->setUserInitiatedAction(false); // If the user clicked on a textfield, make the focusController active // so we show the blinking cursor. @@ -2884,6 +2919,11 @@ static jstring WebCoreStringToJString(JNIEnv *env, WTF::String string) return ret; } +static void RevealSelection(JNIEnv *env, jobject obj) +{ + GET_NATIVE_VIEW(env, obj)->revealSelection(); +} + static jstring RequestLabel(JNIEnv *env, jobject obj, int framePointer, int nodePointer) { @@ -3606,6 +3646,7 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { { "nativeSetJsFlags", "(Ljava/lang/String;)V", (void*) SetJsFlags }, { "nativeRequestLabel", "(II)Ljava/lang/String;", (void*) RequestLabel }, + { "nativeRevealSelection", "()V", (void*) RevealSelection }, { "nativeUpdateFrameCacheIfLoading", "()V", (void*) UpdateFrameCacheIfLoading }, { "nativeProvideVisitedHistory", "([Ljava/lang/String;)V", diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h index 89cdc8a..176e1bf 100644 --- a/WebKit/android/jni/WebViewCore.h +++ b/WebKit/android/jni/WebViewCore.h @@ -261,6 +261,9 @@ namespace android { WTF::String retrieveAnchorText(WebCore::Frame* frame, WebCore::Node* node); WTF::String requestLabel(WebCore::Frame* , WebCore::Node* ); + // If the focus is a textfield (), textarea, or contentEditable, + // scroll the selection on screen (if necessary). + void revealSelection(); // Create a single picture to represent the drawn DOM (used by navcache) void recordPicture(SkPicture* picture); -- cgit v1.1