summaryrefslogtreecommitdiffstats
path: root/WebKit
diff options
context:
space:
mode:
authorLeon Scroggins <scroggo@google.com>2009-08-12 18:41:12 -0400
committerLeon Scroggins <scroggo@google.com>2009-08-13 13:50:46 -0400
commit44206d7109052a5a98a832db4a9b960cf859dee9 (patch)
tree1816168f93979c2a209a7ffd6dfe416792cf0041 /WebKit
parentded6424aa933a9c87efa7ddede8635e6e266f6ce (diff)
downloadexternal_webkit-44206d7109052a5a98a832db4a9b960cf859dee9.zip
external_webkit-44206d7109052a5a98a832db4a9b960cf859dee9.tar.gz
external_webkit-44206d7109052a5a98a832db4a9b960cf859dee9.tar.bz2
Pass clicks to webkit's textfield to determine the new selection.
Requires a corresponding change to frameworks/base. We were previously letting WebTextView handle clicks, determine the change in selection, and pass that down to webkit. This sometimes resulted in a different placement of the caret if the WebTextView and the webkit-rendered textfield did not line up exactly. Now, we pass the click directly to webkit, which determines the new selection and passes that info back to the WebTextView. This also has the benefit of letting the WebTextView reflect changes in the selection that originated from webkit. Also remove some unused parameters.
Diffstat (limited to 'WebKit')
-rw-r--r--WebKit/android/WebCoreSupport/EditorClientAndroid.cpp20
-rw-r--r--WebKit/android/WebCoreSupport/EditorClientAndroid.h11
-rw-r--r--WebKit/android/jni/WebViewCore.cpp75
-rw-r--r--WebKit/android/jni/WebViewCore.h13
-rw-r--r--WebKit/android/nav/WebView.cpp39
5 files changed, 137 insertions, 21 deletions
diff --git a/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp b/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp
index 4918ee9..d2e45ff 100644
--- a/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp
+++ b/WebKit/android/WebCoreSupport/EditorClientAndroid.cpp
@@ -36,6 +36,7 @@
#include "NotImplemented.h"
#include "PlatformKeyboardEvent.h"
#include "PlatformString.h"
+#include "WebViewCore.h"
namespace android {
@@ -225,8 +226,23 @@ void EditorClientAndroid::textDidChangeInTextArea(Element*) {}
void EditorClientAndroid::textDidChangeInTextField(Element*) {}
void EditorClientAndroid::textFieldDidBeginEditing(Element*) {}
void EditorClientAndroid::ignoreWordInSpellDocument(String const&) {}
-void EditorClientAndroid::respondToChangedSelection() {}
-bool EditorClientAndroid::shouldChangeSelectedRange(Range*, Range*, EAffinity, bool) { return m_notFromClick; }
+
+// We need to pass the selection up to the WebTextView
+void EditorClientAndroid::respondToChangedSelection() {
+ if (m_uiGeneratedSelectionChange)
+ return;
+ Frame* frame = m_page->focusController()->focusedOrMainFrame();
+ if (!frame || !frame->view())
+ return;
+ WebViewCore* webViewCore = WebViewCore::getWebViewCore(frame->view());
+ webViewCore->updateTextSelection();
+}
+
+bool EditorClientAndroid::shouldChangeSelectedRange(Range*, Range*, EAffinity,
+ bool) {
+ return m_shouldChangeSelectedRange;
+}
+
bool EditorClientAndroid::doTextFieldCommandFromEvent(Element*, KeyboardEvent*) { return false; }
void EditorClientAndroid::textWillBeDeletedInTextField(Element*) {}
void EditorClientAndroid::updateSpellingUIWithGrammarString(String const&, GrammarDetail const&) {}
diff --git a/WebKit/android/WebCoreSupport/EditorClientAndroid.h b/WebKit/android/WebCoreSupport/EditorClientAndroid.h
index 9697d66..3569f10 100644
--- a/WebKit/android/WebCoreSupport/EditorClientAndroid.h
+++ b/WebKit/android/WebCoreSupport/EditorClientAndroid.h
@@ -35,7 +35,10 @@ namespace android {
class EditorClientAndroid : public EditorClient {
public:
- EditorClientAndroid() { m_notFromClick = true; }
+ EditorClientAndroid() {
+ m_shouldChangeSelectedRange = true;
+ m_uiGeneratedSelectionChange = false;
+ }
virtual void pageDestroyed();
virtual bool shouldDeleteRange(Range*);
@@ -105,10 +108,12 @@ public:
// Android specific:
void setPage(Page* page) { m_page = page; }
- void setFromClick(bool fromClick) { m_notFromClick = !fromClick; }
+ void setShouldChangeSelectedRange(bool shouldChangeSelectedRange) { m_shouldChangeSelectedRange = shouldChangeSelectedRange; }
+ void setUiGeneratedSelectionChange(bool uiGenerated) { m_uiGeneratedSelectionChange = uiGenerated; }
private:
Page* m_page;
- bool m_notFromClick;
+ bool m_shouldChangeSelectedRange;
+ bool m_uiGeneratedSelectionChange;
};
}
diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp
index 973e317..3e4254d 100644
--- a/WebKit/android/jni/WebViewCore.cpp
+++ b/WebKit/android/jni/WebViewCore.cpp
@@ -171,6 +171,7 @@ struct WebViewCore::JavaGlue {
jmethodID m_sendNotifyProgressFinished;
jmethodID m_sendViewInvalidate;
jmethodID m_updateTextfield;
+ jmethodID m_updateTextSelection;
jmethodID m_clearTextEntry;
jmethodID m_restoreScale;
jmethodID m_restoreScreenWidthScale;
@@ -244,6 +245,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_javaGlue->m_sendNotifyProgressFinished = GetJMethod(env, clazz, "sendNotifyProgressFinished", "()V");
m_javaGlue->m_sendViewInvalidate = GetJMethod(env, clazz, "sendViewInvalidate", "(IIII)V");
m_javaGlue->m_updateTextfield = GetJMethod(env, clazz, "updateTextfield", "(IZLjava/lang/String;I)V");
+ m_javaGlue->m_updateTextSelection = GetJMethod(env, clazz, "updateTextSelection", "(IIII)V");
m_javaGlue->m_clearTextEntry = GetJMethod(env, clazz, "clearTextEntry", "()V");
m_javaGlue->m_restoreScale = GetJMethod(env, clazz, "restoreScale", "(I)V");
m_javaGlue->m_restoreScreenWidthScale = GetJMethod(env, clazz, "restoreScreenWidthScale", "(I)V");
@@ -1499,7 +1501,13 @@ void WebViewCore::setSelection(int start, int end)
start = end;
end = temp;
}
+ // Tell our EditorClient that this change was generated from the UI, so it
+ // does not need to echo it to the UI.
+ EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
+ m_mainFrame->editor()->client());
+ client->setUiGeneratedSelectionChange(true);
rtc->setSelectionRange(start, end);
+ client->setUiGeneratedSelectionChange(false);
focus->document()->frame()->revealSelection();
setFocusControllerActive(true);
}
@@ -1524,8 +1532,14 @@ void WebViewCore::replaceTextfieldText(int oldStart,
if (!focus)
return;
setSelection(oldStart, oldEnd);
+ // Prevent our editor client from passing a message to change the
+ // selection.
+ EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
+ m_mainFrame->editor()->client());
+ client->setUiGeneratedSelectionChange(true);
WebCore::TypingCommand::insertText(focus->document(), replace,
false);
+ client->setUiGeneratedSelectionChange(false);
setSelection(start, end);
m_textGeneration = textGeneration;
}
@@ -1547,7 +1561,13 @@ void WebViewCore::passToJs(int generation, const WebCore::String& current,
}
// Block text field updates during a key press.
m_blockTextfieldUpdates = true;
+ // Also prevent our editor client from passing a message to change the
+ // selection.
+ EditorClientAndroid* client = static_cast<EditorClientAndroid*>(
+ m_mainFrame->editor()->client());
+ client->setUiGeneratedSelectionChange(true);
key(event);
+ client->setUiGeneratedSelectionChange(false);
m_blockTextfieldUpdates = false;
m_textGeneration = generation;
setFocusControllerActive(true);
@@ -1783,8 +1803,14 @@ void WebViewCore::click(WebCore::Frame* frame, WebCore::Node* node) {
" node=%p", m_mousePos.x(), m_mousePos.y(),
m_scrollOffsetX, m_scrollOffsetY, pt.x(), pt.y(), node);
}
- if (node)
+ if (node) {
+ EditorClientAndroid* client
+ = static_cast<EditorClientAndroid*>(
+ m_mainFrame->editor()->client());
+ client->setShouldChangeSelectedRange(false);
handleMouseClick(frame, node);
+ client->setShouldChangeSelectedRange(true);
+ }
}
bool WebViewCore::handleTouchEvent(int action, int x, int y)
@@ -1816,7 +1842,7 @@ bool WebViewCore::handleTouchEvent(int action, int x, int y)
}
void WebViewCore::touchUp(int touchGeneration,
- WebCore::Frame* frame, WebCore::Node* node, int x, int y, int size)
+ WebCore::Frame* frame, WebCore::Node* node, int x, int y)
{
if (m_touchGeneration > touchGeneration) {
DBG_NAV_LOGD("m_touchGeneration=%d > touchGeneration=%d"
@@ -1828,12 +1854,30 @@ void WebViewCore::touchUp(int touchGeneration,
if (frame && CacheBuilder::validNode(m_mainFrame, frame, 0)) {
frame->loader()->resetMultipleFormSubmissionProtection();
}
- EditorClientAndroid* client = static_cast<EditorClientAndroid*>(m_mainFrame->editor()->client());
- client->setFromClick(true);
+ // If the click is on an unselected textfield/area we do not want to allow
+ // the click to change the selection, because we will set it ourselves
+ // elsewhere - beginning for textareas, end for textfields
+ bool needToIgnoreChangesToSelectedRange = true;
+ WebCore::Node* focusNode = currentFocus();
+ if (focusNode) {
+ WebCore::RenderObject* renderer = focusNode->renderer();
+ if (renderer && (renderer->isTextField() || renderer->isTextArea())) {
+ // Now check to see if the click is inside the focused textfield
+ if (focusNode->getRect().contains(x, y))
+ needToIgnoreChangesToSelectedRange = false;
+ }
+ }
+ EditorClientAndroid* client = 0;
+ if (needToIgnoreChangesToSelectedRange) {
+ client = static_cast<EditorClientAndroid*>(
+ m_mainFrame->editor()->client());
+ client->setShouldChangeSelectedRange(false);
+ }
DBG_NAV_LOGD("touchGeneration=%d handleMouseClick frame=%p node=%p"
" x=%d y=%d", touchGeneration, frame, node, x, y);
handleMouseClick(frame, node);
- client->setFromClick(false);
+ if (needToIgnoreChangesToSelectedRange)
+ client->setShouldChangeSelectedRange(true);
}
// Common code for both clicking with the trackball and touchUp
@@ -2056,6 +2100,21 @@ WebViewCore::getWebViewJavaObject()
return env->GetObjectField(m_javaGlue->object(env).get(), gWebViewCoreFields.m_webView);
}
+void WebViewCore::updateTextSelection() {
+ WebCore::Node* focusNode = currentFocus();
+ if (!focusNode)
+ return;
+ RenderObject* renderer = focusNode->renderer();
+ if (!renderer || (!renderer->isTextArea() && !renderer->isTextField()))
+ return;
+ RenderTextControl* rtc = static_cast<RenderTextControl*>(renderer);
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ env->CallVoidMethod(m_javaGlue->object(env).get(),
+ m_javaGlue->m_updateTextSelection, reinterpret_cast<int>(focusNode),
+ rtc->selectionStart(), rtc->selectionEnd(), m_textGeneration);
+ checkException(env);
+}
+
void WebViewCore::updateTextfield(WebCore::Node* ptr, bool changeToPassword,
const WebCore::String& text)
{
@@ -2369,7 +2428,7 @@ static jboolean HandleTouchEvent(JNIEnv *env, jobject obj, jint action, jint x,
}
static void TouchUp(JNIEnv *env, jobject obj, jint touchGeneration,
- jint frame, jint node, jint x, jint y, jint size)
+ jint frame, jint node, jint x, jint y)
{
#ifdef ANDROID_INSTRUMENT
TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
@@ -2377,7 +2436,7 @@ static void TouchUp(JNIEnv *env, jobject obj, jint touchGeneration,
WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj);
LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__);
viewImpl->touchUp(touchGeneration,
- (WebCore::Frame*) frame, (WebCore::Node*) node, x, y, size);
+ (WebCore::Frame*) frame, (WebCore::Node*) node, x, y);
}
static jstring RetrieveHref(JNIEnv *env, jobject obj, jint frame,
@@ -2702,7 +2761,7 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
(void*) FindAddress },
{ "nativeHandleTouchEvent", "(III)Z",
(void*) HandleTouchEvent },
- { "nativeTouchUp", "(IIIIII)V",
+ { "nativeTouchUp", "(IIIII)V",
(void*) TouchUp },
{ "nativeRetrieveHref", "(II)Ljava/lang/String;",
(void*) RetrieveHref },
diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h
index 22e00e2..1408cb7 100644
--- a/WebKit/android/jni/WebViewCore.h
+++ b/WebKit/android/jni/WebViewCore.h
@@ -173,6 +173,15 @@ namespace android {
*/
void updateTextfield(WebCore::Node* pointer,
bool changeToPassword, const WebCore::String& text);
+
+ /**
+ * Tell the java side to update the current selection in the focused
+ * textfield to the WebTextView. This function finds the currently
+ * focused textinput, and passes its selection to java.
+ * If there is no focus, or it is not a text input, this does nothing.
+ */
+ void updateTextSelection();
+
void clearTextEntry();
// JavaScript support
void jsAlert(const WebCore::String& url, const WebCore::String& text);
@@ -260,8 +269,8 @@ namespace android {
* Handle motionUp event from the UI thread (called touchUp in the
* WebCore thread).
*/
- void touchUp(int touchGeneration,
- WebCore::Frame* frame, WebCore::Node* node, int x, int y, int size);
+ void touchUp(int touchGeneration, WebCore::Frame* frame,
+ WebCore::Node* node, int x, int y);
/**
* Sets the index of the label from a popup
diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp
index a920777..59d0c6f 100644
--- a/WebKit/android/nav/WebView.cpp
+++ b/WebKit/android/nav/WebView.cpp
@@ -131,7 +131,7 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl)
m_javaGlue.m_sendPluginState = GetJMethod(env, clazz, "sendPluginState", "(I)V");
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", "(IIIIII)V");
+ m_javaGlue.m_sendMotionUp = GetJMethod(env, clazz, "sendMotionUp", "(IIIII)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;");
@@ -909,6 +909,26 @@ void setNavBounds(const WebCore::IntRect& rect)
root->rootHistory()->setNavBounds(rect);
}
+/**
+ * This function is only to be called by WebTextView, when there is a motion up
+ * on an already focused text input. Unlike motionUp which may change our
+ * cursor, it simply passes the click, so it can change the selection.
+ * Variables are in content space, relative to the page.
+ */
+void textInputMotionUp(int x, int y)
+{
+ const CachedRoot* root = getFrameCache(DontAllowNewer);
+ if (!root) {
+ return;
+ }
+ const CachedFrame* frame;
+ const CachedNode* node = root->currentCursor(&frame);
+ if (node) {
+ sendMotionUp(static_cast<WebCore::Frame*>(frame->framePointer()),
+ static_cast<WebCore::Node*>(node->nodePointer()), x, y);
+ }
+}
+
bool motionUp(int x, int y, int slop)
{
bool pageScrolled = false;
@@ -931,7 +951,7 @@ bool motionUp(int x, int y, int slop)
pageScrolled = true;
}
sendMotionUp(frame ? (WebCore::Frame*) frame->framePointer() : 0,
- 0, x, y, slop);
+ 0, x, y);
viewInvalidate();
clearTextEntry();
setPluginReceivesEvents(false);
@@ -948,8 +968,7 @@ bool motionUp(int x, int y, int slop)
if (type == NORMAL_CACHEDNODETYPE) {
sendMotionUp(
frame ? (WebCore::Frame*) frame->framePointer() : 0,
- result ? (WebCore::Node*) result->nodePointer() : 0, rx, ry,
- slop);
+ result ? (WebCore::Node*) result->nodePointer() : 0, rx, ry);
}
viewInvalidate();
if (result->isTextField() || result->isTextArea()) {
@@ -1177,7 +1196,7 @@ void sendMoveMouseIfLatest(bool disableFocusController)
}
void sendMotionUp(
- WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int y, int slop)
+ WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int y)
{
m_viewImpl->m_touchGeneration = m_viewImpl->m_generation = ++m_generation;
DBG_NAV_LOGD("m_generation=%d framePtr=%p nodePtr=%p x=%d y=%d slop=%d",
@@ -1185,7 +1204,7 @@ void sendMotionUp(
LOG_ASSERT(m_javaGlue.m_obj, "A WebView was not associated with this WebViewNative!");
JNIEnv* env = JSC::Bindings::getJNIEnv();
env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_sendMotionUp,
- m_generation, (jint) framePtr, (jint) nodePtr, x, y, slop);
+ m_generation, (jint) framePtr, (jint) nodePtr, x, y);
checkException(env);
}
@@ -1699,6 +1718,12 @@ static jint nativeTextGeneration(JNIEnv *env, jobject obj)
return root ? root->textGeneration() : 0;
}
+static void nativeTextInputMotionUp(JNIEnv *env, jobject obj, int x, int y)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ view->textInputMotionUp(x, y);
+}
+
static bool nativeMotionUp(JNIEnv *env, jobject obj,
int x, int y, int slop)
{
@@ -2057,6 +2082,8 @@ static JNINativeMethod gJavaWebViewMethods[] = {
(void*) nativeImageURI },
{ "nativeInstrumentReport", "()V",
(void*) nativeInstrumentReport },
+ { "nativeTextInputMotionUp", "(II)V",
+ (void*) nativeTextInputMotionUp },
{ "nativeMotionUp", "(III)Z",
(void*) nativeMotionUp },
{ "nativeMoveCursor", "(IIZ)Z",