2 * Copyright 2007, The Android Open Source Project
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #define LOG_TAG "webviewglue"
30 #include "AndroidAnimation.h"
31 #include "AndroidLog.h"
32 #include "BaseLayerAndroid.h"
33 #include "CachedFrame.h"
34 #include "CachedNode.h"
35 #include "CachedRoot.h"
36 #include "DrawExtra.h"
37 #include "FindCanvas.h"
39 #include "GraphicsJNI.h"
40 #include "HTMLInputElement.h"
43 #include "LayerAndroid.h"
45 #include "utils/Functor.h"
46 #include "private/hwui/DrawGlInfo.h"
47 #include "PlatformGraphicsContext.h"
48 #include "PlatformString.h"
49 #include "ScrollableLayerAndroid.h"
50 #include "SelectText.h"
52 #include "SkDumpCanvas.h"
53 #include "SkPicture.h"
56 #ifdef ANDROID_INSTRUMENT
57 #include "TimeCounter.h"
59 #include "TilesManager.h"
60 #include "WebCoreJni.h"
61 #include "WebRequestContext.h"
62 #include "WebViewCore.h"
63 #include "android_graphics.h"
65 #ifdef GET_NATIVE_VIEW
66 #undef GET_NATIVE_VIEW
69 #define GET_NATIVE_VIEW(env, obj) ((WebView*)env->GetIntField(obj, gWebViewField))
71 #include <JNIUtility.h>
74 #include <ui/KeycodeLabels.h>
75 #include <wtf/text/AtomicString.h>
76 #include <wtf/text/CString.h>
78 // Free as much as we possible can
79 #define TRIM_MEMORY_COMPLETE 80
80 // Free a lot (all textures gone)
81 #define TRIM_MEMORY_MODERATE 60
82 // More moderate free (keep bare minimum to restore quickly-ish - possibly clear all textures)
83 #define TRIM_MEMORY_BACKGROUND 40
84 // Moderate free (clear cached tiles, keep visible ones)
85 #define TRIM_MEMORY_UI_HIDDEN 20
86 // Duration to show the pressed cursor ring
87 #define PRESSED_STATE_DURATION 400
91 static jfieldID gWebViewField;
93 //-------------------------------------
95 static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[], const char signature[])
97 jmethodID m = env->GetMethodID(clazz, name, signature);
98 LOG_ASSERT(m, "Could not find method %s", name);
102 //-------------------------------------
103 // This class provides JNI for making calls into native code from the UI side
104 // of the multi-threaded WebView.
108 enum FrameCachePermission {
113 enum DrawExtras { // keep this in sync with WebView.java
116 DrawExtrasSelection = 2,
117 DrawExtrasCursorRing = 3
122 jmethodID m_overrideLoading;
123 jmethodID m_scrollBy;
124 jmethodID m_sendMoveFocus;
125 jmethodID m_sendMoveMouse;
126 jmethodID m_sendMoveMouseIfLatest;
127 jmethodID m_sendMotionUp;
128 jmethodID m_domChangedFocus;
129 jmethodID m_getScaledMaxXScroll;
130 jmethodID m_getScaledMaxYScroll;
131 jmethodID m_getVisibleRect;
132 jmethodID m_rebuildWebTextView;
133 jmethodID m_viewInvalidate;
134 jmethodID m_viewInvalidateRect;
135 jmethodID m_postInvalidateDelayed;
136 jmethodID m_pageSwapCallback;
137 jmethodID m_inFullScreenMode;
140 jmethodID m_rectWidth;
141 jmethodID m_rectHeight;
142 jfieldID m_rectFLeft;
144 jmethodID m_rectFWidth;
145 jmethodID m_rectFHeight;
146 jmethodID m_getTextHandleScale;
147 AutoJObject object(JNIEnv* env) {
148 return getRealObject(env, m_obj);
152 WebView(JNIEnv* env, jobject javaWebView, int viewImpl, WTF::String drawableDir,
154 m_ring((WebViewCore*) viewImpl)
155 , m_isHighEndGfx(isHighEndGfx)
157 jclass clazz = env->FindClass("android/webkit/WebView");
158 // m_javaGlue = new JavaGlue;
159 m_javaGlue.m_obj = env->NewWeakGlobalRef(javaWebView);
160 m_javaGlue.m_scrollBy = GetJMethod(env, clazz, "setContentScrollBy", "(IIZ)Z");
161 m_javaGlue.m_overrideLoading = GetJMethod(env, clazz, "overrideLoading", "(Ljava/lang/String;)V");
162 m_javaGlue.m_sendMoveFocus = GetJMethod(env, clazz, "sendMoveFocus", "(II)V");
163 m_javaGlue.m_sendMoveMouse = GetJMethod(env, clazz, "sendMoveMouse", "(IIII)V");
164 m_javaGlue.m_sendMoveMouseIfLatest = GetJMethod(env, clazz, "sendMoveMouseIfLatest", "(ZZ)V");
165 m_javaGlue.m_sendMotionUp = GetJMethod(env, clazz, "sendMotionUp", "(IIIII)V");
166 m_javaGlue.m_domChangedFocus = GetJMethod(env, clazz, "domChangedFocus", "()V");
167 m_javaGlue.m_getScaledMaxXScroll = GetJMethod(env, clazz, "getScaledMaxXScroll", "()I");
168 m_javaGlue.m_getScaledMaxYScroll = GetJMethod(env, clazz, "getScaledMaxYScroll", "()I");
169 m_javaGlue.m_getVisibleRect = GetJMethod(env, clazz, "sendOurVisibleRect", "()Landroid/graphics/Rect;");
170 m_javaGlue.m_rebuildWebTextView = GetJMethod(env, clazz, "rebuildWebTextView", "()V");
171 m_javaGlue.m_viewInvalidate = GetJMethod(env, clazz, "viewInvalidate", "()V");
172 m_javaGlue.m_viewInvalidateRect = GetJMethod(env, clazz, "viewInvalidate", "(IIII)V");
173 m_javaGlue.m_postInvalidateDelayed = GetJMethod(env, clazz,
174 "viewInvalidateDelayed", "(JIIII)V");
175 m_javaGlue.m_pageSwapCallback = GetJMethod(env, clazz, "pageSwapCallback", "(Z)V");
176 m_javaGlue.m_inFullScreenMode = GetJMethod(env, clazz, "inFullScreenMode", "()Z");
177 m_javaGlue.m_getTextHandleScale = GetJMethod(env, clazz, "getTextHandleScale", "()F");
178 env->DeleteLocalRef(clazz);
180 jclass rectClass = env->FindClass("android/graphics/Rect");
181 LOG_ASSERT(rectClass, "Could not find Rect class");
182 m_javaGlue.m_rectLeft = env->GetFieldID(rectClass, "left", "I");
183 m_javaGlue.m_rectTop = env->GetFieldID(rectClass, "top", "I");
184 m_javaGlue.m_rectWidth = GetJMethod(env, rectClass, "width", "()I");
185 m_javaGlue.m_rectHeight = GetJMethod(env, rectClass, "height", "()I");
186 env->DeleteLocalRef(rectClass);
188 jclass rectClassF = env->FindClass("android/graphics/RectF");
189 LOG_ASSERT(rectClassF, "Could not find RectF class");
190 m_javaGlue.m_rectFLeft = env->GetFieldID(rectClassF, "left", "F");
191 m_javaGlue.m_rectFTop = env->GetFieldID(rectClassF, "top", "F");
192 m_javaGlue.m_rectFWidth = GetJMethod(env, rectClassF, "width", "()F");
193 m_javaGlue.m_rectFHeight = GetJMethod(env, rectClassF, "height", "()F");
194 env->DeleteLocalRef(rectClassF);
196 env->SetIntField(javaWebView, gWebViewField, (jint)this);
197 m_viewImpl = (WebViewCore*) viewImpl;
201 m_heightCanMeasure = false;
204 m_ringAnimationEnd = 0;
207 m_isDrawingPaused = false;
208 m_buttonSkin = drawableDir.isEmpty() ? 0 : new RenderSkinButton(drawableDir);
209 #if USE(ACCELERATED_COMPOSITING)
210 m_glWebViewState = 0;
211 m_pageSwapCallbackRegistered = false;
217 if (m_javaGlue.m_obj)
219 JNIEnv* env = JSC::Bindings::getJNIEnv();
220 env->DeleteWeakGlobalRef(m_javaGlue.m_obj);
221 m_javaGlue.m_obj = 0;
223 #if USE(ACCELERATED_COMPOSITING)
224 // We must remove the m_glWebViewState prior to deleting m_baseLayer. If we
225 // do not remove it here, we risk having BaseTiles trying to paint using a
226 // deallocated base layer.
229 delete m_frameCacheUI;
230 delete m_navPictureUI;
231 SkSafeUnref(m_baseLayer);
232 delete m_glDrawFunctor;
238 #if USE(ACCELERATED_COMPOSITING)
239 delete m_glWebViewState;
240 m_glWebViewState = 0;
244 WebViewCore* getWebViewCore() const {
248 float getTextHandleScale()
250 LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
251 JNIEnv* env = JSC::Bindings::getJNIEnv();
252 AutoJObject javaObject = m_javaGlue.object(env);
253 if (!javaObject.get())
255 float result = env->CallFloatMethod(javaObject.get(), m_javaGlue.m_getTextHandleScale);
260 void updateSelectionHandles()
264 // Adjust for device density & scale
265 m_selectText.updateHandleScale(getTextHandleScale());
268 // removes the cursor altogether (e.g., when going to a new page)
271 CachedRoot* root = getFrameCache(AllowNewer);
275 m_viewImpl->m_hasCursorBounds = false;
280 // leaves the cursor where it is, but suppresses drawing it
283 CachedRoot* root = getFrameCache(AllowNewer);
291 void hideCursor(CachedRoot* root)
293 DBG_NAV_LOG("inner");
294 m_viewImpl->m_hasCursorBounds = false;
301 CachedRoot* root = getFrameCache(DontAllowNewer);
303 root->mDebug.print();
307 void scrollToCurrentMatch()
309 if (!m_findOnPage.currentMatchIsInLayer()) {
310 scrollRectOnScreen(m_findOnPage.currentMatchBounds());
314 SkRect matchBounds = m_findOnPage.currentMatchBounds();
315 LayerAndroid* rootLayer = getFrameCache(DontAllowNewer)->rootLayer();
316 Layer* layerContainingMatch = rootLayer->findById(m_findOnPage.currentMatchLayerId());
317 ASSERT(layerContainingMatch);
319 // If the match is in a fixed position layer, there's nothing to do.
320 if (layerContainingMatch->shouldInheritFromRootTransform())
323 // If the match is in a scrollable layer or a descendant of such a layer,
324 // there may be a range of of scroll configurations that will make the
325 // current match visible. Our approach is the simplest possible. Starting at
326 // the layer in which the match is found, we move up the layer tree,
327 // scrolling any scrollable layers as little as possible to make sure that
328 // the current match is in view. This approach has the disadvantage that we
329 // may end up scrolling a larger number of elements than is necessary, which
330 // may be visually jarring. However, minimising the number of layers
331 // scrolled would complicate the code significantly.
333 bool didScrollLayer = false;
334 for (Layer* layer = layerContainingMatch; layer; layer = layer->getParent()) {
335 ASSERT(layer->getParent() || layer == rootLayer);
337 if (layer->contentIsScrollable()) {
338 // Convert the match location to layer's local space and scroll it.
339 // Repeatedly calling Layer::localToAncestor() is inefficient as
340 // each call repeats part of the calculation. It would be more
341 // efficient to maintain the transform here and update it on each
342 // iteration, but that would mean duplicating logic from
343 // Layer::localToAncestor() and would complicate things.
345 layerContainingMatch->localToAncestor(layer, &transform);
346 SkRect transformedMatchBounds;
347 transform.mapRect(&transformedMatchBounds, matchBounds);
348 SkIRect roundedTransformedMatchBounds;
349 transformedMatchBounds.roundOut(&roundedTransformedMatchBounds);
350 // Only ScrollableLayerAndroid returns true for contentIsScrollable().
351 didScrollLayer |= static_cast<ScrollableLayerAndroid*>(layer)->scrollRectIntoView(roundedTransformedMatchBounds);
354 // Invalidate, as the call below to scroll the main page may be a no-op.
358 // Convert matchBounds to the global space so we can scroll the main page.
360 layerContainingMatch->localToGlobal(&transform);
361 SkRect transformedMatchBounds;
362 transform.mapRect(&transformedMatchBounds, matchBounds);
363 SkIRect roundedTransformedMatchBounds;
364 transformedMatchBounds.roundOut(&roundedTransformedMatchBounds);
365 scrollRectOnScreen(roundedTransformedMatchBounds);
368 void scrollRectOnScreen(const IntRect& rect)
374 int right = rect.maxX();
375 if (left < m_visibleRect.fLeft)
376 dx = left - m_visibleRect.fLeft;
377 // Only scroll right if the entire width can fit on screen.
378 else if (right > m_visibleRect.fRight
379 && right - left < m_visibleRect.width())
380 dx = right - m_visibleRect.fRight;
383 int bottom = rect.maxY();
384 if (top < m_visibleRect.fTop)
385 dy = top - m_visibleRect.fTop;
386 // Only scroll down if the entire height can fit on screen
387 else if (bottom > m_visibleRect.fBottom
388 && bottom - top < m_visibleRect.height())
389 dy = bottom - m_visibleRect.fBottom;
390 if ((dx|dy) == 0 || !scrollBy(dx, dy))
395 void resetCursorRing()
397 m_ringAnimationEnd = 0;
398 m_viewImpl->m_hasCursorBounds = false;
401 bool drawCursorPreamble(CachedRoot* root)
403 if (!root) return false;
404 const CachedFrame* frame;
405 const CachedNode* node = root->currentCursor(&frame);
407 DBG_NAV_LOGV("%s", "!node");
411 m_ring.setIsButton(node);
412 if (node->isHidden()) {
413 DBG_NAV_LOG("node->isHidden()");
414 m_viewImpl->m_hasCursorBounds = false;
417 #if USE(ACCELERATED_COMPOSITING)
418 if (node->isInLayer() && root->rootLayer()) {
419 LayerAndroid* layer = root->rootLayer();
420 layer->updateFixedLayersPositions(m_visibleRect);
421 layer->updatePositions();
424 setVisibleRect(root);
425 m_ring.m_root = root;
426 m_ring.m_frame = frame;
427 m_ring.m_node = node;
428 SkMSec time = SkTime::GetMSecs();
429 m_ring.m_isPressed = time < m_ringAnimationEnd
430 && m_ringAnimationEnd != UINT_MAX;
434 void drawCursorPostamble()
436 if (m_ringAnimationEnd == UINT_MAX)
438 SkMSec time = SkTime::GetMSecs();
439 if (time < m_ringAnimationEnd) {
440 // views assume that inval bounds coordinates are non-negative
441 WebCore::IntRect invalBounds(0, 0, INT_MAX, INT_MAX);
442 invalBounds.intersect(m_ring.m_absBounds);
443 postInvalidateDelayed(m_ringAnimationEnd - time, invalBounds);
445 hideCursor(const_cast<CachedRoot*>(m_ring.m_root));
449 bool drawGL(WebCore::IntRect& viewRect, WebCore::IntRect* invalRect,
450 WebCore::IntRect& webViewRect, int titleBarHeight,
451 WebCore::IntRect& clip, float scale, int extras)
453 #if USE(ACCELERATED_COMPOSITING)
454 if (!m_baseLayer || inFullScreenMode())
457 if (!m_glWebViewState) {
458 m_glWebViewState = new GLWebViewState();
459 m_glWebViewState->setHighEndGfx(m_isHighEndGfx);
460 m_glWebViewState->glExtras()->setCursorRingExtra(&m_ring);
461 m_glWebViewState->glExtras()->setFindOnPageExtra(&m_findOnPage);
462 if (m_baseLayer->content()) {
465 rect.set(0, 0, m_baseLayer->content()->width(), m_baseLayer->content()->height());
466 region.setRect(rect);
467 m_glWebViewState->setBaseLayer(m_baseLayer, region, false, true);
471 CachedRoot* root = getFrameCache(AllowNewer);
473 DBG_NAV_LOG("!root");
474 if (extras == DrawExtrasCursorRing)
477 DrawExtra* extra = 0;
480 extra = &m_findOnPage;
482 case DrawExtrasSelection:
483 // This will involve a JNI call, but under normal circumstances we will
484 // not hit this anyway. Only if USE_JAVA_TEXT_SELECTION is disabled
485 // in WebView.java will we hit this (so really debug only)
486 updateSelectionHandles();
487 extra = &m_selectText;
489 case DrawExtrasCursorRing:
490 if (drawCursorPreamble(root) && m_ring.setup()) {
491 if (m_ring.m_isPressed || m_ringAnimationEnd == UINT_MAX)
493 drawCursorPostamble();
500 unsigned int pic = m_glWebViewState->currentPictureCounter();
501 m_glWebViewState->glExtras()->setDrawExtra(extra);
503 // Make sure we have valid coordinates. We might not have valid coords
504 // if the zoom manager is still initializing. We will be redrawn
505 // once the correct scale is set
506 if (!m_visibleRect.hasValidCoordinates())
508 bool treesSwapped = false;
509 bool newTreeHasAnim = false;
510 bool ret = m_glWebViewState->drawGL(viewRect, m_visibleRect, invalRect,
511 webViewRect, titleBarHeight, clip, scale,
512 &treesSwapped, &newTreeHasAnim);
513 if (treesSwapped && (m_pageSwapCallbackRegistered || newTreeHasAnim)) {
514 m_pageSwapCallbackRegistered = false;
515 LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
516 JNIEnv* env = JSC::Bindings::getJNIEnv();
517 AutoJObject javaObject = m_javaGlue.object(env);
518 if (javaObject.get()) {
519 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_pageSwapCallback, newTreeHasAnim);
523 if (ret || m_glWebViewState->currentPictureCounter() != pic)
524 return !m_isDrawingPaused;
529 PictureSet* draw(SkCanvas* canvas, SkColor bgColor, int extras, bool split)
533 canvas->drawColor(bgColor);
537 // draw the content of the base layer first
538 PictureSet* content = m_baseLayer->content();
539 int sc = canvas->save(SkCanvas::kClip_SaveFlag);
540 canvas->clipRect(SkRect::MakeLTRB(0, 0, content->width(),
541 content->height()), SkRegion::kDifference_Op);
542 canvas->drawColor(bgColor);
543 canvas->restoreToCount(sc);
544 if (content->draw(canvas))
545 ret = split ? new PictureSet(*content) : 0;
547 CachedRoot* root = getFrameCache(AllowNewer);
549 DBG_NAV_LOG("!root");
550 if (extras == DrawExtrasCursorRing)
553 LayerAndroid mainPicture(m_navPictureUI);
554 DrawExtra* extra = 0;
557 extra = &m_findOnPage;
559 case DrawExtrasSelection:
560 // This will involve a JNI call, but under normal circumstances we will
561 // not hit this anyway. Only if USE_JAVA_TEXT_SELECTION is disabled
562 // in WebView.java will we hit this (so really debug only)
563 updateSelectionHandles();
564 extra = &m_selectText;
566 case DrawExtrasCursorRing:
567 if (drawCursorPreamble(root) && m_ring.setup()) {
569 drawCursorPostamble();
575 #if USE(ACCELERATED_COMPOSITING)
576 LayerAndroid* compositeLayer = compositeRoot();
577 if (compositeLayer) {
578 // call this to be sure we've adjusted for any scrolling or animations
579 // before we actually draw
580 compositeLayer->updateFixedLayersPositions(m_visibleRect);
581 compositeLayer->updatePositions();
582 // We have to set the canvas' matrix on the base layer
583 // (to have fixed layers work as intended)
584 SkAutoCanvasRestore restore(canvas, true);
585 m_baseLayer->setMatrix(canvas->getTotalMatrix());
586 canvas->resetMatrix();
587 m_baseLayer->draw(canvas);
591 IntRect dummy; // inval area, unused for now
592 extra->draw(canvas, &mainPicture, &dummy);
598 bool cursorIsTextInput(FrameCachePermission allowNewer)
600 CachedRoot* root = getFrameCache(allowNewer);
602 DBG_NAV_LOG("!root");
605 const CachedNode* cursor = root->currentCursor();
607 DBG_NAV_LOG("!cursor");
610 DBG_NAV_LOGD("%s", cursor->isTextInput() ? "true" : "false");
611 return cursor->isTextInput();
614 void cursorRingBounds(WebCore::IntRect* bounds)
616 DBG_NAV_LOGD("%s", "");
617 CachedRoot* root = getFrameCache(DontAllowNewer);
619 const CachedFrame* cachedFrame;
620 const CachedNode* cachedNode = root->currentCursor(&cachedFrame);
622 *bounds = cachedNode->cursorRingBounds(cachedFrame);
623 DBG_NAV_LOGD("bounds={%d,%d,%d,%d}", bounds->x(), bounds->y(),
624 bounds->width(), bounds->height());
628 *bounds = WebCore::IntRect(0, 0, 0, 0);
633 m_viewImpl->gCursorBoundsMutex.lock();
634 bool hasCursorBounds = m_viewImpl->m_hasCursorBounds;
635 IntRect bounds = m_viewImpl->m_cursorBounds;
636 m_viewImpl->gCursorBoundsMutex.unlock();
637 if (!hasCursorBounds)
640 const CachedFrame* frame;
641 const CachedNode* node = m_frameCacheUI->findAt(bounds, &frame, &x, &y, true);
644 // require that node have approximately the same bounds (+/- 4) and the same
646 IntPoint oldCenter = IntPoint(bounds.x() + (bounds.width() >> 1),
647 bounds.y() + (bounds.height() >> 1));
648 IntRect newBounds = node->bounds(frame);
649 IntPoint newCenter = IntPoint(newBounds.x() + (newBounds.width() >> 1),
650 newBounds.y() + (newBounds.height() >> 1));
651 DBG_NAV_LOGD("oldCenter=(%d,%d) newCenter=(%d,%d)"
652 " bounds=(%d,%d,w=%d,h=%d) newBounds=(%d,%d,w=%d,h=%d)",
653 oldCenter.x(), oldCenter.y(), newCenter.x(), newCenter.y(),
654 bounds.x(), bounds.y(), bounds.width(), bounds.height(),
655 newBounds.x(), newBounds.y(), newBounds.width(), newBounds.height());
656 if (abs(oldCenter.x() - newCenter.x()) > 2)
658 if (abs(oldCenter.y() - newCenter.y()) > 2)
660 if (abs(bounds.x() - newBounds.x()) > 4)
662 if (abs(bounds.y() - newBounds.y()) > 4)
664 if (abs(bounds.maxX() - newBounds.maxX()) > 4)
666 if (abs(bounds.maxY() - newBounds.maxY()) > 4)
668 DBG_NAV_LOGD("node=%p frame=%p x=%d y=%d bounds=(%d,%d,w=%d,h=%d)",
669 node, frame, x, y, bounds.x(), bounds.y(), bounds.width(),
671 m_frameCacheUI->setCursor(const_cast<CachedFrame*>(frame),
672 const_cast<CachedNode*>(node));
675 CachedRoot* getFrameCache(FrameCachePermission allowNewer)
677 if (!m_viewImpl->m_updatedFrameCache) {
678 DBG_NAV_LOGV("%s", "!m_viewImpl->m_updatedFrameCache");
679 return m_frameCacheUI;
681 if (allowNewer == DontAllowNewer && m_viewImpl->m_lastGeneration < m_generation) {
682 DBG_NAV_LOGD("allowNewer==DontAllowNewer m_viewImpl->m_lastGeneration=%d"
683 " < m_generation=%d", m_viewImpl->m_lastGeneration, m_generation);
684 return m_frameCacheUI;
686 DBG_NAV_LOGD("%s", "m_viewImpl->m_updatedFrameCache == true");
687 const CachedFrame* oldCursorFrame;
688 const CachedNode* oldCursorNode = m_frameCacheUI ?
689 m_frameCacheUI->currentCursor(&oldCursorFrame) : 0;
690 #if USE(ACCELERATED_COMPOSITING)
692 if (oldCursorNode && oldCursorNode->isInLayer()) {
693 const LayerAndroid* cursorLayer = oldCursorFrame->layer(oldCursorNode)
694 ->layer(m_frameCacheUI->rootLayer());
696 layerId = cursorLayer->uniqueId();
699 // get id from old layer and use to find new layer
700 bool oldFocusIsTextInput = false;
701 void* oldFocusNodePointer = 0;
702 if (m_frameCacheUI) {
703 const CachedNode* oldFocus = m_frameCacheUI->currentFocus();
705 oldFocusIsTextInput = oldFocus->isTextInput();
706 oldFocusNodePointer = oldFocus->nodePointer();
709 m_viewImpl->gFrameCacheMutex.lock();
710 delete m_frameCacheUI;
711 SkSafeUnref(m_navPictureUI);
712 m_viewImpl->m_updatedFrameCache = false;
713 m_frameCacheUI = m_viewImpl->m_frameCacheKit;
714 m_navPictureUI = m_viewImpl->m_navPictureKit;
715 m_viewImpl->m_frameCacheKit = 0;
716 m_viewImpl->m_navPictureKit = 0;
717 m_viewImpl->gFrameCacheMutex.unlock();
719 m_frameCacheUI->setRootLayer(compositeRoot());
720 #if USE(ACCELERATED_COMPOSITING)
722 LayerAndroid* layer = const_cast<LayerAndroid*>(
723 m_frameCacheUI->rootLayer());
725 layer->updateFixedLayersPositions(m_visibleRect);
726 layer->updatePositions();
731 if (oldFocusIsTextInput) {
732 const CachedNode* newFocus = m_frameCacheUI->currentFocus();
733 if (newFocus && oldFocusNodePointer != newFocus->nodePointer()
734 && newFocus->isTextInput()
735 && newFocus != m_frameCacheUI->currentCursor()) {
736 // The focus has changed. We may need to update things.
737 LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
738 JNIEnv* env = JSC::Bindings::getJNIEnv();
739 AutoJObject javaObject = m_javaGlue.object(env);
740 if (javaObject.get()) {
741 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_domChangedFocus);
746 if (oldCursorNode && (!m_frameCacheUI || !m_frameCacheUI->currentCursor()))
747 viewInvalidate(); // redraw in case cursor ring is still visible
748 return m_frameCacheUI;
751 int getScaledMaxXScroll()
753 LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
754 JNIEnv* env = JSC::Bindings::getJNIEnv();
755 AutoJObject javaObject = m_javaGlue.object(env);
756 if (!javaObject.get())
758 int result = env->CallIntMethod(javaObject.get(), m_javaGlue.m_getScaledMaxXScroll);
763 int getScaledMaxYScroll()
765 LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
766 JNIEnv* env = JSC::Bindings::getJNIEnv();
767 AutoJObject javaObject = m_javaGlue.object(env);
768 if (!javaObject.get())
770 int result = env->CallIntMethod(javaObject.get(), m_javaGlue.m_getScaledMaxYScroll);
775 IntRect getVisibleRect()
778 LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
779 JNIEnv* env = JSC::Bindings::getJNIEnv();
780 AutoJObject javaObject = m_javaGlue.object(env);
781 if (!javaObject.get())
783 jobject jRect = env->CallObjectMethod(javaObject.get(), m_javaGlue.m_getVisibleRect);
785 rect.setX(env->GetIntField(jRect, m_javaGlue.m_rectLeft));
787 rect.setY(env->GetIntField(jRect, m_javaGlue.m_rectTop));
789 rect.setWidth(env->CallIntMethod(jRect, m_javaGlue.m_rectWidth));
791 rect.setHeight(env->CallIntMethod(jRect, m_javaGlue.m_rectHeight));
793 env->DeleteLocalRef(jRect);
798 static CachedFrame::Direction KeyToDirection(int32_t keyCode)
801 case AKEYCODE_DPAD_RIGHT:
802 DBG_NAV_LOGD("keyCode=%s", "right");
803 return CachedFrame::RIGHT;
804 case AKEYCODE_DPAD_LEFT:
805 DBG_NAV_LOGD("keyCode=%s", "left");
806 return CachedFrame::LEFT;
807 case AKEYCODE_DPAD_DOWN:
808 DBG_NAV_LOGD("keyCode=%s", "down");
809 return CachedFrame::DOWN;
810 case AKEYCODE_DPAD_UP:
811 DBG_NAV_LOGD("keyCode=%s", "up");
812 return CachedFrame::UP;
814 DBG_NAV_LOGD("bad key %d sent", keyCode);
815 return CachedFrame::UNINITIALIZED;
819 WTF::String imageURI(int x, int y)
821 const CachedRoot* root = getFrameCache(DontAllowNewer);
822 return root ? root->imageURI(x, y) : WTF::String();
825 bool cursorWantsKeyEvents()
827 const CachedRoot* root = getFrameCache(DontAllowNewer);
829 const CachedNode* focus = root->currentCursor();
831 return focus->wantsKeyEvents();
837 /* returns true if the key had no effect (neither scrolled nor changed cursor) */
838 bool moveCursor(int keyCode, int count, bool ignoreScroll)
840 CachedRoot* root = getFrameCache(AllowNewer);
842 DBG_NAV_LOG("!root");
846 m_viewImpl->m_moveGeneration++;
847 CachedFrame::Direction direction = KeyToDirection(keyCode);
848 const CachedFrame* cachedFrame, * oldFrame = 0;
849 const CachedNode* cursor = root->currentCursor(&oldFrame);
850 WebCore::IntPoint cursorLocation = root->cursorLocation();
851 DBG_NAV_LOGD("old cursor %d (nativeNode=%p) cursorLocation={%d, %d}",
852 cursor ? cursor->index() : 0,
853 cursor ? cursor->nodePointer() : 0, cursorLocation.x(), cursorLocation.y());
854 WebCore::IntRect visibleRect = setVisibleRect(root);
855 int xMax = getScaledMaxXScroll();
856 int yMax = getScaledMaxYScroll();
857 root->setMaxScroll(xMax, yMax);
858 const CachedNode* cachedNode = 0;
862 while (--counter >= 0) {
863 WebCore::IntPoint scroll = WebCore::IntPoint(0, 0);
864 cachedNode = root->moveCursor(direction, &cachedFrame, &scroll);
868 DBG_NAV_LOGD("new cursor %d (nativeNode=%p) cursorLocation={%d, %d}"
869 "bounds={%d,%d,w=%d,h=%d}", cachedNode ? cachedNode->index() : 0,
870 cachedNode ? cachedNode->nodePointer() : 0,
871 root->cursorLocation().x(), root->cursorLocation().y(),
872 cachedNode ? cachedNode->bounds(cachedFrame).x() : 0,
873 cachedNode ? cachedNode->bounds(cachedFrame).y() : 0,
874 cachedNode ? cachedNode->bounds(cachedFrame).width() : 0,
875 cachedNode ? cachedNode->bounds(cachedFrame).height() : 0);
876 // If !m_heightCanMeasure (such as in the browser), we want to scroll no
878 if (!ignoreScroll && (!m_heightCanMeasure ||
880 (cursor && cursor->nodePointer() == cachedNode->nodePointer())))
882 if (count == 1 && dx != 0 && dy == 0 && -m_lastDx == dx &&
883 SkTime::GetMSecs() - m_lastDxTime < 1000)
884 root->checkForJiggle(&dx);
885 DBG_NAV_LOGD("scrollBy %d,%d", dx, dy);
887 this->scrollBy(dx, dy);
889 m_lastDxTime = SkTime::GetMSecs();
894 m_viewImpl->updateCursorBounds(root, cachedFrame, cachedNode);
895 root->setCursor(const_cast<CachedFrame*>(cachedFrame),
896 const_cast<CachedNode*>(cachedNode));
897 const CachedNode* focus = root->currentFocus();
898 bool clearTextEntry = cachedNode != focus && focus
899 && cachedNode->nodePointer() != focus->nodePointer() && focus->isTextInput();
900 // Stop painting the caret if the old focus was a text input and so is the new cursor.
901 bool stopPaintingCaret = clearTextEntry && cachedNode->wantsKeyEvents();
902 sendMoveMouseIfLatest(clearTextEntry, stopPaintingCaret);
904 int docHeight = root->documentHeight();
905 int docWidth = root->documentWidth();
906 if (visibleRect.maxY() + dy > docHeight)
907 dy = docHeight - visibleRect.maxY();
908 else if (visibleRect.y() + dy < 0)
909 dy = -visibleRect.y();
910 if (visibleRect.maxX() + dx > docWidth)
911 dx = docWidth - visibleRect.maxX();
912 else if (visibleRect.x() < 0)
913 dx = -visibleRect.x();
914 result = direction == CachedFrame::LEFT ? dx >= 0 :
915 direction == CachedFrame::RIGHT ? dx <= 0 :
916 direction == CachedFrame::UP ? dy >= 0 : dy <= 0;
921 void notifyProgressFinished()
923 DBG_NAV_LOGD("cursorIsTextInput=%d", cursorIsTextInput(DontAllowNewer));
924 rebuildWebTextView();
926 if (m_frameCacheUI) {
927 const CachedNode* focus = m_frameCacheUI->currentFocus();
928 DBG_NAV_LOGD("focus %d (nativeNode=%p)",
929 focus ? focus->index() : 0,
930 focus ? focus->nodePointer() : 0);
935 const CachedNode* findAt(CachedRoot* root, const WebCore::IntRect& rect,
936 const CachedFrame** framePtr, int* rxPtr, int* ryPtr)
943 setVisibleRect(root);
944 return root->findAt(rect, framePtr, rxPtr, ryPtr, true);
947 IntRect setVisibleRect(CachedRoot* root)
949 IntRect visibleRect = getVisibleRect();
950 DBG_NAV_LOGD("getVisibleRect %d,%d,%d,%d",
951 visibleRect.x(), visibleRect.y(), visibleRect.width(), visibleRect.height());
952 root->setVisibleRect(visibleRect);
956 void selectBestAt(const WebCore::IntRect& rect)
958 const CachedFrame* frame;
960 CachedRoot* root = getFrameCache(AllowNewer);
963 const CachedNode* node = findAt(root, rect, &frame, &rx, &ry);
965 DBG_NAV_LOGD("no nodes found root=%p", root);
966 root->rootHistory()->setMouseBounds(rect);
967 m_viewImpl->m_hasCursorBounds = false;
968 root->setCursor(0, 0);
971 DBG_NAV_LOGD("CachedNode:%p (%d)", node, node->index());
972 WebCore::IntRect bounds = node->bounds(frame);
973 root->rootHistory()->setMouseBounds(bounds);
974 m_viewImpl->updateCursorBounds(root, frame, node);
976 root->setCursor(const_cast<CachedFrame*>(frame),
977 const_cast<CachedNode*>(node));
979 sendMoveMouseIfLatest(false, false);
982 const CachedNode* m_cacheHitNode;
983 const CachedFrame* m_cacheHitFrame;
985 bool pointInNavCache(int x, int y, int slop)
987 CachedRoot* root = getFrameCache(AllowNewer);
990 IntRect rect = IntRect(x - slop, y - slop, slop * 2, slop * 2);
992 return (m_cacheHitNode = findAt(root, rect, &m_cacheHitFrame, &rx, &ry));
995 bool motionUp(int x, int y, int slop)
997 bool pageScrolled = false;
998 IntRect rect = IntRect(x - slop, y - slop, slop * 2, slop * 2);
1000 CachedRoot* root = getFrameCache(AllowNewer);
1003 const CachedFrame* frame = 0;
1004 const CachedNode* result = findAt(root, rect, &frame, &rx, &ry);
1005 CachedHistory* history = root->rootHistory();
1007 DBG_NAV_LOGD("no nodes found root=%p", root);
1008 history->setNavBounds(rect);
1009 m_viewImpl->m_hasCursorBounds = false;
1011 int dx = root->checkForCenter(x, y);
1014 pageScrolled = true;
1016 sendMotionUp(frame ? (WebCore::Frame*) frame->framePointer() : 0,
1019 return pageScrolled;
1021 DBG_NAV_LOGD("CachedNode:%p (%d) x=%d y=%d rx=%d ry=%d", result,
1022 result->index(), x, y, rx, ry);
1023 WebCore::IntRect navBounds = WebCore::IntRect(rx, ry, 1, 1);
1024 history->setNavBounds(navBounds);
1025 history->setMouseBounds(navBounds);
1026 m_viewImpl->updateCursorBounds(root, frame, result);
1027 root->setCursor(const_cast<CachedFrame*>(frame),
1028 const_cast<CachedNode*>(result));
1029 if (result->isSyntheticLink())
1030 overrideUrlLoading(result->getExport());
1033 (WebCore::Frame*) frame->framePointer(),
1034 (WebCore::Node*) result->nodePointer(), rx, ry);
1036 if (result->isTextInput() || result->isSelect()
1037 || result->isContentEditable()) {
1038 showCursorUntimed();
1041 return pageScrolled;
1044 #if USE(ACCELERATED_COMPOSITING)
1045 static const ScrollableLayerAndroid* findScrollableLayer(
1046 const LayerAndroid* parent, int x, int y, SkIRect* foundBounds) {
1048 parent->bounds(&bounds);
1049 // Check the parent bounds first; this will clip to within a masking layer's
1051 if (parent->masksToBounds() && !bounds.contains(x, y))
1053 // Move the hit test local to parent.
1056 int count = parent->countChildren();
1058 const LayerAndroid* child = parent->getChild(count);
1059 const ScrollableLayerAndroid* result = findScrollableLayer(child, x, y,
1062 foundBounds->offset(bounds.fLeft, bounds.fTop);
1063 if (parent->masksToBounds()) {
1064 if (bounds.width() < foundBounds->width())
1065 foundBounds->fRight = foundBounds->fLeft + bounds.width();
1066 if (bounds.height() < foundBounds->height())
1067 foundBounds->fBottom = foundBounds->fTop + bounds.height();
1072 if (parent->contentIsScrollable()) {
1073 foundBounds->set(0, 0, bounds.width(), bounds.height());
1074 return static_cast<const ScrollableLayerAndroid*>(parent);
1080 int scrollableLayer(int x, int y, SkIRect* layerRect, SkIRect* bounds)
1082 #if USE(ACCELERATED_COMPOSITING)
1083 const LayerAndroid* layerRoot = compositeRoot();
1086 const ScrollableLayerAndroid* result = findScrollableLayer(layerRoot, x, y,
1089 result->getScrollRect(layerRect);
1090 return result->uniqueId();
1096 void scrollLayer(int layerId, int x, int y)
1098 if (m_glWebViewState)
1099 m_glWebViewState->scrollLayer(layerId, x, y);
1102 int getBlockLeftEdge(int x, int y, float scale)
1104 CachedRoot* root = getFrameCache(AllowNewer);
1106 return root->getBlockLeftEdge(x, y, scale);
1110 void overrideUrlLoading(const WTF::String& url)
1112 JNIEnv* env = JSC::Bindings::getJNIEnv();
1113 AutoJObject javaObject = m_javaGlue.object(env);
1114 if (!javaObject.get())
1116 jstring jName = wtfStringToJstring(env, url);
1117 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_overrideLoading, jName);
1118 env->DeleteLocalRef(jName);
1121 void setFindIsUp(bool up)
1123 DBG_NAV_LOGD("up=%d", up);
1124 m_viewImpl->m_findIsUp = up;
1127 void setFindIsEmpty()
1130 m_findOnPage.clearCurrentLocation();
1133 void showCursorTimed()
1136 m_ringAnimationEnd = SkTime::GetMSecs() + PRESSED_STATE_DURATION;
1140 void showCursorUntimed()
1143 m_ring.m_isPressed = false;
1144 m_ringAnimationEnd = UINT_MAX;
1148 void setHeightCanMeasure(bool measure)
1150 m_heightCanMeasure = measure;
1153 String getSelection()
1155 return m_selectText.getSelection();
1158 void moveSelection(int x, int y)
1160 m_selectText.moveSelection(getVisibleRect(), x, y);
1163 IntPoint selectableText()
1165 const CachedRoot* root = getFrameCache(DontAllowNewer);
1167 return IntPoint(0, 0);
1168 return m_selectText.selectableText(root);
1173 m_selectText.selectAll();
1178 return m_selectText.selectionX();
1183 return m_selectText.selectionY();
1186 void resetSelection()
1188 m_selectText.reset();
1191 bool startSelection(int x, int y)
1193 const CachedRoot* root = getFrameCache(DontAllowNewer);
1196 updateSelectionHandles();
1197 return m_selectText.startSelection(root, getVisibleRect(), x, y);
1200 bool wordSelection(int x, int y)
1202 const CachedRoot* root = getFrameCache(DontAllowNewer);
1205 updateSelectionHandles();
1206 return m_selectText.wordSelection(root, getVisibleRect(), x, y);
1209 bool extendSelection(int x, int y)
1211 m_selectText.extendSelection(getVisibleRect(), x, y);
1215 bool hitSelection(int x, int y)
1217 updateSelectionHandles();
1218 return m_selectText.hitSelection(x, y);
1221 void setExtendSelection()
1223 m_selectText.setExtendSelection(true);
1226 void setSelectionPointer(bool set, float scale, int x, int y)
1228 m_selectText.setDrawPointer(set);
1231 m_selectText.m_inverseScale = scale;
1232 m_selectText.m_selectX = x;
1233 m_selectText.m_selectY = y;
1236 void sendMoveFocus(WebCore::Frame* framePtr, WebCore::Node* nodePtr)
1238 DBG_NAV_LOGD("framePtr=%p nodePtr=%p", framePtr, nodePtr);
1239 JNIEnv* env = JSC::Bindings::getJNIEnv();
1240 AutoJObject javaObject = m_javaGlue.object(env);
1241 if (!javaObject.get())
1243 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_sendMoveFocus, (jint) framePtr, (jint) nodePtr);
1244 checkException(env);
1247 void sendMoveMouse(WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int y)
1249 DBG_NAV_LOGD("framePtr=%p nodePtr=%p x=%d y=%d", framePtr, nodePtr, x, y);
1250 JNIEnv* env = JSC::Bindings::getJNIEnv();
1251 AutoJObject javaObject = m_javaGlue.object(env);
1252 if (!javaObject.get())
1254 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_sendMoveMouse, reinterpret_cast<jint>(framePtr), reinterpret_cast<jint>(nodePtr), x, y);
1255 checkException(env);
1258 void sendMoveMouseIfLatest(bool clearTextEntry, bool stopPaintingCaret)
1260 LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
1261 JNIEnv* env = JSC::Bindings::getJNIEnv();
1262 AutoJObject javaObject = m_javaGlue.object(env);
1263 if (!javaObject.get())
1265 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_sendMoveMouseIfLatest, clearTextEntry, stopPaintingCaret);
1266 checkException(env);
1269 void sendMotionUp(WebCore::Frame* framePtr, WebCore::Node* nodePtr, int x, int y)
1271 DBG_NAV_LOGD("m_generation=%d framePtr=%p nodePtr=%p x=%d y=%d", m_generation, framePtr, nodePtr, x, y);
1272 LOG_ASSERT(m_javaGlue.m_obj, "A WebView was not associated with this WebViewNative!");
1274 JNIEnv* env = JSC::Bindings::getJNIEnv();
1275 AutoJObject javaObject = m_javaGlue.object(env);
1276 if (!javaObject.get())
1278 m_viewImpl->m_touchGeneration = ++m_generation;
1279 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_sendMotionUp, m_generation, (jint) framePtr, (jint) nodePtr, x, y);
1280 checkException(env);
1283 void findNext(bool forward)
1285 m_findOnPage.findNext(forward);
1286 scrollToCurrentMatch();
1290 // With this call, WebView takes ownership of matches, and is responsible for
1292 void setMatches(WTF::Vector<MatchInfo>* matches, jboolean sameAsLastSearch)
1294 // If this search is the same as the last one, check against the old
1295 // location to determine whether to scroll. If the same word is found
1296 // in the same place, then do not scroll.
1297 IntRect oldLocation;
1298 bool checkAgainstOldLocation = false;
1299 if (sameAsLastSearch && m_findOnPage.isCurrentLocationValid()) {
1300 oldLocation = m_findOnPage.currentMatchBounds();
1301 checkAgainstOldLocation = true;
1304 m_findOnPage.setMatches(matches);
1306 if (!checkAgainstOldLocation || oldLocation != m_findOnPage.currentMatchBounds())
1307 scrollToCurrentMatch();
1311 int currentMatchIndex()
1313 return m_findOnPage.currentMatchIndex();
1316 bool scrollBy(int dx, int dy)
1318 LOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!");
1320 JNIEnv* env = JSC::Bindings::getJNIEnv();
1321 AutoJObject javaObject = m_javaGlue.object(env);
1322 if (!javaObject.get())
1324 bool result = env->CallBooleanMethod(javaObject.get(), m_javaGlue.m_scrollBy, dx, dy, true);
1325 checkException(env);
1329 void setIsScrolling(bool isScrolling)
1331 #if USE(ACCELERATED_COMPOSITING)
1332 if (m_glWebViewState)
1333 m_glWebViewState->setIsScrolling(isScrolling);
1337 bool hasCursorNode()
1339 CachedRoot* root = getFrameCache(DontAllowNewer);
1341 DBG_NAV_LOG("!root");
1344 const CachedNode* cursorNode = root->currentCursor();
1345 DBG_NAV_LOGD("cursorNode=%d (nodePointer=%p)",
1346 cursorNode ? cursorNode->index() : -1,
1347 cursorNode ? cursorNode->nodePointer() : 0);
1353 CachedRoot* root = getFrameCache(DontAllowNewer);
1355 DBG_NAV_LOG("!root");
1358 const CachedNode* focusNode = root->currentFocus();
1359 DBG_NAV_LOGD("focusNode=%d (nodePointer=%p)",
1360 focusNode ? focusNode->index() : -1,
1361 focusNode ? focusNode->nodePointer() : 0);
1365 void rebuildWebTextView()
1367 JNIEnv* env = JSC::Bindings::getJNIEnv();
1368 AutoJObject javaObject = m_javaGlue.object(env);
1369 if (!javaObject.get())
1371 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_rebuildWebTextView);
1372 checkException(env);
1375 void viewInvalidate()
1377 JNIEnv* env = JSC::Bindings::getJNIEnv();
1378 AutoJObject javaObject = m_javaGlue.object(env);
1379 if (!javaObject.get())
1381 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_viewInvalidate);
1382 checkException(env);
1385 void viewInvalidateRect(int l, int t, int r, int b)
1387 JNIEnv* env = JSC::Bindings::getJNIEnv();
1388 AutoJObject javaObject = m_javaGlue.object(env);
1389 if (!javaObject.get())
1391 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_viewInvalidateRect, l, r, t, b);
1392 checkException(env);
1395 void postInvalidateDelayed(int64_t delay, const WebCore::IntRect& bounds)
1397 JNIEnv* env = JSC::Bindings::getJNIEnv();
1398 AutoJObject javaObject = m_javaGlue.object(env);
1399 if (!javaObject.get())
1401 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_postInvalidateDelayed,
1402 delay, bounds.x(), bounds.y(), bounds.maxX(), bounds.maxY());
1403 checkException(env);
1406 bool inFullScreenMode()
1408 JNIEnv* env = JSC::Bindings::getJNIEnv();
1409 AutoJObject javaObject = m_javaGlue.object(env);
1410 if (!javaObject.get())
1412 jboolean result = env->CallBooleanMethod(javaObject.get(), m_javaGlue.m_inFullScreenMode);
1413 checkException(env);
1417 int moveGeneration()
1419 return m_viewImpl->m_moveGeneration;
1422 LayerAndroid* compositeRoot() const
1424 LOG_ASSERT(!m_baseLayer || m_baseLayer->countChildren() == 1,
1425 "base layer can't have more than one child %s", __FUNCTION__);
1426 if (m_baseLayer && m_baseLayer->countChildren() == 1)
1427 return static_cast<LayerAndroid*>(m_baseLayer->getChild(0));
1432 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
1433 static void copyScrollPositionRecursive(const LayerAndroid* from,
1438 for (int i = 0; i < from->countChildren(); i++) {
1439 const LayerAndroid* l = from->getChild(i);
1440 if (l->contentIsScrollable()) {
1441 const SkPoint& pos = l->getPosition();
1442 LayerAndroid* match = root->findById(l->uniqueId());
1443 if (match && match->contentIsScrollable())
1444 match->setPosition(pos.fX, pos.fY);
1446 copyScrollPositionRecursive(l, root);
1451 void registerPageSwapCallback()
1453 m_pageSwapCallbackRegistered = true;
1456 void setBaseLayer(BaseLayerAndroid* layer, SkRegion& inval, bool showVisualIndicator,
1457 bool isPictureAfterFirstLayout, bool registerPageSwapCallback)
1459 #if USE(ACCELERATED_COMPOSITING)
1460 if (m_glWebViewState)
1461 m_glWebViewState->setBaseLayer(layer, inval, showVisualIndicator,
1462 isPictureAfterFirstLayout);
1463 m_pageSwapCallbackRegistered |= registerPageSwapCallback;
1466 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
1468 // TODO: the below tree copies are only necessary in software rendering
1469 LayerAndroid* newCompositeRoot = static_cast<LayerAndroid*>(layer->getChild(0));
1470 copyScrollPositionRecursive(compositeRoot(), newCompositeRoot);
1473 SkSafeUnref(m_baseLayer);
1474 m_baseLayer = layer;
1475 CachedRoot* root = getFrameCache(DontAllowNewer);
1478 root->resetLayers();
1479 root->setRootLayer(compositeRoot());
1482 void getTextSelectionRegion(SkRegion *region)
1484 m_selectText.getSelectionRegion(getVisibleRect(), region, compositeRoot());
1487 void getTextSelectionHandles(int* handles)
1489 m_selectText.getSelectionHandles(handles, compositeRoot());
1492 void replaceBaseContent(PictureSet* set)
1496 m_baseLayer->setContent(*set);
1500 void copyBaseContentToPicture(SkPicture* picture)
1504 PictureSet* content = m_baseLayer->content();
1505 m_baseLayer->drawCanvas(picture->beginRecording(content->width(), content->height(),
1506 SkPicture::kUsePathBoundsForClip_RecordingFlag));
1507 picture->endRecording();
1513 return !m_baseLayer->content()->isEmpty();
1516 void setFunctor(Functor* functor) {
1517 delete m_glDrawFunctor;
1518 m_glDrawFunctor = functor;
1521 Functor* getFunctor() {
1522 return m_glDrawFunctor;
1525 BaseLayerAndroid* getBaseLayer() {
1529 void setVisibleRect(SkRect& visibleRect) {
1530 m_visibleRect = visibleRect;
1533 bool m_isDrawingPaused;
1534 private: // local state for WebView
1535 // private to getFrameCache(); other functions operate in a different thread
1536 CachedRoot* m_frameCacheUI; // navigation data ready for use
1537 WebViewCore* m_viewImpl;
1538 int m_generation; // associate unique ID with sent kit focus to match with ui
1539 SkPicture* m_navPictureUI;
1540 SkMSec m_ringAnimationEnd;
1541 // Corresponds to the same-named boolean on the java side.
1542 bool m_heightCanMeasure;
1544 SkMSec m_lastDxTime;
1545 SelectText m_selectText;
1546 FindOnPage m_findOnPage;
1548 BaseLayerAndroid* m_baseLayer;
1549 Functor* m_glDrawFunctor;
1550 #if USE(ACCELERATED_COMPOSITING)
1551 GLWebViewState* m_glWebViewState;
1552 bool m_pageSwapCallbackRegistered;
1554 RenderSkinButton* m_buttonSkin;
1555 SkRect m_visibleRect;
1556 bool m_isHighEndGfx;
1557 }; // end of WebView class
1561 * This class holds a function pointer and parameters for calling drawGL into a specific
1562 * viewport. The pointer to the Functor will be put on a framework display list to be called
1563 * when the display list is replayed.
1565 class GLDrawFunctor : Functor {
1567 GLDrawFunctor(WebView* _wvInstance,
1568 bool(WebView::*_funcPtr)(WebCore::IntRect&, WebCore::IntRect*,
1569 WebCore::IntRect&, int, WebCore::IntRect&,
1571 WebCore::IntRect _viewRect, float _scale, int _extras) {
1572 wvInstance = _wvInstance;
1574 viewRect = _viewRect;
1578 status_t operator()(int messageId, void* data) {
1579 if (viewRect.isEmpty()) {
1580 // NOOP operation if viewport is empty
1584 WebCore::IntRect inval;
1585 int titlebarHeight = webViewRect.height() - viewRect.height();
1587 uirenderer::DrawGlInfo* info = reinterpret_cast<uirenderer::DrawGlInfo*>(data);
1588 WebCore::IntRect localViewRect = viewRect;
1590 localViewRect.move(-1 * localViewRect.x(), -1 * localViewRect.y());
1592 WebCore::IntRect clip(info->clipLeft, info->clipTop,
1593 info->clipRight - info->clipLeft,
1594 info->clipBottom - info->clipTop);
1595 TilesManager::instance()->shader()->setWebViewMatrix(info->transform, info->isLayer);
1597 bool retVal = (*wvInstance.*funcPtr)(localViewRect, &inval, webViewRect,
1598 titlebarHeight, clip, scale, extras);
1601 if (inval.isEmpty()) {
1602 finalInval = webViewRect;
1605 finalInval.setX(webViewRect.x() + inval.x());
1606 finalInval.setY(webViewRect.y() + titlebarHeight + inval.y());
1607 finalInval.setWidth(inval.width());
1608 finalInval.setHeight(inval.height());
1610 info->dirtyLeft = finalInval.x();
1611 info->dirtyTop = finalInval.y();
1612 info->dirtyRight = finalInval.maxX();
1613 info->dirtyBottom = finalInval.maxY();
1615 // return 1 if invalidation needed, 0 otherwise
1616 return retVal ? 1 : 0;
1618 void updateRect(WebCore::IntRect& _viewRect) {
1619 viewRect = _viewRect;
1621 void updateViewRect(WebCore::IntRect& _viewRect) {
1622 webViewRect = _viewRect;
1625 WebView* wvInstance;
1626 bool (WebView::*funcPtr)(WebCore::IntRect&, WebCore::IntRect*,
1627 WebCore::IntRect&, int, WebCore::IntRect&, float, int);
1628 WebCore::IntRect viewRect;
1629 WebCore::IntRect webViewRect;
1634 static jobject createJavaRect(JNIEnv* env, int x, int y, int right, int bottom)
1636 jclass rectClass = env->FindClass("android/graphics/Rect");
1637 jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
1638 jobject rect = env->NewObject(rectClass, init, x, y, right, bottom);
1639 env->DeleteLocalRef(rectClass);
1644 * Native JNI methods
1646 static int nativeCacheHitFramePointer(JNIEnv *env, jobject obj)
1648 return reinterpret_cast<int>(GET_NATIVE_VIEW(env, obj)
1649 ->m_cacheHitFrame->framePointer());
1652 static jobject nativeCacheHitNodeBounds(JNIEnv *env, jobject obj)
1654 WebCore::IntRect bounds = GET_NATIVE_VIEW(env, obj)
1655 ->m_cacheHitNode->originalAbsoluteBounds();
1656 return createJavaRect(env, bounds.x(), bounds.y(),
1657 bounds.maxX(), bounds.maxY());
1660 static int nativeCacheHitNodePointer(JNIEnv *env, jobject obj)
1662 return reinterpret_cast<int>(GET_NATIVE_VIEW(env, obj)
1663 ->m_cacheHitNode->nodePointer());
1666 static bool nativeCacheHitIsPlugin(JNIEnv *env, jobject obj)
1668 return GET_NATIVE_VIEW(env, obj)->m_cacheHitNode->isPlugin();
1671 static void nativeClearCursor(JNIEnv *env, jobject obj)
1673 WebView* view = GET_NATIVE_VIEW(env, obj);
1674 LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
1675 view->clearCursor();
1678 static void nativeCreate(JNIEnv *env, jobject obj, int viewImpl,
1679 jstring drawableDir, jboolean isHighEndGfx)
1681 WTF::String dir = jstringToWtfString(env, drawableDir);
1682 WebView* webview = new WebView(env, obj, viewImpl, dir, isHighEndGfx);
1683 // NEED THIS OR SOMETHING LIKE IT!
1687 static jint nativeCursorFramePointer(JNIEnv *env, jobject obj)
1689 WebView* view = GET_NATIVE_VIEW(env, obj);
1690 CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1693 const CachedFrame* frame = 0;
1694 (void) root->currentCursor(&frame);
1695 return reinterpret_cast<int>(frame ? frame->framePointer() : 0);
1698 static const CachedNode* getCursorNode(JNIEnv *env, jobject obj)
1700 WebView* view = GET_NATIVE_VIEW(env, obj);
1701 CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1702 return root ? root->currentCursor() : 0;
1705 static const CachedNode* getCursorNode(JNIEnv *env, jobject obj,
1706 const CachedFrame** frame)
1708 WebView* view = GET_NATIVE_VIEW(env, obj);
1709 CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1710 return root ? root->currentCursor(frame) : 0;
1713 static const CachedNode* getFocusCandidate(JNIEnv *env, jobject obj,
1714 const CachedFrame** frame)
1716 WebView* view = GET_NATIVE_VIEW(env, obj);
1717 CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1720 const CachedNode* cursor = root->currentCursor(frame);
1721 if (cursor && cursor->wantsKeyEvents())
1723 return root->currentFocus(frame);
1726 static bool focusCandidateHasNextTextfield(JNIEnv *env, jobject obj)
1728 WebView* view = GET_NATIVE_VIEW(env, obj);
1729 CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1732 const CachedNode* cursor = root->currentCursor();
1733 if (!cursor || !cursor->isTextInput())
1734 cursor = root->currentFocus();
1735 if (!cursor || !cursor->isTextInput()) return false;
1736 return root->nextTextField(cursor, 0);
1739 static const CachedNode* getFocusNode(JNIEnv *env, jobject obj)
1741 WebView* view = GET_NATIVE_VIEW(env, obj);
1742 CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1743 return root ? root->currentFocus() : 0;
1746 static const CachedNode* getFocusNode(JNIEnv *env, jobject obj,
1747 const CachedFrame** frame)
1749 WebView* view = GET_NATIVE_VIEW(env, obj);
1750 CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1751 return root ? root->currentFocus(frame) : 0;
1754 static const CachedInput* getInputCandidate(JNIEnv *env, jobject obj)
1756 WebView* view = GET_NATIVE_VIEW(env, obj);
1757 CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1760 const CachedFrame* frame;
1761 const CachedNode* cursor = root->currentCursor(&frame);
1762 if (!cursor || !cursor->wantsKeyEvents())
1763 cursor = root->currentFocus(&frame);
1764 return cursor ? frame->textInput(cursor) : 0;
1767 static jboolean nativePageShouldHandleShiftAndArrows(JNIEnv *env, jobject obj)
1769 const CachedNode* focus = getFocusNode(env, obj);
1770 if (!focus) return false;
1771 // Plugins handle shift and arrows whether or not they have focus.
1772 if (focus->isPlugin()) return true;
1773 const CachedNode* cursor = getCursorNode(env, obj);
1774 // ContentEditable nodes should only receive shift and arrows if they have
1775 // both the cursor and the focus.
1776 return cursor && cursor->nodePointer() == focus->nodePointer()
1777 && cursor->isContentEditable();
1780 static jobject nativeCursorNodeBounds(JNIEnv *env, jobject obj)
1782 const CachedFrame* frame;
1783 const CachedNode* node = getCursorNode(env, obj, &frame);
1784 WebCore::IntRect bounds = node ? node->bounds(frame)
1785 : WebCore::IntRect(0, 0, 0, 0);
1786 return createJavaRect(env, bounds.x(), bounds.y(),
1787 bounds.maxX(), bounds.maxY());
1790 static jint nativeCursorNodePointer(JNIEnv *env, jobject obj)
1792 const CachedNode* node = getCursorNode(env, obj);
1793 return reinterpret_cast<int>(node ? node->nodePointer() : 0);
1796 static jobject nativeCursorPosition(JNIEnv *env, jobject obj)
1798 WebView* view = GET_NATIVE_VIEW(env, obj);
1799 const CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1800 WebCore::IntPoint pos = WebCore::IntPoint(0, 0);
1802 root->getSimulatedMousePosition(&pos);
1803 jclass pointClass = env->FindClass("android/graphics/Point");
1804 jmethodID init = env->GetMethodID(pointClass, "<init>", "(II)V");
1805 jobject point = env->NewObject(pointClass, init, pos.x(), pos.y());
1806 env->DeleteLocalRef(pointClass);
1810 static WebCore::IntRect jrect_to_webrect(JNIEnv* env, jobject obj)
1814 GraphicsJNI::get_jrect(env, obj, &L, &T, &R, &B);
1815 return WebCore::IntRect(L, T, R - L, B - T);
1817 return WebCore::IntRect();
1820 static SkRect jrectf_to_rect(JNIEnv* env, jobject obj)
1822 SkRect rect = SkRect::MakeEmpty();
1824 GraphicsJNI::jrectf_to_rect(env, obj, &rect);
1828 static bool nativeCursorIntersects(JNIEnv *env, jobject obj, jobject visRect)
1830 const CachedFrame* frame;
1831 const CachedNode* node = getCursorNode(env, obj, &frame);
1832 return node ? node->bounds(frame).intersects(
1833 jrect_to_webrect(env, visRect)) : false;
1836 static bool nativeCursorIsAnchor(JNIEnv *env, jobject obj)
1838 const CachedNode* node = getCursorNode(env, obj);
1839 return node ? node->isAnchor() : false;
1842 static bool nativeCursorIsTextInput(JNIEnv *env, jobject obj)
1844 const CachedNode* node = getCursorNode(env, obj);
1845 return node ? node->isTextInput() : false;
1848 static jobject nativeCursorText(JNIEnv *env, jobject obj)
1850 const CachedNode* node = getCursorNode(env, obj);
1853 WTF::String value = node->getExport();
1854 return wtfStringToJstring(env, value);
1857 static void nativeDebugDump(JNIEnv *env, jobject obj)
1860 WebView* view = GET_NATIVE_VIEW(env, obj);
1861 LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
1866 static jint nativeDraw(JNIEnv *env, jobject obj, jobject canv,
1867 jobject visible, jint color,
1868 jint extras, jboolean split) {
1869 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv);
1870 WebView* webView = GET_NATIVE_VIEW(env, obj);
1871 SkRect visibleRect = jrectf_to_rect(env, visible);
1872 webView->setVisibleRect(visibleRect);
1873 PictureSet* pictureSet = webView->draw(canvas, color, extras, split);
1874 return reinterpret_cast<jint>(pictureSet);
1877 static jint nativeGetDrawGLFunction(JNIEnv *env, jobject obj, jint nativeView,
1878 jobject jrect, jobject jviewrect,
1879 jobject jvisiblerect,
1880 jfloat scale, jint extras) {
1881 WebCore::IntRect viewRect = jrect_to_webrect(env, jrect);
1882 WebView *wvInstance = (WebView*) nativeView;
1883 SkRect visibleRect = jrectf_to_rect(env, jvisiblerect);
1884 wvInstance->setVisibleRect(visibleRect);
1886 GLDrawFunctor* functor = new GLDrawFunctor(wvInstance,
1887 &android::WebView::drawGL, viewRect, scale, extras);
1888 wvInstance->setFunctor((Functor*) functor);
1890 WebCore::IntRect webViewRect = jrect_to_webrect(env, jviewrect);
1891 functor->updateViewRect(webViewRect);
1893 return (jint)functor;
1896 static void nativeUpdateDrawGLFunction(JNIEnv *env, jobject obj, jobject jrect,
1897 jobject jviewrect, jobject jvisiblerect) {
1898 WebView *wvInstance = GET_NATIVE_VIEW(env, obj);
1900 GLDrawFunctor* functor = (GLDrawFunctor*) wvInstance->getFunctor();
1902 WebCore::IntRect viewRect = jrect_to_webrect(env, jrect);
1903 functor->updateRect(viewRect);
1905 SkRect visibleRect = jrectf_to_rect(env, jvisiblerect);
1906 wvInstance->setVisibleRect(visibleRect);
1908 WebCore::IntRect webViewRect = jrect_to_webrect(env, jviewrect);
1909 functor->updateViewRect(webViewRect);
1914 static bool nativeEvaluateLayersAnimations(JNIEnv *env, jobject obj, jint nativeView)
1916 // only call in software rendering, initialize and evaluate animations
1917 #if USE(ACCELERATED_COMPOSITING)
1918 LayerAndroid* root = ((WebView*)nativeView)->compositeRoot();
1920 root->initAnimations();
1921 return root->evaluateAnimations();
1927 static void nativeSetBaseLayer(JNIEnv *env, jobject obj, jint layer, jobject inval,
1928 jboolean showVisualIndicator,
1929 jboolean isPictureAfterFirstLayout,
1930 jboolean registerPageSwapCallback)
1932 BaseLayerAndroid* layerImpl = reinterpret_cast<BaseLayerAndroid*>(layer);
1933 SkRegion invalRegion;
1935 invalRegion = *GraphicsJNI::getNativeRegion(env, inval);
1936 GET_NATIVE_VIEW(env, obj)->setBaseLayer(layerImpl, invalRegion, showVisualIndicator,
1937 isPictureAfterFirstLayout,
1938 registerPageSwapCallback);
1941 static void nativeGetTextSelectionRegion(JNIEnv *env, jobject obj, jint view,
1946 SkRegion* nregion = GraphicsJNI::getNativeRegion(env, region);
1947 ((WebView*)view)->getTextSelectionRegion(nregion);
1950 static void nativeGetSelectionHandles(JNIEnv *env, jobject obj, jint view,
1954 ((WebView*)view)->getTextSelectionHandles(handles);
1955 env->SetIntArrayRegion(arr, 0, 4, handles);
1956 checkException(env);
1959 static BaseLayerAndroid* nativeGetBaseLayer(JNIEnv *env, jobject obj)
1961 return GET_NATIVE_VIEW(env, obj)->getBaseLayer();
1964 static void nativeReplaceBaseContent(JNIEnv *env, jobject obj, jint content)
1966 PictureSet* set = reinterpret_cast<PictureSet*>(content);
1967 GET_NATIVE_VIEW(env, obj)->replaceBaseContent(set);
1970 static void nativeCopyBaseContentToPicture(JNIEnv *env, jobject obj, jobject pict)
1972 SkPicture* picture = GraphicsJNI::getNativePicture(env, pict);
1973 GET_NATIVE_VIEW(env, obj)->copyBaseContentToPicture(picture);
1976 static bool nativeHasContent(JNIEnv *env, jobject obj)
1978 return GET_NATIVE_VIEW(env, obj)->hasContent();
1981 static jobject nativeImageURI(JNIEnv *env, jobject obj, jint x, jint y)
1983 WebView* view = GET_NATIVE_VIEW(env, obj);
1984 LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
1985 WTF::String uri = view->imageURI(x, y);
1986 return wtfStringToJstring(env, uri);
1989 static jint nativeFocusCandidateFramePointer(JNIEnv *env, jobject obj)
1991 WebView* view = GET_NATIVE_VIEW(env, obj);
1992 CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
1995 const CachedFrame* frame = 0;
1996 const CachedNode* cursor = root->currentCursor(&frame);
1997 if (!cursor || !cursor->wantsKeyEvents())
1998 (void) root->currentFocus(&frame);
1999 return reinterpret_cast<int>(frame ? frame->framePointer() : 0);
2002 static bool nativeFocusCandidateIsPassword(JNIEnv *env, jobject obj)
2004 const CachedInput* input = getInputCandidate(env, obj);
2005 return input && input->getType() == CachedInput::PASSWORD;
2008 static bool nativeFocusCandidateIsRtlText(JNIEnv *env, jobject obj)
2010 const CachedInput* input = getInputCandidate(env, obj);
2011 return input ? input->isRtlText() : false;
2014 static bool nativeFocusCandidateIsTextInput(JNIEnv *env, jobject obj)
2016 const CachedNode* node = getFocusCandidate(env, obj, 0);
2017 return node ? node->isTextInput() : false;
2020 static jint nativeFocusCandidateMaxLength(JNIEnv *env, jobject obj)
2022 const CachedInput* input = getInputCandidate(env, obj);
2023 return input ? input->maxLength() : false;
2026 static jint nativeFocusCandidateIsAutoComplete(JNIEnv *env, jobject obj)
2028 const CachedInput* input = getInputCandidate(env, obj);
2029 return input ? input->autoComplete() : false;
2032 static jobject nativeFocusCandidateName(JNIEnv *env, jobject obj)
2034 const CachedInput* input = getInputCandidate(env, obj);
2037 const WTF::String& name = input->name();
2038 return wtfStringToJstring(env, name);
2041 static jobject nativeFocusCandidateNodeBounds(JNIEnv *env, jobject obj)
2043 const CachedFrame* frame;
2044 const CachedNode* node = getFocusCandidate(env, obj, &frame);
2045 WebCore::IntRect bounds = node ? node->originalAbsoluteBounds()
2046 : WebCore::IntRect(0, 0, 0, 0);
2047 // Inset the rect by 1 unit, so that the focus candidate's border can still
2048 // be seen behind it.
2049 return createJavaRect(env, bounds.x(), bounds.y(),
2050 bounds.maxX(), bounds.maxY());
2053 static jobject nativeFocusCandidatePaddingRect(JNIEnv *env, jobject obj)
2055 const CachedInput* input = getInputCandidate(env, obj);
2058 // Note that the Java Rect is being used to pass four integers, rather than
2059 // being used as an actual rectangle.
2060 return createJavaRect(env, input->paddingLeft(), input->paddingTop(),
2061 input->paddingRight(), input->paddingBottom());
2064 static jint nativeFocusCandidatePointer(JNIEnv *env, jobject obj)
2066 const CachedNode* node = getFocusCandidate(env, obj, 0);
2067 return reinterpret_cast<int>(node ? node->nodePointer() : 0);
2070 static jint nativeFocusCandidateIsSpellcheck(JNIEnv *env, jobject obj)
2072 const CachedInput* input = getInputCandidate(env, obj);
2073 return input ? input->spellcheck() : false;
2076 static jobject nativeFocusCandidateText(JNIEnv *env, jobject obj)
2078 const CachedNode* node = getFocusCandidate(env, obj, 0);
2081 WTF::String value = node->getExport();
2082 return wtfStringToJstring(env, value);
2085 static int nativeFocusCandidateLineHeight(JNIEnv *env, jobject obj)
2087 const CachedInput* input = getInputCandidate(env, obj);
2088 return input ? input->lineHeight() : 0;
2091 static jfloat nativeFocusCandidateTextSize(JNIEnv *env, jobject obj)
2093 const CachedInput* input = getInputCandidate(env, obj);
2094 return input ? input->textSize() : 0.f;
2097 static int nativeFocusCandidateType(JNIEnv *env, jobject obj)
2099 const CachedInput* input = getInputCandidate(env, obj);
2101 return CachedInput::NONE;
2103 if (input->isTextArea())
2104 return CachedInput::TEXT_AREA;
2106 return input->getType();
2109 static int nativeFocusCandidateLayerId(JNIEnv *env, jobject obj)
2111 const CachedFrame* frame;
2112 const CachedNode* node = getFocusNode(env, obj, &frame);
2115 return frame->layer(node)->uniqueId();
2118 static bool nativeFocusIsPlugin(JNIEnv *env, jobject obj)
2120 const CachedNode* node = getFocusNode(env, obj);
2121 return node ? node->isPlugin() : false;
2124 static jobject nativeFocusNodeBounds(JNIEnv *env, jobject obj)
2126 const CachedFrame* frame;
2127 const CachedNode* node = getFocusNode(env, obj, &frame);
2128 WebCore::IntRect bounds = node ? node->bounds(frame)
2129 : WebCore::IntRect(0, 0, 0, 0);
2130 return createJavaRect(env, bounds.x(), bounds.y(),
2131 bounds.maxX(), bounds.maxY());
2134 static jint nativeFocusNodePointer(JNIEnv *env, jobject obj)
2136 const CachedNode* node = getFocusNode(env, obj);
2137 return node ? reinterpret_cast<int>(node->nodePointer()) : 0;
2140 static bool nativeCursorWantsKeyEvents(JNIEnv* env, jobject jwebview) {
2141 WebView* view = GET_NATIVE_VIEW(env, jwebview);
2142 LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
2143 return view->cursorWantsKeyEvents();
2146 static void nativeHideCursor(JNIEnv *env, jobject obj)
2148 WebView* view = GET_NATIVE_VIEW(env, obj);
2149 LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
2153 static void nativeInstrumentReport(JNIEnv *env, jobject obj)
2155 #ifdef ANDROID_INSTRUMENT
2156 TimeCounter::reportNow();
2160 static void nativeSelectBestAt(JNIEnv *env, jobject obj, jobject jrect)
2162 WebView* view = GET_NATIVE_VIEW(env, obj);
2163 LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
2164 WebCore::IntRect rect = jrect_to_webrect(env, jrect);
2165 view->selectBestAt(rect);
2168 static void nativeSelectAt(JNIEnv *env, jobject obj, jint x, jint y)
2170 WebView* view = GET_NATIVE_VIEW(env, obj);
2171 LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
2172 WebCore::IntRect rect = IntRect(x, y , 1, 1);
2173 view->selectBestAt(rect);
2174 if (view->hasCursorNode())
2175 view->showCursorUntimed();
2178 static jobject nativeLayerBounds(JNIEnv* env, jobject obj, jint jlayer)
2181 #if USE(ACCELERATED_COMPOSITING)
2182 LayerAndroid* layer = (LayerAndroid*) jlayer;
2183 r = layer->bounds();
2189 jclass rectClass = env->FindClass("android/graphics/Rect");
2190 jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
2191 jobject rect = env->NewObject(rectClass, init, irect.fLeft, irect.fTop,
2192 irect.fRight, irect.fBottom);
2193 env->DeleteLocalRef(rectClass);
2197 static jobject nativeSubtractLayers(JNIEnv* env, jobject obj, jobject jrect)
2199 SkIRect irect = jrect_to_webrect(env, jrect);
2200 #if USE(ACCELERATED_COMPOSITING)
2201 LayerAndroid* root = GET_NATIVE_VIEW(env, obj)->compositeRoot();
2205 rect = root->subtractLayers(rect);
2209 jclass rectClass = env->FindClass("android/graphics/Rect");
2210 jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
2211 jobject rect = env->NewObject(rectClass, init, irect.fLeft, irect.fTop,
2212 irect.fRight, irect.fBottom);
2213 env->DeleteLocalRef(rectClass);
2217 static jint nativeTextGeneration(JNIEnv *env, jobject obj)
2219 WebView* view = GET_NATIVE_VIEW(env, obj);
2220 CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
2221 return root ? root->textGeneration() : 0;
2224 static bool nativePointInNavCache(JNIEnv *env, jobject obj,
2225 int x, int y, int slop)
2227 return GET_NATIVE_VIEW(env, obj)->pointInNavCache(x, y, slop);
2230 static bool nativeMotionUp(JNIEnv *env, jobject obj,
2231 int x, int y, int slop)
2233 WebView* view = GET_NATIVE_VIEW(env, obj);
2234 LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
2235 return view->motionUp(x, y, slop);
2238 static bool nativeHasCursorNode(JNIEnv *env, jobject obj)
2240 return GET_NATIVE_VIEW(env, obj)->hasCursorNode();
2243 static bool nativeHasFocusNode(JNIEnv *env, jobject obj)
2245 return GET_NATIVE_VIEW(env, obj)->hasFocusNode();
2248 static bool nativeMoveCursor(JNIEnv *env, jobject obj,
2249 int key, int count, bool ignoreScroll)
2251 WebView* view = GET_NATIVE_VIEW(env, obj);
2252 DBG_NAV_LOGD("env=%p obj=%p view=%p", env, obj, view);
2253 LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
2254 return view->moveCursor(key, count, ignoreScroll);
2257 static void nativeSetFindIsUp(JNIEnv *env, jobject obj, jboolean isUp)
2259 WebView* view = GET_NATIVE_VIEW(env, obj);
2260 LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
2261 view->setFindIsUp(isUp);
2264 static void nativeSetFindIsEmpty(JNIEnv *env, jobject obj)
2266 GET_NATIVE_VIEW(env, obj)->setFindIsEmpty();
2269 static void nativeShowCursorTimed(JNIEnv *env, jobject obj)
2271 GET_NATIVE_VIEW(env, obj)->showCursorTimed();
2274 static void nativeSetHeightCanMeasure(JNIEnv *env, jobject obj, bool measure)
2276 WebView* view = GET_NATIVE_VIEW(env, obj);
2277 LOG_ASSERT(view, "view not set in nativeSetHeightCanMeasure");
2278 view->setHeightCanMeasure(measure);
2281 static jobject nativeGetCursorRingBounds(JNIEnv *env, jobject obj)
2283 WebView* view = GET_NATIVE_VIEW(env, obj);
2284 LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
2285 jclass rectClass = env->FindClass("android/graphics/Rect");
2286 LOG_ASSERT(rectClass, "Could not find Rect class!");
2287 jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V");
2288 LOG_ASSERT(init, "Could not find constructor for Rect");
2289 WebCore::IntRect webRect;
2290 view->cursorRingBounds(&webRect);
2291 jobject rect = env->NewObject(rectClass, init, webRect.x(),
2292 webRect.y(), webRect.maxX(), webRect.maxY());
2293 env->DeleteLocalRef(rectClass);
2297 static int nativeFindAll(JNIEnv *env, jobject obj, jstring findLower,
2298 jstring findUpper, jboolean sameAsLastSearch)
2300 // If one or the other is null, do not search.
2301 if (!(findLower && findUpper))
2303 // Obtain the characters for both the lower case string and the upper case
2304 // string representing the same word.
2305 const jchar* findLowerChars = env->GetStringChars(findLower, 0);
2306 const jchar* findUpperChars = env->GetStringChars(findUpper, 0);
2307 // If one or the other is null, do not search.
2308 if (!(findLowerChars && findUpperChars)) {
2310 env->ReleaseStringChars(findLower, findLowerChars);
2312 env->ReleaseStringChars(findUpper, findUpperChars);
2313 checkException(env);
2316 WebView* view = GET_NATIVE_VIEW(env, obj);
2317 LOG_ASSERT(view, "view not set in nativeFindAll");
2318 CachedRoot* root = view->getFrameCache(WebView::AllowNewer);
2320 env->ReleaseStringChars(findLower, findLowerChars);
2321 env->ReleaseStringChars(findUpper, findUpperChars);
2322 checkException(env);
2325 int length = env->GetStringLength(findLower);
2326 // If the lengths of the strings do not match, then they are not the same
2327 // word, so do not search.
2328 if (!length || env->GetStringLength(findUpper) != length) {
2329 env->ReleaseStringChars(findLower, findLowerChars);
2330 env->ReleaseStringChars(findUpper, findUpperChars);
2331 checkException(env);
2334 int width = root->documentWidth();
2335 int height = root->documentHeight();
2336 // Create a FindCanvas, which allows us to fake draw into it so we can
2337 // figure out where our search string is rendered (and how many times).
2338 FindCanvas canvas(width, height, (const UChar*) findLowerChars,
2339 (const UChar*) findUpperChars, length << 1);
2341 bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
2342 canvas.setBitmapDevice(bitmap);
2344 WTF::Vector<MatchInfo>* matches = canvas.detachMatches();
2345 // With setMatches, the WebView takes ownership of matches
2346 view->setMatches(matches, sameAsLastSearch);
2348 env->ReleaseStringChars(findLower, findLowerChars);
2349 env->ReleaseStringChars(findUpper, findUpperChars);
2350 checkException(env);
2351 return canvas.found();
2354 static void nativeFindNext(JNIEnv *env, jobject obj, bool forward)
2356 WebView* view = GET_NATIVE_VIEW(env, obj);
2357 LOG_ASSERT(view, "view not set in nativeFindNext");
2358 view->findNext(forward);
2361 static int nativeFindIndex(JNIEnv *env, jobject obj)
2363 WebView* view = GET_NATIVE_VIEW(env, obj);
2364 LOG_ASSERT(view, "view not set in nativeFindIndex");
2365 return view->currentMatchIndex();
2368 static void nativeUpdateCachedTextfield(JNIEnv *env, jobject obj, jstring updatedText, jint generation)
2370 WebView* view = GET_NATIVE_VIEW(env, obj);
2371 LOG_ASSERT(view, "view not set in nativeUpdateCachedTextfield");
2372 CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
2375 const CachedNode* cachedFocusNode = root->currentFocus();
2376 if (!cachedFocusNode || !cachedFocusNode->isTextInput())
2378 WTF::String webcoreString = jstringToWtfString(env, updatedText);
2379 (const_cast<CachedNode*>(cachedFocusNode))->setExport(webcoreString);
2380 root->setTextGeneration(generation);
2381 checkException(env);
2384 static jint nativeGetBlockLeftEdge(JNIEnv *env, jobject obj, jint x, jint y,
2387 WebView* view = GET_NATIVE_VIEW(env, obj);
2388 LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
2391 return view->getBlockLeftEdge(x, y, scale);
2394 static void nativeDestroy(JNIEnv *env, jobject obj)
2396 WebView* view = GET_NATIVE_VIEW(env, obj);
2397 LOGD("nativeDestroy view: %p", view);
2398 LOG_ASSERT(view, "view not set in nativeDestroy");
2402 static void nativeStopGL(JNIEnv *env, jobject obj)
2404 GET_NATIVE_VIEW(env, obj)->stopGL();
2407 static bool nativeMoveCursorToNextTextInput(JNIEnv *env, jobject obj)
2409 WebView* view = GET_NATIVE_VIEW(env, obj);
2410 CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
2413 const CachedNode* current = root->currentCursor();
2414 if (!current || !current->isTextInput())
2415 current = root->currentFocus();
2416 if (!current || !current->isTextInput())
2418 const CachedFrame* frame;
2419 const CachedNode* next = root->nextTextField(current, &frame);
2422 const WebCore::IntRect& bounds = next->bounds(frame);
2423 root->rootHistory()->setMouseBounds(bounds);
2424 view->getWebViewCore()->updateCursorBounds(root, frame, next);
2425 view->showCursorUntimed();
2426 root->setCursor(const_cast<CachedFrame*>(frame),
2427 const_cast<CachedNode*>(next));
2428 view->sendMoveFocus(static_cast<WebCore::Frame*>(frame->framePointer()),
2429 static_cast<WebCore::Node*>(next->nodePointer()));
2430 if (!next->isInLayer())
2431 view->scrollRectOnScreen(bounds);
2432 view->getWebViewCore()->m_moveGeneration++;
2436 static int nativeMoveGeneration(JNIEnv *env, jobject obj)
2438 WebView* view = GET_NATIVE_VIEW(env, obj);
2441 return view->moveGeneration();
2444 static void nativeMoveSelection(JNIEnv *env, jobject obj, int x, int y)
2446 GET_NATIVE_VIEW(env, obj)->moveSelection(x, y);
2449 static void nativeResetSelection(JNIEnv *env, jobject obj)
2451 return GET_NATIVE_VIEW(env, obj)->resetSelection();
2454 static jobject nativeSelectableText(JNIEnv* env, jobject obj)
2456 IntPoint pos = GET_NATIVE_VIEW(env, obj)->selectableText();
2457 jclass pointClass = env->FindClass("android/graphics/Point");
2458 jmethodID init = env->GetMethodID(pointClass, "<init>", "(II)V");
2459 jobject point = env->NewObject(pointClass, init, pos.x(), pos.y());
2460 env->DeleteLocalRef(pointClass);
2464 static void nativeSelectAll(JNIEnv* env, jobject obj)
2466 GET_NATIVE_VIEW(env, obj)->selectAll();
2469 static void nativeSetExtendSelection(JNIEnv *env, jobject obj)
2471 GET_NATIVE_VIEW(env, obj)->setExtendSelection();
2474 static jboolean nativeStartSelection(JNIEnv *env, jobject obj, int x, int y)
2476 return GET_NATIVE_VIEW(env, obj)->startSelection(x, y);
2479 static jboolean nativeWordSelection(JNIEnv *env, jobject obj, int x, int y)
2481 return GET_NATIVE_VIEW(env, obj)->wordSelection(x, y);
2484 static void nativeExtendSelection(JNIEnv *env, jobject obj, int x, int y)
2486 GET_NATIVE_VIEW(env, obj)->extendSelection(x, y);
2489 static jobject nativeGetSelection(JNIEnv *env, jobject obj)
2491 WebView* view = GET_NATIVE_VIEW(env, obj);
2492 LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
2493 String selection = view->getSelection();
2494 return wtfStringToJstring(env, selection);
2497 static jboolean nativeHitSelection(JNIEnv *env, jobject obj, int x, int y)
2499 return GET_NATIVE_VIEW(env, obj)->hitSelection(x, y);
2502 static jint nativeSelectionX(JNIEnv *env, jobject obj)
2504 return GET_NATIVE_VIEW(env, obj)->selectionX();
2507 static jint nativeSelectionY(JNIEnv *env, jobject obj)
2509 return GET_NATIVE_VIEW(env, obj)->selectionY();
2512 static void nativeSetSelectionPointer(JNIEnv *env, jobject obj, jint nativeView,
2513 jboolean set, jfloat scale, jint x, jint y)
2515 ((WebView*)nativeView)->setSelectionPointer(set, scale, x, y);
2518 static void nativeRegisterPageSwapCallback(JNIEnv *env, jobject obj)
2520 GET_NATIVE_VIEW(env, obj)->registerPageSwapCallback();
2523 static void nativeTileProfilingStart(JNIEnv *env, jobject obj)
2525 TilesManager::instance()->getProfiler()->start();
2528 static float nativeTileProfilingStop(JNIEnv *env, jobject obj)
2530 return TilesManager::instance()->getProfiler()->stop();
2533 static void nativeTileProfilingClear(JNIEnv *env, jobject obj)
2535 TilesManager::instance()->getProfiler()->clear();
2538 static int nativeTileProfilingNumFrames(JNIEnv *env, jobject obj)
2540 return TilesManager::instance()->getProfiler()->numFrames();
2543 static int nativeTileProfilingNumTilesInFrame(JNIEnv *env, jobject obj, int frame)
2545 return TilesManager::instance()->getProfiler()->numTilesInFrame(frame);
2548 static int nativeTileProfilingGetInt(JNIEnv *env, jobject obj, int frame, int tile, jstring jkey)
2550 WTF::String key = jstringToWtfString(env, jkey);
2551 TileProfileRecord* record = TilesManager::instance()->getProfiler()->getTile(frame, tile);
2554 return record->left;
2558 return record->right;
2559 if (key == "bottom")
2560 return record->bottom;
2562 return record->level;
2563 if (key == "isReady")
2564 return record->isReady ? 1 : 0;
2568 static float nativeTileProfilingGetFloat(JNIEnv *env, jobject obj, int frame, int tile, jstring jkey)
2570 TileProfileRecord* record = TilesManager::instance()->getProfiler()->getTile(frame, tile);
2571 return record->scale;
2574 #ifdef ANDROID_DUMP_DISPLAY_TREE
2575 static void dumpToFile(const char text[], void* file) {
2576 fwrite(text, 1, strlen(text), reinterpret_cast<FILE*>(file));
2577 fwrite("\n", 1, 1, reinterpret_cast<FILE*>(file));
2581 static bool nativeSetProperty(JNIEnv *env, jobject obj, jstring jkey, jstring jvalue)
2583 WTF::String key = jstringToWtfString(env, jkey);
2584 WTF::String value = jstringToWtfString(env, jvalue);
2585 if (key == "inverted") {
2586 if (value == "true")
2587 TilesManager::instance()->setInvertedScreen(true);
2589 TilesManager::instance()->setInvertedScreen(false);
2592 else if (key == "inverted_contrast") {
2593 float contrast = value.toFloat();
2594 TilesManager::instance()->setInvertedScreenContrast(contrast);
2597 else if (key == "enable_cpu_upload_path") {
2598 TilesManager::instance()->transferQueue()->setTextureUploadType(
2599 value == "true" ? CpuUpload : GpuUpload);
2602 else if (key == "use_minimal_memory") {
2603 TilesManager::instance()->setUseMinimalMemory(value == "true");
2609 static jstring nativeGetProperty(JNIEnv *env, jobject obj, jstring key)
2614 static void nativeOnTrimMemory(JNIEnv *env, jobject obj, jint level)
2616 if (TilesManager::hardwareAccelerationEnabled()) {
2617 bool freeAllTextures = (level > TRIM_MEMORY_UI_HIDDEN);
2618 TilesManager::instance()->deallocateTextures(freeAllTextures);
2622 static void nativeDumpDisplayTree(JNIEnv* env, jobject jwebview, jstring jurl)
2624 #ifdef ANDROID_DUMP_DISPLAY_TREE
2625 WebView* view = GET_NATIVE_VIEW(env, jwebview);
2626 LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
2628 if (view && view->getWebViewCore()) {
2629 FILE* file = fopen(DISPLAY_TREE_LOG_FILE, "w");
2631 SkFormatDumper dumper(dumpToFile, file);
2634 const char* str = env->GetStringUTFChars(jurl, 0);
2635 SkDebugf("Dumping %s to %s\n", str, DISPLAY_TREE_LOG_FILE);
2636 dumpToFile(str, file);
2637 env->ReleaseStringUTFChars(jurl, str);
2639 // now dump the display tree
2640 SkDumpCanvas canvas(&dumper);
2641 // this will playback the picture into the canvas, which will
2642 // spew its contents to the dumper
2643 view->draw(&canvas, 0, 0, false);
2644 // we're done with the file now
2645 fwrite("\n", 1, 1, file);
2648 #if USE(ACCELERATED_COMPOSITING)
2649 const LayerAndroid* rootLayer = view->compositeRoot();
2651 FILE* file = fopen(LAYERS_TREE_LOG_FILE,"w");
2653 rootLayer->dumpLayers(file, 0);
2662 static int nativeScrollableLayer(JNIEnv* env, jobject jwebview, jint x, jint y,
2663 jobject rect, jobject bounds)
2665 WebView* view = GET_NATIVE_VIEW(env, jwebview);
2666 LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
2667 SkIRect nativeRect, nativeBounds;
2668 int id = view->scrollableLayer(x, y, &nativeRect, &nativeBounds);
2670 GraphicsJNI::irect_to_jrect(nativeRect, env, rect);
2672 GraphicsJNI::irect_to_jrect(nativeBounds, env, bounds);
2676 static bool nativeScrollLayer(JNIEnv* env, jobject obj, jint layerId, jint x,
2679 #if ENABLE(ANDROID_OVERFLOW_SCROLL)
2680 WebView* view = GET_NATIVE_VIEW(env, obj);
2681 view->scrollLayer(layerId, x, y);
2683 //TODO: the below only needed for the SW rendering path
2684 LayerAndroid* root = view->compositeRoot();
2687 LayerAndroid* layer = root->findById(layerId);
2688 if (!layer || !layer->contentIsScrollable())
2690 return static_cast<ScrollableLayerAndroid*>(layer)->scrollTo(x, y);
2695 static void nativeSetIsScrolling(JNIEnv* env, jobject jwebview, jboolean isScrolling)
2697 WebView* view = GET_NATIVE_VIEW(env, jwebview);
2698 LOG_ASSERT(view, "view not set in %s", __FUNCTION__);
2699 view->setIsScrolling(isScrolling);
2702 static void nativeUseHardwareAccelSkia(JNIEnv*, jobject, jboolean enabled)
2704 BaseRenderer::setCurrentRendererType(enabled ? BaseRenderer::Ganesh : BaseRenderer::Raster);
2707 static int nativeGetBackgroundColor(JNIEnv* env, jobject obj)
2709 WebView* view = GET_NATIVE_VIEW(env, obj);
2710 BaseLayerAndroid* baseLayer = view->getBaseLayer();
2712 WebCore::Color color = baseLayer->getBackgroundColor();
2713 if (color.isValid())
2714 return SkColorSetARGB(color.alpha(), color.red(),
2715 color.green(), color.blue());
2717 return SK_ColorWHITE;
2720 static void nativeSetPauseDrawing(JNIEnv *env, jobject obj, jint nativeView,
2723 ((WebView*)nativeView)->m_isDrawingPaused = pause;
2729 static JNINativeMethod gJavaWebViewMethods[] = {
2730 { "nativeCacheHitFramePointer", "()I",
2731 (void*) nativeCacheHitFramePointer },
2732 { "nativeCacheHitIsPlugin", "()Z",
2733 (void*) nativeCacheHitIsPlugin },
2734 { "nativeCacheHitNodeBounds", "()Landroid/graphics/Rect;",
2735 (void*) nativeCacheHitNodeBounds },
2736 { "nativeCacheHitNodePointer", "()I",
2737 (void*) nativeCacheHitNodePointer },
2738 { "nativeClearCursor", "()V",
2739 (void*) nativeClearCursor },
2740 { "nativeCreate", "(ILjava/lang/String;Z)V",
2741 (void*) nativeCreate },
2742 { "nativeCursorFramePointer", "()I",
2743 (void*) nativeCursorFramePointer },
2744 { "nativePageShouldHandleShiftAndArrows", "()Z",
2745 (void*) nativePageShouldHandleShiftAndArrows },
2746 { "nativeCursorNodeBounds", "()Landroid/graphics/Rect;",
2747 (void*) nativeCursorNodeBounds },
2748 { "nativeCursorNodePointer", "()I",
2749 (void*) nativeCursorNodePointer },
2750 { "nativeCursorIntersects", "(Landroid/graphics/Rect;)Z",
2751 (void*) nativeCursorIntersects },
2752 { "nativeCursorIsAnchor", "()Z",
2753 (void*) nativeCursorIsAnchor },
2754 { "nativeCursorIsTextInput", "()Z",
2755 (void*) nativeCursorIsTextInput },
2756 { "nativeCursorPosition", "()Landroid/graphics/Point;",
2757 (void*) nativeCursorPosition },
2758 { "nativeCursorText", "()Ljava/lang/String;",
2759 (void*) nativeCursorText },
2760 { "nativeCursorWantsKeyEvents", "()Z",
2761 (void*)nativeCursorWantsKeyEvents },
2762 { "nativeDebugDump", "()V",
2763 (void*) nativeDebugDump },
2764 { "nativeDestroy", "()V",
2765 (void*) nativeDestroy },
2766 { "nativeDraw", "(Landroid/graphics/Canvas;Landroid/graphics/RectF;IIZ)I",
2767 (void*) nativeDraw },
2768 { "nativeGetDrawGLFunction", "(ILandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/RectF;FI)I",
2769 (void*) nativeGetDrawGLFunction },
2770 { "nativeUpdateDrawGLFunction", "(Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/RectF;)V",
2771 (void*) nativeUpdateDrawGLFunction },
2772 { "nativeDumpDisplayTree", "(Ljava/lang/String;)V",
2773 (void*) nativeDumpDisplayTree },
2774 { "nativeEvaluateLayersAnimations", "(I)Z",
2775 (void*) nativeEvaluateLayersAnimations },
2776 { "nativeExtendSelection", "(II)V",
2777 (void*) nativeExtendSelection },
2778 { "nativeFindAll", "(Ljava/lang/String;Ljava/lang/String;Z)I",
2779 (void*) nativeFindAll },
2780 { "nativeFindNext", "(Z)V",
2781 (void*) nativeFindNext },
2782 { "nativeFindIndex", "()I",
2783 (void*) nativeFindIndex},
2784 { "nativeFocusCandidateFramePointer", "()I",
2785 (void*) nativeFocusCandidateFramePointer },
2786 { "nativeFocusCandidateHasNextTextfield", "()Z",
2787 (void*) focusCandidateHasNextTextfield },
2788 { "nativeFocusCandidateIsPassword", "()Z",
2789 (void*) nativeFocusCandidateIsPassword },
2790 { "nativeFocusCandidateIsRtlText", "()Z",
2791 (void*) nativeFocusCandidateIsRtlText },
2792 { "nativeFocusCandidateIsTextInput", "()Z",
2793 (void*) nativeFocusCandidateIsTextInput },
2794 { "nativeFocusCandidateLineHeight", "()I",
2795 (void*) nativeFocusCandidateLineHeight },
2796 { "nativeFocusCandidateMaxLength", "()I",
2797 (void*) nativeFocusCandidateMaxLength },
2798 { "nativeFocusCandidateIsAutoComplete", "()Z",
2799 (void*) nativeFocusCandidateIsAutoComplete },
2800 { "nativeFocusCandidateIsSpellcheck", "()Z",
2801 (void*) nativeFocusCandidateIsSpellcheck },
2802 { "nativeFocusCandidateName", "()Ljava/lang/String;",
2803 (void*) nativeFocusCandidateName },
2804 { "nativeFocusCandidateNodeBounds", "()Landroid/graphics/Rect;",
2805 (void*) nativeFocusCandidateNodeBounds },
2806 { "nativeFocusCandidatePaddingRect", "()Landroid/graphics/Rect;",
2807 (void*) nativeFocusCandidatePaddingRect },
2808 { "nativeFocusCandidatePointer", "()I",
2809 (void*) nativeFocusCandidatePointer },
2810 { "nativeFocusCandidateText", "()Ljava/lang/String;",
2811 (void*) nativeFocusCandidateText },
2812 { "nativeFocusCandidateTextSize", "()F",
2813 (void*) nativeFocusCandidateTextSize },
2814 { "nativeFocusCandidateType", "()I",
2815 (void*) nativeFocusCandidateType },
2816 { "nativeFocusCandidateLayerId", "()I",
2817 (void*) nativeFocusCandidateLayerId },
2818 { "nativeFocusIsPlugin", "()Z",
2819 (void*) nativeFocusIsPlugin },
2820 { "nativeFocusNodeBounds", "()Landroid/graphics/Rect;",
2821 (void*) nativeFocusNodeBounds },
2822 { "nativeFocusNodePointer", "()I",
2823 (void*) nativeFocusNodePointer },
2824 { "nativeGetCursorRingBounds", "()Landroid/graphics/Rect;",
2825 (void*) nativeGetCursorRingBounds },
2826 { "nativeGetSelection", "()Ljava/lang/String;",
2827 (void*) nativeGetSelection },
2828 { "nativeHasCursorNode", "()Z",
2829 (void*) nativeHasCursorNode },
2830 { "nativeHasFocusNode", "()Z",
2831 (void*) nativeHasFocusNode },
2832 { "nativeHideCursor", "()V",
2833 (void*) nativeHideCursor },
2834 { "nativeHitSelection", "(II)Z",
2835 (void*) nativeHitSelection },
2836 { "nativeImageURI", "(II)Ljava/lang/String;",
2837 (void*) nativeImageURI },
2838 { "nativeInstrumentReport", "()V",
2839 (void*) nativeInstrumentReport },
2840 { "nativeLayerBounds", "(I)Landroid/graphics/Rect;",
2841 (void*) nativeLayerBounds },
2842 { "nativeMotionUp", "(III)Z",
2843 (void*) nativeMotionUp },
2844 { "nativeMoveCursor", "(IIZ)Z",
2845 (void*) nativeMoveCursor },
2846 { "nativeMoveCursorToNextTextInput", "()Z",
2847 (void*) nativeMoveCursorToNextTextInput },
2848 { "nativeMoveGeneration", "()I",
2849 (void*) nativeMoveGeneration },
2850 { "nativeMoveSelection", "(II)V",
2851 (void*) nativeMoveSelection },
2852 { "nativePointInNavCache", "(III)Z",
2853 (void*) nativePointInNavCache },
2854 { "nativeResetSelection", "()V",
2855 (void*) nativeResetSelection },
2856 { "nativeSelectableText", "()Landroid/graphics/Point;",
2857 (void*) nativeSelectableText },
2858 { "nativeSelectAll", "()V",
2859 (void*) nativeSelectAll },
2860 { "nativeSelectBestAt", "(Landroid/graphics/Rect;)V",
2861 (void*) nativeSelectBestAt },
2862 { "nativeSelectAt", "(II)V",
2863 (void*) nativeSelectAt },
2864 { "nativeSelectionX", "()I",
2865 (void*) nativeSelectionX },
2866 { "nativeSelectionY", "()I",
2867 (void*) nativeSelectionY },
2868 { "nativeSetExtendSelection", "()V",
2869 (void*) nativeSetExtendSelection },
2870 { "nativeSetFindIsEmpty", "()V",
2871 (void*) nativeSetFindIsEmpty },
2872 { "nativeSetFindIsUp", "(Z)V",
2873 (void*) nativeSetFindIsUp },
2874 { "nativeSetHeightCanMeasure", "(Z)V",
2875 (void*) nativeSetHeightCanMeasure },
2876 { "nativeSetBaseLayer", "(ILandroid/graphics/Region;ZZZ)V",
2877 (void*) nativeSetBaseLayer },
2878 { "nativeGetTextSelectionRegion", "(ILandroid/graphics/Region;)V",
2879 (void*) nativeGetTextSelectionRegion },
2880 { "nativeGetSelectionHandles", "(I[I)V",
2881 (void*) nativeGetSelectionHandles },
2882 { "nativeGetBaseLayer", "()I",
2883 (void*) nativeGetBaseLayer },
2884 { "nativeReplaceBaseContent", "(I)V",
2885 (void*) nativeReplaceBaseContent },
2886 { "nativeCopyBaseContentToPicture", "(Landroid/graphics/Picture;)V",
2887 (void*) nativeCopyBaseContentToPicture },
2888 { "nativeHasContent", "()Z",
2889 (void*) nativeHasContent },
2890 { "nativeSetSelectionPointer", "(IZFII)V",
2891 (void*) nativeSetSelectionPointer },
2892 { "nativeShowCursorTimed", "()V",
2893 (void*) nativeShowCursorTimed },
2894 { "nativeRegisterPageSwapCallback", "()V",
2895 (void*) nativeRegisterPageSwapCallback },
2896 { "nativeTileProfilingStart", "()V",
2897 (void*) nativeTileProfilingStart },
2898 { "nativeTileProfilingStop", "()F",
2899 (void*) nativeTileProfilingStop },
2900 { "nativeTileProfilingClear", "()V",
2901 (void*) nativeTileProfilingClear },
2902 { "nativeTileProfilingNumFrames", "()I",
2903 (void*) nativeTileProfilingNumFrames },
2904 { "nativeTileProfilingNumTilesInFrame", "(I)I",
2905 (void*) nativeTileProfilingNumTilesInFrame },
2906 { "nativeTileProfilingGetInt", "(IILjava/lang/String;)I",
2907 (void*) nativeTileProfilingGetInt },
2908 { "nativeTileProfilingGetFloat", "(IILjava/lang/String;)F",
2909 (void*) nativeTileProfilingGetFloat },
2910 { "nativeStartSelection", "(II)Z",
2911 (void*) nativeStartSelection },
2912 { "nativeStopGL", "()V",
2913 (void*) nativeStopGL },
2914 { "nativeSubtractLayers", "(Landroid/graphics/Rect;)Landroid/graphics/Rect;",
2915 (void*) nativeSubtractLayers },
2916 { "nativeTextGeneration", "()I",
2917 (void*) nativeTextGeneration },
2918 { "nativeUpdateCachedTextfield", "(Ljava/lang/String;I)V",
2919 (void*) nativeUpdateCachedTextfield },
2920 { "nativeWordSelection", "(II)Z",
2921 (void*) nativeWordSelection },
2922 { "nativeGetBlockLeftEdge", "(IIF)I",
2923 (void*) nativeGetBlockLeftEdge },
2924 { "nativeScrollableLayer", "(IILandroid/graphics/Rect;Landroid/graphics/Rect;)I",
2925 (void*) nativeScrollableLayer },
2926 { "nativeScrollLayer", "(III)Z",
2927 (void*) nativeScrollLayer },
2928 { "nativeSetIsScrolling", "(Z)V",
2929 (void*) nativeSetIsScrolling },
2930 { "nativeUseHardwareAccelSkia", "(Z)V",
2931 (void*) nativeUseHardwareAccelSkia },
2932 { "nativeGetBackgroundColor", "()I",
2933 (void*) nativeGetBackgroundColor },
2934 { "nativeSetProperty", "(Ljava/lang/String;Ljava/lang/String;)Z",
2935 (void*) nativeSetProperty },
2936 { "nativeGetProperty", "(Ljava/lang/String;)Ljava/lang/String;",
2937 (void*) nativeGetProperty },
2938 { "nativeOnTrimMemory", "(I)V",
2939 (void*) nativeOnTrimMemory },
2940 { "nativeSetPauseDrawing", "(IZ)V",
2941 (void*) nativeSetPauseDrawing },
2944 int registerWebView(JNIEnv* env)
2946 jclass clazz = env->FindClass("android/webkit/WebView");
2947 LOG_ASSERT(clazz, "Unable to find class android/webkit/WebView");
2948 gWebViewField = env->GetFieldID(clazz, "mNativeClass", "I");
2949 LOG_ASSERT(gWebViewField, "Unable to find android/webkit/WebView.mNativeClass");
2950 env->DeleteLocalRef(clazz);
2952 return jniRegisterNativeMethods(env, "android/webkit/WebView", gJavaWebViewMethods, NELEM(gJavaWebViewMethods));
2955 } // namespace android