summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorge Mount <mount@google.com>2012-01-12 13:40:49 -0800
committerGeorge Mount <mount@google.com>2012-01-18 16:29:03 -0800
commit7c77e50c5cdcaa7074e8db703224450fef254107 (patch)
tree3f536ba84c8284732d115cc4c727e1a1391155d9
parentf41a6c48daf18b146426dfb9887c3caff55b4ebc (diff)
downloadexternal_webkit-7c77e50c5cdcaa7074e8db703224450fef254107.zip
external_webkit-7c77e50c5cdcaa7074e8db703224450fef254107.tar.gz
external_webkit-7c77e50c5cdcaa7074e8db703224450fef254107.tar.bz2
Add cut and paste to ContentEditable.
Bug 5806267 Use visual selection to determine the webkit selection. The webkit selection can be used to cut text from an editable area. It can also be used to do better complex character text copy. Framework Change: I56543d17670a8c98484314c89c7fa6a94cb809e4 Change-Id: I194c6d9e2add67151b97092a1a54f5c081296000
-rw-r--r--Source/WebKit/android/jni/WebViewCore.cpp161
-rw-r--r--Source/WebKit/android/jni/WebViewCore.h18
-rw-r--r--Source/WebKit/android/nav/WebView.cpp21
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)