summaryrefslogtreecommitdiffstats
path: root/WebKit/android/nav/WebView.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebKit/android/nav/WebView.cpp')
-rw-r--r--WebKit/android/nav/WebView.cpp2322
1 files changed, 0 insertions, 2322 deletions
diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp
deleted file mode 100644
index 52bb6a5..0000000
--- a/WebKit/android/nav/WebView.cpp
+++ /dev/null
@@ -1,2322 +0,0 @@
-/*
- * Copyright 2007, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#define LOG_TAG "webviewglue"
-
-#include <config.h>
-
-#include "android_graphics.h"
-#include "AndroidLog.h"
-#include "AtomicString.h"
-#include "CachedFrame.h"
-#include "CachedNode.h"
-#include "CachedRoot.h"
-#include "FindCanvas.h"
-#include "Frame.h"
-#include "GraphicsJNI.h"
-#include "IntPoint.h"
-#include "IntRect.h"
-#include "Node.h"
-#include "PlatformGraphicsContext.h"
-#include "PlatformString.h"
-#include "SelectText.h"
-#include "SkBlurMaskFilter.h"
-#include "SkCanvas.h"
-#include "SkCornerPathEffect.h"
-#include "SkDumpCanvas.h"
-#include "SkPath.h"
-#include "SkPicture.h"
-#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
-
-#ifdef GET_NATIVE_VIEW
-#undef GET_NATIVE_VIEW
-#endif
-
-#define GET_NATIVE_VIEW(env, obj) ((WebView*)env->GetIntField(obj, gWebViewField))
-
-#include <ui/KeycodeLabels.h>
-#include <JNIHelp.h>
-#include <jni.h>
-
-#define REPLAY_BUFFER_SIZE 4096
-
-namespace android {
-
-struct CommonParams {
- enum Trigger {
- NoData,
- ClearFocusParams,
- FirstMoveFocusParams,
- MoveFocusParams,
- MotionUpParams
- } m_trigger;
- int m_generation;
-};
-
-struct CacheParams {
- void setFocus(const CachedNode* node,
- const CachedFrame* frame, const CachedRoot* root,
- const WebCore::IntPoint& focusLocation)
- {
- m_node = (WebCore::Node*) (node ? node->nodePointer() : 0);
- m_frame = (WebCore::Frame*) (node ? frame->framePointer() : 0);
- m_x = focusLocation.x();
- m_y = focusLocation.y();
- }
-
- WebCore::Node* m_node;
- WebCore::Frame* m_frame;
- int m_x;
- int m_y;
-};
-
-struct ClearFocusParams {
- CommonParams d;
- CacheParams c;
- int m_x;
- int m_y;
-};
-
-struct MotionUpParams {
- CommonParams d;
- int m_x;
- int m_y;
- int m_slop;
- bool m_isClick;
-};
-
-struct FirstMoveFocusParams {
- CommonParams d;
- int m_keyCode;
- int m_count;
- bool m_ignoreScroll;
-};
-
-struct MoveFocusParams {
- FirstMoveFocusParams d;
- CacheParams c;
- void* m_sentFocus;
- WebCore::IntRect m_sentBounds;
- WebCore::IntRect m_visibleRect;
- CachedHistory m_history; // FIXME: make this a subset
- int m_xMax;
- int m_yMax;
-};
-
-typedef MoveFocusParams LargestParams;
-
-#if DEBUG_NAV_UI
-static const char* TriggerNames[] = {
- "*** no data ! ***",
- "clearFocus",
- "firstMoveFocus",
- "moveFocus",
- "motionUp"
-};
-#endif
-
-class FocusReplay {
-public:
-FocusReplay() : m_start(m_buffer), m_end(m_buffer), m_lastGeneration(0)
-{
-}
-
-// find the most recent common data
-void add(const CommonParams& data, size_t len)
-{
- DBG_NAV_LOGD("m_start=%d m_end=%d trigger=%s moveGeneration=%d", m_start - m_buffer,
- m_end - m_buffer, TriggerNames[data.m_trigger], data.m_generation);
- m_lastGeneration = data.m_generation;
- char* limit = m_buffer + sizeof(m_buffer);
- int used = m_end - m_start;
- if (used < 0)
- used += sizeof(m_buffer);
- int needed = (int) len - ((int) sizeof(m_buffer) - used);
- if (needed >= 0)
- reclaim(++needed);
- if (m_end + len <= limit) {
- memcpy(m_end, (void*) &data, len);
- m_end += len;
- DBG_NAV_LOGD("m_start=%d m_end=%d", m_start - m_buffer, m_end - m_buffer);
- return;
- }
- size_t partial = limit - m_end;
- memcpy(m_end, (void*) &data, partial);
- const void* remainder = (const void*) ((const char*) &data + partial);
- partial = len - partial;
- memcpy(m_buffer, remainder, partial);
- m_end = m_buffer + partial;
- DBG_NAV_LOGD("wrap m_start=%d m_end=%d",
- m_start - m_buffer, m_end - m_buffer);
-}
-
-int count()
-{
- DBG_NAV_LOGD("m_start=%d m_end=%d",
- m_start - m_buffer, m_end - m_buffer);
- if (m_start == m_end)
- return 0;
- char* limit = m_buffer + sizeof(m_buffer);
- char* saveStart = m_start;
- int result = 0;
- while (true) {
- ++result;
- m_start += triggerSize();
- if (m_start == m_end)
- break;
- if (m_start < limit)
- continue;
- m_start -= sizeof(m_buffer);
- if (m_start == m_end)
- break;
- }
- m_start = saveStart;
- DBG_NAV_LOGD("count=%d", result);
- return result;
-}
-
-void discard(int generation)
-{
- DBG_NAV_LOGD("generation=%d", generation);
- LargestParams storage;
- const CommonParams& params = storage.d.d;
- char* pos = position();
- retrieve(&storage.d.d);
- if (params.m_generation > generation) {
- DBG_NAV_LOGD("params.m_generation=%d > generation=%d",
- params.m_generation, generation);
- rewind(pos);
- DBG_NAV_LOGD("m_start=%d m_end=%d", m_start - m_buffer, m_end - m_buffer);
- return;
- }
- LOG_ASSERT(params.m_generation == generation, "params.m_generation != generation");
- DBG_NAV_LOGD("m_start=%d m_end=%d", m_start - m_buffer, m_end - m_buffer);
-}
-
-int lastAdd()
-{
- return m_lastGeneration;
-}
-
-char* position()
-{
- return m_start;
-}
-
-int retrieve(CommonParams* data)
-{
- if (m_end == m_start) {
- // changed from LOGD to LOGV, as it always fires when I click to center
- // text (mrr)
- LOGV("%s *** no data to retrieve (error condition) ***", __FUNCTION__);
- data->m_trigger = CommonParams::NoData;
- return data->m_generation = INT_MAX;
- }
- DBG_NAV_LOGD("m_start=%d m_end=%d",
- m_start - m_buffer, m_end - m_buffer);
- char* limit = m_buffer + sizeof(m_buffer);
- size_t size = triggerSize();
- if (m_start < m_end) {
- LOG_ASSERT((size_t) (m_end - m_start) >= size, "m_end - m_start < size");
- memcpy(data, m_start, size);
- m_start += size;
- } else {
- int partial = limit - m_start;
- if (partial > (int) size)
- partial = size;
- memcpy(data, m_start, partial);
- m_start += partial;
- void* remainder = (void*) ((char*) data + partial);
- partial = size - partial;
- if (partial > 0) {
- memcpy(remainder, m_buffer, partial);
- m_start = m_buffer + partial;
- LOG_ASSERT(m_start <= m_end, "m_start > m_end");
- }
- }
- if (m_start == limit) {
- m_start = m_buffer;
- if (m_end == limit)
- m_end = m_buffer;
- }
- DBG_NAV_LOGD("m_start=%d m_end=%d trigger=%s moveGeneration=%d",
- m_start - m_buffer, m_end - m_buffer, TriggerNames[data->m_trigger],
- data->m_generation);
- return data->m_generation;
-}
-
-void rewind(char* pos)
-{
- m_start = pos;
-}
-
-private:
-void reclaim(int needed)
-{
- DBG_NAV_LOGD("needed=%d", needed);
- char* limit = m_buffer + sizeof(m_buffer);
- do {
- size_t size = triggerSize();
- m_start += size;
- needed -= size;
- if (m_start >= limit) {
- m_start = m_buffer + (m_start - limit);
- if (m_end == limit)
- m_end = m_buffer;
- }
- } while (needed > 0 && m_start != m_end);
- DBG_NAV_LOGD("m_start=%d m_end=%d",
- m_start - m_buffer, m_end - m_buffer);
-}
-
-size_t triggerSize()
-{
- LOG_ASSERT(m_start != m_end, "m_start == m_end");
- char* limit = m_buffer + sizeof(m_buffer);
- LOG_ASSERT(m_start + sizeof(CommonParams::Trigger) <= limit, "trigger not in limit");
- CommonParams::Trigger trigger;
- memcpy(&trigger, m_start, sizeof(trigger));
- switch (trigger) {
- case CommonParams::ClearFocusParams:
- return sizeof(ClearFocusParams);
- case CommonParams::FirstMoveFocusParams:
- return sizeof(FirstMoveFocusParams);
- case CommonParams::MoveFocusParams:
- return sizeof(MoveFocusParams);
- case CommonParams::MotionUpParams:
- return sizeof(MotionUpParams);
- default:
- LOG_ASSERT(0, "trigger undefined");
- }
- return 0;
-}
-
-char m_buffer[REPLAY_BUFFER_SIZE];
-char* m_start;
-char* m_end;
-int m_lastGeneration;
-}; // end of helper class ReplayFocus
-
-static jfieldID gWebViewField;
-
-//-------------------------------------
-
-static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[], const char signature[])
-{
- jmethodID m = env->GetMethodID(clazz, name, signature);
- LOG_ASSERT(m, "Could not find method %s", name);
- return m;
-}
-
-//-------------------------------------
-// This class provides JNI for making calls into native code from the UI side
-// of the multi-threaded WebView.
-class WebView
-{
-public:
-enum FrameCachePermission {
- DontAllowNewer,
- AllowNewer,
- AllowNewest
-};
-
-enum OutOfFocusFix {
- DoNothing,
- ClearTextEntry,
- UpdateTextEntry
-};
-
-struct JavaGlue {
- jobject m_obj;
- jmethodID m_clearTextEntry;
- jmethodID m_overrideLoading;
- jmethodID m_scrollBy;
- jmethodID m_sendFinalFocus;
- jmethodID m_sendKitFocus;
- jmethodID m_sendMotionUp;
- jmethodID m_setFocusData;
- jmethodID m_getScaledMaxXScroll;
- jmethodID m_getScaledMaxYScroll;
- jmethodID m_getVisibleRect;
- jmethodID m_updateTextEntry;
- jmethodID m_displaySoftKeyboard;
- jmethodID m_viewInvalidate;
- jmethodID m_viewInvalidateRect;
- jmethodID m_postInvalidateDelayed;
- jfieldID m_rectLeft;
- jfieldID m_rectTop;
- jmethodID m_rectWidth;
- jmethodID m_rectHeight;
- jfieldID m_focusNode;
- jmethodID m_setAll;
- AutoJObject object(JNIEnv* env) {
- return getRealObject(env, m_obj);
- }
-} m_javaGlue;
-
-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_scrollBy = GetJMethod(env, clazz, "setContentScrollBy", "(IIZ)V");
- m_javaGlue.m_clearTextEntry = GetJMethod(env, clazz, "clearTextEntry", "()V");
- m_javaGlue.m_overrideLoading = GetJMethod(env, clazz, "overrideLoading", "(Ljava/lang/String;)V");
- m_javaGlue.m_sendFinalFocus = GetJMethod(env, clazz, "sendFinalFocus", "(IIII)V");
- m_javaGlue.m_sendKitFocus = GetJMethod(env, clazz, "sendKitFocus", "()V");
- m_javaGlue.m_sendMotionUp = GetJMethod(env, clazz, "sendMotionUp", "(IIIIIIIZZ)V");
- m_javaGlue.m_setFocusData = GetJMethod(env, clazz, "setFocusData", "(IIIIIIZ)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;");
- m_javaGlue.m_updateTextEntry = GetJMethod(env, clazz, "updateTextEntry", "()V");
- m_javaGlue.m_displaySoftKeyboard = GetJMethod(env, clazz, "displaySoftKeyboard", "()V");
- m_javaGlue.m_viewInvalidate = GetJMethod(env, clazz, "viewInvalidate", "()V");
- m_javaGlue.m_viewInvalidateRect = GetJMethod(env, clazz, "viewInvalidate", "(IIII)V");
- m_javaGlue.m_postInvalidateDelayed = GetJMethod(env, clazz,
- "viewInvalidateDelayed", "(JIIII)V");
- jclass rectClass = env->FindClass("android/graphics/Rect");
- LOG_ASSERT(rectClass, "Could not find Rect class");
- m_javaGlue.m_rectLeft = env->GetFieldID(rectClass, "left", "I");
- m_javaGlue.m_rectTop = env->GetFieldID(rectClass, "top", "I");
- m_javaGlue.m_rectWidth = GetJMethod(env, rectClass, "width", "()I");
- m_javaGlue.m_rectHeight = GetJMethod(env, rectClass, "height", "()I");
-
- // Set up class for updateFocusNode
- jclass focusnodeClass = env->FindClass("android/webkit/WebView$FocusNode");
- LOG_ASSERT(focusnodeClass, "Could not find FocusNode class!");
- m_javaGlue.m_focusNode = env->GetFieldID(clazz, "mFocusNode", "Landroid/webkit/WebView$FocusNode;");
- m_javaGlue.m_setAll = GetJMethod(env, focusnodeClass, "setAll", "(ZZZZZIIIIIIIILjava/lang/String;Ljava/lang/String;I)V");
- env->DeleteLocalRef(focusnodeClass);
-
- env->SetIntField(javaWebView, gWebViewField, (jint)this);
- m_viewImpl = (WebViewCore*) viewImpl;
- m_frameCacheUI = 0;
- m_navPictureUI = 0;
- m_invalidNode = 0;
- m_generation = 0;
- m_heightCanMeasure = false;
- m_followedLink = false;
- m_lastDx = 0;
- m_lastDxTime = 0;
- m_ringAnimationEnd = 0;
- m_selStart.setEmpty();
- m_selEnd.setEmpty();
- m_matches = 0;
- m_hasCurrentLocation = false;
- m_isFindPaintSetUp = false;
-}
-
-~WebView()
-{
- if (m_javaGlue.m_obj)
- {
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->DeleteGlobalRef(m_javaGlue.m_obj);
- m_javaGlue.m_obj = 0;
- }
- delete m_frameCacheUI;
- delete m_navPictureUI;
- if (m_matches)
- delete m_matches;
-}
-
-void clearFocus(int x, int y, bool inval)
-{
- DBG_NAV_LOGD("x=%d y=%d inval=%s", x, y,
- inval ? "true" : "false");
- clearTextEntry();
- CachedRoot* root = getFrameCache(AllowNewer);
- if (!root)
- return;
- const CachedFrame* oldFrame = 0;
- const CachedNode* oldFocusNode = root->currentFocus(&oldFrame);
- WebCore::IntPoint focusLocation = WebCore::IntPoint(0, 0);
- setFocusData(root->generation(), 0, 0, x, y, !oldFocusNode);
- sendKitFocus();
- if (oldFocusNode) {
- DBG_NAV_LOG("oldFocusNode");
- focusLocation = root->focusLocation();
- root->setCachedFocus(0, 0);
- if (inval)
- viewInvalidate();
- }
- ClearFocusParams params;
- params.d.m_trigger = CommonParams::ClearFocusParams;
- params.d.m_generation = m_generation;
- params.c.setFocus(oldFocusNode, oldFrame, root, focusLocation);
- params.m_x = x;
- params.m_y = y;
- m_replay.add(params.d, sizeof(params));
-}
-
-void clearTextEntry()
-{
- DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_clearTextEntry);
- checkException(env);
-}
-
-#if DUMP_NAV_CACHE
-void debugDump()
-{
- CachedRoot* root = getFrameCache(DontAllowNewer);
- if (root)
- root->mDebug.print();
-}
-#endif
-
-// Traverse our stored array of buttons that are in our picture, and update
-// their subpictures according to their current focus state.
-// Called from the UI thread. This is the one place in the UI thread where we
-// access the buttons stored in the WebCore thread.
-// hasFocus keeps track of whether the WebView has focus && windowFocus.
-// If not, we do not want to draw the button in a focused or pressed state
-void nativeRecordButtons(bool hasFocus, bool pressed, bool invalidate)
-{
- bool focusIsButton = false;
- const CachedNode* cachedFocus = 0;
- // Lock the mutex, since we now share with the WebCore thread.
- m_viewImpl->gButtonMutex.lock();
- if (m_viewImpl->m_buttons.size()) {
- // Find the focused node so we can determine which node has focus, and
- // therefore which state to paint them in.
- // FIXME: In a future change, we should keep track of whether the focus
- // has changed to short circuit (note that we would still need to update
- // if we received new buttons from the WebCore thread).
- WebCore::Node* focus = 0;
- CachedRoot* root = getFrameCache(DontAllowNewer);
- if (root) {
- cachedFocus = root->currentFocus();
- if (cachedFocus)
- focus = (WebCore::Node*) cachedFocus->nodePointer();
- }
-
- // Traverse the array, and update each button, depending on whether it
- // is focused.
- Container* end = m_viewImpl->m_buttons.end();
- for (Container* ptr = m_viewImpl->m_buttons.begin(); ptr != end; ptr++) {
- WebCore::RenderSkinAndroid::State state;
- if (ptr->matches(focus)) {
- focusIsButton = true;
- // If the WebView is out of focus/window focus, set the state to
- // normal, but still keep track of the fact that the focus is a
- // button
- if (!hasFocus) {
- state = WebCore::RenderSkinAndroid::kNormal;
- } else if (m_followedLink || pressed) {
- state = WebCore::RenderSkinAndroid::kPressed;
- } else {
- state = WebCore::RenderSkinAndroid::kFocused;
- }
- } else {
- state = WebCore::RenderSkinAndroid::kNormal;
- }
- ptr->updateFocusState(state);
- }
- }
- m_viewImpl->gButtonMutex.unlock();
- if (invalidate && cachedFocus && focusIsButton) {
- const WebCore::IntRect& b = cachedFocus->getBounds();
- viewInvalidateRect(b.x(), b.y(), b.right(), b.bottom());
- }
-}
-
-// These two functions separate out the particular look of the drawn find
-// matches from the code that draws them. This function sets up the paints that
-// are used to draw the matches.
-void setUpFindPaint()
-{
- // Set up the foreground paint
- m_findPaint.setAntiAlias(true);
- const SkScalar roundiness = SkIntToScalar(2);
- SkCornerPathEffect* cornerEffect = new SkCornerPathEffect(roundiness);
- m_findPaint.setPathEffect(cornerEffect);
- m_findPaint.setARGB(255, 132, 190, 0);
-
- // Set up the background blur paint.
- m_findBlurPaint.setAntiAlias(true);
- m_findBlurPaint.setARGB(204, 0, 0, 0);
- m_findBlurPaint.setPathEffect(cornerEffect);
- cornerEffect->unref();
- SkMaskFilter* blurFilter = SkBlurMaskFilter::Create(SK_Scalar1,
- SkBlurMaskFilter::kNormal_BlurStyle);
- m_findBlurPaint.setMaskFilter(blurFilter)->unref();
- m_isFindPaintSetUp = true;
-}
-
-// Draw the match specified by region to the canvas.
-void drawMatch(const SkRegion& region, SkCanvas* canvas, bool focused)
-{
- // For the match which has focus, use a filled paint. For the others, use
- // a stroked paint.
- if (focused) {
- m_findPaint.setStyle(SkPaint::kFill_Style);
- m_findBlurPaint.setStyle(SkPaint::kFill_Style);
- } else {
- m_findPaint.setStyle(SkPaint::kStroke_Style);
- m_findPaint.setStrokeWidth(SK_Scalar1);
- m_findBlurPaint.setStyle(SkPaint::kStroke_Style);
- m_findBlurPaint.setStrokeWidth(SkIntToScalar(2));
- }
- // Find the path for the current match
- SkPath matchPath;
- region.getBoundaryPath(&matchPath);
- // Offset the path for a blurred shadow
- SkPath blurPath;
- matchPath.offset(SK_Scalar1, SkIntToScalar(2), &blurPath);
- int saveCount = 0;
- if (!focused) {
- saveCount = canvas->save();
- canvas->clipPath(matchPath, SkRegion::kDifference_Op);
- }
- // Draw the blurred background
- canvas->drawPath(blurPath, m_findBlurPaint);
- if (!focused) {
- canvas->restoreToCount(saveCount);
- }
- // Draw the foreground
- canvas->drawPath(matchPath, m_findPaint);
-}
-
-// Put a cap on the number of matches to draw. If the current page has more
-// matches than this, only draw the focused match.
-#define MAX_NUMBER_OF_MATCHES_TO_DRAW 101
-
-void drawMatches(SkCanvas* canvas)
-{
- if (!m_matches || !m_matches->size()) {
- return;
- }
- if (m_findIndex >= m_matches->size()) {
- m_findIndex = 0;
- }
- const MatchInfo& matchInfo = (*m_matches)[m_findIndex];
- const SkRegion& currentMatchRegion = matchInfo.getLocation();
- const SkIRect& currentMatchBounds = currentMatchRegion.getBounds();
- int left = currentMatchBounds.fLeft;
- int top = currentMatchBounds.fTop;
- int right = currentMatchBounds.fRight;
- int bottom = currentMatchBounds.fBottom;
- WebCore::IntRect visible;
- getVisibleRect(&visible);
- // Check to make sure that the highlighted match is on screen. If not,
- // scroll it onscreen and return.
- int dx = 0;
- if (left < visible.x()) {
- dx = left - visible.x();
- // Only scroll right if the entire width can fit on screen.
- } else if (right > visible.right() && right - left < visible.width()) {
- dx = right - visible.right();
- }
- int dy = 0;
- if (top < visible.y()) {
- dy = top - visible.y();
- // Only scroll down if the entire height can fit on screen
- } else if (bottom > visible.bottom() && bottom - top < visible.height()) {
- dy = bottom - visible.bottom();
- }
- if ((dx|dy)) {
- scrollBy(dx, dy);
- viewInvalidate();
- return;
- }
- // Set up the paints used for drawing the matches
- if (!m_isFindPaintSetUp)
- setUpFindPaint();
-
- // Draw the current match
- drawMatch(currentMatchRegion, canvas, true);
- // Now draw the picture, so that it shows up on top of the rectangle
- canvas->drawPicture(*matchInfo.getPicture());
-
- // Draw the rest
- unsigned numberOfMatches = m_matches->size();
- if (numberOfMatches > 1
- && numberOfMatches < MAX_NUMBER_OF_MATCHES_TO_DRAW) {
- SkIRect visibleIRect;
- android_setrect(&visibleIRect, visible);
- for(unsigned i = 0; i < numberOfMatches; i++) {
- // The current match has already been drawn
- if (i == m_findIndex)
- continue;
- const SkRegion& region = (*m_matches)[i].getLocation();
- // Do not draw matches which intersect the current one, or if it is
- // offscreen
- if (currentMatchRegion.intersects(region)
- || !region.intersects(visibleIRect))
- continue;
- drawMatch(region, canvas, false);
- }
- }
-}
-
-void drawFocusRing(SkCanvas* canvas)
-{
- const CachedRoot* root = getFrameCache(AllowNewer);
- if (!root) {
- DBG_NAV_LOG("!root");
- m_followedLink = false;
- return;
- }
- const CachedNode* node = root->currentFocus();
- if (!node) {
- DBG_NAV_LOG("!node");
- m_followedLink = false;
- return;
- }
- if (!node->hasFocusRing()) {
- DBG_NAV_LOG("!node->hasFocusRing()");
- return;
- }
- const WTF::Vector<WebCore::IntRect>& rings = node->focusRings();
- if (!rings.size()) {
- DBG_NAV_LOG("!rings.size()");
- return;
- }
-
- bool isButton = false;
- m_viewImpl->gButtonMutex.lock();
- // If this is a button drawn by us (rather than webkit) do not draw the
- // focus ring, since its focus will be shown by a change in what we draw.
- // Should be in sync with recordButtons, since that will be called
- // before this.
- if (m_viewImpl->m_buttons.size() > 0) {
- WebCore::Node* focusPointer = (WebCore::Node*) node->nodePointer();
- Container* end = m_viewImpl->m_buttons.end();
- for (Container* ptr = m_viewImpl->m_buttons.begin(); ptr != end; ptr++) {
- if (ptr->matches(focusPointer)) {
- isButton = true;
- break;
- }
- }
- }
- m_viewImpl->gButtonMutex.unlock();
- WebCore::IntRect bounds = node->bounds();
- bounds.inflate(SkScalarCeil(FOCUS_RING_OUTER_DIAMETER));
- SkRect sbounds;
- android_setrect(&sbounds, bounds);
- if (canvas->quickReject(sbounds, SkCanvas::kAA_EdgeType)) {
- DBG_NAV_LOG("canvas->quickReject");
- m_followedLink = false;
- return;
- }
- FocusRing::Flavor flavor = FocusRing::NORMAL_FLAVOR;
- if (!isButton) {
- flavor = node->type() != NORMAL_CACHEDNODETYPE ?
- FocusRing::FAKE_FLAVOR : node->nodePointer() == m_invalidNode ?
- FocusRing::INVALID_FLAVOR : FocusRing::NORMAL_FLAVOR;
- if (flavor != FocusRing::INVALID_FLAVOR && m_followedLink) {
- flavor = (FocusRing::Flavor) (flavor + FocusRing::NORMAL_ANIMATING);
- }
-#if DEBUG_NAV_UI
- const WebCore::IntRect& ring = rings[0];
- DBG_NAV_LOGD("cachedFocusNode=%d (nodePointer=%p) flavor=%s rings=%d"
- " (%d, %d, %d, %d)", node->index(), node->nodePointer(),
- flavor == FocusRing::FAKE_FLAVOR ? "FAKE_FLAVOR" :
- flavor == FocusRing::INVALID_FLAVOR ? "INVALID_FLAVOR" :
- flavor == FocusRing::NORMAL_ANIMATING ? "NORMAL_ANIMATING" :
- flavor == FocusRing::FAKE_ANIMATING ? "FAKE_ANIMATING" : "NORMAL_FLAVOR",
- rings.size(), ring.x(), ring.y(), ring.width(), ring.height());
-#endif
- }
- if (isButton || flavor >= FocusRing::NORMAL_ANIMATING) {
- SkMSec time = SkTime::GetMSecs();
- if (time < m_ringAnimationEnd) {
- // views assume that inval bounds coordinates are non-negative
- bounds.intersect(WebCore::IntRect(0, 0, INT_MAX, INT_MAX));
- postInvalidateDelayed(m_ringAnimationEnd - time, bounds);
- } else {
- m_followedLink = false;
- flavor = (FocusRing::Flavor) (flavor - FocusRing::NORMAL_ANIMATING);
- }
- }
- if (!isButton)
- FocusRing::DrawRing(canvas, rings, flavor);
-}
-
-OutOfFocusFix fixOutOfDateFocus(bool useReplay)
-{
- if (!m_frameCacheUI) {
- DBG_NAV_LOG("!m_frameCacheUI");
- return DoNothing;
- }
- const CachedFrame* cachedFrame = 0;
- const CachedNode* cachedFocusNode = m_frameCacheUI->currentFocus(&cachedFrame);
- if (!cachedFocusNode) {
- DBG_NAV_LOG("!cachedFocusNode");
- return DoNothing;
- }
- CachedRoot* webRoot = m_viewImpl->m_frameCacheKit;
- if (!webRoot) {
- DBG_NAV_LOG("!webRoot");
- return DoNothing;
- }
- int uiWidth = m_frameCacheUI->width();
- int webWidth = webRoot->width();
- if (uiWidth != webWidth) {
- DBG_NAV_LOGD("uiWidth=%d webWidth=%d", uiWidth, webWidth);
- return DoNothing; // allow text inputs to preserve their state
- } else {
- const WebCore::IntRect& cachedBounds = m_frameCacheUI->focusBounds();
- const CachedFrame* webFrame = 0;
- const CachedNode* webFocusNode = webRoot->currentFocus(&webFrame);
- DBG_NAV_LOGD("cachedBounds=(%d,%d,w=%d,h=%d) cachedFrame=%p (%d)"
- " webFocusNode=%p (%d) webFrame=%p (%d)",
- cachedBounds.x(), cachedBounds.y(),
- cachedBounds.width(), cachedBounds.height(),
- cachedFrame, cachedFrame ? cachedFrame->indexInParent() : -1,
- webFocusNode, webFocusNode ? webFocusNode->index() : -1,
- webFrame, webFrame ? webFrame->indexInParent() : -1);
- if (webFocusNode && webFrame && webFrame->sameFrame(cachedFrame)) {
- if (useReplay && !m_replay.count()) {
- DBG_NAV_LOG("!m_replay.count()");
- return DoNothing;
- }
- if (webFocusNode->index() == cachedFocusNode->index()) {
- DBG_NAV_LOG("index ==");
- return DoNothing;
- }
- const WebCore::IntRect& webBounds = webRoot->focusBounds();
- DBG_NAV_LOGD("webBounds=(%d,%d,w=%d,h=%d)",
- webBounds.x(), webBounds.y(),
- webBounds.width(), webBounds.height());
- if (cachedBounds.contains(webBounds)) {
- DBG_NAV_LOG("contains");
- return DoNothing;
- }
- if (webBounds.contains(cachedBounds)) {
- DBG_NAV_LOG("webBounds contains");
- return DoNothing;
- }
- }
- const CachedFrame* foundFrame = 0;
- int x, y;
- const CachedNode* found = findAt(webRoot, cachedBounds, &foundFrame, &x, &y);
-#if DEBUG_NAV_UI
- DBG_NAV_LOGD("found=%p (%d) frame=%p (%d)",
- found, found ? found->index() : -1,
- foundFrame, foundFrame ? foundFrame->indexInParent() : -1);
- if (found) {
- WebCore::IntRect newBounds = found->bounds();
- DBG_NAV_LOGD("found=(%d,%d,w=%d,h=%d) x=%d y=%d",
- newBounds.x(), newBounds.y(), newBounds.width(),
- newBounds.height(), x, y);
- }
-#endif
- webRoot->setCachedFocus(const_cast<CachedFrame*>(foundFrame),
- const_cast<CachedNode*>(found));
- if (found)
- webRoot->rootHistory()->setNavBounds(found->bounds());
- WebCore::Frame* framePointer = foundFrame ? (WebCore::Frame*) foundFrame->framePointer() : 0;
- WebCore::Node* nodePointer = found ? (WebCore::Node*) found->nodePointer() : 0;
- setFocusData(webRoot->generation(), framePointer, nodePointer, x, y, !found);
- sendFinalFocus(framePointer, nodePointer, x, y);
- if (found && (found->isTextArea() || found->isTextField()))
- return UpdateTextEntry;
- }
-checkOldFocus:
- return cachedFocusNode->isTextArea() || cachedFocusNode->isTextField() ? ClearTextEntry : DoNothing;
-}
-
-bool focusIsTextArea(FrameCachePermission allowNewer)
-{
- CachedRoot* root = getFrameCache(allowNewer);
- if (!root) {
- DBG_NAV_LOG("!root");
- return false;
- }
- const CachedNode* focus = root->currentFocus();
- if (!focus)
- return false;
- return focus->isTextArea() || focus->isTextField();
-}
-
-void focusRingBounds(WebCore::IntRect* bounds)
-{
- DBG_NAV_LOGD("%s", "");
- CachedRoot* root = getFrameCache(DontAllowNewer);
- if (root) {
- const CachedNode* cachedNode = root->currentFocus();
- if (cachedNode) {
- cachedNode->focusRingBounds(bounds);
- DBG_NAV_LOGD("bounds={%d,%d,%d,%d}", bounds->x(), bounds->y(),
- bounds->width(), bounds->height());
- return;
- }
- }
- *bounds = WebCore::IntRect(0, 0, 0, 0);
-}
-
-CachedRoot* getFrameCache(FrameCachePermission allowNewer)
-{
- if (!m_viewImpl->m_updatedFrameCache)
- return m_frameCacheUI;
- m_viewImpl->gRecomputeFocusMutex.lock();
- bool recomputeInProgress = m_viewImpl->m_recomputeEvents.size() > 0;
- m_viewImpl->gRecomputeFocusMutex.unlock();
- if (allowNewer != AllowNewest && recomputeInProgress)
- return m_frameCacheUI;
- if (allowNewer == DontAllowNewer && m_viewImpl->m_lastGeneration < m_generation)
- return m_frameCacheUI;
- DBG_NAV_LOGD("%s", "m_viewImpl->m_updatedFrameCache == true");
- m_viewImpl->gFrameCacheMutex.lock();
- OutOfFocusFix fix = DoNothing;
- if (allowNewer != DontAllowNewer)
- fix = fixOutOfDateFocus(m_viewImpl->m_useReplay);
- delete m_frameCacheUI;
- delete m_navPictureUI;
- m_viewImpl->m_updatedFrameCache = false;
- m_frameCacheUI = m_viewImpl->m_frameCacheKit;
- m_navPictureUI = m_viewImpl->m_navPictureKit;
- m_viewImpl->m_frameCacheKit = 0;
- m_viewImpl->m_navPictureKit = 0;
- m_viewImpl->gFrameCacheMutex.unlock();
- if (fix == UpdateTextEntry)
- updateTextEntry();
- else if (fix == ClearTextEntry)
- clearTextEntry();
- return m_frameCacheUI;
-}
-
-int getScaledMaxXScroll()
-{
- LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- int result = env->CallIntMethod(m_javaGlue.object(env).get(), m_javaGlue.m_getScaledMaxXScroll);
- checkException(env);
- return result;
-}
-
-int getScaledMaxYScroll()
-{
- LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- int result = env->CallIntMethod(m_javaGlue.object(env).get(), m_javaGlue.m_getScaledMaxYScroll);
- checkException(env);
- return result;
-}
-
-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();
- 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);
- rect->setX(left);
- int top = (int) env->GetIntField(jRect, m_javaGlue.m_rectTop);
- checkException(env);
- rect->setY(top);
- int width = (int) env->CallIntMethod(jRect, m_javaGlue.m_rectWidth);
- checkException(env);
- rect->setWidth(width);
- int height = (int) env->CallIntMethod(jRect, m_javaGlue.m_rectHeight);
- checkException(env);
- rect->setHeight(height);
- env->DeleteLocalRef(jRect);
- checkException(env);
-}
-
-static CachedFrame::Direction KeyToDirection(KeyCode keyCode)
-{
- switch (keyCode) {
- case kKeyCodeDpadRight:
- DBG_NAV_LOGD("keyCode=%s", "right");
- return CachedFrame::RIGHT;
- case kKeyCodeDpadLeft:
- DBG_NAV_LOGD("keyCode=%s", "left");
- return CachedFrame::LEFT;
- case kKeyCodeDpadDown:
- DBG_NAV_LOGD("keyCode=%s", "down");
- return CachedFrame::DOWN;
- case kKeyCodeDpadUp:
- DBG_NAV_LOGD("keyCode=%s", "up");
- return CachedFrame::UP;
- default:
- LOGD("------- bad key sent to WebView::moveFocus");
- return CachedFrame::UNINITIALIZED;
- }
-}
-
-bool invalidFrame(WebCore::Frame* frame, const CachedRoot* root)
-{
- if (!frame)
- return false;
- int frameBuild = m_viewImpl->retrieveFrameGeneration(frame);
- int rootBuild = root->generation();
- return frameBuild > rootBuild;
-}
-
-WebCore::String imageURI(int x, int y)
-{
- const CachedRoot* root = getFrameCache(DontAllowNewer);
- return root ? root->imageURI(x, y) : WebCore::String();
-}
-
-bool focusNodeWantsKeyEvents()
-{
- const CachedRoot* root = getFrameCache(DontAllowNewer);
- if (root) {
- const CachedNode* focus = root->currentFocus();
- if (focus) {
- return focus->isWantsKeyEvents();
- }
- }
- return false;
-}
-
-/* returns true if the key had no effect (neither scrolled nor changed focus) */
-bool moveFocus(int keyCode, int count, bool ignoreScroll, bool inval,
- void* lastSentFocus, const WebCore::IntRect* lastSentBounds)
-{
- CachedRoot* root = getFrameCache(AllowNewer);
- if (!root) {
- DBG_NAV_LOG("!root");
- setFocusData(0, 0, 0, 0, 0, true);
- sendKitFocus(); // will build cache and retry
- FirstMoveFocusParams params;
- params.d.m_trigger = CommonParams::FirstMoveFocusParams;
- params.d.m_generation = m_generation;
- params.m_keyCode = keyCode;
- params.m_count = count;
- params.m_ignoreScroll = ignoreScroll;
- m_replay.add(params.d, sizeof(params));
- return true;
- }
-
- CachedFrame::Direction direction = KeyToDirection((KeyCode) keyCode);
- const CachedFrame* cachedFrame, * oldFrame = 0;
- const CachedNode* focus = root->currentFocus(&oldFrame);
- WebCore::IntPoint focusLocation = root->focusLocation();
- DBG_NAV_LOGD("old focus %d (nativeNode=%p) focusLocation={%d, %d}",
- focus ? focus->index() : 0,
- focus ? focus->nodePointer() : 0, focusLocation.x(), focusLocation.y());
- WebCore::IntRect visibleRect;
- getVisibleRect(&visibleRect);
- DBG_NAV_LOGD("getVisibleRect %d,%d,%d,%d",
- visibleRect.x(), visibleRect.y(), visibleRect.width(), visibleRect.height());
- root->setVisibleRect(visibleRect);
- int xMax = getScaledMaxXScroll();
- int yMax = getScaledMaxYScroll();
- root->setMaxScroll(xMax, yMax);
- CachedHistory savedHistory = *root->rootHistory();
- bool oldNodeIsTextArea = focusIsTextArea(DontAllowNewer);
- const CachedNode* cachedNode = 0;
- int dx = 0;
- int dy = 0;
- int counter = count;
- if (!focus || !focus->isInput() || !m_followedLink)
- root->setScrollOnly(m_followedLink);
- while (--counter >= 0) {
- WebCore::IntPoint scroll = WebCore::IntPoint(0, 0);
- cachedNode = root->moveFocus(direction, &cachedFrame, &scroll);
- dx += scroll.x();
- dy += scroll.y();
- }
- DBG_NAV_LOGD("new focus %d (nativeNode=%p) focusLocation={%d, %d}",
- cachedNode ? cachedNode->index() : 0,
- cachedNode ? cachedNode->nodePointer() : 0, root->focusLocation().x(),
- root->focusLocation().y());
- // If !m_heightCanMeasure (such as in the browser), we want to scroll no
- // matter what
- if (!ignoreScroll && (!m_heightCanMeasure ||
- !cachedNode ||
- (focus && focus->nodePointer() == cachedNode->nodePointer())))
- {
- if (count == 1 && dx != 0 && dy == 0 && -m_lastDx == dx &&
- SkTime::GetMSecs() - m_lastDxTime < 1000)
- root->checkForJiggle(&dx);
- DBG_NAV_LOGD("scrollBy %d,%d", dx, dy);
- if ((dx | dy))
- this->scrollBy(dx, dy);
- m_lastDx = dx;
- m_lastDxTime = SkTime::GetMSecs();
- ignoreScroll = true; // if move re-executes, don't scroll the second time
- }
- bool result = false;
- if (cachedNode) {
- WebCore::IntPoint pos;
- root->setCachedFocus((CachedFrame*) cachedFrame, (CachedNode*) cachedNode);
- root->getSimulatedMousePosition(&pos);
- if (lastSentFocus == cachedNode->nodePointer() && lastSentBounds &&
- *lastSentBounds == cachedNode->bounds())
- {
- sendFinalFocus((WebCore::Frame*) cachedFrame->framePointer(),
- (WebCore::Node*) cachedNode->nodePointer(), pos.x(), pos.y());
- } else {
- setFocusData(root->generation(),
- (WebCore::Frame*) cachedFrame->framePointer(),
- (WebCore::Node*) cachedNode->nodePointer(), pos.x(), pos.y(),
- true);
- sendKitFocus();
- if (inval)
- viewInvalidate();
- MoveFocusParams params;
- params.d.d.m_trigger = CommonParams::MoveFocusParams;
- params.d.d.m_generation = m_generation;
- params.c.setFocus(focus, oldFrame, root, focusLocation);
- params.m_sentFocus = cachedNode->nodePointer();
- params.m_sentBounds = cachedNode->bounds();
- params.m_visibleRect = visibleRect;
- params.m_history = savedHistory;
- DBG_NAV_LOGD("history.mDidFirstLayout=%s",
- params.m_history.didFirstLayout() ? "true" : "false");
- params.m_xMax = xMax;
- params.m_yMax = yMax;
- params.d.m_keyCode = keyCode;
- params.d.m_count = count;
- params.d.m_ignoreScroll = ignoreScroll;
- m_replay.add(params.d.d, sizeof(params));
- }
- } else {
- if (visibleRect.intersects(root->focusBounds()) == false) {
- setFocusData(root->generation(), 0, 0, 0, 0, true);
- sendKitFocus(); // will build cache and retry
- }
- FirstMoveFocusParams params;
- params.d.m_trigger = CommonParams::FirstMoveFocusParams;
- params.d.m_generation = m_generation;
- params.m_keyCode = keyCode;
- params.m_count = count;
- params.m_ignoreScroll = ignoreScroll;
- m_replay.add(params.d, sizeof(params));
- int docHeight = root->documentHeight();
- int docWidth = root->documentWidth();
- if (visibleRect.bottom() + dy > docHeight)
- dy = docHeight - visibleRect.bottom();
- else if (visibleRect.y() + dy < 0)
- dy = -visibleRect.y();
- if (visibleRect.right() + dx > docWidth)
- dx = docWidth - visibleRect.right();
- else if (visibleRect.x() < 0)
- dx = -visibleRect.x();
- result = direction == CachedFrame::LEFT ? dx >= 0 :
- direction == CachedFrame::RIGHT ? dx <= 0 :
- direction == CachedFrame::UP ? dy >= 0 : dy <= 0;
- }
- if (focusIsTextArea(DontAllowNewer))
- updateTextEntry();
- else if (oldNodeIsTextArea)
- clearTextEntry();
- return result;
-}
-
-void notifyFocusSet(FrameCachePermission inEditingMode)
-{
- CachedRoot* root = getFrameCache(DontAllowNewer);
- if (root) {
- // make sure the mFocusData in WebView.java is in sync with WebView.cpp
- const CachedFrame* frame = 0;
- const CachedNode* node = root->currentFocus(&frame);
- const WebCore::IntPoint& focusLocation = root->focusLocation();
- setFocusData(root->generation(),
- frame ? (WebCore::Frame*) frame->framePointer() : 0,
- node ? (WebCore::Node*) node->nodePointer() : 0,
- focusLocation.x(), focusLocation.y(), false);
- }
-
- if (focusIsTextArea(inEditingMode))
- updateTextEntry();
- else if (inEditingMode)
- clearTextEntry();
-#if DEBUG_NAV_UI
- if (m_frameCacheUI) {
- const CachedNode* focus = m_frameCacheUI->currentFocus();
- DBG_NAV_LOGD("focus %d (nativeNode=%p)",
- focus ? focus->index() : 0,
- focus ? focus->nodePointer() : 0);
- }
-#endif
-}
-
-void notifyProgressFinished()
-{
- DBG_NAV_LOGD("focusIsTextArea=%d", focusIsTextArea(DontAllowNewer));
- updateTextEntry();
-#if DEBUG_NAV_UI
- if (m_frameCacheUI) {
- const CachedNode* focus = m_frameCacheUI->currentFocus();
- DBG_NAV_LOGD("focus %d (nativeNode=%p)",
- focus ? focus->index() : 0,
- focus ? focus->nodePointer() : 0);
- }
-#endif
-}
-
-void recomputeFocus()
-{
- int generation;
- do {
- m_viewImpl->gRecomputeFocusMutex.lock();
- if (!m_viewImpl->m_recomputeEvents.size()) {
- m_viewImpl->gRecomputeFocusMutex.unlock();
- return;
- }
- generation = m_viewImpl->m_recomputeEvents.first();
- m_viewImpl->m_recomputeEvents.remove(0);
- m_viewImpl->gRecomputeFocusMutex.unlock();
- DBG_NAV_LOGD("generation=%d", generation);
- CachedRoot* root = getFrameCache(AllowNewest);
- if (!root) {
- DBG_NAV_LOG("!root");
- return;
- }
- LargestParams storage;
- const CommonParams& params = storage.d.d;
- char* pos = m_replay.position();
- while (m_replay.retrieve(&storage.d.d) < generation)
- DBG_NAV_LOGD("dropped ", params.m_generation);
- if (params.m_generation > generation) {
- DBG_NAV_LOGD("params.m_generation=%d > generation=%d",
- params.m_generation, generation);
- m_replay.rewind(pos);
- return;
- }
- int lastAdd = m_replay.lastAdd();
- do {
- LOG_ASSERT(params.m_trigger != CommonParams::NoData, "expected data");
- bool inval = generation == m_generation;
- switch (params.m_trigger) {
- case CommonParams::ClearFocusParams: {
- const ClearFocusParams& sParams = *(ClearFocusParams*) &storage;
- const CacheParams& cParams = sParams.c;
- if (invalidFrame(cParams.m_frame, root)) {
- DBG_NAV_LOGD("dropped %s generation=%d",
- TriggerNames[params.m_trigger], generation);
- return;
- }
- root->setFocus(cParams.m_frame, cParams.m_node, cParams.m_x, cParams.m_y);
- clearFocus(sParams.m_x, sParams.m_y, inval);
- DBG_NAV_LOGD("clearFocus(x,y)={%d,%d}", sParams.m_x, sParams.m_y);
- } break;
- case CommonParams::MotionUpParams: {
- const MotionUpParams& mParams = *(MotionUpParams*) &storage;
- // const CacheParams& cParams = mParams.c;
- // if (invalidFrame(cParams.m_frame, root) == false)
- // root->setFocus(cParams.m_frame, cParams.m_node,
- // cParams.m_x, cParams.m_y);
- motionUp(mParams.m_x, mParams.m_y, mParams.m_slop, mParams.m_isClick, inval, true);
- DBG_NAV_LOGD("motionUp m_x=%d m_y=%d", mParams.m_x, mParams.m_y);
- } break;
- case CommonParams::FirstMoveFocusParams: {
- if (invalidFrame((WebCore::Frame*) root->framePointer(), root)) {
- DBG_NAV_LOGD("dropped %s generation=%d",
- TriggerNames[params.m_trigger], generation);
- return;
- }
- const FirstMoveFocusParams& fParams = *(FirstMoveFocusParams*) &storage;
- DBG_NAV_LOGD("first moveFocus keyCode=%d count=%d"
- " ignoreScroll=%s", fParams.m_keyCode, fParams.m_count,
- fParams.m_ignoreScroll ? "true" : "false");
- moveFocus(fParams.m_keyCode, fParams.m_count,
- fParams.m_ignoreScroll, inval, 0, 0);
- } break;
- case CommonParams::MoveFocusParams: {
- const MoveFocusParams& mParams = *(MoveFocusParams*) &storage;
- const CacheParams& cParams = mParams.c;
- if (invalidFrame(cParams.m_frame, root)) {
- DBG_NAV_LOGD("dropped %s generation=%d",
- TriggerNames[params.m_trigger], generation);
- return;
- }
- DBG_NAV_LOGD("moveFocus keyCode=%d count=%d ignoreScroll=%s "
- "history.mDidFirstLayout=%s", mParams.d.m_keyCode,
- mParams.d.m_count, mParams.d.m_ignoreScroll ? "true" : "false",
- mParams.m_history.didFirstLayout() ? "true" : "false");
- if (!root->setFocus(cParams.m_frame, cParams.m_node,
- cParams.m_x, cParams.m_y)) {
- DBG_NAV_LOGD("can't restore focus frame=%p node=%p",
- "x=%d y=%d %s", cParams.m_frame, cParams.m_node,
- cParams.m_x, cParams.m_y, TriggerNames[params.m_trigger]);
- return;
- }
- root->setVisibleRect(mParams.m_visibleRect);
- root->setMaxScroll(mParams.m_xMax, mParams.m_yMax);
- *root->rootHistory() = mParams.m_history;
- moveFocus(mParams.d.m_keyCode, mParams.d.m_count,
- mParams.d.m_ignoreScroll, inval,
- mParams.m_sentFocus, &mParams.m_sentBounds);
- } break;
- default:
- LOG_ASSERT(0, "unknown trigger");
- }
- if (params.m_generation >= lastAdd)
- break;
- root = getFrameCache(DontAllowNewer); // re-execution may have retrieved newer cache
- m_replay.retrieve(&storage.d.d);
- DBG_NAV_LOGD("continuation m_generation %d", params.m_generation);
- } while (true);
- } while (true);
-}
-
-void resetFocus()
-{
- DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
- CachedRoot* root = getFrameCache(AllowNewer);
- if (!root)
- return;
- root->setCachedFocus(0, 0);
-}
-
-const CachedNode* findAt(CachedRoot* root, const WebCore::IntRect& rect,
- const CachedFrame** framePtr, int* rxPtr, int* ryPtr)
-{
- *rxPtr = 0;
- *ryPtr = 0;
- *framePtr = 0;
- if (!root)
- return 0;
- WebCore::IntRect visibleRect;
- getVisibleRect(&visibleRect);
- root->setVisibleRect(visibleRect);
- return root->findAt(rect, framePtr, rxPtr, ryPtr);
-}
-
-void selectBestAt(const WebCore::IntRect& rect)
-{
- const CachedFrame* frame;
- int rx, ry;
- CachedRoot* root = getFrameCache(DontAllowNewer);
- const CachedNode* node = findAt(root, rect, &frame, &rx, &ry);
- int rootGeneration = root ? root->generation() : 0;
- setFocusData(rootGeneration,
- frame ? (WebCore::Frame*) frame->framePointer() : 0,
- node ? (WebCore::Node*) node->nodePointer() : 0, rx, ry, false);
- if (!node) {
- DBG_NAV_LOGD("no nodes found root=%p", root);
- if (root) {
- root->clearFocus();
- root->setCachedFocus(0, 0);
- }
- sendKitFocus();
- viewInvalidate();
- clearTextEntry();
- return;
- }
- DBG_NAV_LOGD("CachedNode:%p (%d)", node, node->index());
- const CachedFrame* oldFrame = 0;
- const CachedNode* oldFocusNode = root->currentFocus(&oldFrame);
- bool oldNodeIsTextArea = focusIsTextArea(DontAllowNewer);
- root->setCachedFocus(const_cast<CachedFrame*>(frame),
- const_cast<CachedNode*>(node));
- viewInvalidate();
- if (focusIsTextArea(DontAllowNewer))
- updateTextEntry();
- else if (oldNodeIsTextArea)
- clearTextEntry();
-}
-
-WebCore::IntRect getNavBounds()
-{
- CachedRoot* root = getFrameCache(DontAllowNewer);
- if (!root)
- return WebCore::IntRect(0, 0, 0, 0);
- return root->rootHistory()->navBounds();
-}
-
-void setNavBounds(const WebCore::IntRect& rect)
-{
- CachedRoot* root = getFrameCache(DontAllowNewer);
- if (!root)
- return;
- root->rootHistory()->setNavBounds(rect);
-}
-
-void markNodeInvalid(WebCore::Node* node)
-{
- DBG_NAV_LOGD("node=%p", node);
- m_invalidNode = node;
- viewInvalidate();
-}
-
-bool motionUp(int x, int y, int slop, bool isClick, bool inval, bool retry)
-{
- bool pageScrolled = false;
- m_followedLink = false;
- const CachedFrame* frame;
- WebCore::IntRect rect = WebCore::IntRect(x - slop, y - slop, slop * 2, slop * 2);
- int rx, ry;
- CachedRoot* root = getFrameCache(AllowNewer);
- const CachedNode* result = findAt(root, rect, &frame, &rx, &ry);
- if (!result) {
- DBG_NAV_LOGD("no nodes found root=%p", root);
- int rootGeneration = 0;
- if (root) {
- root->clearFocus();
- rootGeneration = root->generation();
- if (!retry) { // scroll first time only
- int dx = root->checkForCenter(x, y);
- if (dx) {
- scrollBy(dx, 0);
- retry = true; // don't recompute later since we scrolled
- pageScrolled = true;
- }
- }
- }
- sendMotionUp(rootGeneration, frame ?
- (WebCore::Frame*) frame->framePointer() : 0,
- 0, x, y, slop, isClick, retry);
- if (inval)
- viewInvalidate();
- if (!retry) {
- MotionUpParams params;
- params.d.m_trigger = CommonParams::MotionUpParams;
- params.d.m_generation = m_generation;
- params.m_x = x;
- params.m_y = y;
- params.m_slop = slop;
- params.m_isClick = isClick;
- m_replay.add(params.d, sizeof(params));
- }
- clearTextEntry();
- return pageScrolled;
- }
- DBG_NAV_LOGD("CachedNode:%p (%d) x=%d y=%d rx=%d ry=%d", result,
- result->index(), x, y, rx, ry);
- // const CachedFrame* oldFrame = 0;
- // const CachedNode* oldFocusNode = root->currentFocus(&oldFrame);
- // WebCore::IntPoint focusLocation = root->focusLocation();
- bool oldNodeIsTextArea = !retry && focusIsTextArea(DontAllowNewer);
- root->setCachedFocus(const_cast<CachedFrame*>(frame),
- const_cast<CachedNode*>(result));
- bool newNodeIsTextArea = focusIsTextArea(DontAllowNewer);
- CachedNodeType type = result->type();
- if (type == NORMAL_CACHEDNODETYPE || newNodeIsTextArea) {
- sendMotionUp(root->generation(),
- frame ? (WebCore::Frame*) frame->framePointer() : 0,
- result ? (WebCore::Node*) result->nodePointer() : 0, rx, ry,
- slop, isClick, retry);
- if (inval)
- viewInvalidate();
- if (!retry) {
- MotionUpParams params;
- params.d.m_trigger = CommonParams::MotionUpParams;
- params.d.m_generation = m_generation;
- params.m_x = x;
- params.m_y = y;
- params.m_slop = slop;
- params.m_isClick = isClick;
- // params.c.setFocus(oldFocusNode, oldFrame, root, focusLocation);
- m_replay.add(params.d, sizeof(params));
- }
- } else if (inval)
- viewInvalidate();
- if (newNodeIsTextArea) {
- updateTextEntry();
- displaySoftKeyboard();
- } else {
- if (isClick) {
- setFollowedLink(true);
- if (type != NORMAL_CACHEDNODETYPE) {
- overrideUrlLoading(result->getExport());
- }
- }
- if (oldNodeIsTextArea)
- clearTextEntry();
- }
- return pageScrolled;
-}
-
-void overrideUrlLoading(const WebCore::String& url)
-{
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- jstring jName = env->NewString((jchar*) url.characters(), url.length());
- env->CallVoidMethod(m_javaGlue.object(env).get(),
- m_javaGlue.m_overrideLoading, jName);
- env->DeleteLocalRef(jName);
-}
-
-void setFindIsUp(bool up)
-{
- m_viewImpl->m_findIsUp = up;
- if (!up)
- m_hasCurrentLocation = false;
-}
-
-void setFollowedLink(bool followed)
-{
- if ((m_followedLink = followed) != false) {
- m_ringAnimationEnd = SkTime::GetMSecs() + 500;
- viewInvalidate();
- }
-}
-
-void setHeightCanMeasure(bool measure)
-{
- m_heightCanMeasure = measure;
-}
-
-SkIRect m_selStart, m_selEnd;
-SkRegion m_selRegion;
-#define MIN_ARROW_DISTANCE (20 * 20)
-
-void moveSelection(int x, int y, bool extendSelection)
-{
- CachedRoot* root = getFrameCache(DontAllowNewer);
- if (!root)
- return;
- const SkPicture& picture = *m_navPictureUI;
- WebCore::IntRect r;
- getVisibleRect(&r);
- SkIRect area;
- area.set(r.x(), r.y(), r.right(), r.bottom());
- if (!extendSelection)
- m_selStart = m_selEnd = CopyPaste::findClosest(picture, area, x, y);
- else
- m_selEnd = CopyPaste::findClosest(picture, area, x, y);
- DBG_NAV_LOGD("x=%d y=%d extendSelection=%s m_selStart=(%d, %d, %d, %d)"
- " m_selEnd=(%d, %d, %d, %d)", x, y, extendSelection ? "true" : "false",
- m_selStart.fLeft, m_selStart.fTop, m_selStart.fRight, m_selStart.fBottom,
- m_selEnd.fLeft, m_selEnd.fTop, m_selEnd.fRight, m_selEnd.fBottom);
-}
-
-const SkRegion& getSelection()
-{
- return m_selRegion;
-}
-
-void drawSelection(SkCanvas* canvas, int x, int y, bool extendSelection)
-{
- if (!extendSelection) {
- int dx = x - m_selStart.fLeft;
- dx *= dx;
- int otherX = x - m_selStart.fRight;
- if (dx > (otherX *= otherX))
- dx = otherX;
- int dy = y - m_selStart.fTop;
- int dist = dx * dx + dy * dy;
- if (dist > MIN_ARROW_DISTANCE)
- drawSelectionArrow(canvas, x, y);
- else
- drawSelectionPointer(canvas, x, y, true);
- } else {
- drawSelectionRegion(canvas);
- drawSelectionPointer(canvas, x, y, false);
- }
-}
-
-void drawSelectionRegion(SkCanvas* canvas)
-{
- CachedRoot* root = getFrameCache(DontAllowNewer);
- if (!root)
- return;
- WebCore::IntRect r;
- getVisibleRect(&r);
- SkIRect area;
- area.set(r.x(), r.y(), r.right(), r.bottom());
- m_selRegion.setEmpty();
- CopyPaste::buildSelection(*m_navPictureUI, area, m_selStart, m_selEnd, &m_selRegion);
- SkPath path;
- m_selRegion.getBoundaryPath(&path);
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setColor(SkColorSetARGB(0x40, 255, 51, 204));
- canvas->drawPath(path, paint);
-}
-
-void drawSelectionPointer(SkCanvas* canvas, int x, int y, bool gridded)
-{
- SkPath path;
- getSelectionCaret(&path);
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setColor(SK_ColorBLACK);
- SkPixelXorXfermode xorMode(SK_ColorWHITE);
- paint.setXfermode(&xorMode);
- int sc = canvas->save();
- if (gridded) {
- bool useLeft = x <= (m_selStart.fLeft + m_selStart.fRight) >> 1;
- canvas->translate(SkIntToScalar(useLeft ? m_selStart.fLeft :
- m_selStart.fRight), SkIntToScalar(m_selStart.fTop));
- } else
- canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
- canvas->drawPath(path, paint);
- canvas->restoreToCount(sc);
-}
-
-void drawSelectionArrow(SkCanvas* canvas, int x, int y)
-{
- SkPath path;
- getSelectionArrow(&path);
- SkPaint paint;
- paint.setAntiAlias(true);
- paint.setStyle(SkPaint::kStroke_Style);
- paint.setColor(SK_ColorBLACK);
- paint.setStrokeWidth(SK_Scalar1 * 2);
- int sc = canvas->save();
- canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
- canvas->drawPath(path, paint);
- paint.setStyle(SkPaint::kFill_Style);
- paint.setColor(SK_ColorWHITE);
- canvas->drawPath(path, paint);
- canvas->restoreToCount(sc);
-}
-
-void getSelectionArrow(SkPath* path)
-{
- const int arrow[] = {
- 0, 14, 3, 11, 5, 15, 9, 15, 7, 11, 11, 11
- };
- for (unsigned index = 0; index < sizeof(arrow)/sizeof(arrow[0]); index += 2)
- path->lineTo(SkIntToScalar(arrow[index]), SkIntToScalar(arrow[index + 1]));
- path->close();
-}
-
-void getSelectionCaret(SkPath* path)
-{
- SkScalar height = SkIntToScalar(m_selStart.fBottom - m_selStart.fTop);
- SkScalar dist = height / 4;
- path->lineTo(0, height);
- SkScalar bottom = height + dist;
- path->lineTo(-dist, bottom);
- SkScalar edge = bottom - SK_Scalar1/2;
- path->moveTo(-dist, edge);
- path->lineTo(dist, edge);
- path->moveTo(dist, bottom);
- path->lineTo(0, height);
-}
-
-void sendFinalFocus(WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int y)
-{
- DBG_NAV_LOGD("framePtr=%p nodePtr=%p x=%d y=%d", framePtr, nodePtr, x, y);
- LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_sendFinalFocus,
- (jint) framePtr, (jint) nodePtr, x, y);
- checkException(env);
-}
-
-void sendKitFocus()
-{
- LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_sendKitFocus);
- checkException(env);
-}
-
-void sendMotionUp(int buildGeneration,
- WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int y, int slop,
- bool isClick, bool retry)
-{
- m_viewImpl->m_touchGeneration = m_viewImpl->m_generation = ++m_generation;
- DBG_NAV_LOGD("buildGeneration=%d m_generation=%d framePtr=%p nodePtr=%p"
- " x=%d y=%d slop=%d", buildGeneration,
- m_generation, framePtr, nodePtr, x, y, slop);
- 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,
- buildGeneration, (jint) framePtr, (jint) nodePtr, x, y, slop, isClick, retry);
- checkException(env);
-}
-
-void setFocusData(int buildGeneration, WebCore::Frame* framePtr,
- WebCore::Node* nodePtr, int x, int y, bool ignoreNullFocus)
-{
- m_viewImpl->m_moveGeneration = m_viewImpl->m_generation = ++m_generation;
- DBG_NAV_LOGD("moveGeneration=%d buildGeneration=%d framePtr=%p nodePtr=%p"
- " x=%d y=%d", m_generation, buildGeneration, framePtr, nodePtr, x, y);
- LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_setFocusData, m_generation,
- buildGeneration, (jint) framePtr, (jint) nodePtr, x, y, ignoreNullFocus);
- checkException(env);
-}
-
-// This function is only used by findNext and setMatches. In it, we store
-// upper left corner of the match specified by m_findIndex in
-// m_currentMatchLocation.
-void inline storeCurrentMatchLocation()
-{
- SkASSERT(m_findIndex < m_matches->size());
- const SkIRect& bounds = (*m_matches)[m_findIndex].getLocation().getBounds();
- m_currentMatchLocation.set(bounds.fLeft, bounds.fTop);
- m_hasCurrentLocation = true;
-}
-
-void findNext(bool forward)
-{
- if (!m_matches || !m_matches->size())
- return;
- if (forward) {
- m_findIndex++;
- if (m_findIndex == m_matches->size())
- m_findIndex = 0;
- } else {
- if (m_findIndex == 0) {
- m_findIndex = m_matches->size() - 1;
- } else {
- m_findIndex--;
- }
- }
- storeCurrentMatchLocation();
- viewInvalidate();
-}
-
-// With this call, WebView takes ownership of matches, and is responsible for
-// deleting it.
-void setMatches(WTF::Vector<MatchInfo>* matches)
-{
- if (m_matches)
- delete m_matches;
- m_matches = matches;
- if (m_matches->size()) {
- if (m_hasCurrentLocation) {
- for (unsigned i = 0; i < m_matches->size(); i++) {
- const SkIRect& rect = (*m_matches)[i].getLocation().getBounds();
- if (rect.fLeft == m_currentMatchLocation.fX
- && rect.fTop == m_currentMatchLocation.fY) {
- m_findIndex = i;
- viewInvalidate();
- return;
- }
- }
- }
- // If we did not have a stored location, or if we were unable to restore
- // it, store the new one.
- m_findIndex = 0;
- storeCurrentMatchLocation();
- } else {
- m_hasCurrentLocation = false;
- }
- viewInvalidate();
-}
-
-void 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();
- env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_scrollBy,
- dx, dy, true);
- checkException(env);
-}
-
-bool updateFocusNode(JNIEnv* env)
-{
- CachedRoot* root = getFrameCache(DontAllowNewer);
- if (!root) {
- DBG_NAV_LOG("!root");
- return false;
- }
- const CachedFrame* cachedFrame = 0;
- const CachedNode* cachedFocusNode = root->currentFocus(&cachedFrame);
- if (!cachedFocusNode) {
- DBG_NAV_LOG("!cachedFocusNode");
- return false;
- }
- DBG_NAV_LOGD("cachedFocusNode=%d (nodePointer=%p)",
- cachedFocusNode->index(),
- cachedFocusNode->nodePointer());
- jobject focusnode = env->GetObjectField(m_javaGlue.object(env).get(), m_javaGlue.m_focusNode);
- LOG_ASSERT(focusnode, "Could not find WebView's FocusNode");
-
- bool isTextArea = cachedFocusNode->isTextArea();
- bool isTextField = cachedFocusNode->isTextField();
- int maxLength;
- jstring jName;
- if (isTextField) {
- maxLength = cachedFocusNode->maxLength();
- const WebCore::String& name = cachedFocusNode->name();
- jName = env->NewString((jchar*)name.characters(), name.length());
- } else {
- maxLength = -1;
- jName = 0;
- }
- WebCore::IntRect bounds = cachedFocusNode->bounds();
- WebCore::String value = cachedFocusNode->getExport();
- jstring val = !value.isEmpty() ? env->NewString((jchar *)value.characters(), value.length()) : 0;
- env->CallVoidMethod(focusnode, m_javaGlue.m_setAll, isTextField, isTextArea, cachedFocusNode->isPassword(),
- cachedFocusNode->isAnchor(), cachedFocusNode->isRtlText(), maxLength, cachedFocusNode->textSize(),
- bounds.x(), bounds.y(), bounds.right(), bounds.bottom(), (int)(cachedFocusNode->nodePointer()),
- (int)(cachedFrame->framePointer()), val, jName, root->textGeneration());
- env->DeleteLocalRef(val);
- env->DeleteLocalRef(focusnode);
- if (isTextField)
- env->DeleteLocalRef(jName);
- return true;
-}
-
-void updateTextEntry()
-{
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_updateTextEntry);
- checkException(env);
-}
-
-void displaySoftKeyboard()
-{
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue.object(env).get(),
- m_javaGlue.m_displaySoftKeyboard);
- checkException(env);
-}
-
-void viewInvalidate()
-{
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- 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();
- 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();
- env->CallVoidMethod(m_javaGlue.object(env).get(), m_javaGlue.m_postInvalidateDelayed,
- delay, bounds.x(), bounds.y(), bounds.right(), bounds.bottom());
- checkException(env);
-}
-
-private: // local state for WebView
- // private to getFrameCache(); other functions operate in a different thread
- CachedRoot* m_frameCacheUI; // navigation data ready for use
- FocusReplay m_replay;
- WebViewCore* m_viewImpl;
- WebCore::Node* m_invalidNode;
- int m_generation; // associate unique ID with sent kit focus to match with ui
- SkPicture* m_navPictureUI;
- bool m_followedLink;
- SkMSec m_ringAnimationEnd;
- // Corresponds to the same-named boolean on the java side.
- bool m_heightCanMeasure;
- int m_lastDx;
- SkMSec m_lastDxTime;
- WTF::Vector<MatchInfo>* m_matches;
- // Stores the location of the current match.
- SkIPoint m_currentMatchLocation;
- // Tells whether the value in m_currentMatchLocation is valid.
- bool m_hasCurrentLocation;
- // Tells whether we have done the setup to draw the Find matches.
- bool m_isFindPaintSetUp;
- // Paint used to draw our Find matches.
- SkPaint m_findPaint;
- // Paint used for the background of our Find matches.
- SkPaint m_findBlurPaint;
- unsigned m_findIndex;
-}; // end of WebView class
-
-/*
- * Native JNI methods
- */
-static jstring WebCoreStringToJString(JNIEnv *env, WebCore::String string)
-{
- int length = string.length();
- if (!length)
- return 0;
- jstring ret = env->NewString((jchar *)string.characters(), length);
- env->DeleteLocalRef(ret);
- return ret;
-}
-
-static void nativeClearFocus(JNIEnv *env, jobject obj, int x, int y)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
- view->clearFocus(x, y, true);
-}
-
-static void nativeCreate(JNIEnv *env, jobject obj, int viewImpl)
-{
- WebView* webview = new WebView(env, obj, viewImpl);
- // NEED THIS OR SOMETHING LIKE IT!
- //Release(obj);
-}
-
-static void nativeDebugDump(JNIEnv *env, jobject obj)
-{
-#if DUMP_NAV_CACHE
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
- view->debugDump();
-#endif
-}
-
-static void nativeDrawMatches(JNIEnv *env, jobject obj, jobject canv)
-{
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv);
- if (!canv) {
- DBG_NAV_LOG("!canv");
- return;
- }
- WebView* view = GET_NATIVE_VIEW(env, obj);
- if (!view) {
- DBG_NAV_LOG("!view");
- return;
- }
- view->drawMatches(canvas);
-}
-
-static void nativeDrawFocusRing(JNIEnv *env, jobject obj,
- jobject canv)
-{
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv);
- if (!canv) {
- DBG_NAV_LOG("!canv");
- return;
- }
- WebView* view = GET_NATIVE_VIEW(env, obj);
- if (!view) {
- DBG_NAV_LOG("!view");
- return;
- }
- view->drawFocusRing(canvas);
-}
-
-static void nativeDrawSelection(JNIEnv *env, jobject obj,
- jobject canv, jint x, jint y, bool ex)
-{
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv);
- if (!canv) {
- DBG_NAV_LOG("!canv");
- return;
- }
- WebView* view = GET_NATIVE_VIEW(env, obj);
- if (!view) {
- DBG_NAV_LOG("!view");
- return;
- }
- view->drawSelection(canvas, x, y, ex);
-}
-
-static void nativeDrawSelectionRegion(JNIEnv *env, jobject obj, jobject canv)
-{
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv);
- if (!canv) {
- DBG_NAV_LOG("!canv");
- return;
- }
- WebView* view = GET_NATIVE_VIEW(env, obj);
- if (!view) {
- DBG_NAV_LOG("!view");
- return;
- }
- view->drawSelectionRegion(canvas);
-}
-
-static jobject nativeImageURI(JNIEnv *env, jobject obj, jint x, jint y)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
- WebCore::String uri = view->imageURI(x, y);
- jstring ret = 0;
- unsigned len = uri.length();
- if (len) {
- ret = env->NewString((jchar*) uri.characters(), len);
- env->DeleteLocalRef(ret);
- }
- return ret;
-}
-
-static bool nativeFocusNodeWantsKeyEvents(JNIEnv* env, jobject jwebview) {
- WebView* view = GET_NATIVE_VIEW(env, jwebview);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
- return view->focusNodeWantsKeyEvents();
-}
-
-static void nativeInstrumentReport(JNIEnv *env, jobject obj)
-{
-#ifdef ANDROID_INSTRUMENT
- TimeCounter::reportNow();
-#endif
-}
-
-static WebCore::IntRect jrect_to_webrect(JNIEnv* env, jobject obj)
-{
- int L, T, R, B;
- GraphicsJNI::get_jrect(env, obj, &L, &T, &R, &B);
- return WebCore::IntRect(L, T, R - L, B - T);
-}
-
-static void nativeSelectBestAt(JNIEnv *env, jobject obj, jobject jrect)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
- WebCore::IntRect rect = jrect_to_webrect(env, jrect);
- view->selectBestAt(rect);
-}
-
-static void nativeMarkNodeInvalid(JNIEnv *env, jobject obj, int node)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
- view->markNodeInvalid((WebCore::Node*) node);
-}
-
-static bool nativeMotionUp(JNIEnv *env, jobject obj,
- int x, int y, int slop, bool isClick)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
- return view->motionUp(x, y, slop, isClick, true, false);
-}
-
-static bool nativeUpdateFocusNode(JNIEnv *env, jobject obj)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
- return view->updateFocusNode(env);
-}
-
-static bool nativeMoveFocus(JNIEnv *env, jobject obj,
- int key, int count, bool ignoreScroll)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- DBG_NAV_LOGD("env=%p obj=%p view=%p", env, obj, view);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
- return view->moveFocus(key, count, ignoreScroll, true, 0, 0);
-}
-
-static void nativeNotifyFocusSet(JNIEnv *env, jobject obj, bool inEditingMode)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
- view->notifyFocusSet((WebView::FrameCachePermission) inEditingMode);
-}
-
-static void nativeRecomputeFocus(JNIEnv *env, jobject obj)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
- view->recomputeFocus();
-}
-
-static void nativeRecordButtons(JNIEnv* env, jobject obj, bool hasFocus,
- bool pressed, bool invalidate)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
- view->nativeRecordButtons(hasFocus, pressed, invalidate);
-}
-
-static void nativeResetFocus(JNIEnv *env, jobject obj)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
- view->resetFocus();
-}
-
-static void nativeSetFindIsDown(JNIEnv *env, jobject obj)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
- view->setFindIsUp(false);
-}
-
-static void nativeSetFollowedLink(JNIEnv *env, jobject obj, bool followed)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
- view->setFollowedLink(followed);
-}
-
-static void nativeSetHeightCanMeasure(JNIEnv *env, jobject obj, bool measure)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in nativeSetHeightCanMeasure");
- view->setHeightCanMeasure(measure);
-}
-
-static jobject nativeGetFocusRingBounds(JNIEnv *env, jobject obj)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
- jclass rectClass = env->FindClass("android/graphics/Rect");
- LOG_ASSERT(rectClass, "Could not find Rect class!");
- jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
- LOG_ASSERT(init, "Could not find constructor for Rect");
- WebCore::IntRect webRect;
- view->focusRingBounds(&webRect);
- jobject rect = env->NewObject(rectClass, init, webRect.x(),
- webRect.y(), webRect.right(), webRect.bottom());
- return rect;
-}
-
-static jobject nativeGetNavBounds(JNIEnv *env, jobject obj)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
- jclass rectClass = env->FindClass("android/graphics/Rect");
- LOG_ASSERT(rectClass, "Could not find Rect class!");
- jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
- LOG_ASSERT(init, "Could not find constructor for Rect");
- WebCore::IntRect webRect = view->getNavBounds();
- jobject rect = env->NewObject(rectClass, init, webRect.x(),
- webRect.y(), webRect.right(), webRect.bottom());
- return rect;
-}
-
-static void nativeSetNavBounds(JNIEnv *env, jobject obj, jobject jrect)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
- WebCore::IntRect rect = jrect_to_webrect(env, jrect);
- view->setNavBounds(rect);
-}
-
-static int nativeFindAll(JNIEnv *env, jobject obj, jstring findLower,
- jstring findUpper)
-{
- // If one or the other is null, do not search.
- if (!(findLower && findUpper))
- return 0;
- // Obtain the characters for both the lower case string and the upper case
- // string representing the same word.
- const jchar* findLowerChars = env->GetStringChars(findLower, 0);
- const jchar* findUpperChars = env->GetStringChars(findUpper, 0);
- // If one or the other is null, do not search.
- if (!(findLowerChars && findUpperChars)) {
- if (findLowerChars)
- env->ReleaseStringChars(findLower, findLowerChars);
- if (findUpperChars)
- env->ReleaseStringChars(findUpper, findUpperChars);
- checkException(env);
- return 0;
- }
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in nativeFindAll");
- view->setFindIsUp(true);
- CachedRoot* root = view->getFrameCache(WebView::AllowNewer);
- if (!root) {
- env->ReleaseStringChars(findLower, findLowerChars);
- env->ReleaseStringChars(findUpper, findUpperChars);
- checkException(env);
- return 0;
- }
- int length = env->GetStringLength(findLower);
- // If the lengths of the strings do not match, then they are not the same
- // word, so do not search.
- if (!length || env->GetStringLength(findUpper) != length) {
- env->ReleaseStringChars(findLower, findLowerChars);
- env->ReleaseStringChars(findUpper, findUpperChars);
- checkException(env);
- return 0;
- }
-
- int width = root->documentWidth();
- int height = root->documentHeight();
- // Create a FindCanvas, which allows us to fake draw into it so we can
- // figure out where our search string is rendered (and how many times).
- FindCanvas canvas(width, height, (const UChar*) findLowerChars,
- (const UChar*) findUpperChars, length << 1);
- SkBitmap bitmap;
- bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
- canvas.setBitmapDevice(bitmap);
- canvas.drawPicture(*(root->getPicture()));
- WTF::Vector<MatchInfo>* matches = canvas.detachMatches();
- // With setMatches, the WebView takes ownership of matches
- view->setMatches(matches);
-
- env->ReleaseStringChars(findLower, findLowerChars);
- env->ReleaseStringChars(findUpper, findUpperChars);
- checkException(env);
- return canvas.found();
-}
-
-static void nativeFindNext(JNIEnv *env, jobject obj, bool forward)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in nativeFindNext");
- view->findNext(forward);
-}
-
-static void nativeUpdateCachedTextfield(JNIEnv *env, jobject obj, jstring updatedText, jint generation)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in nativeUpdateCachedTextfield");
- CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
- if (!root)
- return;
- const CachedNode* cachedFocusNode = root->currentFocus();
- if (!cachedFocusNode || (!cachedFocusNode->isTextField() && !cachedFocusNode->isTextArea()))
- return;
- WebCore::String webcoreString = to_string(env, updatedText);
- (const_cast<CachedNode*>(cachedFocusNode))->setExport(webcoreString);
- root->setTextGeneration(generation);
- checkException(env);
-}
-
-static void nativeDestroy(JNIEnv *env, jobject obj)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOGD("nativeDestroy view: %p", view);
- LOG_ASSERT(view, "view not set in nativeDestroy");
- delete view;
-}
-
-static void nativeMoveSelection(JNIEnv *env, jobject obj, int x, int y, bool ex)
-{
- WebView* view = GET_NATIVE_VIEW(env, obj);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
- view->moveSelection(x, y, ex);
-}
-
-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()));
-}
-
-#ifdef ANDROID_DUMP_DISPLAY_TREE
-static void dumpToFile(const char text[], void* file) {
- fwrite(text, 1, strlen(text), reinterpret_cast<FILE*>(file));
- fwrite("\n", 1, 1, reinterpret_cast<FILE*>(file));
-}
-#endif
-
-static void nativeDumpDisplayTree(JNIEnv* env, jobject jwebview, jstring jurl)
-{
-#ifdef ANDROID_DUMP_DISPLAY_TREE
- WebView* view = GET_NATIVE_VIEW(env, jwebview);
- LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
-
- CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
- if (root) {
- SkPicture* picture = root->getPicture();
- if (picture) {
- FILE* file = fopen(DISPLAY_TREE_LOG_FILE, "w");
- if (file) {
- SkFormatDumper dumper(dumpToFile, file);
- // dump the URL
- if (jurl) {
- const char* str = env->GetStringUTFChars(jurl, 0);
- SkDebugf("Dumping %s to %s\n", str, DISPLAY_TREE_LOG_FILE);
- dumpToFile(str, file);
- env->ReleaseStringUTFChars(jurl, str);
- }
- // now dump the display tree
- SkDumpCanvas canvas(&dumper);
- // this will playback the picture into the canvas, which will
- // spew its contents to the dumper
- picture->draw(&canvas);
- // we're done with the file now
- fwrite("\n", 1, 1, file);
- fclose(file);
- }
- }
- }
-#endif
-}
-
-/*
- * JNI registration
- */
-static JNINativeMethod gJavaWebViewMethods[] = {
- { "nativeFindAll", "(Ljava/lang/String;Ljava/lang/String;)I",
- (void*) nativeFindAll },
- { "nativeFindNext", "(Z)V",
- (void*) nativeFindNext },
- { "nativeClearFocus", "(II)V",
- (void*) nativeClearFocus },
- { "nativeCreate", "(I)V",
- (void*) nativeCreate },
- { "nativeDebugDump", "()V",
- (void*) nativeDebugDump },
- { "nativeDestroy", "()V",
- (void*) nativeDestroy },
- { "nativeDrawMatches", "(Landroid/graphics/Canvas;)V",
- (void*) nativeDrawMatches },
- { "nativeDrawFocusRing", "(Landroid/graphics/Canvas;)V",
- (void*) nativeDrawFocusRing },
- { "nativeDrawSelection", "(Landroid/graphics/Canvas;IIZ)V",
- (void*) nativeDrawSelection },
- { "nativeDrawSelectionRegion", "(Landroid/graphics/Canvas;)V",
- (void*) nativeDrawSelectionRegion },
- { "nativeUpdateFocusNode", "()Z",
- (void*) nativeUpdateFocusNode },
- { "nativeGetFocusRingBounds", "()Landroid/graphics/Rect;",
- (void*) nativeGetFocusRingBounds },
- { "nativeGetNavBounds", "()Landroid/graphics/Rect;",
- (void*) nativeGetNavBounds },
- { "nativeInstrumentReport", "()V",
- (void*) nativeInstrumentReport },
- { "nativeMarkNodeInvalid", "(I)V",
- (void*) nativeMarkNodeInvalid },
- { "nativeMotionUp", "(IIIZ)Z",
- (void*) nativeMotionUp },
- { "nativeMoveFocus", "(IIZ)Z",
- (void*) nativeMoveFocus },
- { "nativeNotifyFocusSet", "(Z)V",
- (void*) nativeNotifyFocusSet },
- { "nativeRecomputeFocus", "()V",
- (void*) nativeRecomputeFocus },
- { "nativeRecordButtons", "(ZZZ)V",
- (void*) nativeRecordButtons },
- { "nativeResetFocus", "()V",
- (void*) nativeResetFocus },
- { "nativeSelectBestAt", "(Landroid/graphics/Rect;)V",
- (void*) nativeSelectBestAt },
- { "nativeSetFindIsDown", "()V",
- (void*) nativeSetFindIsDown },
- { "nativeSetFollowedLink", "(Z)V",
- (void*) nativeSetFollowedLink },
- { "nativeSetHeightCanMeasure", "(Z)V",
- (void*) nativeSetHeightCanMeasure },
- { "nativeSetNavBounds", "(Landroid/graphics/Rect;)V",
- (void*) nativeSetNavBounds },
- { "nativeImageURI", "(II)Ljava/lang/String;",
- (void*) nativeImageURI },
- { "nativeFocusNodeWantsKeyEvents", "()Z",
- (void*)nativeFocusNodeWantsKeyEvents },
- { "nativeUpdateCachedTextfield", "(Ljava/lang/String;I)V",
- (void*) nativeUpdateCachedTextfield },
- { "nativeMoveSelection", "(IIZ)V",
- (void*) nativeMoveSelection },
- { "nativeGetSelection", "()Landroid/graphics/Region;",
- (void*) nativeGetSelection },
- { "nativeDumpDisplayTree", "(Ljava/lang/String;)V",
- (void*) nativeDumpDisplayTree }
-};
-
-int register_webview(JNIEnv* env)
-{
- jclass clazz = env->FindClass("android/webkit/WebView");
- LOG_ASSERT(clazz, "Unable to find class android/webkit/WebView");
- gWebViewField = env->GetFieldID(clazz, "mNativeClass", "I");
- LOG_ASSERT(gWebViewField, "Unable to find android/webkit/WebView.mNativeClass");
-
- return jniRegisterNativeMethods(env, "android/webkit/WebView", gJavaWebViewMethods, NELEM(gJavaWebViewMethods));
-}
-
-} // namespace android