diff options
Diffstat (limited to 'WebKit/android/nav')
| -rw-r--r-- | WebKit/android/nav/CachedRoot.cpp | 10 | ||||
| -rw-r--r-- | WebKit/android/nav/SelectText.cpp | 88 | ||||
| -rw-r--r-- | WebKit/android/nav/SelectText.h | 4 | ||||
| -rw-r--r-- | WebKit/android/nav/WebView.cpp | 152 |
4 files changed, 141 insertions, 113 deletions
diff --git a/WebKit/android/nav/CachedRoot.cpp b/WebKit/android/nav/CachedRoot.cpp index d9669bd..5805e5f 100644 --- a/WebKit/android/nav/CachedRoot.cpp +++ b/WebKit/android/nav/CachedRoot.cpp @@ -154,11 +154,11 @@ public: } if (interestingType == false) return false; - if (mBoundsSlop.contains(rect) || + if (!mDrawnOver.contains(rect) && (mBoundsSlop.contains(rect) || (mBounds.fLeft == rect.fLeft && mBounds.fRight == rect.fRight && mBounds.fTop >= rect.fTop && mBounds.fBottom <= rect.fBottom) || (mBounds.fTop == rect.fTop && mBounds.fBottom == rect.fBottom && - mBounds.fLeft >= rect.fLeft && mBounds.fRight <= rect.fRight)) { + mBounds.fLeft >= rect.fLeft && mBounds.fRight <= rect.fRight))) { mDrawnOver.setEmpty(); mAllDrawnIn.join(rect); DBG_NAV_LOGD("BoundsCheck (contains) rect={%d,%d,%d,%d}" @@ -1125,8 +1125,8 @@ bool CachedRoot::maskIfHidden(BestData* best) const checker.drawPicture(*mPicture); boundsCheck.checkLast(); // was it not drawn or clipped out? + CachedNode* node = const_cast<CachedNode*>(best->mNode); if (boundsCheck.hidden()) { // if hidden, return false so that nav can try again - CachedNode* node = const_cast<CachedNode*>(best->mNode); #if DEBUG_NAV_UI const SkIRect& m = boundsCheck.mBounds; const SkIRect& s = boundsCheck.mBoundsSlop; @@ -1177,12 +1177,14 @@ bool CachedRoot::maskIfHidden(BestData* best) const #if DEBUG_NAV_UI const SkIRect& modded = boundsCheck.mBounds; DBG_NAV_LOGD("partially occluded node:%p (%d) old:{%d,%d,%d,%d}" - " new:{%d,%d,%d,%d}", best->mNode, best->mNode->index(), + " new:{%d,%d,%d,%d}", node, node->index(), orig.fLeft, orig.fTop, orig.fRight, orig.fBottom, base.fLeft, base.fTop, base.fRight, base.fBottom); #endif best->mMouseBounds = WebCore::IntRect(bounds.x() + base.fLeft - kMargin, bounds.y() + base.fTop - kMargin, base.width(), base.height()); + node->clip(best->mMouseBounds); + return true; } return false; } diff --git a/WebKit/android/nav/SelectText.cpp b/WebKit/android/nav/SelectText.cpp index 9a9f8d2..d8b184a 100644 --- a/WebKit/android/nav/SelectText.cpp +++ b/WebKit/android/nav/SelectText.cpp @@ -35,14 +35,17 @@ #include "SkPoint.h" #include "SkRect.h" #include "SkRegion.h" +#include "SkUtils.h" class CommonCheck : public SkBounder { public: CommonCheck() : mMatrix(NULL), mPaint(NULL) {} - virtual void setUp(const SkPaint& paint, const SkMatrix& matrix, SkScalar y) { + virtual void setUp(const SkPaint& paint, const SkMatrix& matrix, SkScalar y, + const void* text) { mMatrix = &matrix; mPaint = &paint; + mText = static_cast<const uint16_t*>(text); mY = y; mBase = mBottom = mTop = INT_MAX; } @@ -81,10 +84,11 @@ public: protected: const SkMatrix* mMatrix; const SkPaint* mPaint; + const uint16_t* mText; + SkScalar mY; int mBase; int mBottom; int mTop; - SkScalar mY; }; class FirstCheck : public CommonCheck { @@ -162,6 +166,8 @@ public: full.fRight = mLast.fLeft; } mSelectRegion->op(full, SkRegion::kUnion_Op); + DBG_NAV_LOGD("MultilineBuilder full=(%d,%d,r=%d,b=%d)", + full.fLeft, full.fTop, full.fRight, full.fBottom); mLast = full; mLastBase = base(); if (mStart == mEnd) @@ -178,6 +184,66 @@ protected: bool mCapture; }; +class TextExtractor : public CommonCheck { +public: + TextExtractor(const SkRegion& region) : mSelectRegion(region), + mSkipFirstSpace(true) { // don't start with a space + } + + virtual void setUp(const SkPaint& paint, const SkMatrix& matrix, SkScalar y, + const void* text) { + INHERITED::setUp(paint, matrix, y, text); + SkPaint charPaint = paint; + charPaint.setTextEncoding(SkPaint::kUTF8_TextEncoding); + mMinSpaceWidth = charPaint.measureText(" ", 1) * 3 / 4; + } + + virtual bool onIRect(const SkIRect& rect, uint16_t glyphID) { + SkIRect full; + full.set(rect.fLeft, top(), rect.fRight, bottom()); + if (mSelectRegion.contains(full)) { + if (!mSkipFirstSpace + && ((mLast.fTop < top() && mLast.fBottom < top() + 2) + || (mLast.fLeft < rect.fLeft // glyphs are LTR + && mLast.fRight + mMinSpaceWidth < rect.fLeft))) { + DBG_NAV_LOGD("TextExtractor [%02x] append space", glyphID); + *mSelectText.append() = ' '; + } else + mSkipFirstSpace = false; + DBG_NAV_LOGD("TextExtractor [%02x] append full=(%d,%d,r=%d,b=%d)", + glyphID, full.fLeft, full.fTop, full.fRight, full.fBottom); + SkUnichar uni; + SkPaint utfPaint = *mPaint; + utfPaint.setTextEncoding(SkPaint::kUTF16_TextEncoding); + utfPaint.glyphsToUnichars(&glyphID, 1, &uni); + if (uni) { + uint16_t chars[2]; + size_t count = SkUTF16_FromUnichar(uni, chars); + *mSelectText.append() = chars[0]; + if (count == 2) + *mSelectText.append() = chars[1]; + } + mLast = full; + } else + DBG_NAV_LOGD("TextExtractor [%02x] skip full=(%d,%d,r=%d,b=%d)", + glyphID, full.fLeft, full.fTop, full.fRight, full.fBottom); + return false; + } + + WebCore::String text() { + return WebCore::String(mSelectText.begin(), mSelectText.count()); + } + +protected: + const SkRegion& mSelectRegion; + SkTDArray<uint16_t> mSelectText; + SkIRect mLast; + SkScalar mMinSpaceWidth; + bool mSkipFirstSpace; +private: + typedef CommonCheck INHERITED; +}; + class TextCanvas : public SkCanvas { public: @@ -218,14 +284,14 @@ public: virtual void drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, const SkPaint& paint) { - mBounder.setUp(paint, getTotalMatrix(), y); + mBounder.setUp(paint, getTotalMatrix(), y, text); SkCanvas::drawText(text, byteLength, x, y, paint); } virtual void drawPosTextH(const void* text, size_t byteLength, const SkScalar xpos[], SkScalar constY, const SkPaint& paint) { - mBounder.setUp(paint, getTotalMatrix(), constY); + mBounder.setUp(paint, getTotalMatrix(), constY, text); SkCanvas::drawPosTextH(text, byteLength, xpos, constY, paint); } @@ -262,3 +328,17 @@ SkIRect CopyPaste::findClosest(const SkPicture& picture, const SkIRect& area, _check.offsetBounds(area.fLeft, area.fTop); return _check.bestBounds(); } + +WebCore::String CopyPaste::text(const SkPicture& picture, const SkIRect& area, + const SkRegion& region) { + SkRegion copy = region; + copy.translate(-area.fLeft, -area.fTop); + const SkIRect& bounds = copy.getBounds(); + DBG_NAV_LOGD("area=(%d, %d, %d, %d) region=(%d, %d, %d, %d)", + area.fLeft, area.fTop, area.fRight, area.fBottom, + bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom); + TextExtractor extractor(copy); + TextCanvas checker(&extractor, picture, area); + checker.drawPicture(const_cast<SkPicture&>(picture)); + return extractor.text(); +} diff --git a/WebKit/android/nav/SelectText.h b/WebKit/android/nav/SelectText.h index 3365816..32d8311 100644 --- a/WebKit/android/nav/SelectText.h +++ b/WebKit/android/nav/SelectText.h @@ -26,6 +26,8 @@ #ifndef SELECT_TEXT_H #define SELECT_TEXT_H +#include "PlatformString.h" + class SkPicture; struct SkIRect; struct SkIPoint; @@ -37,6 +39,8 @@ public: const SkIRect& selStart, const SkIRect& selEnd, SkRegion* region); static SkIRect findClosest(const SkPicture& , const SkIRect& area, int x, int y); + static WebCore::String text(const SkPicture& , const SkIRect& area, + const SkRegion& ); }; #endif diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp index 1c98b87..dae93fc 100644 --- a/WebKit/android/nav/WebView.cpp +++ b/WebKit/android/nav/WebView.cpp @@ -25,15 +25,15 @@ #define LOG_TAG "webviewglue" -#include <config.h> +#include "config.h" -#include "android_graphics.h" #include "AndroidAnimation.h" #include "AndroidLog.h" #include "AtomicString.h" #include "CachedFrame.h" #include "CachedNode.h" #include "CachedRoot.h" +#include "CString.h" #include "FindCanvas.h" #include "Frame.h" #include "GraphicsJNI.h" @@ -54,13 +54,12 @@ #include "SkPixelXorXfermode.h" #include "SkRect.h" #include "SkTime.h" -#include "WebCoreJni.h" -#include "WebViewCore.h" -#include "jni_utility.h" - #ifdef ANDROID_INSTRUMENT #include "TimeCounter.h" #endif +#include "WebCoreJni.h" +#include "WebViewCore.h" +#include "android_graphics.h" #ifdef GET_NATIVE_VIEW #undef GET_NATIVE_VIEW @@ -68,9 +67,10 @@ #define GET_NATIVE_VIEW(env, obj) ((WebView*)env->GetIntField(obj, gWebViewField)) -#include <ui/KeycodeLabels.h> +#include <JNIUtility.h> #include <JNIHelp.h> #include <jni.h> +#include <ui/KeycodeLabels.h> namespace android { @@ -98,7 +98,7 @@ enum FrameCachePermission { }; struct JavaGlue { - jobject m_obj; + jweak m_obj; jmethodID m_clearTextEntry; jmethodID m_overrideLoading; jmethodID m_scrollBy; @@ -127,7 +127,7 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) { jclass clazz = env->FindClass("android/webkit/WebView"); // m_javaGlue = new JavaGlue; - m_javaGlue.m_obj = adoptGlobalRef(env, javaWebView); + m_javaGlue.m_obj = env->NewWeakGlobalRef(javaWebView); m_javaGlue.m_scrollBy = GetJMethod(env, clazz, "setContentScrollBy", "(IIZ)Z"); m_javaGlue.m_clearTextEntry = GetJMethod(env, clazz, "clearTextEntry", "()V"); m_javaGlue.m_overrideLoading = GetJMethod(env, clazz, "overrideLoading", "(Ljava/lang/String;)V"); @@ -173,7 +173,7 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl) if (m_javaGlue.m_obj) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->DeleteGlobalRef(m_javaGlue.m_obj); + env->DeleteWeakGlobalRef(m_javaGlue.m_obj); m_javaGlue.m_obj = 0; } delete m_frameCacheUI; @@ -214,12 +214,7 @@ void clearTextEntry() { DEBUG_NAV_UI_LOGD("%s", __FUNCTION__); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue.m_clearTextEntry); + env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_clearTextEntry); checkException(env); } @@ -646,12 +641,7 @@ int getScaledMaxXScroll() { LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return 0; - int result = env->CallIntMethod(obj.get(), m_javaGlue.m_getScaledMaxXScroll); + int result = env->CallIntMethod(m_javaGlue.object(env).get(), m_javaGlue.m_getScaledMaxXScroll); checkException(env); return result; } @@ -660,12 +650,7 @@ int getScaledMaxYScroll() { LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return 0; - int result = env->CallIntMethod(obj.get(), m_javaGlue.m_getScaledMaxYScroll); + int result = env->CallIntMethod(m_javaGlue.object(env).get(), m_javaGlue.m_getScaledMaxYScroll); checkException(env); return result; } @@ -674,12 +659,7 @@ void getVisibleRect(WebCore::IntRect* rect) { LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - jobject jRect = env->CallObjectMethod(obj.get(), m_javaGlue.m_getVisibleRect); + jobject jRect = env->CallObjectMethod(m_javaGlue.object(env).get(), m_javaGlue.m_getVisibleRect); checkException(env); int left = (int) env->GetIntField(jRect, m_javaGlue.m_rectLeft); checkException(env); @@ -946,7 +926,7 @@ bool motionUp(int x, int y, int slop) if (!root) return 0; const CachedFrame* frame = 0; - const CachedNode* result = slop ? findAt(root, rect, &frame, &rx, &ry) : 0; + const CachedNode* result = findAt(root, rect, &frame, &rx, &ry); if (!result) { DBG_NAV_LOGD("no nodes found root=%p", root); setNavBounds(rect); @@ -998,13 +978,9 @@ int getBlockLeftEdge(int x, int y, float scale) void overrideUrlLoading(const WebCore::String& url) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; jstring jName = env->NewString((jchar*) url.characters(), url.length()); - env->CallVoidMethod(obj.get(), m_javaGlue.m_overrideLoading, jName); + env->CallVoidMethod(m_javaGlue.object(env).get(), + m_javaGlue.m_overrideLoading, jName); env->DeleteLocalRef(jName); } @@ -1051,9 +1027,15 @@ void moveSelection(int x, int y, bool extendSelection) m_selEnd.fLeft, m_selEnd.fTop, m_selEnd.fRight, m_selEnd.fBottom); } -const SkRegion& getSelection() +const String getSelection() { - return m_selRegion; + WebCore::IntRect r; + getVisibleRect(&r); + SkIRect area; + area.set(r.x(), r.y(), r.right(), r.bottom()); + String result = CopyPaste::text(*m_navPictureUI, area, m_selRegion); + DBG_NAV_LOGD("text=%s", result.latin1().data()); + return result; } void drawSelectionRegion(SkCanvas* canvas) @@ -1128,15 +1110,10 @@ void getSelectionCaret(SkPath* path) void sendMoveFocus(WebCore::Frame* framePtr, WebCore::Node* nodePtr) { - DBG_NAV_LOGD("framePtr=%p nodePtr=%p x=%d y=%d", framePtr, nodePtr, x, y); + DBG_NAV_LOGD("framePtr=%p nodePtr=%p", framePtr, nodePtr); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue.m_sendMoveFocus, (jint) framePtr, - (jint) nodePtr); + env->CallVoidMethod(m_javaGlue.object(env).get(), + m_javaGlue.m_sendMoveFocus, (jint) framePtr, (jint) nodePtr); checkException(env); } @@ -1144,12 +1121,7 @@ void sendMoveMouse(WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int { DBG_NAV_LOGD("framePtr=%p nodePtr=%p x=%d y=%d", framePtr, nodePtr, x, y); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue.m_sendMoveMouse, + env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_sendMoveMouse, (jint) framePtr, (jint) nodePtr, x, y); checkException(env); } @@ -1158,12 +1130,8 @@ void sendMoveMouseIfLatest(bool disableFocusController) { LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue.m_sendMoveMouseIfLatest, disableFocusController); + env->CallVoidMethod(m_javaGlue.object(env).get(), + m_javaGlue.m_sendMoveMouseIfLatest, disableFocusController); checkException(env); } @@ -1175,12 +1143,7 @@ void sendMotionUp( m_generation, framePtr, nodePtr, x, y); LOG_ASSERT(m_javaGlue.m_obj, "A WebView was not associated with this WebViewNative!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue.m_sendMotionUp, + env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_sendMotionUp, m_generation, (jint) framePtr, (jint) nodePtr, x, y); checkException(env); } @@ -1249,12 +1212,7 @@ bool scrollBy(int dx, int dy) LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return false; - bool result = env->CallBooleanMethod(obj.get(), + bool result = env->CallBooleanMethod(m_javaGlue.object(env).get(), m_javaGlue.m_scrollBy, dx, dy, true); checkException(env); return result; @@ -1291,49 +1249,30 @@ bool hasFocusNode() void rebuildWebTextView() { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue.m_rebuildWebTextView); + env->CallVoidMethod(m_javaGlue.object(env).get(), + m_javaGlue.m_rebuildWebTextView); checkException(env); } void viewInvalidate() { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue.m_viewInvalidate); + env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_viewInvalidate); checkException(env); } void viewInvalidateRect(int l, int t, int r, int b) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue.m_viewInvalidateRect, l, r, t, b); + env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_viewInvalidateRect, l, r, t, b); checkException(env); } void postInvalidateDelayed(int64_t delay, const WebCore::IntRect& bounds) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue.object(env); - // if it is called during or after DESTROY is handled, the real object of - // WebView can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue.m_postInvalidateDelayed, - delay, bounds.x(), bounds.y(), bounds.right(), bounds.bottom()); + env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_postInvalidateDelayed, + delay, bounds.x(), bounds.y(), bounds.right(), bounds.bottom()); checkException(env); } @@ -2059,13 +1998,15 @@ static void nativeMoveCursorToNextTextInput(JNIEnv *env, jobject obj) CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer); if (!root) return; - const CachedNode* current = root->currentCursor(); + const CachedFrame* containingFrame; + const CachedNode* current = root->currentCursor(&containingFrame); if (!current) - current = root->currentFocus(); + current = root->currentFocus(&containingFrame); if (!current) return; const CachedFrame* frame; - const CachedNode* next = root->nextTextField(current, &frame, true); + const CachedNode* next = containingFrame->nextTextField(current, &frame, + true); if (!next) return; const WebCore::IntRect& bounds = next->bounds(); @@ -2108,7 +2049,8 @@ static jobject nativeGetSelection(JNIEnv *env, jobject obj) { WebView* view = GET_NATIVE_VIEW(env, obj); LOG_ASSERT(view, "view not set in %s", __FUNCTION__); - return GraphicsJNI::createRegion(env, new SkRegion(view->getSelection())); + String selection = view->getSelection(); + return env->NewString((jchar*)selection.characters(), selection.length()); } #ifdef ANDROID_DUMP_DISPLAY_TREE @@ -2238,7 +2180,7 @@ static JNINativeMethod gJavaWebViewMethods[] = { (void*) nativeFocusNodePointer }, { "nativeGetCursorRingBounds", "()Landroid/graphics/Rect;", (void*) nativeGetCursorRingBounds }, - { "nativeGetSelection", "()Landroid/graphics/Region;", + { "nativeGetSelection", "()Ljava/lang/String;", (void*) nativeGetSelection }, { "nativeHasCursorNode", "()Z", (void*) nativeHasCursorNode }, |
