diff options
author | George Mount <mount@google.com> | 2012-01-23 07:30:20 -0800 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2012-01-23 07:30:20 -0800 |
commit | 2641f0118c78c83b37b7dd9ee6f6cb793cdb8cfb (patch) | |
tree | 8ad9ff3b9a722533f60663e3bf7eb350c9e67a37 | |
parent | 66df18e3ce1aefb177e33918f83161f1d4b1b2d1 (diff) | |
parent | 7c77e50c5cdcaa7074e8db703224450fef254107 (diff) | |
download | external_webkit-2641f0118c78c83b37b7dd9ee6f6cb793cdb8cfb.zip external_webkit-2641f0118c78c83b37b7dd9ee6f6cb793cdb8cfb.tar.gz external_webkit-2641f0118c78c83b37b7dd9ee6f6cb793cdb8cfb.tar.bz2 |
Merge "Add cut and paste to ContentEditable."
-rw-r--r-- | Source/WebKit/android/jni/WebViewCore.cpp | 161 | ||||
-rw-r--r-- | Source/WebKit/android/jni/WebViewCore.h | 18 | ||||
-rw-r--r-- | Source/WebKit/android/nav/WebView.cpp | 21 |
3 files changed, 200 insertions, 0 deletions
diff --git a/Source/WebKit/android/jni/WebViewCore.cpp b/Source/WebKit/android/jni/WebViewCore.cpp index 703f177..e429ae8 100644 --- a/Source/WebKit/android/jni/WebViewCore.cpp +++ b/Source/WebKit/android/jni/WebViewCore.cpp @@ -114,6 +114,7 @@ #include "SkPicture.h" #include "SkUtils.h" #include "Text.h" +#include "TextIterator.h" #include "TypingCommand.h" #include "WebCache.h" #include "WebCoreFrameBridge.h" @@ -3997,6 +3998,137 @@ void WebViewCore::scrollRenderLayer(int layer, const SkRect& rect) #endif } +Vector<VisibleSelection> WebViewCore::getTextRanges( + int startX, int startY, int endX, int endY) +{ + // These are the positions of the selection handles, + // which reside below the line that they are selecting. + // Use the vertical position higher, which will include + // the selected text. + startY--; + endY--; + VisiblePosition startSelect = visiblePositionForWindowPoint( + startX - m_scrollOffsetX, startY - m_scrollOffsetY); + VisiblePosition endSelect = visiblePositionForWindowPoint( + endX - m_scrollOffsetX, endY - m_scrollOffsetY); + Position start = startSelect.deepEquivalent(); + Position end = endSelect.deepEquivalent(); + Vector<VisibleSelection> ranges; + if (!start.isNull() && !end.isNull()) { + if (comparePositions(start, end) > 0) { + swap(start, end); // RTL start/end positions may be swapped + } + Position nextRangeStart = start; + Position previousRangeEnd; + int i = 0; + do { + VisibleSelection selection(nextRangeStart, end); + ranges.append(selection); + previousRangeEnd = selection.end(); + nextRangeStart = nextCandidate(previousRangeEnd); + } while (comparePositions(previousRangeEnd, end) < 0); + } + return ranges; +} + +void WebViewCore::deleteText(int startX, int startY, int endX, int endY) +{ + Vector<VisibleSelection> ranges = + getTextRanges(startX, startY, endX, endY); + + EditorClientAndroid* client = static_cast<EditorClientAndroid*>( + m_mainFrame->editor()->client()); + client->setUiGeneratedSelectionChange(true); + + SelectionController* selector = m_mainFrame->selection(); + for (size_t i = 0; i < ranges.size(); i++) { + const VisibleSelection& selection = ranges[i]; + if (selection.isContentEditable()) { + selector->setSelection(selection, CharacterGranularity); + Document* document = selection.start().anchorNode()->document(); + WebCore::TypingCommand::deleteSelection(document, 0); + } + } + client->setUiGeneratedSelectionChange(false); +} + +void WebViewCore::insertText(const WTF::String &text) +{ + WebCore::Node* focus = currentFocus(); + if (!focus || !isTextInput(focus)) + return; + + Document* document = focus->document(); + Frame* frame = document->frame(); + + EditorClientAndroid* client = static_cast<EditorClientAndroid*>( + m_mainFrame->editor()->client()); + if (!client) + return; + client->setUiGeneratedSelectionChange(true); + WebCore::TypingCommand::insertText(document, text, + TypingCommand::PreventSpellChecking); + client->setUiGeneratedSelectionChange(false); +} + +String WebViewCore::getText(int startX, int startY, int endX, int endY) +{ + String text; + + Vector<VisibleSelection> ranges = + getTextRanges(startX, startY, endX, endY); + + for (size_t i = 0; i < ranges.size(); i++) { + const VisibleSelection& selection = ranges[i]; + PassRefPtr<Range> range = selection.firstRange(); + String textInRange = range->text(); + if (textInRange.length() > 0) { + if (text.length() > 0) + text.append('\n'); + text.append(textInRange); + } + } + + return text; +} + +VisiblePosition WebViewCore::visiblePositionForWindowPoint(int x, int y) +{ + HitTestRequest::HitTestRequestType hitType = HitTestRequest::MouseMove; + hitType |= HitTestRequest::ReadOnly; + hitType |= HitTestRequest::Active; + HitTestRequest request(hitType); + FrameView* view = m_mainFrame->view(); + IntPoint point(view->windowToContents( + view->convertFromContainingWindow(IntPoint(x, y)))); + + // Look for the inner-most frame containing the hit. Its document + // contains the document with the selected text. + Frame* frame = m_mainFrame; + Frame* hitFrame = m_mainFrame; + Node* node = 0; + IntPoint localPoint = point; + do { + HitTestResult result(localPoint); + frame = hitFrame; + frame->document()->renderView()->layer()->hitTest(request, result); + node = result.innerNode(); + if (!node) + return VisiblePosition(); + + if (node->isFrameOwnerElement()) + hitFrame = static_cast<HTMLFrameOwnerElement*>(node)->contentFrame(); + localPoint = result.localPoint(); + } while (hitFrame && hitFrame != frame); + + Element* element = node->parentElement(); + if (!node->inDocument() && element && element->inDocument()) + node = element; + + RenderObject* renderer = node->renderer(); + return renderer->positionForPoint(localPoint); +} + //---------------------------------------------------------------------- // Native JNI methods //---------------------------------------------------------------------- @@ -4634,6 +4766,29 @@ static void ScrollRenderLayer(JNIEnv* env, jobject obj, jint nativeClass, reinterpret_cast<WebViewCore*>(nativeClass)->scrollRenderLayer(layer, rect); } +static void DeleteText(JNIEnv* env, jobject obj, jint nativeClass, + jint startX, jint startY, jint endX, jint endY) +{ + WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass); + viewImpl->deleteText(startX, startY, endX, endY); +} + +static void InsertText(JNIEnv* env, jobject obj, jint nativeClass, + jstring text) +{ + WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass); + WTF::String wtfText = jstringToWtfString(env, text); + viewImpl->insertText(wtfText); +} + +static jobject GetText(JNIEnv* env, jobject obj, jint nativeClass, + jint startX, jint startY, jint endX, jint endY) +{ + WebViewCore* viewImpl = reinterpret_cast<WebViewCore*>(nativeClass); + WTF::String text = viewImpl->getText(startX, startY, endX, endY); + return text.isEmpty() ? 0 : wtfStringToJstring(env, text); +} + // ---------------------------------------------------------------------------- /* @@ -4752,6 +4907,12 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) ScrollRenderLayer }, { "nativeCloseIdleConnections", "(I)V", (void*) CloseIdleConnections }, + { "nativeDeleteText", "(IIIII)V", + (void*) DeleteText }, + { "nativeInsertText", "(ILjava/lang/String;)V", + (void*) InsertText }, + { "nativeGetText", "(IIIII)Ljava/lang/String;", + (void*) GetText }, }; int registerWebViewCore(JNIEnv* env) diff --git a/Source/WebKit/android/jni/WebViewCore.h b/Source/WebKit/android/jni/WebViewCore.h index 06f6b97..d753b6d 100644 --- a/Source/WebKit/android/jni/WebViewCore.h +++ b/Source/WebKit/android/jni/WebViewCore.h @@ -43,6 +43,7 @@ #include "WebCoreJni.h" #include "WebRequestContext.h" #include "android_npapi.h" +#include "VisiblePosition.h" #include <jni.h> #include <ui/KeycodeLabels.h> @@ -560,6 +561,10 @@ namespace android { void notifyWebAppCanBeInstalled(); + void deleteText(int startX, int startY, int endX, int endY); + WTF::String getText(int startX, int startY, int endX, int endY); + void insertText(const WTF::String &text); + #if ENABLE(VIDEO) void enterFullscreenForVideoLayer(int layerId, const WTF::String& url); void exitFullscreenVideo(); @@ -597,6 +602,19 @@ namespace android { // Check whether a media mimeType is supported in Android media framework. static bool isSupportedMediaMimeType(const WTF::String& mimeType); + /** + * Returns all text ranges consumed by the cursor points referred + * to by startX, startY, endX, and endY. The vector will be empty + * if no text is in the given area or if the positions are invalid. + */ + Vector<WebCore::VisibleSelection> getTextRanges( + int startX, int startY, int endX, int endY); + + /** + * Returns a text position at a given coordinate. + */ + WebCore::VisiblePosition visiblePositionForWindowPoint(int x, int y); + // these members are shared with webview.cpp static Mutex gFrameCacheMutex; CachedRoot* m_frameCacheKit; // nav data being built by webcore diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp index 0d8a716..dede152 100644 --- a/Source/WebKit/android/nav/WebView.cpp +++ b/Source/WebKit/android/nav/WebView.cpp @@ -1983,6 +1983,25 @@ static jint nativeFocusCandidateFramePointer(JNIEnv *env, jobject obj) return reinterpret_cast<int>(frame ? frame->framePointer() : 0); } +static bool nativeFocusCandidateIsEditableText(JNIEnv* env, jobject obj, + jint nativeClass) +{ + WebView* view = reinterpret_cast<WebView*>(nativeClass); + CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer); + bool isEditable = false; + if (root) { + const CachedFrame* frame = NULL; + const CachedNode* cursor = root->currentCursor(&frame); + const CachedNode* focus = cursor; + if (!cursor || !cursor->wantsKeyEvents()) + focus = root->currentFocus(&frame); + if (focus) { + isEditable = (focus->isTextInput() || focus->isContentEditable()); + } + } + return isEditable; +} + static bool nativeFocusCandidateIsPassword(JNIEnv *env, jobject obj) { const CachedInput* input = getInputCandidate(env, obj); @@ -2950,6 +2969,8 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeSetPauseDrawing }, { "nativeDisableNavcache", "()Z", (void*) nativeDisableNavcache }, + { "nativeFocusCandidateIsEditableText", "(I)Z", + (void*) nativeFocusCandidateIsEditableText }, }; int registerWebView(JNIEnv* env) |