diff options
-rw-r--r-- | WebKit/android/jni/WebViewCore.cpp | 79 | ||||
-rw-r--r-- | WebKit/android/jni/WebViewCore.h | 17 | ||||
-rw-r--r-- | WebKit/android/nav/WebView.cpp | 15 |
3 files changed, 108 insertions, 3 deletions
diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp index 9c3f0a1..f7f1058 100644 --- a/WebKit/android/jni/WebViewCore.cpp +++ b/WebKit/android/jni/WebViewCore.cpp @@ -2037,6 +2037,61 @@ String WebViewCore::modifySelection(const int direction, const int axis) } } +String WebViewCore::moveSelection(WebCore::Frame* frame, WebCore::Node* node) +{ + if (!frame || !node) + return String(); + + if (!CacheBuilder::validNode(m_mainFrame, frame, node)) + return String(); + + PassRefPtr<Range> rangeRef = 0; + ExceptionCode ec = 0; + DOMSelection* selection = frame->domWindow()->getSelection(); + if (selection->rangeCount() > 0) { + rangeRef = selection->getRangeAt(0, ec); + if (ec) + return String(); + selection->removeAllRanges(); + } else { + rangeRef = frame->document()->createRange(); + } + + rangeRef->selectNode(node, ec); + if (ec) + return String(); + + selection->addRange(rangeRef.get()); + + scrollNodeIntoView(frame, node); + + String markup = formatMarkup(selection).stripWhiteSpace(); + LOGV("Selection markup: %s", markup.utf8().data()); + return markup; +} + +void WebViewCore::scrollNodeIntoView(Frame* frame, Node* node) +{ + if (!frame || !node) + return; + + Element* elementNode = 0; + + // If not an Element, find a visible predecessor + // Element to scroll into view. + if (!node->isElementNode()) { + HTMLElement* body = frame->document()->body(); + do { + if (!node || node == body) + return; + node = node->parentNode(); + } while (!node->isElementNode() && !isVisible(node)); + } + + elementNode = static_cast<Element*>(node); + elementNode->scrollIntoViewIfNeeded(true); +} + String WebViewCore::modifySelectionTextNavigationAxis(DOMSelection* selection, int direction, int axis) { String directionString; @@ -2166,10 +2221,14 @@ String WebViewCore::modifySelectionTextNavigationAxis(DOMSelection* selection, i } } + if (direction == DIRECTION_FORWARD) + scrollNodeIntoView(m_mainFrame, selection->focusNode()); + else + scrollNodeIntoView(m_mainFrame, selection->anchorNode()); + tryFocusInlineSelectionElement(selection); - // TODO (svetoslavganov): Draw the selected text in the WebView - a-la-Android String markup = formatMarkup(selection).stripWhiteSpace(); - LOGD("Selection markup: %s", markup.utf8().data()); + LOGV("Selection markup: %s", markup.utf8().data()); return markup; } @@ -2284,10 +2343,11 @@ String WebViewCore::modifySelectionDomNavigationAxis(DOMSelection* selection, in } if (currentNode) { m_currentNodeDomNavigationAxis = currentNode; + scrollNodeIntoView(m_mainFrame, currentNode); focusIfFocusableAndNotTextInput(selection, currentNode); // TODO (svetoslavganov): Draw the selected text in the WebView - a-la-Android String selectionString = createMarkup(currentNode); - LOGD("Selection markup: %s", selectionString.utf8().data()); + LOGV("Selection markup: %s", selectionString.utf8().data()); return selectionString; } return String(); @@ -3523,6 +3583,17 @@ static jstring ModifySelection(JNIEnv *env, jobject obj, jint direction, jint gr return wtfStringToJstring(env, selectionString); } +static jstring MoveSelection(JNIEnv *env, jobject obj, jint framePtr, jint nodePtr) +{ +#ifdef ANDROID_INSTRUMENT + TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); +#endif + WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); + String selectionString = viewImpl->moveSelection((WebCore::Frame*) framePtr, + (WebCore::Node*) nodePtr); + return wtfStringToJstring(env, selectionString); +} + static void ReplaceTextfieldText(JNIEnv *env, jobject obj, jint oldStart, jint oldEnd, jstring replace, jint start, jint end, jint textGeneration) @@ -4107,6 +4178,8 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) SetSelection } , { "nativeModifySelection", "(II)Ljava/lang/String;", (void*) ModifySelection }, + { "nativeMoveSelection", "(II)Ljava/lang/String;", + (void*) MoveSelection }, { "nativeDeleteSelection", "(III)V", (void*) DeleteSelection } , { "nativeReplaceTextfieldText", "(IILjava/lang/String;III)V", diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h index b13e3a5..fa474ce 100644 --- a/WebKit/android/jni/WebViewCore.h +++ b/WebKit/android/jni/WebViewCore.h @@ -364,6 +364,8 @@ namespace android { /** * Modifies the current selection. * + * Note: Accessibility support. + * * direction - The direction in which to alter the selection. * granularity - The granularity of the selection modification. * @@ -374,6 +376,20 @@ namespace android { String modifySelection(const int direction, const int granularity); /** + * Moves the selection to the given node in a given frame i.e. selects that node. + * + * Note: Accessibility support. + * + * frame - The frame in which to select is the node to be selected. + * node - The node to be selected. + * + * returns - The selected HTML as a string. This is not a well formed + * HTML, rather the selection annotated with the tags of all + * intermediary elements it crosses. + */ + String moveSelection(WebCore::Frame* frame, WebCore::Node* node); + + /** * In the currently focused textfield, replace the characters from oldStart to oldEnd * (if oldStart == oldEnd, this will be an insert at that position) with replace, * and set the selection to (start, end). @@ -632,6 +648,7 @@ namespace android { bool setSelection(DOMSelection* selection, Text* textNode, int direction); bool setSelection(DOMSelection* selection, Node* startNode, Node* endNode, int startOffset, int endOffset); Node* m_currentNodeDomNavigationAxis; + void scrollNodeIntoView(Frame* frame, Node* node); #if ENABLE(TOUCH_EVENTS) bool m_forwardingTouchEvents; #endif diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp index 4b0f21d..862b99b 100644 --- a/WebKit/android/nav/WebView.cpp +++ b/WebKit/android/nav/WebView.cpp @@ -113,6 +113,7 @@ struct JavaGlue { jmethodID m_sendMoveFocus; jmethodID m_sendMoveMouse; jmethodID m_sendMoveMouseIfLatest; + jmethodID m_sendMoveSelection; jmethodID m_sendMotionUp; jmethodID m_domChangedFocus; jmethodID m_getScaledMaxXScroll; @@ -147,6 +148,7 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) : m_javaGlue.m_sendMoveFocus = GetJMethod(env, clazz, "sendMoveFocus", "(II)V"); m_javaGlue.m_sendMoveMouse = GetJMethod(env, clazz, "sendMoveMouse", "(IIII)V"); m_javaGlue.m_sendMoveMouseIfLatest = GetJMethod(env, clazz, "sendMoveMouseIfLatest", "(Z)V"); + m_javaGlue.m_sendMoveSelection = GetJMethod(env, clazz, "sendMoveSelection", "(II)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"); @@ -841,6 +843,8 @@ bool moveCursor(int keyCode, int count, bool ignoreScroll) bool disableFocusController = cachedNode != root->currentFocus() && cachedNode->wantsKeyEvents(); sendMoveMouseIfLatest(disableFocusController); + sendMoveSelection((WebCore::Frame*) cachedFrame->framePointer(), + (WebCore::Node*) cachedNode->nodePointer()); } else { int docHeight = root->documentHeight(); int docWidth = root->documentWidth(); @@ -917,6 +921,8 @@ void selectBestAt(const WebCore::IntRect& rect) const_cast<CachedNode*>(node)); } sendMoveMouseIfLatest(false); + sendMoveSelection((WebCore::Frame*) frame->framePointer(), + (WebCore::Node*) node->nodePointer()); } const CachedNode* m_cacheHitNode; @@ -1178,6 +1184,15 @@ void sendMoveMouseIfLatest(bool disableFocusController) checkException(env); } +void sendMoveSelection(WebCore::Frame* frame, WebCore::Node* node) +{ + DBG_NAV_LOGD("framePtr=%p nodePtr=%p x=%d y=%d", frame, node); + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->CallVoidMethod(m_javaGlue.object(env).get(), + m_javaGlue.m_sendMoveSelection, (jint) frame, (jint) node); + checkException(env); +} + void sendMotionUp( WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int y) { |