summaryrefslogtreecommitdiffstats
path: root/Source/WebKit/android/nav/WebView.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit/android/nav/WebView.cpp')
-rw-r--r--Source/WebKit/android/nav/WebView.cpp2718
1 files changed, 2147 insertions, 571 deletions
diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp
index a67b5fd..7cb41d9 100644
--- a/Source/WebKit/android/nav/WebView.cpp
+++ b/Source/WebKit/android/nav/WebView.cpp
@@ -30,16 +30,17 @@
#include "AndroidAnimation.h"
#include "AndroidLog.h"
#include "BaseLayerAndroid.h"
-#include "BaseRenderer.h"
+#include "CachedFrame.h"
+#include "CachedNode.h"
+#include "CachedRoot.h"
#include "DrawExtra.h"
+#include "FindCanvas.h"
#include "Frame.h"
-#include "GLWebViewState.h"
#include "GraphicsJNI.h"
#include "HTMLInputElement.h"
#include "IntPoint.h"
#include "IntRect.h"
#include "LayerAndroid.h"
-#include "LayerContent.h"
#include "Node.h"
#include "utils/Functor.h"
#include "private/hwui/DrawGlInfo.h"
@@ -52,8 +53,10 @@
#include "SkPicture.h"
#include "SkRect.h"
#include "SkTime.h"
+#ifdef ANDROID_INSTRUMENT
+#include "TimeCounter.h"
+#endif
#include "TilesManager.h"
-#include "TransferQueue.h"
#include "WebCoreJni.h"
#include "WebRequestContext.h"
#include "WebViewCore.h"
@@ -68,7 +71,7 @@
#include <JNIUtility.h>
#include <JNIHelp.h>
#include <jni.h>
-#include <androidfw/KeycodeLabels.h>
+#include <ui/KeycodeLabels.h>
#include <wtf/text/AtomicString.h>
#include <wtf/text/CString.h>
@@ -92,7 +95,7 @@ static jfieldID gWebViewField;
static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[], const char signature[])
{
jmethodID m = env->GetMethodID(clazz, name, signature);
- ALOG_ASSERT(m, "Could not find method %s", name);
+ LOG_ASSERT(m, "Could not find method %s", name);
return m;
}
@@ -107,81 +110,105 @@ enum FrameCachePermission {
AllowNewer
};
-#define DRAW_EXTRAS_SIZE 2
enum DrawExtras { // keep this in sync with WebView.java
DrawExtrasNone = 0,
- DrawExtrasSelection = 1,
- DrawExtrasCursorRing = 2
+ DrawExtrasFind = 1,
+ DrawExtrasSelection = 2,
+ DrawExtrasCursorRing = 3
};
struct JavaGlue {
jweak m_obj;
+ jmethodID m_overrideLoading;
jmethodID m_scrollBy;
+ jmethodID m_sendMoveFocus;
+ jmethodID m_sendMoveMouse;
+ jmethodID m_sendMoveMouseIfLatest;
+ jmethodID m_sendMotionUp;
+ jmethodID m_domChangedFocus;
jmethodID m_getScaledMaxXScroll;
jmethodID m_getScaledMaxYScroll;
- jmethodID m_updateRectsForGL;
+ jmethodID m_getVisibleRect;
+ jmethodID m_rebuildWebTextView;
jmethodID m_viewInvalidate;
jmethodID m_viewInvalidateRect;
jmethodID m_postInvalidateDelayed;
jmethodID m_pageSwapCallback;
+ jmethodID m_inFullScreenMode;
jfieldID m_rectLeft;
jfieldID m_rectTop;
jmethodID m_rectWidth;
jmethodID m_rectHeight;
- jfieldID m_quadFP1;
- jfieldID m_quadFP2;
- jfieldID m_quadFP3;
- jfieldID m_quadFP4;
+ jfieldID m_rectFLeft;
+ jfieldID m_rectFTop;
+ jmethodID m_rectFWidth;
+ jmethodID m_rectFHeight;
+ jmethodID m_getTextHandleScale;
AutoJObject object(JNIEnv* env) {
return getRealObject(env, m_obj);
}
} m_javaGlue;
WebView(JNIEnv* env, jobject javaWebView, int viewImpl, WTF::String drawableDir,
- bool isHighEndGfx)
- : m_isHighEndGfx(isHighEndGfx)
+ bool isHighEndGfx) :
+ m_ring((WebViewCore*) viewImpl)
+ , m_isHighEndGfx(isHighEndGfx)
{
- memset(m_extras, 0, DRAW_EXTRAS_SIZE * sizeof(DrawExtra*));
- jclass clazz = env->FindClass("android/webkit/WebViewClassic");
+ jclass clazz = env->FindClass("android/webkit/WebView");
+ // m_javaGlue = new JavaGlue;
m_javaGlue.m_obj = env->NewWeakGlobalRef(javaWebView);
m_javaGlue.m_scrollBy = GetJMethod(env, clazz, "setContentScrollBy", "(IIZ)Z");
+ m_javaGlue.m_overrideLoading = GetJMethod(env, clazz, "overrideLoading", "(Ljava/lang/String;)V");
+ m_javaGlue.m_sendMoveFocus = GetJMethod(env, clazz, "sendMoveFocus", "(II)V");
+ m_javaGlue.m_sendMoveMouse = GetJMethod(env, clazz, "sendMoveMouse", "(IIII)V");
+ m_javaGlue.m_sendMoveMouseIfLatest = GetJMethod(env, clazz, "sendMoveMouseIfLatest", "(ZZ)V");
+ m_javaGlue.m_sendMotionUp = GetJMethod(env, clazz, "sendMotionUp", "(IIIII)V");
+ m_javaGlue.m_domChangedFocus = GetJMethod(env, clazz, "domChangedFocus", "()V");
m_javaGlue.m_getScaledMaxXScroll = GetJMethod(env, clazz, "getScaledMaxXScroll", "()I");
m_javaGlue.m_getScaledMaxYScroll = GetJMethod(env, clazz, "getScaledMaxYScroll", "()I");
- m_javaGlue.m_updateRectsForGL = GetJMethod(env, clazz, "updateRectsForGL", "()V");
+ m_javaGlue.m_getVisibleRect = GetJMethod(env, clazz, "sendOurVisibleRect", "()Landroid/graphics/Rect;");
+ m_javaGlue.m_rebuildWebTextView = GetJMethod(env, clazz, "rebuildWebTextView", "()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");
m_javaGlue.m_pageSwapCallback = GetJMethod(env, clazz, "pageSwapCallback", "(Z)V");
+ m_javaGlue.m_inFullScreenMode = GetJMethod(env, clazz, "inFullScreenMode", "()Z");
+ m_javaGlue.m_getTextHandleScale = GetJMethod(env, clazz, "getTextHandleScale", "()F");
env->DeleteLocalRef(clazz);
jclass rectClass = env->FindClass("android/graphics/Rect");
- ALOG_ASSERT(rectClass, "Could not find Rect class");
+ 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");
env->DeleteLocalRef(rectClass);
- jclass quadFClass = env->FindClass("android/webkit/QuadF");
- ALOG_ASSERT(quadFClass, "Could not find QuadF class");
- m_javaGlue.m_quadFP1 = env->GetFieldID(quadFClass, "p1", "Landroid/graphics/PointF;");
- m_javaGlue.m_quadFP2 = env->GetFieldID(quadFClass, "p2", "Landroid/graphics/PointF;");
- m_javaGlue.m_quadFP3 = env->GetFieldID(quadFClass, "p3", "Landroid/graphics/PointF;");
- m_javaGlue.m_quadFP4 = env->GetFieldID(quadFClass, "p4", "Landroid/graphics/PointF;");
- env->DeleteLocalRef(quadFClass);
+ jclass rectClassF = env->FindClass("android/graphics/RectF");
+ LOG_ASSERT(rectClassF, "Could not find RectF class");
+ m_javaGlue.m_rectFLeft = env->GetFieldID(rectClassF, "left", "F");
+ m_javaGlue.m_rectFTop = env->GetFieldID(rectClassF, "top", "F");
+ m_javaGlue.m_rectFWidth = GetJMethod(env, rectClassF, "width", "()F");
+ m_javaGlue.m_rectFHeight = GetJMethod(env, rectClassF, "height", "()F");
+ env->DeleteLocalRef(rectClassF);
env->SetIntField(javaWebView, gWebViewField, (jint)this);
m_viewImpl = (WebViewCore*) viewImpl;
+ m_frameCacheUI = 0;
+ m_navPictureUI = 0;
m_generation = 0;
m_heightCanMeasure = false;
m_lastDx = 0;
m_lastDxTime = 0;
+ m_ringAnimationEnd = 0;
m_baseLayer = 0;
m_glDrawFunctor = 0;
m_isDrawingPaused = false;
+ m_buttonSkin = drawableDir.isEmpty() ? 0 : new RenderSkinButton(drawableDir);
#if USE(ACCELERATED_COMPOSITING)
m_glWebViewState = 0;
+ m_pageSwapCallbackRegistered = false;
#endif
}
@@ -199,17 +226,11 @@ WebView(JNIEnv* env, jobject javaWebView, int viewImpl, WTF::String drawableDir,
// deallocated base layer.
stopGL();
#endif
+ delete m_frameCacheUI;
+ delete m_navPictureUI;
SkSafeUnref(m_baseLayer);
delete m_glDrawFunctor;
- for (int i = 0; i < DRAW_EXTRAS_SIZE; i++)
- delete m_extras[i];
-}
-
-DrawExtra* getDrawExtra(DrawExtras extras)
-{
- if (extras == DrawExtrasNone)
- return 0;
- return m_extras[extras - 1];
+ delete m_buttonSkin;
}
void stopGL()
@@ -224,6 +245,126 @@ WebViewCore* getWebViewCore() const {
return m_viewImpl;
}
+float getTextHandleScale()
+{
+ LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ AutoJObject javaObject = m_javaGlue.object(env);
+ if (!javaObject.get())
+ return 0;
+ float result = env->CallFloatMethod(javaObject.get(), m_javaGlue.m_getTextHandleScale);
+ checkException(env);
+ return result;
+}
+
+void updateSelectionHandles()
+{
+ if (!m_baseLayer)
+ return;
+ // Adjust for device density & scale
+ m_selectText.updateHandleScale(getTextHandleScale());
+}
+
+// removes the cursor altogether (e.g., when going to a new page)
+void clearCursor()
+{
+ CachedRoot* root = getFrameCache(AllowNewer);
+ if (!root)
+ return;
+ DBG_NAV_LOG("");
+ m_viewImpl->m_hasCursorBounds = false;
+ root->clearCursor();
+ viewInvalidate();
+}
+
+// leaves the cursor where it is, but suppresses drawing it
+void hideCursor()
+{
+ CachedRoot* root = getFrameCache(AllowNewer);
+ if (!root)
+ return;
+ DBG_NAV_LOG("");
+ hideCursor(root);
+ viewInvalidate();
+}
+
+void hideCursor(CachedRoot* root)
+{
+ DBG_NAV_LOG("inner");
+ m_viewImpl->m_hasCursorBounds = false;
+ root->hideCursor();
+}
+
+#if DUMP_NAV_CACHE
+void debugDump()
+{
+ CachedRoot* root = getFrameCache(DontAllowNewer);
+ if (root)
+ root->mDebug.print();
+}
+#endif
+
+void scrollToCurrentMatch()
+{
+ if (!m_findOnPage.currentMatchIsInLayer()) {
+ scrollRectOnScreen(m_findOnPage.currentMatchBounds());
+ return;
+ }
+
+ SkRect matchBounds = m_findOnPage.currentMatchBounds();
+ LayerAndroid* rootLayer = getFrameCache(DontAllowNewer)->rootLayer();
+ Layer* layerContainingMatch = rootLayer->findById(m_findOnPage.currentMatchLayerId());
+ ASSERT(layerContainingMatch);
+
+ // If the match is in a fixed position layer, there's nothing to do.
+ if (layerContainingMatch->shouldInheritFromRootTransform())
+ return;
+
+ // If the match is in a scrollable layer or a descendant of such a layer,
+ // there may be a range of of scroll configurations that will make the
+ // current match visible. Our approach is the simplest possible. Starting at
+ // the layer in which the match is found, we move up the layer tree,
+ // scrolling any scrollable layers as little as possible to make sure that
+ // the current match is in view. This approach has the disadvantage that we
+ // may end up scrolling a larger number of elements than is necessary, which
+ // may be visually jarring. However, minimising the number of layers
+ // scrolled would complicate the code significantly.
+
+ bool didScrollLayer = false;
+ for (Layer* layer = layerContainingMatch; layer; layer = layer->getParent()) {
+ ASSERT(layer->getParent() || layer == rootLayer);
+
+ if (layer->contentIsScrollable()) {
+ // Convert the match location to layer's local space and scroll it.
+ // Repeatedly calling Layer::localToAncestor() is inefficient as
+ // each call repeats part of the calculation. It would be more
+ // efficient to maintain the transform here and update it on each
+ // iteration, but that would mean duplicating logic from
+ // Layer::localToAncestor() and would complicate things.
+ SkMatrix transform;
+ layerContainingMatch->localToAncestor(layer, &transform);
+ SkRect transformedMatchBounds;
+ transform.mapRect(&transformedMatchBounds, matchBounds);
+ SkIRect roundedTransformedMatchBounds;
+ transformedMatchBounds.roundOut(&roundedTransformedMatchBounds);
+ // Only ScrollableLayerAndroid returns true for contentIsScrollable().
+ didScrollLayer |= static_cast<ScrollableLayerAndroid*>(layer)->scrollRectIntoView(roundedTransformedMatchBounds);
+ }
+ }
+ // Invalidate, as the call below to scroll the main page may be a no-op.
+ if (didScrollLayer)
+ viewInvalidate();
+
+ // Convert matchBounds to the global space so we can scroll the main page.
+ SkMatrix transform;
+ layerContainingMatch->localToGlobal(&transform);
+ SkRect transformedMatchBounds;
+ transform.mapRect(&transformedMatchBounds, matchBounds);
+ SkIRect roundedTransformedMatchBounds;
+ transformedMatchBounds.roundOut(&roundedTransformedMatchBounds);
+ scrollRectOnScreen(roundedTransformedMatchBounds);
+}
+
void scrollRectOnScreen(const IntRect& rect)
{
if (rect.isEmpty())
@@ -231,59 +372,147 @@ void scrollRectOnScreen(const IntRect& rect)
int dx = 0;
int left = rect.x();
int right = rect.maxX();
- if (left < m_visibleContentRect.fLeft)
- dx = left - m_visibleContentRect.fLeft;
+ if (left < m_visibleRect.fLeft)
+ dx = left - m_visibleRect.fLeft;
// Only scroll right if the entire width can fit on screen.
- else if (right > m_visibleContentRect.fRight
- && right - left < m_visibleContentRect.width())
- dx = right - m_visibleContentRect.fRight;
+ else if (right > m_visibleRect.fRight
+ && right - left < m_visibleRect.width())
+ dx = right - m_visibleRect.fRight;
int dy = 0;
int top = rect.y();
int bottom = rect.maxY();
- if (top < m_visibleContentRect.fTop)
- dy = top - m_visibleContentRect.fTop;
+ if (top < m_visibleRect.fTop)
+ dy = top - m_visibleRect.fTop;
// Only scroll down if the entire height can fit on screen
- else if (bottom > m_visibleContentRect.fBottom
- && bottom - top < m_visibleContentRect.height())
- dy = bottom - m_visibleContentRect.fBottom;
+ else if (bottom > m_visibleRect.fBottom
+ && bottom - top < m_visibleRect.height())
+ dy = bottom - m_visibleRect.fBottom;
if ((dx|dy) == 0 || !scrollBy(dx, dy))
return;
viewInvalidate();
}
-int drawGL(WebCore::IntRect& invScreenRect, WebCore::IntRect* invalRect,
- WebCore::IntRect& screenRect, int titleBarHeight,
- WebCore::IntRect& screenClip, float scale, int extras, bool shouldDraw)
+void resetCursorRing()
{
+ m_ringAnimationEnd = 0;
+ m_viewImpl->m_hasCursorBounds = false;
+}
+
+bool drawCursorPreamble(CachedRoot* root)
+{
+ if (!root) return false;
+ const CachedFrame* frame;
+ const CachedNode* node = root->currentCursor(&frame);
+ if (!node) {
+ DBG_NAV_LOGV("%s", "!node");
+ resetCursorRing();
+ return false;
+ }
+ m_ring.setIsButton(node);
+ if (node->isHidden()) {
+ DBG_NAV_LOG("node->isHidden()");
+ m_viewImpl->m_hasCursorBounds = false;
+ return false;
+ }
#if USE(ACCELERATED_COMPOSITING)
- if (!m_baseLayer)
- return 0;
+ if (node->isInLayer() && root->rootLayer()) {
+ LayerAndroid* layer = root->rootLayer();
+ layer->updateFixedLayersPositions(m_visibleRect);
+ layer->updatePositions();
+ }
+#endif
+ setVisibleRect(root);
+ m_ring.m_root = root;
+ m_ring.m_frame = frame;
+ m_ring.m_node = node;
+ SkMSec time = SkTime::GetMSecs();
+ m_ring.m_isPressed = time < m_ringAnimationEnd
+ && m_ringAnimationEnd != UINT_MAX;
+ return true;
+}
- if (m_viewImpl)
- m_viewImpl->setPrerenderingEnabled(!m_isDrawingPaused);
+void drawCursorPostamble()
+{
+ if (m_ringAnimationEnd == UINT_MAX)
+ return;
+ SkMSec time = SkTime::GetMSecs();
+ if (time < m_ringAnimationEnd) {
+ // views assume that inval bounds coordinates are non-negative
+ WebCore::IntRect invalBounds(0, 0, INT_MAX, INT_MAX);
+ invalBounds.intersect(m_ring.m_absBounds);
+ postInvalidateDelayed(m_ringAnimationEnd - time, invalBounds);
+ } else {
+ hideCursor(const_cast<CachedRoot*>(m_ring.m_root));
+ }
+}
+
+bool drawGL(WebCore::IntRect& viewRect, WebCore::IntRect* invalRect,
+ WebCore::IntRect& webViewRect, int titleBarHeight,
+ WebCore::IntRect& clip, float scale, int extras)
+{
+#if USE(ACCELERATED_COMPOSITING)
+ if (!m_baseLayer || inFullScreenMode())
+ return false;
if (!m_glWebViewState) {
- TilesManager::instance()->setHighEndGfx(m_isHighEndGfx);
m_glWebViewState = new GLWebViewState();
- m_glWebViewState->setBaseLayer(m_baseLayer, false, true);
+ m_glWebViewState->setHighEndGfx(m_isHighEndGfx);
+ m_glWebViewState->glExtras()->setCursorRingExtra(&m_ring);
+ m_glWebViewState->glExtras()->setFindOnPageExtra(&m_findOnPage);
+ if (m_baseLayer->content()) {
+ SkRegion region;
+ SkIRect rect;
+ rect.set(0, 0, m_baseLayer->content()->width(), m_baseLayer->content()->height());
+ region.setRect(rect);
+ m_glWebViewState->setBaseLayer(m_baseLayer, region, false, true);
+ }
}
- DrawExtra* extra = getDrawExtra((DrawExtras) extras);
+ CachedRoot* root = getFrameCache(AllowNewer);
+ if (!root) {
+ DBG_NAV_LOG("!root");
+ if (extras == DrawExtrasCursorRing)
+ resetCursorRing();
+ }
+ DrawExtra* extra = 0;
+ switch (extras) {
+ case DrawExtrasFind:
+ extra = &m_findOnPage;
+ break;
+ case DrawExtrasSelection:
+ // This will involve a JNI call, but under normal circumstances we will
+ // not hit this anyway. Only if USE_JAVA_TEXT_SELECTION is disabled
+ // in WebView.java will we hit this (so really debug only)
+ updateSelectionHandles();
+ extra = &m_selectText;
+ break;
+ case DrawExtrasCursorRing:
+ if (drawCursorPreamble(root) && m_ring.setup()) {
+ if (m_ring.m_isPressed || m_ringAnimationEnd == UINT_MAX)
+ extra = &m_ring;
+ drawCursorPostamble();
+ }
+ break;
+ default:
+ ;
+ }
+ unsigned int pic = m_glWebViewState->currentPictureCounter();
m_glWebViewState->glExtras()->setDrawExtra(extra);
// Make sure we have valid coordinates. We might not have valid coords
// if the zoom manager is still initializing. We will be redrawn
// once the correct scale is set
- if (!m_visibleContentRect.isFinite())
- return 0;
+ if (!m_visibleRect.isFinite())
+ return false;
bool treesSwapped = false;
bool newTreeHasAnim = false;
- int ret = m_glWebViewState->drawGL(invScreenRect, m_visibleContentRect, invalRect,
- screenRect, titleBarHeight, screenClip, scale,
- &treesSwapped, &newTreeHasAnim, shouldDraw);
- if (treesSwapped) {
- ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
+ bool ret = m_glWebViewState->drawGL(viewRect, m_visibleRect, invalRect,
+ webViewRect, titleBarHeight, clip, scale,
+ &treesSwapped, &newTreeHasAnim);
+ if (treesSwapped && (m_pageSwapCallbackRegistered || newTreeHasAnim)) {
+ m_pageSwapCallbackRegistered = false;
+ LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
JNIEnv* env = JSC::Bindings::getJNIEnv();
AutoJObject javaObject = m_javaGlue.object(env);
if (javaObject.get()) {
@@ -291,45 +520,237 @@ int drawGL(WebCore::IntRect& invScreenRect, WebCore::IntRect* invalRect,
checkException(env);
}
}
- return m_isDrawingPaused ? 0 : ret;
+ if (ret || m_glWebViewState->currentPictureCounter() != pic)
+ return !m_isDrawingPaused;
#endif
- return 0;
+ return false;
}
-void draw(SkCanvas* canvas, SkColor bgColor, DrawExtras extras)
+PictureSet* draw(SkCanvas* canvas, SkColor bgColor, int extras, bool split)
{
+ PictureSet* ret = 0;
if (!m_baseLayer) {
canvas->drawColor(bgColor);
- return;
+ return ret;
}
// draw the content of the base layer first
- LayerContent* content = m_baseLayer->content();
+ PictureSet* content = m_baseLayer->content();
int sc = canvas->save(SkCanvas::kClip_SaveFlag);
- if (content) {
- canvas->clipRect(SkRect::MakeLTRB(0, 0, content->width(), content->height()),
- SkRegion::kDifference_Op);
- }
- Color c = m_baseLayer->getBackgroundColor();
- canvas->drawColor(SkColorSetARGBInline(c.alpha(), c.red(), c.green(), c.blue()));
+ canvas->clipRect(SkRect::MakeLTRB(0, 0, content->width(),
+ content->height()), SkRegion::kDifference_Op);
+ canvas->drawColor(bgColor);
canvas->restoreToCount(sc);
+ if (content->draw(canvas))
+ ret = split ? new PictureSet(*content) : 0;
+
+ CachedRoot* root = getFrameCache(AllowNewer);
+ if (!root) {
+ DBG_NAV_LOG("!root");
+ if (extras == DrawExtrasCursorRing)
+ resetCursorRing();
+ }
+ LayerAndroid mainPicture(m_navPictureUI);
+ DrawExtra* extra = 0;
+ switch (extras) {
+ case DrawExtrasFind:
+ extra = &m_findOnPage;
+ break;
+ case DrawExtrasSelection:
+ // This will involve a JNI call, but under normal circumstances we will
+ // not hit this anyway. Only if USE_JAVA_TEXT_SELECTION is disabled
+ // in WebView.java will we hit this (so really debug only)
+ updateSelectionHandles();
+ extra = &m_selectText;
+ break;
+ case DrawExtrasCursorRing:
+ if (drawCursorPreamble(root) && m_ring.setup()) {
+ extra = &m_ring;
+ drawCursorPostamble();
+ }
+ break;
+ default:
+ ;
+ }
+#if USE(ACCELERATED_COMPOSITING)
+ LayerAndroid* compositeLayer = compositeRoot();
+ if (compositeLayer) {
+ // call this to be sure we've adjusted for any scrolling or animations
+ // before we actually draw
+ compositeLayer->updateFixedLayersPositions(m_visibleRect);
+ compositeLayer->updatePositions();
+ // We have to set the canvas' matrix on the base layer
+ // (to have fixed layers work as intended)
+ SkAutoCanvasRestore restore(canvas, true);
+ m_baseLayer->setMatrix(canvas->getTotalMatrix());
+ canvas->resetMatrix();
+ m_baseLayer->draw(canvas);
+ }
+#endif
+ if (extra) {
+ IntRect dummy; // inval area, unused for now
+ extra->draw(canvas, &mainPicture, &dummy);
+ }
+ return ret;
+}
- // call this to be sure we've adjusted for any scrolling or animations
- // before we actually draw
- m_baseLayer->updatePositionsRecursive(m_visibleContentRect);
- m_baseLayer->updatePositions();
- // We have to set the canvas' matrix on the base layer
- // (to have fixed layers work as intended)
- SkAutoCanvasRestore restore(canvas, true);
- m_baseLayer->setMatrix(canvas->getTotalMatrix());
- canvas->resetMatrix();
- m_baseLayer->draw(canvas, getDrawExtra(extras));
+bool cursorIsTextInput(FrameCachePermission allowNewer)
+{
+ CachedRoot* root = getFrameCache(allowNewer);
+ if (!root) {
+ DBG_NAV_LOG("!root");
+ return false;
+ }
+ const CachedNode* cursor = root->currentCursor();
+ if (!cursor) {
+ DBG_NAV_LOG("!cursor");
+ return false;
+ }
+ DBG_NAV_LOGD("%s", cursor->isTextInput() ? "true" : "false");
+ return cursor->isTextInput();
+}
+
+void cursorRingBounds(WebCore::IntRect* bounds)
+{
+ DBG_NAV_LOGD("%s", "");
+ CachedRoot* root = getFrameCache(DontAllowNewer);
+ if (root) {
+ const CachedFrame* cachedFrame;
+ const CachedNode* cachedNode = root->currentCursor(&cachedFrame);
+ if (cachedNode) {
+ *bounds = cachedNode->cursorRingBounds(cachedFrame);
+ DBG_NAV_LOGD("bounds={%d,%d,%d,%d}", bounds->x(), bounds->y(),
+ bounds->width(), bounds->height());
+ return;
+ }
+ }
+ *bounds = WebCore::IntRect(0, 0, 0, 0);
+}
+
+void fixCursor()
+{
+ m_viewImpl->gCursorBoundsMutex.lock();
+ bool hasCursorBounds = m_viewImpl->m_hasCursorBounds;
+ IntRect bounds = m_viewImpl->m_cursorBounds;
+ m_viewImpl->gCursorBoundsMutex.unlock();
+ if (!hasCursorBounds)
+ return;
+ int x, y;
+ const CachedFrame* frame;
+ const CachedNode* node = m_frameCacheUI->findAt(bounds, &frame, &x, &y, true);
+ if (!node)
+ return;
+ // require that node have approximately the same bounds (+/- 4) and the same
+ // center (+/- 2)
+ IntPoint oldCenter = IntPoint(bounds.x() + (bounds.width() >> 1),
+ bounds.y() + (bounds.height() >> 1));
+ IntRect newBounds = node->bounds(frame);
+ IntPoint newCenter = IntPoint(newBounds.x() + (newBounds.width() >> 1),
+ newBounds.y() + (newBounds.height() >> 1));
+ DBG_NAV_LOGD("oldCenter=(%d,%d) newCenter=(%d,%d)"
+ " bounds=(%d,%d,w=%d,h=%d) newBounds=(%d,%d,w=%d,h=%d)",
+ oldCenter.x(), oldCenter.y(), newCenter.x(), newCenter.y(),
+ bounds.x(), bounds.y(), bounds.width(), bounds.height(),
+ newBounds.x(), newBounds.y(), newBounds.width(), newBounds.height());
+ if (abs(oldCenter.x() - newCenter.x()) > 2)
+ return;
+ if (abs(oldCenter.y() - newCenter.y()) > 2)
+ return;
+ if (abs(bounds.x() - newBounds.x()) > 4)
+ return;
+ if (abs(bounds.y() - newBounds.y()) > 4)
+ return;
+ if (abs(bounds.maxX() - newBounds.maxX()) > 4)
+ return;
+ if (abs(bounds.maxY() - newBounds.maxY()) > 4)
+ return;
+ DBG_NAV_LOGD("node=%p frame=%p x=%d y=%d bounds=(%d,%d,w=%d,h=%d)",
+ node, frame, x, y, bounds.x(), bounds.y(), bounds.width(),
+ bounds.height());
+ m_frameCacheUI->setCursor(const_cast<CachedFrame*>(frame),
+ const_cast<CachedNode*>(node));
+}
+
+CachedRoot* getFrameCache(FrameCachePermission allowNewer)
+{
+ if (!m_viewImpl->m_updatedFrameCache) {
+ DBG_NAV_LOGV("%s", "!m_viewImpl->m_updatedFrameCache");
+ return m_frameCacheUI;
+ }
+ if (allowNewer == DontAllowNewer && m_viewImpl->m_lastGeneration < m_generation) {
+ DBG_NAV_LOGD("allowNewer==DontAllowNewer m_viewImpl->m_lastGeneration=%d"
+ " < m_generation=%d", m_viewImpl->m_lastGeneration, m_generation);
+ return m_frameCacheUI;
+ }
+ DBG_NAV_LOGD("%s", "m_viewImpl->m_updatedFrameCache == true");
+ const CachedFrame* oldCursorFrame;
+ const CachedNode* oldCursorNode = m_frameCacheUI ?
+ m_frameCacheUI->currentCursor(&oldCursorFrame) : 0;
+#if USE(ACCELERATED_COMPOSITING)
+ int layerId = -1;
+ if (oldCursorNode && oldCursorNode->isInLayer()) {
+ const LayerAndroid* cursorLayer = oldCursorFrame->layer(oldCursorNode)
+ ->layer(m_frameCacheUI->rootLayer());
+ if (cursorLayer)
+ layerId = cursorLayer->uniqueId();
+ }
+#endif
+ // get id from old layer and use to find new layer
+ bool oldFocusIsTextInput = false;
+ void* oldFocusNodePointer = 0;
+ if (m_frameCacheUI) {
+ const CachedNode* oldFocus = m_frameCacheUI->currentFocus();
+ if (oldFocus) {
+ oldFocusIsTextInput = oldFocus->isTextInput();
+ oldFocusNodePointer = oldFocus->nodePointer();
+ }
+ }
+ m_viewImpl->gFrameCacheMutex.lock();
+ delete m_frameCacheUI;
+ SkSafeUnref(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 (m_frameCacheUI)
+ m_frameCacheUI->setRootLayer(compositeRoot());
+#if USE(ACCELERATED_COMPOSITING)
+ if (layerId >= 0) {
+ LayerAndroid* layer = const_cast<LayerAndroid*>(
+ m_frameCacheUI->rootLayer());
+ if (layer) {
+ layer->updateFixedLayersPositions(m_visibleRect);
+ layer->updatePositions();
+ }
+ }
+#endif
+ fixCursor();
+ if (oldFocusIsTextInput) {
+ const CachedNode* newFocus = m_frameCacheUI->currentFocus();
+ if (newFocus && oldFocusNodePointer != newFocus->nodePointer()
+ && newFocus->isTextInput()
+ && newFocus != m_frameCacheUI->currentCursor()) {
+ // The focus has changed. We may need to update things.
+ LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ AutoJObject javaObject = m_javaGlue.object(env);
+ if (javaObject.get()) {
+ env->CallVoidMethod(javaObject.get(), m_javaGlue.m_domChangedFocus);
+ checkException(env);
+ }
+ }
+ }
+ if (oldCursorNode && (!m_frameCacheUI || !m_frameCacheUI->currentCursor()))
+ viewInvalidate(); // redraw in case cursor ring is still visible
+ return m_frameCacheUI;
}
int getScaledMaxXScroll()
{
- ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
+ LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
JNIEnv* env = JSC::Bindings::getJNIEnv();
AutoJObject javaObject = m_javaGlue.object(env);
if (!javaObject.get())
@@ -341,7 +762,7 @@ int getScaledMaxXScroll()
int getScaledMaxYScroll()
{
- ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
+ LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
JNIEnv* env = JSC::Bindings::getJNIEnv();
AutoJObject javaObject = m_javaGlue.object(env);
if (!javaObject.get())
@@ -351,37 +772,294 @@ int getScaledMaxYScroll()
return result;
}
-// Call through JNI to ask Java side to update the rectangles for GL functor.
-// This is called at every draw when it is not in process mode, so we should
-// keep this route as efficient as possible. Currently, its average cost on Xoom
-// is about 0.1ms - 0.2ms.
-// Alternatively, this can be achieved by adding more listener on Java side, but
-// that will be more likely causing jank when triggering GC.
-void updateRectsForGL()
+IntRect getVisibleRect()
{
+ IntRect rect;
+ LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
JNIEnv* env = JSC::Bindings::getJNIEnv();
AutoJObject javaObject = m_javaGlue.object(env);
if (!javaObject.get())
- return;
- env->CallVoidMethod(javaObject.get(), m_javaGlue.m_updateRectsForGL);
+ return rect;
+ jobject jRect = env->CallObjectMethod(javaObject.get(), m_javaGlue.m_getVisibleRect);
+ checkException(env);
+ rect.setX(env->GetIntField(jRect, m_javaGlue.m_rectLeft));
+ checkException(env);
+ rect.setY(env->GetIntField(jRect, m_javaGlue.m_rectTop));
+ checkException(env);
+ rect.setWidth(env->CallIntMethod(jRect, m_javaGlue.m_rectWidth));
checkException(env);
+ rect.setHeight(env->CallIntMethod(jRect, m_javaGlue.m_rectHeight));
+ checkException(env);
+ env->DeleteLocalRef(jRect);
+ checkException(env);
+ return rect;
+}
+
+static CachedFrame::Direction KeyToDirection(int32_t keyCode)
+{
+ switch (keyCode) {
+ case AKEYCODE_DPAD_RIGHT:
+ DBG_NAV_LOGD("keyCode=%s", "right");
+ return CachedFrame::RIGHT;
+ case AKEYCODE_DPAD_LEFT:
+ DBG_NAV_LOGD("keyCode=%s", "left");
+ return CachedFrame::LEFT;
+ case AKEYCODE_DPAD_DOWN:
+ DBG_NAV_LOGD("keyCode=%s", "down");
+ return CachedFrame::DOWN;
+ case AKEYCODE_DPAD_UP:
+ DBG_NAV_LOGD("keyCode=%s", "up");
+ return CachedFrame::UP;
+ default:
+ DBG_NAV_LOGD("bad key %d sent", keyCode);
+ return CachedFrame::UNINITIALIZED;
+ }
+}
+
+WTF::String imageURI(int x, int y)
+{
+ const CachedRoot* root = getFrameCache(DontAllowNewer);
+ return root ? root->imageURI(x, y) : WTF::String();
+}
+
+bool cursorWantsKeyEvents()
+{
+ const CachedRoot* root = getFrameCache(DontAllowNewer);
+ if (root) {
+ const CachedNode* focus = root->currentCursor();
+ if (focus)
+ return focus->wantsKeyEvents();
+ }
+ return false;
+}
+
+
+/* returns true if the key had no effect (neither scrolled nor changed cursor) */
+bool moveCursor(int keyCode, int count, bool ignoreScroll)
+{
+ CachedRoot* root = getFrameCache(AllowNewer);
+ if (!root) {
+ DBG_NAV_LOG("!root");
+ return true;
+ }
+
+ m_viewImpl->m_moveGeneration++;
+ CachedFrame::Direction direction = KeyToDirection(keyCode);
+ const CachedFrame* cachedFrame, * oldFrame = 0;
+ const CachedNode* cursor = root->currentCursor(&oldFrame);
+ WebCore::IntPoint cursorLocation = root->cursorLocation();
+ DBG_NAV_LOGD("old cursor %d (nativeNode=%p) cursorLocation={%d, %d}",
+ cursor ? cursor->index() : 0,
+ cursor ? cursor->nodePointer() : 0, cursorLocation.x(), cursorLocation.y());
+ WebCore::IntRect visibleRect = setVisibleRect(root);
+ int xMax = getScaledMaxXScroll();
+ int yMax = getScaledMaxYScroll();
+ root->setMaxScroll(xMax, yMax);
+ const CachedNode* cachedNode = 0;
+ int dx = 0;
+ int dy = 0;
+ int counter = count;
+ while (--counter >= 0) {
+ WebCore::IntPoint scroll = WebCore::IntPoint(0, 0);
+ cachedNode = root->moveCursor(direction, &cachedFrame, &scroll);
+ dx += scroll.x();
+ dy += scroll.y();
+ }
+ DBG_NAV_LOGD("new cursor %d (nativeNode=%p) cursorLocation={%d, %d}"
+ "bounds={%d,%d,w=%d,h=%d}", cachedNode ? cachedNode->index() : 0,
+ cachedNode ? cachedNode->nodePointer() : 0,
+ root->cursorLocation().x(), root->cursorLocation().y(),
+ cachedNode ? cachedNode->bounds(cachedFrame).x() : 0,
+ cachedNode ? cachedNode->bounds(cachedFrame).y() : 0,
+ cachedNode ? cachedNode->bounds(cachedFrame).width() : 0,
+ cachedNode ? cachedNode->bounds(cachedFrame).height() : 0);
+ // If !m_heightCanMeasure (such as in the browser), we want to scroll no
+ // matter what
+ if (!ignoreScroll && (!m_heightCanMeasure ||
+ !cachedNode ||
+ (cursor && cursor->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();
+ }
+ bool result = false;
+ if (cachedNode) {
+ showCursorUntimed();
+ m_viewImpl->updateCursorBounds(root, cachedFrame, cachedNode);
+ root->setCursor(const_cast<CachedFrame*>(cachedFrame),
+ const_cast<CachedNode*>(cachedNode));
+ const CachedNode* focus = root->currentFocus();
+ bool clearTextEntry = cachedNode != focus && focus
+ && cachedNode->nodePointer() != focus->nodePointer() && focus->isTextInput();
+ // Stop painting the caret if the old focus was a text input and so is the new cursor.
+ bool stopPaintingCaret = clearTextEntry && cachedNode->wantsKeyEvents();
+ sendMoveMouseIfLatest(clearTextEntry, stopPaintingCaret);
+ } else {
+ int docHeight = root->documentHeight();
+ int docWidth = root->documentWidth();
+ if (visibleRect.maxY() + dy > docHeight)
+ dy = docHeight - visibleRect.maxY();
+ else if (visibleRect.y() + dy < 0)
+ dy = -visibleRect.y();
+ if (visibleRect.maxX() + dx > docWidth)
+ dx = docWidth - visibleRect.maxX();
+ 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;
+ }
+ return result;
+}
+
+void notifyProgressFinished()
+{
+ DBG_NAV_LOGD("cursorIsTextInput=%d", cursorIsTextInput(DontAllowNewer));
+ rebuildWebTextView();
+#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
+}
+
+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;
+ setVisibleRect(root);
+ return root->findAt(rect, framePtr, rxPtr, ryPtr, true);
+}
+
+IntRect setVisibleRect(CachedRoot* root)
+{
+ IntRect visibleRect = getVisibleRect();
+ DBG_NAV_LOGD("getVisibleRect %d,%d,%d,%d",
+ visibleRect.x(), visibleRect.y(), visibleRect.width(), visibleRect.height());
+ root->setVisibleRect(visibleRect);
+ return visibleRect;
+}
+
+void selectBestAt(const WebCore::IntRect& rect)
+{
+ const CachedFrame* frame;
+ int rx, ry;
+ CachedRoot* root = getFrameCache(AllowNewer);
+ if (!root)
+ return;
+ const CachedNode* node = findAt(root, rect, &frame, &rx, &ry);
+ if (!node) {
+ DBG_NAV_LOGD("no nodes found root=%p", root);
+ root->rootHistory()->setMouseBounds(rect);
+ m_viewImpl->m_hasCursorBounds = false;
+ root->setCursor(0, 0);
+ viewInvalidate();
+ } else {
+ DBG_NAV_LOGD("CachedNode:%p (%d)", node, node->index());
+ WebCore::IntRect bounds = node->bounds(frame);
+ root->rootHistory()->setMouseBounds(bounds);
+ m_viewImpl->updateCursorBounds(root, frame, node);
+ showCursorTimed();
+ root->setCursor(const_cast<CachedFrame*>(frame),
+ const_cast<CachedNode*>(node));
+ }
+ sendMoveMouseIfLatest(false, false);
+}
+
+const CachedNode* m_cacheHitNode;
+const CachedFrame* m_cacheHitFrame;
+
+bool pointInNavCache(int x, int y, int slop)
+{
+ CachedRoot* root = getFrameCache(AllowNewer);
+ if (!root)
+ return false;
+ IntRect rect = IntRect(x - slop, y - slop, slop * 2, slop * 2);
+ int rx, ry;
+ return (m_cacheHitNode = findAt(root, rect, &m_cacheHitFrame, &rx, &ry));
+}
+
+bool motionUp(int x, int y, int slop)
+{
+ bool pageScrolled = false;
+ IntRect rect = IntRect(x - slop, y - slop, slop * 2, slop * 2);
+ int rx, ry;
+ CachedRoot* root = getFrameCache(AllowNewer);
+ if (!root)
+ return 0;
+ const CachedFrame* frame = 0;
+ const CachedNode* result = findAt(root, rect, &frame, &rx, &ry);
+ CachedHistory* history = root->rootHistory();
+ if (!result) {
+ DBG_NAV_LOGD("no nodes found root=%p", root);
+ history->setNavBounds(rect);
+ m_viewImpl->m_hasCursorBounds = false;
+ root->hideCursor();
+ int dx = root->checkForCenter(x, y);
+ if (dx) {
+ scrollBy(dx, 0);
+ pageScrolled = true;
+ }
+ sendMotionUp(frame ? (WebCore::Frame*) frame->framePointer() : 0,
+ 0, x, y);
+ viewInvalidate();
+ return pageScrolled;
+ }
+ DBG_NAV_LOGD("CachedNode:%p (%d) x=%d y=%d rx=%d ry=%d", result,
+ result->index(), x, y, rx, ry);
+ WebCore::IntRect navBounds = WebCore::IntRect(rx, ry, 1, 1);
+ history->setNavBounds(navBounds);
+ history->setMouseBounds(navBounds);
+ m_viewImpl->updateCursorBounds(root, frame, result);
+ root->setCursor(const_cast<CachedFrame*>(frame),
+ const_cast<CachedNode*>(result));
+ if (result->isSyntheticLink())
+ overrideUrlLoading(result->getExport());
+ else {
+ sendMotionUp(
+ (WebCore::Frame*) frame->framePointer(),
+ (WebCore::Node*) result->nodePointer(), rx, ry);
+ }
+ if (result->isTextInput() || result->isSelect()
+ || result->isContentEditable()) {
+ showCursorUntimed();
+ } else
+ showCursorTimed();
+ return pageScrolled;
}
#if USE(ACCELERATED_COMPOSITING)
static const ScrollableLayerAndroid* findScrollableLayer(
const LayerAndroid* parent, int x, int y, SkIRect* foundBounds) {
- IntRect bounds = enclosingIntRect(parent->fullContentAreaMapped());
-
+ SkRect bounds;
+ parent->bounds(&bounds);
// Check the parent bounds first; this will clip to within a masking layer's
// bounds.
if (parent->masksToBounds() && !bounds.contains(x, y))
return 0;
-
+ // Move the hit test local to parent.
+ x -= bounds.fLeft;
+ y -= bounds.fTop;
int count = parent->countChildren();
while (count--) {
const LayerAndroid* child = parent->getChild(count);
- const ScrollableLayerAndroid* result = findScrollableLayer(child, x, y, foundBounds);
+ const ScrollableLayerAndroid* result = findScrollableLayer(child, x, y,
+ foundBounds);
if (result) {
+ foundBounds->offset(bounds.fLeft, bounds.fTop);
if (parent->masksToBounds()) {
if (bounds.width() < foundBounds->width())
foundBounds->fRight = foundBounds->fLeft + bounds.width();
@@ -392,7 +1070,7 @@ static const ScrollableLayerAndroid* findScrollableLayer(
}
}
if (parent->contentIsScrollable()) {
- foundBounds->set(bounds.x(), bounds.y(), bounds.width(), bounds.height());
+ foundBounds->set(0, 0, bounds.width(), bounds.height());
return static_cast<const ScrollableLayerAndroid*>(parent);
}
return 0;
@@ -402,9 +1080,11 @@ static const ScrollableLayerAndroid* findScrollableLayer(
int scrollableLayer(int x, int y, SkIRect* layerRect, SkIRect* bounds)
{
#if USE(ACCELERATED_COMPOSITING)
- if (!m_baseLayer)
+ const LayerAndroid* layerRoot = compositeRoot();
+ if (!layerRoot)
return 0;
- const ScrollableLayerAndroid* result = findScrollableLayer(m_baseLayer, x, y, bounds);
+ const ScrollableLayerAndroid* result = findScrollableLayer(layerRoot, x, y,
+ bounds);
if (result) {
result->getScrollRect(layerRect);
return result->uniqueId();
@@ -419,6 +1099,52 @@ void scrollLayer(int layerId, int x, int y)
m_glWebViewState->scrollLayer(layerId, x, y);
}
+int getBlockLeftEdge(int x, int y, float scale)
+{
+ CachedRoot* root = getFrameCache(AllowNewer);
+ if (root)
+ return root->getBlockLeftEdge(x, y, scale);
+ return -1;
+}
+
+void overrideUrlLoading(const WTF::String& url)
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ AutoJObject javaObject = m_javaGlue.object(env);
+ if (!javaObject.get())
+ return;
+ jstring jName = wtfStringToJstring(env, url);
+ env->CallVoidMethod(javaObject.get(), m_javaGlue.m_overrideLoading, jName);
+ env->DeleteLocalRef(jName);
+}
+
+void setFindIsUp(bool up)
+{
+ DBG_NAV_LOGD("up=%d", up);
+ m_viewImpl->m_findIsUp = up;
+}
+
+void setFindIsEmpty()
+{
+ DBG_NAV_LOG("");
+ m_findOnPage.clearCurrentLocation();
+}
+
+void showCursorTimed()
+{
+ DBG_NAV_LOG("");
+ m_ringAnimationEnd = SkTime::GetMSecs() + PRESSED_STATE_DURATION;
+ viewInvalidate();
+}
+
+void showCursorUntimed()
+{
+ DBG_NAV_LOG("");
+ m_ring.m_isPressed = false;
+ m_ringAnimationEnd = UINT_MAX;
+ viewInvalidate();
+}
+
void setHeightCanMeasure(bool measure)
{
m_heightCanMeasure = measure;
@@ -426,16 +1152,170 @@ void setHeightCanMeasure(bool measure)
String getSelection()
{
- SelectText* select = static_cast<SelectText*>(
- getDrawExtra(WebView::DrawExtrasSelection));
- if (select)
- return select->getText();
- return String();
+ return m_selectText.getSelection();
+}
+
+void moveSelection(int x, int y)
+{
+ m_selectText.moveSelection(getVisibleRect(), x, y);
+}
+
+IntPoint selectableText()
+{
+ const CachedRoot* root = getFrameCache(DontAllowNewer);
+ if (!root)
+ return IntPoint(0, 0);
+ return m_selectText.selectableText(root);
+}
+
+void selectAll()
+{
+ m_selectText.selectAll();
+}
+
+int selectionX()
+{
+ return m_selectText.selectionX();
+}
+
+int selectionY()
+{
+ return m_selectText.selectionY();
+}
+
+void resetSelection()
+{
+ m_selectText.reset();
+}
+
+bool startSelection(int x, int y)
+{
+ const CachedRoot* root = getFrameCache(DontAllowNewer);
+ if (!root)
+ return false;
+ updateSelectionHandles();
+ return m_selectText.startSelection(root, getVisibleRect(), x, y);
+}
+
+bool wordSelection(int x, int y)
+{
+ const CachedRoot* root = getFrameCache(DontAllowNewer);
+ if (!root)
+ return false;
+ updateSelectionHandles();
+ return m_selectText.wordSelection(root, getVisibleRect(), x, y);
+}
+
+bool extendSelection(int x, int y)
+{
+ m_selectText.extendSelection(getVisibleRect(), x, y);
+ return true;
+}
+
+bool hitSelection(int x, int y)
+{
+ updateSelectionHandles();
+ return m_selectText.hitSelection(x, y);
+}
+
+void setExtendSelection()
+{
+ m_selectText.setExtendSelection(true);
+}
+
+void setSelectionPointer(bool set, float scale, int x, int y)
+{
+ m_selectText.setDrawPointer(set);
+ if (!set)
+ return;
+ m_selectText.m_inverseScale = scale;
+ m_selectText.m_selectX = x;
+ m_selectText.m_selectY = y;
+}
+
+void sendMoveFocus(WebCore::Frame* framePtr, WebCore::Node* nodePtr)
+{
+ DBG_NAV_LOGD("framePtr=%p nodePtr=%p", framePtr, nodePtr);
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ AutoJObject javaObject = m_javaGlue.object(env);
+ if (!javaObject.get())
+ return;
+ env->CallVoidMethod(javaObject.get(), m_javaGlue.m_sendMoveFocus, (jint) framePtr, (jint) nodePtr);
+ checkException(env);
+}
+
+void sendMoveMouse(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);
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ AutoJObject javaObject = m_javaGlue.object(env);
+ if (!javaObject.get())
+ return;
+ env->CallVoidMethod(javaObject.get(), m_javaGlue.m_sendMoveMouse, reinterpret_cast<jint>(framePtr), reinterpret_cast<jint>(nodePtr), x, y);
+ checkException(env);
+}
+
+void sendMoveMouseIfLatest(bool clearTextEntry, bool stopPaintingCaret)
+{
+ LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ AutoJObject javaObject = m_javaGlue.object(env);
+ if (!javaObject.get())
+ return;
+ env->CallVoidMethod(javaObject.get(), m_javaGlue.m_sendMoveMouseIfLatest, clearTextEntry, stopPaintingCaret);
+ checkException(env);
+}
+
+void sendMotionUp(WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int y)
+{
+ DBG_NAV_LOGD("m_generation=%d framePtr=%p nodePtr=%p x=%d y=%d", 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 javaObject = m_javaGlue.object(env);
+ if (!javaObject.get())
+ return;
+ m_viewImpl->m_touchGeneration = ++m_generation;
+ env->CallVoidMethod(javaObject.get(), m_javaGlue.m_sendMotionUp, m_generation, (jint) framePtr, (jint) nodePtr, x, y);
+ checkException(env);
+}
+
+void findNext(bool forward)
+{
+ m_findOnPage.findNext(forward);
+ scrollToCurrentMatch();
+ viewInvalidate();
+}
+
+// With this call, WebView takes ownership of matches, and is responsible for
+// deleting it.
+void setMatches(WTF::Vector<MatchInfo>* matches, jboolean sameAsLastSearch)
+{
+ // If this search is the same as the last one, check against the old
+ // location to determine whether to scroll. If the same word is found
+ // in the same place, then do not scroll.
+ IntRect oldLocation;
+ bool checkAgainstOldLocation = false;
+ if (sameAsLastSearch && m_findOnPage.isCurrentLocationValid()) {
+ oldLocation = m_findOnPage.currentMatchBounds();
+ checkAgainstOldLocation = true;
+ }
+
+ m_findOnPage.setMatches(matches);
+
+ if (!checkAgainstOldLocation || oldLocation != m_findOnPage.currentMatchBounds())
+ scrollToCurrentMatch();
+ viewInvalidate();
+}
+
+int currentMatchIndex()
+{
+ return m_findOnPage.currentMatchIndex();
}
bool scrollBy(int dx, int dy)
{
- ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
+ LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
JNIEnv* env = JSC::Bindings::getJNIEnv();
AutoJObject javaObject = m_javaGlue.object(env);
@@ -454,6 +1334,44 @@ void setIsScrolling(bool isScrolling)
#endif
}
+bool hasCursorNode()
+{
+ CachedRoot* root = getFrameCache(DontAllowNewer);
+ if (!root) {
+ DBG_NAV_LOG("!root");
+ return false;
+ }
+ const CachedNode* cursorNode = root->currentCursor();
+ DBG_NAV_LOGD("cursorNode=%d (nodePointer=%p)",
+ cursorNode ? cursorNode->index() : -1,
+ cursorNode ? cursorNode->nodePointer() : 0);
+ return cursorNode;
+}
+
+bool hasFocusNode()
+{
+ CachedRoot* root = getFrameCache(DontAllowNewer);
+ if (!root) {
+ DBG_NAV_LOG("!root");
+ return false;
+ }
+ const CachedNode* focusNode = root->currentFocus();
+ DBG_NAV_LOGD("focusNode=%d (nodePointer=%p)",
+ focusNode ? focusNode->index() : -1,
+ focusNode ? focusNode->nodePointer() : 0);
+ return focusNode;
+}
+
+void rebuildWebTextView()
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ AutoJObject javaObject = m_javaGlue.object(env);
+ if (!javaObject.get())
+ return;
+ env->CallVoidMethod(javaObject.get(), m_javaGlue.m_rebuildWebTextView);
+ checkException(env);
+}
+
void viewInvalidate()
{
JNIEnv* env = JSC::Bindings::getJNIEnv();
@@ -485,64 +1403,112 @@ void postInvalidateDelayed(int64_t delay, const WebCore::IntRect& bounds)
checkException(env);
}
+bool inFullScreenMode()
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ AutoJObject javaObject = m_javaGlue.object(env);
+ if (!javaObject.get())
+ return false;
+ jboolean result = env->CallBooleanMethod(javaObject.get(), m_javaGlue.m_inFullScreenMode);
+ checkException(env);
+ return result;
+}
+
+int moveGeneration()
+{
+ return m_viewImpl->m_moveGeneration;
+}
+
+LayerAndroid* compositeRoot() const
+{
+ LOG_ASSERT(!m_baseLayer || m_baseLayer->countChildren() == 1,
+ "base layer can't have more than one child %s", __FUNCTION__);
+ if (m_baseLayer && m_baseLayer->countChildren() == 1)
+ return static_cast<LayerAndroid*>(m_baseLayer->getChild(0));
+ else
+ return 0;
+}
+
#if ENABLE(ANDROID_OVERFLOW_SCROLL)
-static void copyScrollPosition(const LayerAndroid* fromRoot,
- LayerAndroid* toRoot, int layerId)
+static void copyScrollPositionRecursive(const LayerAndroid* from,
+ LayerAndroid* root)
{
- if (!fromRoot || !toRoot)
- return;
- const LayerAndroid* from = fromRoot->findById(layerId);
- LayerAndroid* to = toRoot->findById(layerId);
- if (!from || !to || !from->contentIsScrollable() || !to->contentIsScrollable())
- return;
- // TODO: Support this for iframes.
- if (to->isIFrameContent() || from->isIFrameContent())
+ if (!from || !root)
return;
- to->setScrollOffset(from->getScrollOffset());
+ for (int i = 0; i < from->countChildren(); i++) {
+ const LayerAndroid* l = from->getChild(i);
+ if (l->contentIsScrollable()) {
+ const SkPoint& pos = l->getPosition();
+ LayerAndroid* match = root->findById(l->uniqueId());
+ if (match && match->contentIsScrollable())
+ match->setPosition(pos.fX, pos.fY);
+ }
+ copyScrollPositionRecursive(l, root);
+ }
}
#endif
-BaseLayerAndroid* getBaseLayer() const { return m_baseLayer; }
+void registerPageSwapCallback()
+{
+ m_pageSwapCallbackRegistered = true;
+}
-bool setBaseLayer(BaseLayerAndroid* newBaseLayer, bool showVisualIndicator,
- bool isPictureAfterFirstLayout, int scrollingLayer)
+void setBaseLayer(BaseLayerAndroid* layer, SkRegion& inval, bool showVisualIndicator,
+ bool isPictureAfterFirstLayout, bool registerPageSwapCallback)
{
- bool queueFull = false;
#if USE(ACCELERATED_COMPOSITING)
if (m_glWebViewState)
- queueFull = m_glWebViewState->setBaseLayer(newBaseLayer, showVisualIndicator,
- isPictureAfterFirstLayout);
+ m_glWebViewState->setBaseLayer(layer, inval, showVisualIndicator,
+ isPictureAfterFirstLayout);
+ m_pageSwapCallbackRegistered |= registerPageSwapCallback;
#endif
#if ENABLE(ANDROID_OVERFLOW_SCROLL)
- copyScrollPosition(m_baseLayer, newBaseLayer, scrollingLayer);
+ if (layer) {
+ // TODO: the below tree copies are only necessary in software rendering
+ LayerAndroid* newCompositeRoot = static_cast<LayerAndroid*>(layer->getChild(0));
+ copyScrollPositionRecursive(compositeRoot(), newCompositeRoot);
+ }
#endif
SkSafeUnref(m_baseLayer);
- m_baseLayer = newBaseLayer;
-
- return queueFull;
+ m_baseLayer = layer;
+ CachedRoot* root = getFrameCache(DontAllowNewer);
+ if (!root)
+ return;
+ root->resetLayers();
+ root->setRootLayer(compositeRoot());
}
-void copyBaseContentToPicture(SkPicture* picture)
+void getTextSelectionRegion(SkRegion *region)
{
- if (!m_baseLayer || !m_baseLayer->content())
- return;
- LayerContent* content = m_baseLayer->content();
- SkCanvas* canvas = picture->beginRecording(content->width(), content->height(),
- SkPicture::kUsePathBoundsForClip_RecordingFlag);
+ m_selectText.getSelectionRegion(getVisibleRect(), region, compositeRoot());
+}
- // clear the BaseLayerAndroid's previous matrix (set at each draw)
- SkMatrix baseMatrix;
- baseMatrix.reset();
- m_baseLayer->setMatrix(baseMatrix);
+void getTextSelectionHandles(int* handles)
+{
+ m_selectText.getSelectionHandles(handles, compositeRoot());
+}
- m_baseLayer->draw(canvas, 0);
+void replaceBaseContent(PictureSet* set)
+{
+ if (!m_baseLayer)
+ return;
+ m_baseLayer->setContent(*set);
+ delete set;
+}
+void copyBaseContentToPicture(SkPicture* picture)
+{
+ if (!m_baseLayer)
+ return;
+ PictureSet* content = m_baseLayer->content();
+ m_baseLayer->drawCanvas(picture->beginRecording(content->width(), content->height(),
+ SkPicture::kUsePathBoundsForClip_RecordingFlag));
picture->endRecording();
}
bool hasContent() {
- if (!m_baseLayer || !m_baseLayer->content())
+ if (!m_baseLayer)
return false;
return !m_baseLayer->content()->isEmpty();
}
@@ -556,197 +1522,37 @@ Functor* getFunctor() {
return m_glDrawFunctor;
}
-void setVisibleContentRect(SkRect& visibleContentRect) {
- m_visibleContentRect = visibleContentRect;
-}
-
-void setDrawExtra(DrawExtra *extra, DrawExtras type)
-{
- if (type == DrawExtrasNone)
- return;
- DrawExtra* old = m_extras[type - 1];
- m_extras[type - 1] = extra;
- if (old != extra) {
- delete old;
- }
-}
-
-void setTextSelection(SelectText *selection) {
- setDrawExtra(selection, DrawExtrasSelection);
-}
-
-const TransformationMatrix* getLayerTransform(int layerId) {
- if (layerId != -1 && m_baseLayer) {
- LayerAndroid* layer = m_baseLayer->findById(layerId);
- // We need to make sure the drawTransform is up to date as this is
- // called before a draw() or drawGL()
- if (layer) {
- m_baseLayer->updatePositionsRecursive(m_visibleContentRect);
- return layer->drawTransform();
- }
- }
- return 0;
-}
-
-int getHandleLayerId(SelectText::HandleId handleId, SkIPoint& cursorPoint,
- FloatQuad& textBounds) {
- SelectText* selectText = static_cast<SelectText*>(getDrawExtra(DrawExtrasSelection));
- if (!selectText || !m_baseLayer)
- return -1;
- int layerId = selectText->caretLayerId(handleId);
- IntRect cursorRect = selectText->caretRect(handleId);
- IntRect textRect = selectText->textRect(handleId);
- // Rects exclude the last pixel on right/bottom. We want only included pixels.
- cursorPoint.set(cursorRect.x(), cursorRect.maxY() - 1);
- textRect.setHeight(std::max(1, textRect.height() - 1));
- textRect.setWidth(std::max(1, textRect.width() - 1));
- textBounds = FloatQuad(textRect);
-
- const TransformationMatrix* transform = getLayerTransform(layerId);
- if (transform) {
- // We're overloading the concept of Rect to be just the two
- // points (bottom-left and top-right.
- cursorPoint = transform->mapPoint(cursorPoint);
- textBounds = transform->mapQuad(textBounds);
- }
- return layerId;
-}
-
-void mapLayerRect(int layerId, SkIRect& rect) {
- const TransformationMatrix* transform = getLayerTransform(layerId);
- if (transform)
- rect = transform->mapRect(rect);
-}
-
-void floatQuadToQuadF(JNIEnv* env, const FloatQuad& nativeTextQuad,
- jobject textQuad)
-{
- jobject p1 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP1);
- jobject p2 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP2);
- jobject p3 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP3);
- jobject p4 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP4);
- GraphicsJNI::point_to_jpointf(nativeTextQuad.p1(), env, p1);
- GraphicsJNI::point_to_jpointf(nativeTextQuad.p2(), env, p2);
- GraphicsJNI::point_to_jpointf(nativeTextQuad.p3(), env, p3);
- GraphicsJNI::point_to_jpointf(nativeTextQuad.p4(), env, p4);
- env->DeleteLocalRef(p1);
- env->DeleteLocalRef(p2);
- env->DeleteLocalRef(p3);
- env->DeleteLocalRef(p4);
+BaseLayerAndroid* getBaseLayer() {
+ return m_baseLayer;
}
-// This is called when WebView switches rendering modes in a more permanent fashion
-// such as when the layer type is set or the view is attached/detached from the window
-int setHwAccelerated(bool hwAccelerated) {
- if (!m_glWebViewState)
- return 0;
- LayerAndroid* root = m_baseLayer;
- if (root)
- return root->setHwAccelerated(hwAccelerated);
- return 0;
+void setVisibleRect(SkRect& visibleRect) {
+ m_visibleRect = visibleRect;
}
-void setDrawingPaused(bool isPaused)
-{
- m_isDrawingPaused = isPaused;
- if (m_viewImpl)
- m_viewImpl->setPrerenderingEnabled(!isPaused);
-}
-
-// Finds the rectangles within world to the left, right, top, and bottom
-// of rect and adds them to rects. If no intersection exists, false is returned.
-static bool findMaskedRects(const FloatRect& world,
- const FloatRect& rect, Vector<FloatRect>& rects) {
- if (!world.intersects(rect))
- return false; // nothing to subtract
-
- // left rectangle
- if (rect.x() > world.x())
- rects.append(FloatRect(world.x(), world.y(),
- rect.x() - world.x(), world.height()));
- // top rectangle
- if (rect.y() > world.y())
- rects.append(FloatRect(world.x(), world.y(),
- world.width(), rect.y() - world.y()));
- // right rectangle
- if (rect.maxX() < world.maxX())
- rects.append(FloatRect(rect.maxX(), world.y(),
- world.maxX() - rect.maxX(), world.height()));
- // bottom rectangle
- if (rect.maxY() < world.maxY())
- rects.append(FloatRect(world.x(), rect.maxY(),
- world.width(), world.maxY() - rect.maxY()));
- return true;
-}
-
-// Returns false if layerId is a fixed position layer, otherwise
-// all fixed position layer rectangles are subtracted from those within
-// rects. Rects will be modified to contain rectangles that don't include
-// the fixed position layer rectangles.
-static bool findMaskedRectsForLayer(LayerAndroid* layer,
- Vector<FloatRect>& rects, int layerId)
-{
- if (layer->isPositionFixed()) {
- if (layerId == layer->uniqueId())
- return false;
- FloatRect layerRect = layer->fullContentAreaMapped();
- for (int i = rects.size() - 1; i >= 0; i--)
- if (findMaskedRects(rects[i], layerRect, rects))
- rects.remove(i);
- }
-
- int childIndex = 0;
- while (LayerAndroid* child = layer->getChild(childIndex++))
- if (!findMaskedRectsForLayer(child, rects, layerId))
- return false;
-
- return true;
-}
-
-// Finds the largest rectangle not masked by any fixed layer.
-void findMaxVisibleRect(int movingLayerId, SkIRect& visibleContentRect)
-{
- if (!m_baseLayer)
- return;
-
- FloatRect visibleContentFloatRect(visibleContentRect);
- m_baseLayer->updatePositionsRecursive(visibleContentFloatRect);
- Vector<FloatRect> rects;
- rects.append(visibleContentFloatRect);
- if (findMaskedRectsForLayer(m_baseLayer, rects, movingLayerId)) {
- float maxSize = 0.0;
- const FloatRect* largest = 0;
- for (int i = 0; i < rects.size(); i++) {
- const FloatRect& rect = rects[i];
- float size = rect.width() * rect.height();
- if (size > maxSize) {
- maxSize = size;
- largest = &rect;
- }
- }
- if (largest) {
- SkRect largeRect = *largest;
- largeRect.round(&visibleContentRect);
- }
- }
-}
-
-private: // local state for WebView
bool m_isDrawingPaused;
+private: // local state for WebView
// private to getFrameCache(); other functions operate in a different thread
+ CachedRoot* m_frameCacheUI; // navigation data ready for use
WebViewCore* m_viewImpl;
int m_generation; // associate unique ID with sent kit focus to match with ui
+ SkPicture* m_navPictureUI;
+ SkMSec m_ringAnimationEnd;
// Corresponds to the same-named boolean on the java side.
bool m_heightCanMeasure;
int m_lastDx;
SkMSec m_lastDxTime;
- DrawExtra* m_extras[DRAW_EXTRAS_SIZE];
+ SelectText m_selectText;
+ FindOnPage m_findOnPage;
+ CursorRing m_ring;
BaseLayerAndroid* m_baseLayer;
Functor* m_glDrawFunctor;
#if USE(ACCELERATED_COMPOSITING)
GLWebViewState* m_glWebViewState;
+ bool m_pageSwapCallbackRegistered;
#endif
- SkRect m_visibleContentRect;
+ RenderSkinButton* m_buttonSkin;
+ SkRect m_visibleRect;
bool m_isHighEndGfx;
}; // end of WebView class
@@ -759,54 +1565,45 @@ private: // local state for WebView
class GLDrawFunctor : Functor {
public:
GLDrawFunctor(WebView* _wvInstance,
- int (WebView::*_funcPtr)(WebCore::IntRect&, WebCore::IntRect*,
- WebCore::IntRect&, int, WebCore::IntRect&, jfloat, jint, bool),
- WebCore::IntRect _invScreenRect, float _scale, int _extras) {
+ bool(WebView::*_funcPtr)(WebCore::IntRect&, WebCore::IntRect*,
+ WebCore::IntRect&, int, WebCore::IntRect&,
+ jfloat, jint),
+ WebCore::IntRect _viewRect, float _scale, int _extras) {
wvInstance = _wvInstance;
funcPtr = _funcPtr;
- invScreenRect = _invScreenRect;
+ viewRect = _viewRect;
scale = _scale;
extras = _extras;
};
-
status_t operator()(int messageId, void* data) {
- TRACE_METHOD();
- bool shouldDraw = (messageId == uirenderer::DrawGlInfo::kModeDraw);
- if (shouldDraw)
- wvInstance->updateRectsForGL();
-
- if (invScreenRect.isEmpty()) {
+ if (viewRect.isEmpty()) {
// NOOP operation if viewport is empty
return 0;
}
WebCore::IntRect inval;
- int titlebarHeight = screenRect.height() - invScreenRect.height();
+ int titlebarHeight = webViewRect.height() - viewRect.height();
uirenderer::DrawGlInfo* info = reinterpret_cast<uirenderer::DrawGlInfo*>(data);
- WebCore::IntRect screenClip(info->clipLeft, info->clipTop,
- info->clipRight - info->clipLeft,
- info->clipBottom - info->clipTop);
-
- WebCore::IntRect localInvScreenRect = invScreenRect;
- if (info->isLayer) {
- // When webview is on a layer, we need to use the viewport relative
- // to the FBO, rather than the screen(which will use invScreenRect).
- localInvScreenRect.setX(screenClip.x());
- localInvScreenRect.setY(info->height - screenClip.y() - screenClip.height());
- }
- // Send the necessary info to the shader.
- TilesManager::instance()->shader()->setGLDrawInfo(info);
-
- int returnFlags = (*wvInstance.*funcPtr)(localInvScreenRect, &inval, screenRect,
- titlebarHeight, screenClip, scale, extras, shouldDraw);
- if ((returnFlags & uirenderer::DrawGlInfo::kStatusDraw) != 0) {
+ WebCore::IntRect localViewRect = viewRect;
+ if (info->isLayer)
+ localViewRect.move(-1 * localViewRect.x(), -1 * localViewRect.y());
+
+ WebCore::IntRect clip(info->clipLeft, info->clipTop,
+ info->clipRight - info->clipLeft,
+ info->clipBottom - info->clipTop);
+ TilesManager::instance()->shader()->setWebViewMatrix(info->transform, info->isLayer);
+
+ bool retVal = (*wvInstance.*funcPtr)(localViewRect, &inval, webViewRect,
+ titlebarHeight, clip, scale, extras);
+ if (retVal) {
IntRect finalInval;
- if (inval.isEmpty())
- finalInval = screenRect;
- else {
- finalInval.setX(screenRect.x() + inval.x());
- finalInval.setY(screenRect.y() + titlebarHeight + inval.y());
+ if (inval.isEmpty()) {
+ finalInval = webViewRect;
+ retVal = true;
+ } else {
+ finalInval.setX(webViewRect.x() + inval.x());
+ finalInval.setY(webViewRect.y() + titlebarHeight + inval.y());
finalInval.setWidth(inval.width());
finalInval.setHeight(inval.height());
}
@@ -815,45 +1612,201 @@ class GLDrawFunctor : Functor {
info->dirtyRight = finalInval.maxX();
info->dirtyBottom = finalInval.maxY();
}
- // return 1 if invalidation needed, 2 to request non-drawing functor callback, 0 otherwise
- ALOGV("returnFlags are %d, shouldDraw %d", returnFlags, shouldDraw);
- return returnFlags;
- }
- void updateScreenRect(WebCore::IntRect& _screenRect) {
- screenRect = _screenRect;
+ // return 1 if invalidation needed, 0 otherwise
+ return retVal ? 1 : 0;
}
- void updateInvScreenRect(WebCore::IntRect& _invScreenRect) {
- invScreenRect = _invScreenRect;
+ void updateRect(WebCore::IntRect& _viewRect) {
+ viewRect = _viewRect;
}
- void updateScale(float _scale) {
- scale = _scale;
- }
- void updateExtras(jint _extras) {
- extras = _extras;
+ void updateViewRect(WebCore::IntRect& _viewRect) {
+ webViewRect = _viewRect;
}
private:
WebView* wvInstance;
- int (WebView::*funcPtr)(WebCore::IntRect&, WebCore::IntRect*,
- WebCore::IntRect&, int, WebCore::IntRect&, float, int, bool);
- WebCore::IntRect invScreenRect;
- WebCore::IntRect screenRect;
+ bool (WebView::*funcPtr)(WebCore::IntRect&, WebCore::IntRect*,
+ WebCore::IntRect&, int, WebCore::IntRect&, float, int);
+ WebCore::IntRect viewRect;
+ WebCore::IntRect webViewRect;
jfloat scale;
jint extras;
};
+static jobject createJavaRect(JNIEnv* env, int x, int y, int right, int bottom)
+{
+ jclass rectClass = env->FindClass("android/graphics/Rect");
+ jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
+ jobject rect = env->NewObject(rectClass, init, x, y, right, bottom);
+ env->DeleteLocalRef(rectClass);
+ return rect;
+}
+
/*
* Native JNI methods
*/
+static int nativeCacheHitFramePointer(JNIEnv *env, jobject obj)
+{
+ return reinterpret_cast<int>(GET_NATIVE_VIEW(env, obj)
+ ->m_cacheHitFrame->framePointer());
+}
+
+static jobject nativeCacheHitNodeBounds(JNIEnv *env, jobject obj)
+{
+ WebCore::IntRect bounds = GET_NATIVE_VIEW(env, obj)
+ ->m_cacheHitNode->originalAbsoluteBounds();
+ return createJavaRect(env, bounds.x(), bounds.y(),
+ bounds.maxX(), bounds.maxY());
+}
+
+static int nativeCacheHitNodePointer(JNIEnv *env, jobject obj)
+{
+ return reinterpret_cast<int>(GET_NATIVE_VIEW(env, obj)
+ ->m_cacheHitNode->nodePointer());
+}
+
+static bool nativeCacheHitIsPlugin(JNIEnv *env, jobject obj)
+{
+ return GET_NATIVE_VIEW(env, obj)->m_cacheHitNode->isPlugin();
+}
+
+static void nativeClearCursor(JNIEnv *env, jobject obj)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+ view->clearCursor();
+}
static void nativeCreate(JNIEnv *env, jobject obj, int viewImpl,
jstring drawableDir, jboolean isHighEndGfx)
{
WTF::String dir = jstringToWtfString(env, drawableDir);
- new WebView(env, obj, viewImpl, dir, isHighEndGfx);
+ WebView* webview = new WebView(env, obj, viewImpl, dir, isHighEndGfx);
// NEED THIS OR SOMETHING LIKE IT!
//Release(obj);
}
+static jint nativeCursorFramePointer(JNIEnv *env, jobject obj)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+ if (!root)
+ return 0;
+ const CachedFrame* frame = 0;
+ (void) root->currentCursor(&frame);
+ return reinterpret_cast<int>(frame ? frame->framePointer() : 0);
+}
+
+static const CachedNode* getCursorNode(JNIEnv *env, jobject obj)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+ return root ? root->currentCursor() : 0;
+}
+
+static const CachedNode* getCursorNode(JNIEnv *env, jobject obj,
+ const CachedFrame** frame)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+ return root ? root->currentCursor(frame) : 0;
+}
+
+static const CachedNode* getFocusCandidate(JNIEnv *env, jobject obj,
+ const CachedFrame** frame)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+ if (!root)
+ return 0;
+ const CachedNode* cursor = root->currentCursor(frame);
+ if (cursor && cursor->wantsKeyEvents())
+ return cursor;
+ return root->currentFocus(frame);
+}
+
+static bool focusCandidateHasNextTextfield(JNIEnv *env, jobject obj)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+ if (!root)
+ return false;
+ const CachedNode* cursor = root->currentCursor();
+ if (!cursor || !cursor->isTextInput())
+ cursor = root->currentFocus();
+ if (!cursor || !cursor->isTextInput()) return false;
+ return root->nextTextField(cursor, 0);
+}
+
+static const CachedNode* getFocusNode(JNIEnv *env, jobject obj)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+ return root ? root->currentFocus() : 0;
+}
+
+static const CachedNode* getFocusNode(JNIEnv *env, jobject obj,
+ const CachedFrame** frame)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+ return root ? root->currentFocus(frame) : 0;
+}
+
+static const CachedInput* getInputCandidate(JNIEnv *env, jobject obj)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+ if (!root)
+ return 0;
+ const CachedFrame* frame;
+ const CachedNode* cursor = root->currentCursor(&frame);
+ if (!cursor || !cursor->wantsKeyEvents())
+ cursor = root->currentFocus(&frame);
+ return cursor ? frame->textInput(cursor) : 0;
+}
+
+static jboolean nativePageShouldHandleShiftAndArrows(JNIEnv *env, jobject obj)
+{
+ const CachedNode* focus = getFocusNode(env, obj);
+ if (!focus) return false;
+ // Plugins handle shift and arrows whether or not they have focus.
+ if (focus->isPlugin()) return true;
+ const CachedNode* cursor = getCursorNode(env, obj);
+ // ContentEditable nodes should only receive shift and arrows if they have
+ // both the cursor and the focus.
+ return cursor && cursor->nodePointer() == focus->nodePointer()
+ && cursor->isContentEditable();
+}
+
+static jobject nativeCursorNodeBounds(JNIEnv *env, jobject obj)
+{
+ const CachedFrame* frame;
+ const CachedNode* node = getCursorNode(env, obj, &frame);
+ WebCore::IntRect bounds = node ? node->bounds(frame)
+ : WebCore::IntRect(0, 0, 0, 0);
+ return createJavaRect(env, bounds.x(), bounds.y(),
+ bounds.maxX(), bounds.maxY());
+}
+
+static jint nativeCursorNodePointer(JNIEnv *env, jobject obj)
+{
+ const CachedNode* node = getCursorNode(env, obj);
+ return reinterpret_cast<int>(node ? node->nodePointer() : 0);
+}
+
+static jobject nativeCursorPosition(JNIEnv *env, jobject obj)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ const CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+ WebCore::IntPoint pos = WebCore::IntPoint(0, 0);
+ if (root)
+ root->getSimulatedMousePosition(&pos);
+ jclass pointClass = env->FindClass("android/graphics/Point");
+ jmethodID init = env->GetMethodID(pointClass, "<init>", "(II)V");
+ jobject point = env->NewObject(pointClass, init, pos.x(), pos.y());
+ env->DeleteLocalRef(pointClass);
+ return point;
+}
+
static WebCore::IntRect jrect_to_webrect(JNIEnv* env, jobject obj)
{
if (obj) {
@@ -872,67 +1825,88 @@ static SkRect jrectf_to_rect(JNIEnv* env, jobject obj)
return rect;
}
-static void nativeDraw(JNIEnv *env, jobject obj, jobject canv,
+static bool nativeCursorIntersects(JNIEnv *env, jobject obj, jobject visRect)
+{
+ const CachedFrame* frame;
+ const CachedNode* node = getCursorNode(env, obj, &frame);
+ return node ? node->bounds(frame).intersects(
+ jrect_to_webrect(env, visRect)) : false;
+}
+
+static bool nativeCursorIsAnchor(JNIEnv *env, jobject obj)
+{
+ const CachedNode* node = getCursorNode(env, obj);
+ return node ? node->isAnchor() : false;
+}
+
+static bool nativeCursorIsTextInput(JNIEnv *env, jobject obj)
+{
+ const CachedNode* node = getCursorNode(env, obj);
+ return node ? node->isTextInput() : false;
+}
+
+static jobject nativeCursorText(JNIEnv *env, jobject obj)
+{
+ const CachedNode* node = getCursorNode(env, obj);
+ if (!node)
+ return 0;
+ WTF::String value = node->getExport();
+ return wtfStringToJstring(env, value);
+}
+
+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 jint nativeDraw(JNIEnv *env, jobject obj, jobject canv,
jobject visible, jint color,
- jint extras) {
+ jint extras, jboolean split) {
SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv);
WebView* webView = GET_NATIVE_VIEW(env, obj);
- SkRect visibleContentRect = jrectf_to_rect(env, visible);
- webView->setVisibleContentRect(visibleContentRect);
- webView->draw(canvas, color, static_cast<WebView::DrawExtras>(extras));
-}
-
-static jint nativeCreateDrawGLFunction(JNIEnv *env, jobject obj, jint nativeView,
- jobject jinvscreenrect, jobject jscreenrect,
- jobject jvisiblecontentrect,
- jfloat scale, jint extras) {
- WebCore::IntRect invScreenRect = jrect_to_webrect(env, jinvscreenrect);
- WebView *wvInstance = reinterpret_cast<WebView*>(nativeView);
- SkRect visibleContentRect = jrectf_to_rect(env, jvisiblecontentrect);
- wvInstance->setVisibleContentRect(visibleContentRect);
-
- GLDrawFunctor* functor = (GLDrawFunctor*) wvInstance->getFunctor();
- if (!functor) {
- functor = new GLDrawFunctor(wvInstance, &android::WebView::drawGL,
- invScreenRect, scale, extras);
- wvInstance->setFunctor((Functor*) functor);
- } else {
- functor->updateInvScreenRect(invScreenRect);
- functor->updateScale(scale);
- functor->updateExtras(extras);
- }
+ SkRect visibleRect = jrectf_to_rect(env, visible);
+ webView->setVisibleRect(visibleRect);
+ PictureSet* pictureSet = webView->draw(canvas, color, extras, split);
+ return reinterpret_cast<jint>(pictureSet);
+}
- WebCore::IntRect rect = jrect_to_webrect(env, jscreenrect);
- functor->updateScreenRect(rect);
+static jint nativeGetDrawGLFunction(JNIEnv *env, jobject obj, jint nativeView,
+ jobject jrect, jobject jviewrect,
+ jobject jvisiblerect,
+ jfloat scale, jint extras) {
+ WebCore::IntRect viewRect = jrect_to_webrect(env, jrect);
+ WebView *wvInstance = (WebView*) nativeView;
+ SkRect visibleRect = jrectf_to_rect(env, jvisiblerect);
+ wvInstance->setVisibleRect(visibleRect);
- return (jint)functor;
-}
+ GLDrawFunctor* functor = new GLDrawFunctor(wvInstance,
+ &android::WebView::drawGL, viewRect, scale, extras);
+ wvInstance->setFunctor((Functor*) functor);
-static jint nativeGetDrawGLFunction(JNIEnv *env, jobject obj, jint nativeView) {
- WebView *wvInstance = reinterpret_cast<WebView*>(nativeView);
- if (!wvInstance)
- return 0;
+ WebCore::IntRect webViewRect = jrect_to_webrect(env, jviewrect);
+ functor->updateViewRect(webViewRect);
- return (jint) wvInstance->getFunctor();
+ return (jint)functor;
}
-static void nativeUpdateDrawGLFunction(JNIEnv *env, jobject obj, jint nativeView,
- jobject jinvscreenrect, jobject jscreenrect,
- jobject jvisiblecontentrect, jfloat scale) {
- WebView *wvInstance = reinterpret_cast<WebView*>(nativeView);
+static void nativeUpdateDrawGLFunction(JNIEnv *env, jobject obj, jobject jrect,
+ jobject jviewrect, jobject jvisiblerect) {
+ WebView *wvInstance = GET_NATIVE_VIEW(env, obj);
if (wvInstance) {
GLDrawFunctor* functor = (GLDrawFunctor*) wvInstance->getFunctor();
if (functor) {
- WebCore::IntRect invScreenRect = jrect_to_webrect(env, jinvscreenrect);
- functor->updateInvScreenRect(invScreenRect);
-
- SkRect visibleContentRect = jrectf_to_rect(env, jvisiblecontentrect);
- wvInstance->setVisibleContentRect(visibleContentRect);
+ WebCore::IntRect viewRect = jrect_to_webrect(env, jrect);
+ functor->updateRect(viewRect);
- WebCore::IntRect screenRect = jrect_to_webrect(env, jscreenrect);
- functor->updateScreenRect(screenRect);
+ SkRect visibleRect = jrectf_to_rect(env, jvisiblerect);
+ wvInstance->setVisibleRect(visibleRect);
- functor->updateScale(scale);
+ WebCore::IntRect webViewRect = jrect_to_webrect(env, jviewrect);
+ functor->updateViewRect(webViewRect);
}
}
}
@@ -941,29 +1915,56 @@ static bool nativeEvaluateLayersAnimations(JNIEnv *env, jobject obj, jint native
{
// only call in software rendering, initialize and evaluate animations
#if USE(ACCELERATED_COMPOSITING)
- BaseLayerAndroid* baseLayer = reinterpret_cast<WebView*>(nativeView)->getBaseLayer();
- if (baseLayer) {
- baseLayer->initAnimations();
- return baseLayer->evaluateAnimations();
+ LayerAndroid* root = ((WebView*)nativeView)->compositeRoot();
+ if (root) {
+ root->initAnimations();
+ return root->evaluateAnimations();
}
#endif
return false;
}
-static bool nativeSetBaseLayer(JNIEnv *env, jobject obj, jint nativeView, jint layer,
- jboolean showVisualIndicator,
- jboolean isPictureAfterFirstLayout,
- jint scrollingLayer)
+static void nativeSetBaseLayer(JNIEnv *env, jobject obj, jint layer, jobject inval,
+ jboolean showVisualIndicator,
+ jboolean isPictureAfterFirstLayout,
+ jboolean registerPageSwapCallback)
{
BaseLayerAndroid* layerImpl = reinterpret_cast<BaseLayerAndroid*>(layer);
- return reinterpret_cast<WebView*>(nativeView)->setBaseLayer(layerImpl, showVisualIndicator,
- isPictureAfterFirstLayout,
- scrollingLayer);
+ SkRegion invalRegion;
+ if (inval)
+ invalRegion = *GraphicsJNI::getNativeRegion(env, inval);
+ GET_NATIVE_VIEW(env, obj)->setBaseLayer(layerImpl, invalRegion, showVisualIndicator,
+ isPictureAfterFirstLayout,
+ registerPageSwapCallback);
+}
+
+static void nativeGetTextSelectionRegion(JNIEnv *env, jobject obj, jint view,
+ jobject region)
+{
+ if (!region)
+ return;
+ SkRegion* nregion = GraphicsJNI::getNativeRegion(env, region);
+ ((WebView*)view)->getTextSelectionRegion(nregion);
+}
+
+static void nativeGetSelectionHandles(JNIEnv *env, jobject obj, jint view,
+ jintArray arr)
+{
+ int handles[4];
+ ((WebView*)view)->getTextSelectionHandles(handles);
+ env->SetIntArrayRegion(arr, 0, 4, handles);
+ checkException(env);
+}
+
+static BaseLayerAndroid* nativeGetBaseLayer(JNIEnv *env, jobject obj)
+{
+ return GET_NATIVE_VIEW(env, obj)->getBaseLayer();
}
-static BaseLayerAndroid* nativeGetBaseLayer(JNIEnv *env, jobject obj, jint nativeView)
+static void nativeReplaceBaseContent(JNIEnv *env, jobject obj, jint content)
{
- return reinterpret_cast<WebView*>(nativeView)->getBaseLayer();
+ PictureSet* set = reinterpret_cast<PictureSet*>(content);
+ GET_NATIVE_VIEW(env, obj)->replaceBaseContent(set);
}
static void nativeCopyBaseContentToPicture(JNIEnv *env, jobject obj, jobject pict)
@@ -977,40 +1978,549 @@ static bool nativeHasContent(JNIEnv *env, jobject obj)
return GET_NATIVE_VIEW(env, obj)->hasContent();
}
+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__);
+ WTF::String uri = view->imageURI(x, y);
+ return wtfStringToJstring(env, uri);
+}
+
+static jint nativeFocusCandidateFramePointer(JNIEnv *env, jobject obj)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+ if (!root)
+ return 0;
+ const CachedFrame* frame = 0;
+ const CachedNode* cursor = root->currentCursor(&frame);
+ if (!cursor || !cursor->wantsKeyEvents())
+ (void) root->currentFocus(&frame);
+ return reinterpret_cast<int>(frame ? frame->framePointer() : 0);
+}
+
+static bool nativeFocusCandidateIsPassword(JNIEnv *env, jobject obj)
+{
+ const CachedInput* input = getInputCandidate(env, obj);
+ return input && input->getType() == CachedInput::PASSWORD;
+}
+
+static bool nativeFocusCandidateIsRtlText(JNIEnv *env, jobject obj)
+{
+ const CachedInput* input = getInputCandidate(env, obj);
+ return input ? input->isRtlText() : false;
+}
+
+static bool nativeFocusCandidateIsTextInput(JNIEnv *env, jobject obj)
+{
+ const CachedNode* node = getFocusCandidate(env, obj, 0);
+ return node ? node->isTextInput() : false;
+}
+
+static jint nativeFocusCandidateMaxLength(JNIEnv *env, jobject obj)
+{
+ const CachedInput* input = getInputCandidate(env, obj);
+ return input ? input->maxLength() : false;
+}
+
+static jint nativeFocusCandidateIsAutoComplete(JNIEnv *env, jobject obj)
+{
+ const CachedInput* input = getInputCandidate(env, obj);
+ return input ? input->autoComplete() : false;
+}
+
+static jobject nativeFocusCandidateName(JNIEnv *env, jobject obj)
+{
+ const CachedInput* input = getInputCandidate(env, obj);
+ if (!input)
+ return 0;
+ const WTF::String& name = input->name();
+ return wtfStringToJstring(env, name);
+}
+
+static jobject nativeFocusCandidateNodeBounds(JNIEnv *env, jobject obj)
+{
+ const CachedFrame* frame;
+ const CachedNode* node = getFocusCandidate(env, obj, &frame);
+ WebCore::IntRect bounds = node ? node->originalAbsoluteBounds()
+ : WebCore::IntRect(0, 0, 0, 0);
+ // Inset the rect by 1 unit, so that the focus candidate's border can still
+ // be seen behind it.
+ return createJavaRect(env, bounds.x(), bounds.y(),
+ bounds.maxX(), bounds.maxY());
+}
+
+static jobject nativeFocusCandidatePaddingRect(JNIEnv *env, jobject obj)
+{
+ const CachedInput* input = getInputCandidate(env, obj);
+ if (!input)
+ return 0;
+ // Note that the Java Rect is being used to pass four integers, rather than
+ // being used as an actual rectangle.
+ return createJavaRect(env, input->paddingLeft(), input->paddingTop(),
+ input->paddingRight(), input->paddingBottom());
+}
+
+static jint nativeFocusCandidatePointer(JNIEnv *env, jobject obj)
+{
+ const CachedNode* node = getFocusCandidate(env, obj, 0);
+ return reinterpret_cast<int>(node ? node->nodePointer() : 0);
+}
+
+static jint nativeFocusCandidateIsSpellcheck(JNIEnv *env, jobject obj)
+{
+ const CachedInput* input = getInputCandidate(env, obj);
+ return input ? input->spellcheck() : false;
+}
+
+static jobject nativeFocusCandidateText(JNIEnv *env, jobject obj)
+{
+ const CachedNode* node = getFocusCandidate(env, obj, 0);
+ if (!node)
+ return 0;
+ WTF::String value = node->getExport();
+ return wtfStringToJstring(env, value);
+}
+
+static int nativeFocusCandidateLineHeight(JNIEnv *env, jobject obj)
+{
+ const CachedInput* input = getInputCandidate(env, obj);
+ return input ? input->lineHeight() : 0;
+}
+
+static jfloat nativeFocusCandidateTextSize(JNIEnv *env, jobject obj)
+{
+ const CachedInput* input = getInputCandidate(env, obj);
+ return input ? input->textSize() : 0.f;
+}
+
+static int nativeFocusCandidateType(JNIEnv *env, jobject obj)
+{
+ const CachedInput* input = getInputCandidate(env, obj);
+ if (!input)
+ return CachedInput::NONE;
+
+ if (input->isTextArea())
+ return CachedInput::TEXT_AREA;
+
+ return input->getType();
+}
+
+static int nativeFocusCandidateLayerId(JNIEnv *env, jobject obj)
+{
+ const CachedFrame* frame = 0;
+ const CachedNode* node = getFocusNode(env, obj, &frame);
+ if (!node || !frame)
+ return -1;
+ const CachedLayer* layer = frame->layer(node);
+ if (!layer)
+ return -1;
+ return layer->uniqueId();
+}
+
+static bool nativeFocusIsPlugin(JNIEnv *env, jobject obj)
+{
+ const CachedNode* node = getFocusNode(env, obj);
+ return node ? node->isPlugin() : false;
+}
+
+static jobject nativeFocusNodeBounds(JNIEnv *env, jobject obj)
+{
+ const CachedFrame* frame;
+ const CachedNode* node = getFocusNode(env, obj, &frame);
+ WebCore::IntRect bounds = node ? node->bounds(frame)
+ : WebCore::IntRect(0, 0, 0, 0);
+ return createJavaRect(env, bounds.x(), bounds.y(),
+ bounds.maxX(), bounds.maxY());
+}
+
+static jint nativeFocusNodePointer(JNIEnv *env, jobject obj)
+{
+ const CachedNode* node = getFocusNode(env, obj);
+ return node ? reinterpret_cast<int>(node->nodePointer()) : 0;
+}
+
+static bool nativeCursorWantsKeyEvents(JNIEnv* env, jobject jwebview) {
+ WebView* view = GET_NATIVE_VIEW(env, jwebview);
+ LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+ return view->cursorWantsKeyEvents();
+}
+
+static void nativeHideCursor(JNIEnv *env, jobject obj)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+ view->hideCursor();
+}
+
+static void nativeInstrumentReport(JNIEnv *env, jobject obj)
+{
+#ifdef ANDROID_INSTRUMENT
+ TimeCounter::reportNow();
+#endif
+}
+
+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 nativeSelectAt(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::IntRect rect = IntRect(x, y , 1, 1);
+ view->selectBestAt(rect);
+ if (view->hasCursorNode())
+ view->showCursorUntimed();
+}
+
+static jobject nativeLayerBounds(JNIEnv* env, jobject obj, jint jlayer)
+{
+ SkRect r;
+#if USE(ACCELERATED_COMPOSITING)
+ LayerAndroid* layer = (LayerAndroid*) jlayer;
+ r = layer->bounds();
+#else
+ r.setEmpty();
+#endif
+ SkIRect irect;
+ r.round(&irect);
+ jclass rectClass = env->FindClass("android/graphics/Rect");
+ jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
+ jobject rect = env->NewObject(rectClass, init, irect.fLeft, irect.fTop,
+ irect.fRight, irect.fBottom);
+ env->DeleteLocalRef(rectClass);
+ return rect;
+}
+
+static jobject nativeSubtractLayers(JNIEnv* env, jobject obj, jobject jrect)
+{
+ SkIRect irect = jrect_to_webrect(env, jrect);
+#if USE(ACCELERATED_COMPOSITING)
+ LayerAndroid* root = GET_NATIVE_VIEW(env, obj)->compositeRoot();
+ if (root) {
+ SkRect rect;
+ rect.set(irect);
+ rect = root->subtractLayers(rect);
+ rect.round(&irect);
+ }
+#endif
+ jclass rectClass = env->FindClass("android/graphics/Rect");
+ jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
+ jobject rect = env->NewObject(rectClass, init, irect.fLeft, irect.fTop,
+ irect.fRight, irect.fBottom);
+ env->DeleteLocalRef(rectClass);
+ return rect;
+}
+
+static jint nativeTextGeneration(JNIEnv *env, jobject obj)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+ return root ? root->textGeneration() : 0;
+}
+
+static bool nativePointInNavCache(JNIEnv *env, jobject obj,
+ int x, int y, int slop)
+{
+ return GET_NATIVE_VIEW(env, obj)->pointInNavCache(x, y, slop);
+}
+
+static bool nativeMotionUp(JNIEnv *env, jobject obj,
+ int x, int y, int slop)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+ return view->motionUp(x, y, slop);
+}
+
+static bool nativeHasCursorNode(JNIEnv *env, jobject obj)
+{
+ return GET_NATIVE_VIEW(env, obj)->hasCursorNode();
+}
+
+static bool nativeHasFocusNode(JNIEnv *env, jobject obj)
+{
+ return GET_NATIVE_VIEW(env, obj)->hasFocusNode();
+}
+
+static bool nativeMoveCursor(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->moveCursor(key, count, ignoreScroll);
+}
+
+static void nativeSetFindIsUp(JNIEnv *env, jobject obj, jboolean isUp)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+ view->setFindIsUp(isUp);
+}
+
+static void nativeSetFindIsEmpty(JNIEnv *env, jobject obj)
+{
+ GET_NATIVE_VIEW(env, obj)->setFindIsEmpty();
+}
+
+static void nativeShowCursorTimed(JNIEnv *env, jobject obj)
+{
+ GET_NATIVE_VIEW(env, obj)->showCursorTimed();
+}
+
static void nativeSetHeightCanMeasure(JNIEnv *env, jobject obj, bool measure)
{
WebView* view = GET_NATIVE_VIEW(env, obj);
- ALOG_ASSERT(view, "view not set in nativeSetHeightCanMeasure");
+ LOG_ASSERT(view, "view not set in nativeSetHeightCanMeasure");
view->setHeightCanMeasure(measure);
}
-static void nativeDestroy(JNIEnv *env, jobject obj, jint ptr)
+static jobject nativeGetCursorRingBounds(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->cursorRingBounds(&webRect);
+ jobject rect = env->NewObject(rectClass, init, webRect.x(),
+ webRect.y(), webRect.maxX(), webRect.maxY());
+ env->DeleteLocalRef(rectClass);
+ return rect;
+}
+
+static int nativeFindAll(JNIEnv *env, jobject obj, jstring findLower,
+ jstring findUpper, jboolean sameAsLastSearch)
+{
+ // 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");
+ 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);
+ root->draw(canvas);
+ WTF::Vector<MatchInfo>* matches = canvas.detachMatches();
+ // With setMatches, the WebView takes ownership of matches
+ view->setMatches(matches, sameAsLastSearch);
+
+ env->ReleaseStringChars(findLower, findLowerChars);
+ env->ReleaseStringChars(findUpper, findUpperChars);
+ checkException(env);
+ return canvas.found();
+}
+
+static void nativeFindNext(JNIEnv *env, jobject obj, bool forward)
{
- WebView* view = reinterpret_cast<WebView*>(ptr);
- ALOGD("nativeDestroy view: %p", view);
- ALOG_ASSERT(view, "view not set in nativeDestroy");
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ LOG_ASSERT(view, "view not set in nativeFindNext");
+ view->findNext(forward);
+}
+
+static int nativeFindIndex(JNIEnv *env, jobject obj)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ LOG_ASSERT(view, "view not set in nativeFindIndex");
+ return view->currentMatchIndex();
+}
+
+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->isTextInput())
+ return;
+ WTF::String webcoreString = jstringToWtfString(env, updatedText);
+ (const_cast<CachedNode*>(cachedFocusNode))->setExport(webcoreString);
+ root->setTextGeneration(generation);
+ checkException(env);
+}
+
+static jint nativeGetBlockLeftEdge(JNIEnv *env, jobject obj, jint x, jint y,
+ jfloat scale)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+ if (!view)
+ return -1;
+ return view->getBlockLeftEdge(x, y, scale);
+}
+
+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 nativeStopGL(JNIEnv *env, jobject obj, jint ptr)
+static void nativeStopGL(JNIEnv *env, jobject obj)
{
- if (ptr)
- reinterpret_cast<WebView*>(ptr)->stopGL();
+ GET_NATIVE_VIEW(env, obj)->stopGL();
+}
+
+static bool nativeMoveCursorToNextTextInput(JNIEnv *env, jobject obj)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
+ if (!root)
+ return false;
+ const CachedNode* current = root->currentCursor();
+ if (!current || !current->isTextInput())
+ current = root->currentFocus();
+ if (!current || !current->isTextInput())
+ return false;
+ const CachedFrame* frame;
+ const CachedNode* next = root->nextTextField(current, &frame);
+ if (!next)
+ return false;
+ const WebCore::IntRect& bounds = next->bounds(frame);
+ root->rootHistory()->setMouseBounds(bounds);
+ view->getWebViewCore()->updateCursorBounds(root, frame, next);
+ view->showCursorUntimed();
+ root->setCursor(const_cast<CachedFrame*>(frame),
+ const_cast<CachedNode*>(next));
+ view->sendMoveFocus(static_cast<WebCore::Frame*>(frame->framePointer()),
+ static_cast<WebCore::Node*>(next->nodePointer()));
+ if (!next->isInLayer())
+ view->scrollRectOnScreen(bounds);
+ view->getWebViewCore()->m_moveGeneration++;
+ return true;
+}
+
+static int nativeMoveGeneration(JNIEnv *env, jobject obj)
+{
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ if (!view)
+ return 0;
+ return view->moveGeneration();
+}
+
+static void nativeMoveSelection(JNIEnv *env, jobject obj, int x, int y)
+{
+ GET_NATIVE_VIEW(env, obj)->moveSelection(x, y);
+}
+
+static void nativeResetSelection(JNIEnv *env, jobject obj)
+{
+ return GET_NATIVE_VIEW(env, obj)->resetSelection();
+}
+
+static jobject nativeSelectableText(JNIEnv* env, jobject obj)
+{
+ IntPoint pos = GET_NATIVE_VIEW(env, obj)->selectableText();
+ jclass pointClass = env->FindClass("android/graphics/Point");
+ jmethodID init = env->GetMethodID(pointClass, "<init>", "(II)V");
+ jobject point = env->NewObject(pointClass, init, pos.x(), pos.y());
+ env->DeleteLocalRef(pointClass);
+ return point;
+}
+
+static void nativeSelectAll(JNIEnv* env, jobject obj)
+{
+ GET_NATIVE_VIEW(env, obj)->selectAll();
+}
+
+static void nativeSetExtendSelection(JNIEnv *env, jobject obj)
+{
+ GET_NATIVE_VIEW(env, obj)->setExtendSelection();
+}
+
+static jboolean nativeStartSelection(JNIEnv *env, jobject obj, int x, int y)
+{
+ return GET_NATIVE_VIEW(env, obj)->startSelection(x, y);
+}
+
+static jboolean nativeWordSelection(JNIEnv *env, jobject obj, int x, int y)
+{
+ return GET_NATIVE_VIEW(env, obj)->wordSelection(x, y);
+}
+
+static void nativeExtendSelection(JNIEnv *env, jobject obj, int x, int y)
+{
+ GET_NATIVE_VIEW(env, obj)->extendSelection(x, y);
}
static jobject nativeGetSelection(JNIEnv *env, jobject obj)
{
WebView* view = GET_NATIVE_VIEW(env, obj);
- ALOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+ LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
String selection = view->getSelection();
return wtfStringToJstring(env, selection);
}
-static void nativeDiscardAllTextures(JNIEnv *env, jobject obj)
+static jboolean nativeHitSelection(JNIEnv *env, jobject obj, int x, int y)
+{
+ return GET_NATIVE_VIEW(env, obj)->hitSelection(x, y);
+}
+
+static jint nativeSelectionX(JNIEnv *env, jobject obj)
+{
+ return GET_NATIVE_VIEW(env, obj)->selectionX();
+}
+
+static jint nativeSelectionY(JNIEnv *env, jobject obj)
+{
+ return GET_NATIVE_VIEW(env, obj)->selectionY();
+}
+
+static void nativeSetSelectionPointer(JNIEnv *env, jobject obj, jint nativeView,
+ jboolean set, jfloat scale, jint x, jint y)
+{
+ ((WebView*)nativeView)->setSelectionPointer(set, scale, x, y);
+}
+
+static void nativeRegisterPageSwapCallback(JNIEnv *env, jobject obj)
{
- //discard all textures for debugging/test purposes, but not gl backing memory
- bool allTextures = true, deleteGLTextures = false;
- TilesManager::instance()->discardTextures(allTextures, deleteGLTextures);
+ GET_NATIVE_VIEW(env, obj)->registerPageSwapCallback();
}
static void nativeTileProfilingStart(JNIEnv *env, jobject obj)
@@ -1071,14 +2581,15 @@ static void dumpToFile(const char text[], void* file) {
}
#endif
-// Return true to view invalidate WebView
static bool nativeSetProperty(JNIEnv *env, jobject obj, jstring jkey, jstring jvalue)
{
WTF::String key = jstringToWtfString(env, jkey);
WTF::String value = jstringToWtfString(env, jvalue);
if (key == "inverted") {
- bool shouldInvert = (value == "true");
- TilesManager::instance()->setInvertedScreen(shouldInvert);
+ if (value == "true")
+ TilesManager::instance()->setInvertedScreen(true);
+ else
+ TilesManager::instance()->setInvertedScreen(false);
return true;
}
else if (key == "inverted_contrast") {
@@ -1089,47 +2600,25 @@ static bool nativeSetProperty(JNIEnv *env, jobject obj, jstring jkey, jstring jv
else if (key == "enable_cpu_upload_path") {
TilesManager::instance()->transferQueue()->setTextureUploadType(
value == "true" ? CpuUpload : GpuUpload);
+ return true;
}
else if (key == "use_minimal_memory") {
TilesManager::instance()->setUseMinimalMemory(value == "true");
- }
- else if (key == "use_double_buffering") {
- TilesManager::instance()->setUseDoubleBuffering(value == "true");
- }
- else if (key == "tree_updates") {
- TilesManager::instance()->clearContentUpdates();
+ return true;
}
return false;
}
-static jstring nativeGetProperty(JNIEnv *env, jobject obj, jstring jkey)
+static jstring nativeGetProperty(JNIEnv *env, jobject obj, jstring key)
{
- WTF::String key = jstringToWtfString(env, jkey);
- if (key == "tree_updates") {
- int updates = TilesManager::instance()->getContentUpdates();
- WTF::String wtfUpdates = WTF::String::number(updates);
- return wtfStringToJstring(env, wtfUpdates);
- }
return 0;
}
static void nativeOnTrimMemory(JNIEnv *env, jobject obj, jint level)
{
if (TilesManager::hardwareAccelerationEnabled()) {
- // When we got TRIM_MEMORY_MODERATE or TRIM_MEMORY_COMPLETE, we should
- // make sure the transfer queue is empty and then abandon the Surface
- // Texture to avoid ANR b/c framework may destroy the EGL context.
- // Refer to WindowManagerImpl.java for conditions we followed.
- TilesManager* tilesManager = TilesManager::instance();
- if ((level >= TRIM_MEMORY_MODERATE
- && !tilesManager->highEndGfx())
- || level >= TRIM_MEMORY_COMPLETE) {
- ALOGD("OnTrimMemory with EGL Context %p", eglGetCurrentContext());
- tilesManager->cleanupGLResources();
- }
-
- bool freeAllTextures = (level > TRIM_MEMORY_UI_HIDDEN), glTextures = true;
- tilesManager->discardTextures(freeAllTextures, glTextures);
+ bool freeAllTextures = (level > TRIM_MEMORY_UI_HIDDEN);
+ TilesManager::instance()->deallocateTextures(freeAllTextures);
}
}
@@ -1137,7 +2626,7 @@ static void nativeDumpDisplayTree(JNIEnv* env, jobject jwebview, jstring jurl)
{
#ifdef ANDROID_DUMP_DISPLAY_TREE
WebView* view = GET_NATIVE_VIEW(env, jwebview);
- ALOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+ LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
if (view && view->getWebViewCore()) {
FILE* file = fopen(DISPLAY_TREE_LOG_FILE, "w");
@@ -1154,17 +2643,17 @@ static void nativeDumpDisplayTree(JNIEnv* env, jobject jwebview, jstring jurl)
SkDumpCanvas canvas(&dumper);
// this will playback the picture into the canvas, which will
// spew its contents to the dumper
- view->draw(&canvas, 0, WebView::DrawExtrasNone);
+ view->draw(&canvas, 0, 0, false);
// we're done with the file now
fwrite("\n", 1, 1, file);
fclose(file);
}
#if USE(ACCELERATED_COMPOSITING)
- const LayerAndroid* baseLayer = view->getBaseLayer();
- if (baseLayer) {
+ const LayerAndroid* rootLayer = view->compositeRoot();
+ if (rootLayer) {
FILE* file = fopen(LAYERS_TREE_LOG_FILE,"w");
if (file) {
- baseLayer->dumpLayers(file, 0);
+ rootLayer->dumpLayers(file, 0);
fclose(file);
}
}
@@ -1173,13 +2662,13 @@ static void nativeDumpDisplayTree(JNIEnv* env, jobject jwebview, jstring jurl)
#endif
}
-static int nativeScrollableLayer(JNIEnv* env, jobject jwebview, jint nativeView,
- jint x, jint y, jobject rect, jobject bounds)
+static int nativeScrollableLayer(JNIEnv* env, jobject jwebview, jint x, jint y,
+ jobject rect, jobject bounds)
{
- WebView* webview = reinterpret_cast<WebView*>(nativeView);
- ALOG_ASSERT(webview, "webview not set in %s", __FUNCTION__);
+ WebView* view = GET_NATIVE_VIEW(env, jwebview);
+ LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
SkIRect nativeRect, nativeBounds;
- int id = webview->scrollableLayer(x, y, &nativeRect, &nativeBounds);
+ int id = view->scrollableLayer(x, y, &nativeRect, &nativeBounds);
if (rect)
GraphicsJNI::irect_to_jrect(nativeRect, env, rect);
if (bounds)
@@ -1187,18 +2676,18 @@ static int nativeScrollableLayer(JNIEnv* env, jobject jwebview, jint nativeView,
return id;
}
-static bool nativeScrollLayer(JNIEnv* env, jobject obj,
- jint nativeView, jint layerId, jint x, jint y)
+static bool nativeScrollLayer(JNIEnv* env, jobject obj, jint layerId, jint x,
+ jint y)
{
#if ENABLE(ANDROID_OVERFLOW_SCROLL)
- WebView* webview = reinterpret_cast<WebView*>(nativeView);
- webview->scrollLayer(layerId, x, y);
+ WebView* view = GET_NATIVE_VIEW(env, obj);
+ view->scrollLayer(layerId, x, y);
//TODO: the below only needed for the SW rendering path
- LayerAndroid* baseLayer = webview->getBaseLayer();
- if (!baseLayer)
+ LayerAndroid* root = view->compositeRoot();
+ if (!root)
return false;
- LayerAndroid* layer = baseLayer->findById(layerId);
+ LayerAndroid* layer = root->findById(layerId);
if (!layer || !layer->contentIsScrollable())
return false;
return static_cast<ScrollableLayerAndroid*>(layer)->scrollTo(x, y);
@@ -1208,10 +2697,9 @@ static bool nativeScrollLayer(JNIEnv* env, jobject obj,
static void nativeSetIsScrolling(JNIEnv* env, jobject jwebview, jboolean isScrolling)
{
- // TODO: Pass in the native pointer instead
WebView* view = GET_NATIVE_VIEW(env, jwebview);
- if (view)
- view->setIsScrolling(isScrolling);
+ LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
+ view->setIsScrolling(isScrolling);
}
static void nativeUseHardwareAccelSkia(JNIEnv*, jobject, jboolean enabled)
@@ -1219,9 +2707,9 @@ static void nativeUseHardwareAccelSkia(JNIEnv*, jobject, jboolean enabled)
BaseRenderer::setCurrentRendererType(enabled ? BaseRenderer::Ganesh : BaseRenderer::Raster);
}
-static int nativeGetBackgroundColor(JNIEnv* env, jobject obj, jint nativeView)
+static int nativeGetBackgroundColor(JNIEnv* env, jobject obj)
{
- WebView* view = reinterpret_cast<WebView*>(nativeView);
+ WebView* view = GET_NATIVE_VIEW(env, obj);
BaseLayerAndroid* baseLayer = view->getBaseLayer();
if (baseLayer) {
WebCore::Color color = baseLayer->getBackgroundColor();
@@ -1235,93 +2723,179 @@ static int nativeGetBackgroundColor(JNIEnv* env, jobject obj, jint nativeView)
static void nativeSetPauseDrawing(JNIEnv *env, jobject obj, jint nativeView,
jboolean pause)
{
- reinterpret_cast<WebView*>(nativeView)->setDrawingPaused(pause);
-}
-
-static void nativeSetTextSelection(JNIEnv *env, jobject obj, jint nativeView,
- jint selectionPtr)
-{
- SelectText* selection = reinterpret_cast<SelectText*>(selectionPtr);
- reinterpret_cast<WebView*>(nativeView)->setTextSelection(selection);
-}
-
-static jint nativeGetHandleLayerId(JNIEnv *env, jobject obj, jint nativeView,
- jint handleIndex, jobject cursorPoint,
- jobject textQuad)
-{
- WebView* webview = reinterpret_cast<WebView*>(nativeView);
- SkIPoint nativePoint;
- FloatQuad nativeTextQuad;
- int layerId = webview->getHandleLayerId((SelectText::HandleId) handleIndex,
- nativePoint, nativeTextQuad);
- if (cursorPoint)
- GraphicsJNI::ipoint_to_jpoint(nativePoint, env, cursorPoint);
- if (textQuad)
- webview->floatQuadToQuadF(env, nativeTextQuad, textQuad);
- return layerId;
-}
-
-static void nativeMapLayerRect(JNIEnv *env, jobject obj, jint nativeView,
- jint layerId, jobject rect)
-{
- WebView* webview = reinterpret_cast<WebView*>(nativeView);
- SkIRect nativeRect;
- GraphicsJNI::jrect_to_irect(env, rect, &nativeRect);
- webview->mapLayerRect(layerId, nativeRect);
- GraphicsJNI::irect_to_jrect(nativeRect, env, rect);
-}
-
-static jint nativeSetHwAccelerated(JNIEnv *env, jobject obj, jint nativeView,
- jboolean hwAccelerated)
-{
- WebView* webview = reinterpret_cast<WebView*>(nativeView);
- return webview->setHwAccelerated(hwAccelerated);
-}
-
-static void nativeFindMaxVisibleRect(JNIEnv *env, jobject obj, jint nativeView,
- jint movingLayerId, jobject visibleContentRect)
-{
- WebView* webview = reinterpret_cast<WebView*>(nativeView);
- SkIRect nativeRect;
- GraphicsJNI::jrect_to_irect(env, visibleContentRect, &nativeRect);
- webview->findMaxVisibleRect(movingLayerId, nativeRect);
- GraphicsJNI::irect_to_jrect(nativeRect, env, visibleContentRect);
+ ((WebView*)nativeView)->m_isDrawingPaused = pause;
}
/*
* JNI registration
*/
static JNINativeMethod gJavaWebViewMethods[] = {
+ { "nativeCacheHitFramePointer", "()I",
+ (void*) nativeCacheHitFramePointer },
+ { "nativeCacheHitIsPlugin", "()Z",
+ (void*) nativeCacheHitIsPlugin },
+ { "nativeCacheHitNodeBounds", "()Landroid/graphics/Rect;",
+ (void*) nativeCacheHitNodeBounds },
+ { "nativeCacheHitNodePointer", "()I",
+ (void*) nativeCacheHitNodePointer },
+ { "nativeClearCursor", "()V",
+ (void*) nativeClearCursor },
{ "nativeCreate", "(ILjava/lang/String;Z)V",
(void*) nativeCreate },
- { "nativeDestroy", "(I)V",
+ { "nativeCursorFramePointer", "()I",
+ (void*) nativeCursorFramePointer },
+ { "nativePageShouldHandleShiftAndArrows", "()Z",
+ (void*) nativePageShouldHandleShiftAndArrows },
+ { "nativeCursorNodeBounds", "()Landroid/graphics/Rect;",
+ (void*) nativeCursorNodeBounds },
+ { "nativeCursorNodePointer", "()I",
+ (void*) nativeCursorNodePointer },
+ { "nativeCursorIntersects", "(Landroid/graphics/Rect;)Z",
+ (void*) nativeCursorIntersects },
+ { "nativeCursorIsAnchor", "()Z",
+ (void*) nativeCursorIsAnchor },
+ { "nativeCursorIsTextInput", "()Z",
+ (void*) nativeCursorIsTextInput },
+ { "nativeCursorPosition", "()Landroid/graphics/Point;",
+ (void*) nativeCursorPosition },
+ { "nativeCursorText", "()Ljava/lang/String;",
+ (void*) nativeCursorText },
+ { "nativeCursorWantsKeyEvents", "()Z",
+ (void*)nativeCursorWantsKeyEvents },
+ { "nativeDebugDump", "()V",
+ (void*) nativeDebugDump },
+ { "nativeDestroy", "()V",
(void*) nativeDestroy },
- { "nativeDraw", "(Landroid/graphics/Canvas;Landroid/graphics/RectF;II)V",
+ { "nativeDraw", "(Landroid/graphics/Canvas;Landroid/graphics/RectF;IIZ)I",
(void*) nativeDraw },
- { "nativeCreateDrawGLFunction", "(ILandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/RectF;FI)I",
- (void*) nativeCreateDrawGLFunction },
- { "nativeGetDrawGLFunction", "(I)I",
+ { "nativeGetDrawGLFunction", "(ILandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/RectF;FI)I",
(void*) nativeGetDrawGLFunction },
- { "nativeUpdateDrawGLFunction", "(ILandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/RectF;F)V",
+ { "nativeUpdateDrawGLFunction", "(Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/RectF;)V",
(void*) nativeUpdateDrawGLFunction },
{ "nativeDumpDisplayTree", "(Ljava/lang/String;)V",
(void*) nativeDumpDisplayTree },
{ "nativeEvaluateLayersAnimations", "(I)Z",
(void*) nativeEvaluateLayersAnimations },
+ { "nativeExtendSelection", "(II)V",
+ (void*) nativeExtendSelection },
+ { "nativeFindAll", "(Ljava/lang/String;Ljava/lang/String;Z)I",
+ (void*) nativeFindAll },
+ { "nativeFindNext", "(Z)V",
+ (void*) nativeFindNext },
+ { "nativeFindIndex", "()I",
+ (void*) nativeFindIndex},
+ { "nativeFocusCandidateFramePointer", "()I",
+ (void*) nativeFocusCandidateFramePointer },
+ { "nativeFocusCandidateHasNextTextfield", "()Z",
+ (void*) focusCandidateHasNextTextfield },
+ { "nativeFocusCandidateIsPassword", "()Z",
+ (void*) nativeFocusCandidateIsPassword },
+ { "nativeFocusCandidateIsRtlText", "()Z",
+ (void*) nativeFocusCandidateIsRtlText },
+ { "nativeFocusCandidateIsTextInput", "()Z",
+ (void*) nativeFocusCandidateIsTextInput },
+ { "nativeFocusCandidateLineHeight", "()I",
+ (void*) nativeFocusCandidateLineHeight },
+ { "nativeFocusCandidateMaxLength", "()I",
+ (void*) nativeFocusCandidateMaxLength },
+ { "nativeFocusCandidateIsAutoComplete", "()Z",
+ (void*) nativeFocusCandidateIsAutoComplete },
+ { "nativeFocusCandidateIsSpellcheck", "()Z",
+ (void*) nativeFocusCandidateIsSpellcheck },
+ { "nativeFocusCandidateName", "()Ljava/lang/String;",
+ (void*) nativeFocusCandidateName },
+ { "nativeFocusCandidateNodeBounds", "()Landroid/graphics/Rect;",
+ (void*) nativeFocusCandidateNodeBounds },
+ { "nativeFocusCandidatePaddingRect", "()Landroid/graphics/Rect;",
+ (void*) nativeFocusCandidatePaddingRect },
+ { "nativeFocusCandidatePointer", "()I",
+ (void*) nativeFocusCandidatePointer },
+ { "nativeFocusCandidateText", "()Ljava/lang/String;",
+ (void*) nativeFocusCandidateText },
+ { "nativeFocusCandidateTextSize", "()F",
+ (void*) nativeFocusCandidateTextSize },
+ { "nativeFocusCandidateType", "()I",
+ (void*) nativeFocusCandidateType },
+ { "nativeFocusCandidateLayerId", "()I",
+ (void*) nativeFocusCandidateLayerId },
+ { "nativeFocusIsPlugin", "()Z",
+ (void*) nativeFocusIsPlugin },
+ { "nativeFocusNodeBounds", "()Landroid/graphics/Rect;",
+ (void*) nativeFocusNodeBounds },
+ { "nativeFocusNodePointer", "()I",
+ (void*) nativeFocusNodePointer },
+ { "nativeGetCursorRingBounds", "()Landroid/graphics/Rect;",
+ (void*) nativeGetCursorRingBounds },
{ "nativeGetSelection", "()Ljava/lang/String;",
(void*) nativeGetSelection },
+ { "nativeHasCursorNode", "()Z",
+ (void*) nativeHasCursorNode },
+ { "nativeHasFocusNode", "()Z",
+ (void*) nativeHasFocusNode },
+ { "nativeHideCursor", "()V",
+ (void*) nativeHideCursor },
+ { "nativeHitSelection", "(II)Z",
+ (void*) nativeHitSelection },
+ { "nativeImageURI", "(II)Ljava/lang/String;",
+ (void*) nativeImageURI },
+ { "nativeInstrumentReport", "()V",
+ (void*) nativeInstrumentReport },
+ { "nativeLayerBounds", "(I)Landroid/graphics/Rect;",
+ (void*) nativeLayerBounds },
+ { "nativeMotionUp", "(III)Z",
+ (void*) nativeMotionUp },
+ { "nativeMoveCursor", "(IIZ)Z",
+ (void*) nativeMoveCursor },
+ { "nativeMoveCursorToNextTextInput", "()Z",
+ (void*) nativeMoveCursorToNextTextInput },
+ { "nativeMoveGeneration", "()I",
+ (void*) nativeMoveGeneration },
+ { "nativeMoveSelection", "(II)V",
+ (void*) nativeMoveSelection },
+ { "nativePointInNavCache", "(III)Z",
+ (void*) nativePointInNavCache },
+ { "nativeResetSelection", "()V",
+ (void*) nativeResetSelection },
+ { "nativeSelectableText", "()Landroid/graphics/Point;",
+ (void*) nativeSelectableText },
+ { "nativeSelectAll", "()V",
+ (void*) nativeSelectAll },
+ { "nativeSelectBestAt", "(Landroid/graphics/Rect;)V",
+ (void*) nativeSelectBestAt },
+ { "nativeSelectAt", "(II)V",
+ (void*) nativeSelectAt },
+ { "nativeSelectionX", "()I",
+ (void*) nativeSelectionX },
+ { "nativeSelectionY", "()I",
+ (void*) nativeSelectionY },
+ { "nativeSetExtendSelection", "()V",
+ (void*) nativeSetExtendSelection },
+ { "nativeSetFindIsEmpty", "()V",
+ (void*) nativeSetFindIsEmpty },
+ { "nativeSetFindIsUp", "(Z)V",
+ (void*) nativeSetFindIsUp },
{ "nativeSetHeightCanMeasure", "(Z)V",
(void*) nativeSetHeightCanMeasure },
- { "nativeSetBaseLayer", "(IIZZI)Z",
+ { "nativeSetBaseLayer", "(ILandroid/graphics/Region;ZZZ)V",
(void*) nativeSetBaseLayer },
- { "nativeGetBaseLayer", "(I)I",
+ { "nativeGetTextSelectionRegion", "(ILandroid/graphics/Region;)V",
+ (void*) nativeGetTextSelectionRegion },
+ { "nativeGetSelectionHandles", "(I[I)V",
+ (void*) nativeGetSelectionHandles },
+ { "nativeGetBaseLayer", "()I",
(void*) nativeGetBaseLayer },
+ { "nativeReplaceBaseContent", "(I)V",
+ (void*) nativeReplaceBaseContent },
{ "nativeCopyBaseContentToPicture", "(Landroid/graphics/Picture;)V",
(void*) nativeCopyBaseContentToPicture },
{ "nativeHasContent", "()Z",
(void*) nativeHasContent },
- { "nativeDiscardAllTextures", "()V",
- (void*) nativeDiscardAllTextures },
+ { "nativeSetSelectionPointer", "(IZFII)V",
+ (void*) nativeSetSelectionPointer },
+ { "nativeShowCursorTimed", "()V",
+ (void*) nativeShowCursorTimed },
+ { "nativeRegisterPageSwapCallback", "()V",
+ (void*) nativeRegisterPageSwapCallback },
{ "nativeTileProfilingStart", "()V",
(void*) nativeTileProfilingStart },
{ "nativeTileProfilingStop", "()F",
@@ -1336,17 +2910,29 @@ static JNINativeMethod gJavaWebViewMethods[] = {
(void*) nativeTileProfilingGetInt },
{ "nativeTileProfilingGetFloat", "(IILjava/lang/String;)F",
(void*) nativeTileProfilingGetFloat },
- { "nativeStopGL", "(I)V",
+ { "nativeStartSelection", "(II)Z",
+ (void*) nativeStartSelection },
+ { "nativeStopGL", "()V",
(void*) nativeStopGL },
- { "nativeScrollableLayer", "(IIILandroid/graphics/Rect;Landroid/graphics/Rect;)I",
+ { "nativeSubtractLayers", "(Landroid/graphics/Rect;)Landroid/graphics/Rect;",
+ (void*) nativeSubtractLayers },
+ { "nativeTextGeneration", "()I",
+ (void*) nativeTextGeneration },
+ { "nativeUpdateCachedTextfield", "(Ljava/lang/String;I)V",
+ (void*) nativeUpdateCachedTextfield },
+ { "nativeWordSelection", "(II)Z",
+ (void*) nativeWordSelection },
+ { "nativeGetBlockLeftEdge", "(IIF)I",
+ (void*) nativeGetBlockLeftEdge },
+ { "nativeScrollableLayer", "(IILandroid/graphics/Rect;Landroid/graphics/Rect;)I",
(void*) nativeScrollableLayer },
- { "nativeScrollLayer", "(IIII)Z",
+ { "nativeScrollLayer", "(III)Z",
(void*) nativeScrollLayer },
{ "nativeSetIsScrolling", "(Z)V",
(void*) nativeSetIsScrolling },
{ "nativeUseHardwareAccelSkia", "(Z)V",
(void*) nativeUseHardwareAccelSkia },
- { "nativeGetBackgroundColor", "(I)I",
+ { "nativeGetBackgroundColor", "()I",
(void*) nativeGetBackgroundColor },
{ "nativeSetProperty", "(Ljava/lang/String;Ljava/lang/String;)Z",
(void*) nativeSetProperty },
@@ -1356,27 +2942,17 @@ static JNINativeMethod gJavaWebViewMethods[] = {
(void*) nativeOnTrimMemory },
{ "nativeSetPauseDrawing", "(IZ)V",
(void*) nativeSetPauseDrawing },
- { "nativeSetTextSelection", "(II)V",
- (void*) nativeSetTextSelection },
- { "nativeGetHandleLayerId", "(IILandroid/graphics/Point;Landroid/webkit/QuadF;)I",
- (void*) nativeGetHandleLayerId },
- { "nativeMapLayerRect", "(IILandroid/graphics/Rect;)V",
- (void*) nativeMapLayerRect },
- { "nativeSetHwAccelerated", "(IZ)I",
- (void*) nativeSetHwAccelerated },
- { "nativeFindMaxVisibleRect", "(IILandroid/graphics/Rect;)V",
- (void*) nativeFindMaxVisibleRect },
};
int registerWebView(JNIEnv* env)
{
- jclass clazz = env->FindClass("android/webkit/WebViewClassic");
- ALOG_ASSERT(clazz, "Unable to find class android/webkit/WebViewClassic");
+ jclass clazz = env->FindClass("android/webkit/WebView");
+ LOG_ASSERT(clazz, "Unable to find class android/webkit/WebView");
gWebViewField = env->GetFieldID(clazz, "mNativeClass", "I");
- ALOG_ASSERT(gWebViewField, "Unable to find android/webkit/WebViewClassic.mNativeClass");
+ LOG_ASSERT(gWebViewField, "Unable to find android/webkit/WebView.mNativeClass");
env->DeleteLocalRef(clazz);
- return jniRegisterNativeMethods(env, "android/webkit/WebViewClassic", gJavaWebViewMethods, NELEM(gJavaWebViewMethods));
+ return jniRegisterNativeMethods(env, "android/webkit/WebView", gJavaWebViewMethods, NELEM(gJavaWebViewMethods));
}
} // namespace android