WebView.cpp revision fa3976234409edb5477e8950204c597cf2a6dda9
1/* 2 * Copyright 2007, The Android Open Source Project 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 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. 12 * 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. 24 */ 25 26#define LOG_TAG "webviewglue" 27 28#include "config.h" 29 30#include "AndroidAnimation.h" 31#include "AndroidLog.h" 32#include "BaseLayerAndroid.h" 33#include "BaseRenderer.h" 34#include "DrawExtra.h" 35#include "Frame.h" 36#include "GLWebViewState.h" 37#include "GraphicsJNI.h" 38#include "HTMLInputElement.h" 39#include "IntPoint.h" 40#include "IntRect.h" 41#include "LayerAndroid.h" 42#include "LayerContent.h" 43#include "Node.h" 44#include "utils/Functor.h" 45#include "private/hwui/DrawGlInfo.h" 46#include "PlatformGraphicsContext.h" 47#include "PlatformString.h" 48#include "ScrollableLayerAndroid.h" 49#include "SelectText.h" 50#include "SkCanvas.h" 51#include "SkDumpCanvas.h" 52#include "SkPicture.h" 53#include "SkRect.h" 54#include "SkTime.h" 55#include "TilesManager.h" 56#include "TransferQueue.h" 57#include "WebCoreJni.h" 58#include "WebRequestContext.h" 59#include "WebViewCore.h" 60#include "android_graphics.h" 61 62#ifdef GET_NATIVE_VIEW 63#undef GET_NATIVE_VIEW 64#endif 65 66#define GET_NATIVE_VIEW(env, obj) ((WebView*)env->GetIntField(obj, gWebViewField)) 67 68#include <JNIUtility.h> 69#include <JNIHelp.h> 70#include <jni.h> 71#include <androidfw/KeycodeLabels.h> 72#include <wtf/text/AtomicString.h> 73#include <wtf/text/CString.h> 74 75// Free as much as we possible can 76#define TRIM_MEMORY_COMPLETE 80 77// Free a lot (all textures gone) 78#define TRIM_MEMORY_MODERATE 60 79// More moderate free (keep bare minimum to restore quickly-ish - possibly clear all textures) 80#define TRIM_MEMORY_BACKGROUND 40 81// Moderate free (clear cached tiles, keep visible ones) 82#define TRIM_MEMORY_UI_HIDDEN 20 83// Duration to show the pressed cursor ring 84#define PRESSED_STATE_DURATION 400 85 86namespace android { 87 88static jfieldID gWebViewField; 89 90//------------------------------------- 91 92static jmethodID GetJMethod(JNIEnv* env, jclass clazz, const char name[], const char signature[]) 93{ 94 jmethodID m = env->GetMethodID(clazz, name, signature); 95 ALOG_ASSERT(m, "Could not find method %s", name); 96 return m; 97} 98 99//------------------------------------- 100// This class provides JNI for making calls into native code from the UI side 101// of the multi-threaded WebView. 102class WebView 103{ 104public: 105enum FrameCachePermission { 106 DontAllowNewer, 107 AllowNewer 108}; 109 110#define DRAW_EXTRAS_SIZE 2 111enum DrawExtras { // keep this in sync with WebView.java 112 DrawExtrasNone = 0, 113 DrawExtrasSelection = 1, 114 DrawExtrasCursorRing = 2 115}; 116 117struct JavaGlue { 118 jweak m_obj; 119 jmethodID m_scrollBy; 120 jmethodID m_getScaledMaxXScroll; 121 jmethodID m_getScaledMaxYScroll; 122 jmethodID m_getVisibleRect; 123 jmethodID m_viewInvalidate; 124 jmethodID m_viewInvalidateRect; 125 jmethodID m_postInvalidateDelayed; 126 jmethodID m_pageSwapCallback; 127 jfieldID m_rectLeft; 128 jfieldID m_rectTop; 129 jmethodID m_rectWidth; 130 jmethodID m_rectHeight; 131 jfieldID m_quadFP1; 132 jfieldID m_quadFP2; 133 jfieldID m_quadFP3; 134 jfieldID m_quadFP4; 135 AutoJObject object(JNIEnv* env) { 136 return getRealObject(env, m_obj); 137 } 138} m_javaGlue; 139 140WebView(JNIEnv* env, jobject javaWebView, int viewImpl, WTF::String drawableDir, 141 bool isHighEndGfx) 142 : m_isHighEndGfx(isHighEndGfx) 143{ 144 memset(m_extras, 0, DRAW_EXTRAS_SIZE * sizeof(DrawExtra*)); 145 jclass clazz = env->FindClass("android/webkit/WebViewClassic"); 146 m_javaGlue.m_obj = env->NewWeakGlobalRef(javaWebView); 147 m_javaGlue.m_scrollBy = GetJMethod(env, clazz, "setContentScrollBy", "(IIZ)Z"); 148 m_javaGlue.m_getScaledMaxXScroll = GetJMethod(env, clazz, "getScaledMaxXScroll", "()I"); 149 m_javaGlue.m_getScaledMaxYScroll = GetJMethod(env, clazz, "getScaledMaxYScroll", "()I"); 150 m_javaGlue.m_getVisibleRect = GetJMethod(env, clazz, "sendOurVisibleRect", "()Landroid/graphics/Rect;"); 151 m_javaGlue.m_viewInvalidate = GetJMethod(env, clazz, "viewInvalidate", "()V"); 152 m_javaGlue.m_viewInvalidateRect = GetJMethod(env, clazz, "viewInvalidate", "(IIII)V"); 153 m_javaGlue.m_postInvalidateDelayed = GetJMethod(env, clazz, 154 "viewInvalidateDelayed", "(JIIII)V"); 155 m_javaGlue.m_pageSwapCallback = GetJMethod(env, clazz, "pageSwapCallback", "(Z)V"); 156 env->DeleteLocalRef(clazz); 157 158 jclass rectClass = env->FindClass("android/graphics/Rect"); 159 ALOG_ASSERT(rectClass, "Could not find Rect class"); 160 m_javaGlue.m_rectLeft = env->GetFieldID(rectClass, "left", "I"); 161 m_javaGlue.m_rectTop = env->GetFieldID(rectClass, "top", "I"); 162 m_javaGlue.m_rectWidth = GetJMethod(env, rectClass, "width", "()I"); 163 m_javaGlue.m_rectHeight = GetJMethod(env, rectClass, "height", "()I"); 164 env->DeleteLocalRef(rectClass); 165 166 jclass quadFClass = env->FindClass("android/webkit/QuadF"); 167 ALOG_ASSERT(quadFClass, "Could not find QuadF class"); 168 m_javaGlue.m_quadFP1 = env->GetFieldID(quadFClass, "p1", "Landroid/graphics/PointF;"); 169 m_javaGlue.m_quadFP2 = env->GetFieldID(quadFClass, "p2", "Landroid/graphics/PointF;"); 170 m_javaGlue.m_quadFP3 = env->GetFieldID(quadFClass, "p3", "Landroid/graphics/PointF;"); 171 m_javaGlue.m_quadFP4 = env->GetFieldID(quadFClass, "p4", "Landroid/graphics/PointF;"); 172 env->DeleteLocalRef(quadFClass); 173 174 env->SetIntField(javaWebView, gWebViewField, (jint)this); 175 m_viewImpl = (WebViewCore*) viewImpl; 176 m_generation = 0; 177 m_heightCanMeasure = false; 178 m_lastDx = 0; 179 m_lastDxTime = 0; 180 m_baseLayer = 0; 181 m_glDrawFunctor = 0; 182 m_isDrawingPaused = false; 183#if USE(ACCELERATED_COMPOSITING) 184 m_glWebViewState = 0; 185#endif 186} 187 188~WebView() 189{ 190 if (m_javaGlue.m_obj) 191 { 192 JNIEnv* env = JSC::Bindings::getJNIEnv(); 193 env->DeleteWeakGlobalRef(m_javaGlue.m_obj); 194 m_javaGlue.m_obj = 0; 195 } 196#if USE(ACCELERATED_COMPOSITING) 197 // We must remove the m_glWebViewState prior to deleting m_baseLayer. If we 198 // do not remove it here, we risk having BaseTiles trying to paint using a 199 // deallocated base layer. 200 stopGL(); 201#endif 202 SkSafeUnref(m_baseLayer); 203 delete m_glDrawFunctor; 204 for (int i = 0; i < DRAW_EXTRAS_SIZE; i++) 205 delete m_extras[i]; 206} 207 208DrawExtra* getDrawExtra(DrawExtras extras) 209{ 210 if (extras == DrawExtrasNone) 211 return 0; 212 return m_extras[extras - 1]; 213} 214 215void stopGL() 216{ 217#if USE(ACCELERATED_COMPOSITING) 218 delete m_glWebViewState; 219 m_glWebViewState = 0; 220#endif 221} 222 223WebViewCore* getWebViewCore() const { 224 return m_viewImpl; 225} 226 227void scrollRectOnScreen(const IntRect& rect) 228{ 229 if (rect.isEmpty()) 230 return; 231 int dx = 0; 232 int left = rect.x(); 233 int right = rect.maxX(); 234 if (left < m_visibleRect.fLeft) 235 dx = left - m_visibleRect.fLeft; 236 // Only scroll right if the entire width can fit on screen. 237 else if (right > m_visibleRect.fRight 238 && right - left < m_visibleRect.width()) 239 dx = right - m_visibleRect.fRight; 240 int dy = 0; 241 int top = rect.y(); 242 int bottom = rect.maxY(); 243 if (top < m_visibleRect.fTop) 244 dy = top - m_visibleRect.fTop; 245 // Only scroll down if the entire height can fit on screen 246 else if (bottom > m_visibleRect.fBottom 247 && bottom - top < m_visibleRect.height()) 248 dy = bottom - m_visibleRect.fBottom; 249 if ((dx|dy) == 0 || !scrollBy(dx, dy)) 250 return; 251 viewInvalidate(); 252} 253 254int drawGL(WebCore::IntRect& viewRect, WebCore::IntRect* invalRect, 255 WebCore::IntRect& webViewRect, int titleBarHeight, 256 WebCore::IntRect& clip, float scale, int extras, bool shouldDraw) 257{ 258#if USE(ACCELERATED_COMPOSITING) 259 if (!m_baseLayer) 260 return 0; 261 262 if (!m_glWebViewState) { 263 TilesManager::instance()->setHighEndGfx(m_isHighEndGfx); 264 m_glWebViewState = new GLWebViewState(); 265 m_glWebViewState->setBaseLayer(m_baseLayer, false, true); 266 } 267 268 DrawExtra* extra = getDrawExtra((DrawExtras) extras); 269 270 m_glWebViewState->glExtras()->setDrawExtra(extra); 271 272 // Make sure we have valid coordinates. We might not have valid coords 273 // if the zoom manager is still initializing. We will be redrawn 274 // once the correct scale is set 275 if (!m_visibleRect.isFinite()) 276 return 0; 277 bool treesSwapped = false; 278 bool newTreeHasAnim = false; 279 int ret = m_glWebViewState->drawGL(viewRect, m_visibleRect, invalRect, 280 webViewRect, titleBarHeight, clip, scale, 281 &treesSwapped, &newTreeHasAnim, shouldDraw); 282 if (treesSwapped) { 283 ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); 284 JNIEnv* env = JSC::Bindings::getJNIEnv(); 285 AutoJObject javaObject = m_javaGlue.object(env); 286 if (javaObject.get()) { 287 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_pageSwapCallback, newTreeHasAnim); 288 checkException(env); 289 } 290 } 291 return m_isDrawingPaused ? 0 : ret; 292#endif 293 return 0; 294} 295 296PictureSet* draw(SkCanvas* canvas, SkColor bgColor, DrawExtras extras, bool split) 297{ 298 PictureSet* ret = 0; 299 if (!m_baseLayer) { 300 canvas->drawColor(bgColor); 301 return ret; 302 } 303 304 // draw the content of the base layer first 305 LayerContent* content = m_baseLayer->content(); 306 int sc = canvas->save(SkCanvas::kClip_SaveFlag); 307 int contentWidth = 0; 308 int contentHeight = 0; 309 if (content) { 310 contentWidth = content->width(); 311 contentHeight = content->height(); 312 } 313 canvas->clipRect(SkRect::MakeLTRB(0, 0, contentWidth, contentHeight), 314 SkRegion::kDifference_Op); 315 Color c = m_baseLayer->getBackgroundColor(); 316 canvas->drawColor(SkColorSetARGBInline(c.alpha(), c.red(), c.green(), c.blue())); 317 canvas->restoreToCount(sc); 318 319 // call this to be sure we've adjusted for any scrolling or animations 320 // before we actually draw 321 m_baseLayer->updateLayerPositions(m_visibleRect); 322 m_baseLayer->updatePositions(); 323 324 // We have to set the canvas' matrix on the base layer 325 // (to have fixed layers work as intended) 326 SkAutoCanvasRestore restore(canvas, true); 327 m_baseLayer->setMatrix(canvas->getTotalMatrix()); 328 canvas->resetMatrix(); 329 m_baseLayer->draw(canvas, getDrawExtra(extras)); 330 331 return ret; 332} 333 334int getScaledMaxXScroll() 335{ 336 ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); 337 JNIEnv* env = JSC::Bindings::getJNIEnv(); 338 AutoJObject javaObject = m_javaGlue.object(env); 339 if (!javaObject.get()) 340 return 0; 341 int result = env->CallIntMethod(javaObject.get(), m_javaGlue.m_getScaledMaxXScroll); 342 checkException(env); 343 return result; 344} 345 346int getScaledMaxYScroll() 347{ 348 ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); 349 JNIEnv* env = JSC::Bindings::getJNIEnv(); 350 AutoJObject javaObject = m_javaGlue.object(env); 351 if (!javaObject.get()) 352 return 0; 353 int result = env->CallIntMethod(javaObject.get(), m_javaGlue.m_getScaledMaxYScroll); 354 checkException(env); 355 return result; 356} 357 358IntRect getVisibleRect() 359{ 360 IntRect rect; 361 ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); 362 JNIEnv* env = JSC::Bindings::getJNIEnv(); 363 AutoJObject javaObject = m_javaGlue.object(env); 364 if (!javaObject.get()) 365 return rect; 366 jobject jRect = env->CallObjectMethod(javaObject.get(), m_javaGlue.m_getVisibleRect); 367 checkException(env); 368 rect.setX(env->GetIntField(jRect, m_javaGlue.m_rectLeft)); 369 checkException(env); 370 rect.setY(env->GetIntField(jRect, m_javaGlue.m_rectTop)); 371 checkException(env); 372 rect.setWidth(env->CallIntMethod(jRect, m_javaGlue.m_rectWidth)); 373 checkException(env); 374 rect.setHeight(env->CallIntMethod(jRect, m_javaGlue.m_rectHeight)); 375 checkException(env); 376 env->DeleteLocalRef(jRect); 377 checkException(env); 378 return rect; 379} 380 381#if USE(ACCELERATED_COMPOSITING) 382static const ScrollableLayerAndroid* findScrollableLayer( 383 const LayerAndroid* parent, int x, int y, SkIRect* foundBounds) { 384 SkRect bounds; 385 parent->bounds(&bounds); 386 // Check the parent bounds first; this will clip to within a masking layer's 387 // bounds. 388 if (parent->masksToBounds() && !bounds.contains(x, y)) 389 return 0; 390 // Move the hit test local to parent. 391 x -= bounds.fLeft; 392 y -= bounds.fTop; 393 int count = parent->countChildren(); 394 while (count--) { 395 const LayerAndroid* child = parent->getChild(count); 396 const ScrollableLayerAndroid* result = findScrollableLayer(child, x, y, 397 foundBounds); 398 if (result) { 399 foundBounds->offset(bounds.fLeft, bounds.fTop); 400 if (parent->masksToBounds()) { 401 if (bounds.width() < foundBounds->width()) 402 foundBounds->fRight = foundBounds->fLeft + bounds.width(); 403 if (bounds.height() < foundBounds->height()) 404 foundBounds->fBottom = foundBounds->fTop + bounds.height(); 405 } 406 return result; 407 } 408 } 409 if (parent->contentIsScrollable()) { 410 foundBounds->set(0, 0, bounds.width(), bounds.height()); 411 return static_cast<const ScrollableLayerAndroid*>(parent); 412 } 413 return 0; 414} 415#endif 416 417int scrollableLayer(int x, int y, SkIRect* layerRect, SkIRect* bounds) 418{ 419#if USE(ACCELERATED_COMPOSITING) 420 if (!m_baseLayer) 421 return 0; 422 const ScrollableLayerAndroid* result = findScrollableLayer(m_baseLayer, x, y, bounds); 423 if (result) { 424 result->getScrollRect(layerRect); 425 return result->uniqueId(); 426 } 427#endif 428 return 0; 429} 430 431void scrollLayer(int layerId, int x, int y) 432{ 433 if (m_glWebViewState) 434 m_glWebViewState->scrollLayer(layerId, x, y); 435} 436 437void setHeightCanMeasure(bool measure) 438{ 439 m_heightCanMeasure = measure; 440} 441 442String getSelection() 443{ 444 SelectText* select = static_cast<SelectText*>( 445 getDrawExtra(WebView::DrawExtrasSelection)); 446 if (select) 447 return select->getText(); 448 return String(); 449} 450 451bool scrollBy(int dx, int dy) 452{ 453 ALOG_ASSERT(m_javaGlue.m_obj, "A java object was not associated with this native WebView!"); 454 455 JNIEnv* env = JSC::Bindings::getJNIEnv(); 456 AutoJObject javaObject = m_javaGlue.object(env); 457 if (!javaObject.get()) 458 return false; 459 bool result = env->CallBooleanMethod(javaObject.get(), m_javaGlue.m_scrollBy, dx, dy, true); 460 checkException(env); 461 return result; 462} 463 464void setIsScrolling(bool isScrolling) 465{ 466#if USE(ACCELERATED_COMPOSITING) 467 if (m_glWebViewState) 468 m_glWebViewState->setIsScrolling(isScrolling); 469#endif 470} 471 472void viewInvalidate() 473{ 474 JNIEnv* env = JSC::Bindings::getJNIEnv(); 475 AutoJObject javaObject = m_javaGlue.object(env); 476 if (!javaObject.get()) 477 return; 478 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_viewInvalidate); 479 checkException(env); 480} 481 482void viewInvalidateRect(int l, int t, int r, int b) 483{ 484 JNIEnv* env = JSC::Bindings::getJNIEnv(); 485 AutoJObject javaObject = m_javaGlue.object(env); 486 if (!javaObject.get()) 487 return; 488 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_viewInvalidateRect, l, r, t, b); 489 checkException(env); 490} 491 492void postInvalidateDelayed(int64_t delay, const WebCore::IntRect& bounds) 493{ 494 JNIEnv* env = JSC::Bindings::getJNIEnv(); 495 AutoJObject javaObject = m_javaGlue.object(env); 496 if (!javaObject.get()) 497 return; 498 env->CallVoidMethod(javaObject.get(), m_javaGlue.m_postInvalidateDelayed, 499 delay, bounds.x(), bounds.y(), bounds.maxX(), bounds.maxY()); 500 checkException(env); 501} 502 503#if ENABLE(ANDROID_OVERFLOW_SCROLL) 504static void copyScrollPositionRecursive(const LayerAndroid* from, 505 LayerAndroid* root) 506{ 507 if (!from || !root) 508 return; 509 for (int i = 0; i < from->countChildren(); i++) { 510 const LayerAndroid* l = from->getChild(i); 511 if (l->contentIsScrollable()) { 512 const SkPoint& pos = l->getPosition(); 513 LayerAndroid* match = root->findById(l->uniqueId()); 514 if (match && match->contentIsScrollable()) 515 match->setPosition(pos.fX, pos.fY); 516 } 517 copyScrollPositionRecursive(l, root); 518 } 519} 520#endif 521 522BaseLayerAndroid* getBaseLayer() const { return m_baseLayer; } 523 524bool setBaseLayer(BaseLayerAndroid* newBaseLayer, bool showVisualIndicator, 525 bool isPictureAfterFirstLayout) 526{ 527 bool queueFull = false; 528#if USE(ACCELERATED_COMPOSITING) 529 if (m_glWebViewState) 530 queueFull = m_glWebViewState->setBaseLayer(newBaseLayer, showVisualIndicator, 531 isPictureAfterFirstLayout); 532#endif 533 534#if ENABLE(ANDROID_OVERFLOW_SCROLL) 535 if (newBaseLayer) { 536 // TODO: the below tree position copies are only necessary in software rendering 537 copyScrollPositionRecursive(m_baseLayer, newBaseLayer); 538 } 539#endif 540 SkSafeUnref(m_baseLayer); 541 m_baseLayer = newBaseLayer; 542 543 return queueFull; 544} 545 546void replaceBaseContent(PictureSet* set) 547{ 548 if (!m_baseLayer) 549 return; 550 // TODO: remove the split picture codepath 551 delete set; 552} 553 554void copyBaseContentToPicture(SkPicture* picture) 555{ 556 if (!m_baseLayer) 557 return; 558 LayerContent* content = m_baseLayer->content(); 559 content->draw(picture->beginRecording(content->width(), content->height(), 560 SkPicture::kUsePathBoundsForClip_RecordingFlag)); 561 picture->endRecording(); 562} 563 564bool hasContent() { 565 if (!m_baseLayer) 566 return false; 567 return !m_baseLayer->content()->isEmpty(); 568} 569 570void setFunctor(Functor* functor) { 571 delete m_glDrawFunctor; 572 m_glDrawFunctor = functor; 573} 574 575Functor* getFunctor() { 576 return m_glDrawFunctor; 577} 578 579void setVisibleRect(SkRect& visibleRect) { 580 m_visibleRect = visibleRect; 581} 582 583void setDrawExtra(DrawExtra *extra, DrawExtras type) 584{ 585 if (type == DrawExtrasNone) 586 return; 587 DrawExtra* old = m_extras[type - 1]; 588 m_extras[type - 1] = extra; 589 if (old != extra) { 590 delete old; 591 } 592} 593 594void setTextSelection(SelectText *selection) { 595 setDrawExtra(selection, DrawExtrasSelection); 596} 597 598const TransformationMatrix* getLayerTransform(int layerId) { 599 if (layerId != -1 && m_baseLayer) { 600 LayerAndroid* layer = m_baseLayer->findById(layerId); 601 // We need to make sure the drawTransform is up to date as this is 602 // called before a draw() or drawGL() 603 if (layer) { 604 m_baseLayer->updateLayerPositions(m_visibleRect); 605 return layer->drawTransform(); 606 } 607 } 608 return 0; 609} 610 611int getHandleLayerId(SelectText::HandleId handleId, SkIPoint& cursorPoint, 612 FloatQuad& textBounds) { 613 SelectText* selectText = static_cast<SelectText*>(getDrawExtra(DrawExtrasSelection)); 614 if (!selectText || !m_baseLayer) 615 return -1; 616 int layerId = selectText->caretLayerId(handleId); 617 IntRect cursorRect = selectText->caretRect(handleId); 618 IntRect textRect = selectText->textRect(handleId); 619 // Rects exclude the last pixel on right/bottom. We want only included pixels. 620 cursorPoint.set(cursorRect.x(), cursorRect.maxY() - 1); 621 textRect.setHeight(std::max(1, textRect.height() - 1)); 622 textRect.setWidth(std::max(1, textRect.width() - 1)); 623 textBounds = FloatQuad(textRect); 624 625 const TransformationMatrix* transform = getLayerTransform(layerId); 626 if (transform) { 627 // We're overloading the concept of Rect to be just the two 628 // points (bottom-left and top-right. 629 cursorPoint = transform->mapPoint(cursorPoint); 630 textBounds = transform->mapQuad(textBounds); 631 } 632 return layerId; 633} 634 635void mapLayerRect(int layerId, SkIRect& rect) { 636 const TransformationMatrix* transform = getLayerTransform(layerId); 637 if (transform) 638 transform->mapRect(rect); 639} 640 641void floatQuadToQuadF(JNIEnv* env, const FloatQuad& nativeTextQuad, 642 jobject textQuad) 643{ 644 jobject p1 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP1); 645 jobject p2 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP2); 646 jobject p3 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP3); 647 jobject p4 = env->GetObjectField(textQuad, m_javaGlue.m_quadFP4); 648 GraphicsJNI::point_to_jpointf(nativeTextQuad.p1(), env, p1); 649 GraphicsJNI::point_to_jpointf(nativeTextQuad.p2(), env, p2); 650 GraphicsJNI::point_to_jpointf(nativeTextQuad.p3(), env, p3); 651 GraphicsJNI::point_to_jpointf(nativeTextQuad.p4(), env, p4); 652 env->DeleteLocalRef(p1); 653 env->DeleteLocalRef(p2); 654 env->DeleteLocalRef(p3); 655 env->DeleteLocalRef(p4); 656} 657 658// This is called when WebView switches rendering modes in a more permanent fashion 659// such as when the layer type is set or the view is attached/detached from the window 660int setHwAccelerated(bool hwAccelerated) { 661 if (!m_glWebViewState) 662 return 0; 663 LayerAndroid* root = m_baseLayer; 664 if (root) 665 return root->setHwAccelerated(hwAccelerated); 666 return 0; 667} 668 669 bool m_isDrawingPaused; 670private: // local state for WebView 671 // private to getFrameCache(); other functions operate in a different thread 672 WebViewCore* m_viewImpl; 673 int m_generation; // associate unique ID with sent kit focus to match with ui 674 // Corresponds to the same-named boolean on the java side. 675 bool m_heightCanMeasure; 676 int m_lastDx; 677 SkMSec m_lastDxTime; 678 DrawExtra* m_extras[DRAW_EXTRAS_SIZE]; 679 BaseLayerAndroid* m_baseLayer; 680 Functor* m_glDrawFunctor; 681#if USE(ACCELERATED_COMPOSITING) 682 GLWebViewState* m_glWebViewState; 683#endif 684 SkRect m_visibleRect; 685 bool m_isHighEndGfx; 686}; // end of WebView class 687 688 689/** 690 * This class holds a function pointer and parameters for calling drawGL into a specific 691 * viewport. The pointer to the Functor will be put on a framework display list to be called 692 * when the display list is replayed. 693 */ 694class GLDrawFunctor : Functor { 695 public: 696 GLDrawFunctor(WebView* _wvInstance, 697 int (WebView::*_funcPtr)(WebCore::IntRect&, WebCore::IntRect*, 698 WebCore::IntRect&, int, WebCore::IntRect&, jfloat, jint, bool), 699 WebCore::IntRect _viewRect, float _scale, int _extras) { 700 wvInstance = _wvInstance; 701 funcPtr = _funcPtr; 702 viewRect = _viewRect; 703 scale = _scale; 704 extras = _extras; 705 }; 706 707 status_t operator()(int messageId, void* data) { 708 TRACE_METHOD(); 709 710 if (viewRect.isEmpty()) { 711 // NOOP operation if viewport is empty 712 return 0; 713 } 714 715 WebCore::IntRect inval; 716 int titlebarHeight = webViewRect.height() - viewRect.height(); 717 718 uirenderer::DrawGlInfo* info = reinterpret_cast<uirenderer::DrawGlInfo*>(data); 719 WebCore::IntRect clip(info->clipLeft, info->clipTop, 720 info->clipRight - info->clipLeft, 721 info->clipBottom - info->clipTop); 722 723 WebCore::IntRect localViewRect = viewRect; 724 if (info->isLayer) { 725 // When webview is on a layer, we need to use the viewport relative 726 // to the FBO, rather than the screen(which will use viewRect). 727 localViewRect.setX(clip.x()); 728 localViewRect.setY(info->height - clip.y() - clip.height()); 729 } 730 bool shouldDraw = (messageId == uirenderer::DrawGlInfo::kModeDraw); 731 // Send the necessary info to the shader. 732 TilesManager::instance()->shader()->setGLDrawInfo(info); 733 734 int returnFlags = (*wvInstance.*funcPtr)(localViewRect, &inval, webViewRect, 735 titlebarHeight, clip, scale, extras, shouldDraw); 736 if ((returnFlags & uirenderer::DrawGlInfo::kStatusDraw) != 0) { 737 IntRect finalInval; 738 if (inval.isEmpty()) 739 finalInval = webViewRect; 740 else { 741 finalInval.setX(webViewRect.x() + inval.x()); 742 finalInval.setY(webViewRect.y() + titlebarHeight + inval.y()); 743 finalInval.setWidth(inval.width()); 744 finalInval.setHeight(inval.height()); 745 } 746 info->dirtyLeft = finalInval.x(); 747 info->dirtyTop = finalInval.y(); 748 info->dirtyRight = finalInval.maxX(); 749 info->dirtyBottom = finalInval.maxY(); 750 } 751 // return 1 if invalidation needed, 2 to request non-drawing functor callback, 0 otherwise 752 ALOGV("returnFlags are %d, shouldDraw %d", returnFlags, shouldDraw); 753 return returnFlags; 754 } 755 void updateRect(WebCore::IntRect& _viewRect) { 756 viewRect = _viewRect; 757 } 758 void updateViewRect(WebCore::IntRect& _viewRect) { 759 webViewRect = _viewRect; 760 } 761 void updateScale(float _scale) { 762 scale = _scale; 763 } 764 private: 765 WebView* wvInstance; 766 int (WebView::*funcPtr)(WebCore::IntRect&, WebCore::IntRect*, 767 WebCore::IntRect&, int, WebCore::IntRect&, float, int, bool); 768 WebCore::IntRect viewRect; 769 WebCore::IntRect webViewRect; 770 jfloat scale; 771 jint extras; 772}; 773 774/* 775 * Native JNI methods 776 */ 777 778static void nativeCreate(JNIEnv *env, jobject obj, int viewImpl, 779 jstring drawableDir, jboolean isHighEndGfx) 780{ 781 WTF::String dir = jstringToWtfString(env, drawableDir); 782 new WebView(env, obj, viewImpl, dir, isHighEndGfx); 783 // NEED THIS OR SOMETHING LIKE IT! 784 //Release(obj); 785} 786 787static WebCore::IntRect jrect_to_webrect(JNIEnv* env, jobject obj) 788{ 789 if (obj) { 790 int L, T, R, B; 791 GraphicsJNI::get_jrect(env, obj, &L, &T, &R, &B); 792 return WebCore::IntRect(L, T, R - L, B - T); 793 } else 794 return WebCore::IntRect(); 795} 796 797static SkRect jrectf_to_rect(JNIEnv* env, jobject obj) 798{ 799 SkRect rect = SkRect::MakeEmpty(); 800 if (obj) 801 GraphicsJNI::jrectf_to_rect(env, obj, &rect); 802 return rect; 803} 804 805static jint nativeDraw(JNIEnv *env, jobject obj, jobject canv, 806 jobject visible, jint color, 807 jint extras, jboolean split) { 808 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, canv); 809 WebView* webView = GET_NATIVE_VIEW(env, obj); 810 SkRect visibleRect = jrectf_to_rect(env, visible); 811 webView->setVisibleRect(visibleRect); 812 PictureSet* pictureSet = webView->draw(canvas, color, 813 static_cast<WebView::DrawExtras>(extras), split); 814 return reinterpret_cast<jint>(pictureSet); 815} 816 817static jint nativeCreateDrawGLFunction(JNIEnv *env, jobject obj, jint nativeView, 818 jobject jrect, jobject jviewrect, 819 jobject jvisiblerect, 820 jfloat scale, jint extras) { 821 WebCore::IntRect viewRect = jrect_to_webrect(env, jrect); 822 WebView *wvInstance = (WebView*) nativeView; 823 SkRect visibleRect = jrectf_to_rect(env, jvisiblerect); 824 wvInstance->setVisibleRect(visibleRect); 825 826 GLDrawFunctor* functor = new GLDrawFunctor(wvInstance, 827 &android::WebView::drawGL, viewRect, scale, extras); 828 wvInstance->setFunctor((Functor*) functor); 829 830 WebCore::IntRect webViewRect = jrect_to_webrect(env, jviewrect); 831 functor->updateViewRect(webViewRect); 832 833 return (jint)functor; 834} 835 836static jint nativeGetDrawGLFunction(JNIEnv *env, jobject obj, jint nativeView) { 837 WebView *wvInstance = (WebView*) nativeView; 838 if (!wvInstance) 839 return 0; 840 841 return (jint) wvInstance->getFunctor(); 842} 843 844static void nativeUpdateDrawGLFunction(JNIEnv *env, jobject obj, jint nativeView, jobject jrect, 845 jobject jviewrect, jobject jvisiblerect, jfloat scale) { 846 WebView *wvInstance = (WebView*) nativeView; 847 if (wvInstance) { 848 GLDrawFunctor* functor = (GLDrawFunctor*) wvInstance->getFunctor(); 849 if (functor) { 850 WebCore::IntRect viewRect = jrect_to_webrect(env, jrect); 851 functor->updateRect(viewRect); 852 853 SkRect visibleRect = jrectf_to_rect(env, jvisiblerect); 854 wvInstance->setVisibleRect(visibleRect); 855 856 WebCore::IntRect webViewRect = jrect_to_webrect(env, jviewrect); 857 functor->updateViewRect(webViewRect); 858 859 functor->updateScale(scale); 860 } 861 } 862} 863 864static bool nativeEvaluateLayersAnimations(JNIEnv *env, jobject obj, jint nativeView) 865{ 866 // only call in software rendering, initialize and evaluate animations 867#if USE(ACCELERATED_COMPOSITING) 868 BaseLayerAndroid* baseLayer = ((WebView*)nativeView)->getBaseLayer(); 869 if (baseLayer) { 870 baseLayer->initAnimations(); 871 return baseLayer->evaluateAnimations(); 872 } 873#endif 874 return false; 875} 876 877static bool nativeSetBaseLayer(JNIEnv *env, jobject obj, jint nativeView, jint layer, 878 jboolean showVisualIndicator, 879 jboolean isPictureAfterFirstLayout) 880{ 881 BaseLayerAndroid* layerImpl = reinterpret_cast<BaseLayerAndroid*>(layer); 882 return ((WebView*)nativeView)->setBaseLayer(layerImpl, showVisualIndicator, 883 isPictureAfterFirstLayout); 884} 885 886static BaseLayerAndroid* nativeGetBaseLayer(JNIEnv *env, jobject obj) 887{ 888 return GET_NATIVE_VIEW(env, obj)->getBaseLayer(); 889} 890 891static void nativeReplaceBaseContent(JNIEnv *env, jobject obj, jint content) 892{ 893 PictureSet* set = reinterpret_cast<PictureSet*>(content); 894 GET_NATIVE_VIEW(env, obj)->replaceBaseContent(set); 895} 896 897static void nativeCopyBaseContentToPicture(JNIEnv *env, jobject obj, jobject pict) 898{ 899 SkPicture* picture = GraphicsJNI::getNativePicture(env, pict); 900 GET_NATIVE_VIEW(env, obj)->copyBaseContentToPicture(picture); 901} 902 903static bool nativeHasContent(JNIEnv *env, jobject obj) 904{ 905 return GET_NATIVE_VIEW(env, obj)->hasContent(); 906} 907 908static jobject nativeLayerBounds(JNIEnv* env, jobject obj, jint jlayer) 909{ 910 SkRect r; 911#if USE(ACCELERATED_COMPOSITING) 912 LayerAndroid* layer = (LayerAndroid*) jlayer; 913 r = layer->bounds(); 914#else 915 r.setEmpty(); 916#endif 917 SkIRect irect; 918 r.round(&irect); 919 jclass rectClass = env->FindClass("android/graphics/Rect"); 920 jmethodID init = env->GetMethodID(rectClass, "<init>", "(IIII)V"); 921 jobject rect = env->NewObject(rectClass, init, irect.fLeft, irect.fTop, 922 irect.fRight, irect.fBottom); 923 env->DeleteLocalRef(rectClass); 924 return rect; 925} 926 927static void nativeSetHeightCanMeasure(JNIEnv *env, jobject obj, bool measure) 928{ 929 WebView* view = GET_NATIVE_VIEW(env, obj); 930 ALOG_ASSERT(view, "view not set in nativeSetHeightCanMeasure"); 931 view->setHeightCanMeasure(measure); 932} 933 934static void nativeDestroy(JNIEnv *env, jobject obj) 935{ 936 WebView* view = GET_NATIVE_VIEW(env, obj); 937 ALOGD("nativeDestroy view: %p", view); 938 ALOG_ASSERT(view, "view not set in nativeDestroy"); 939 delete view; 940} 941 942static void nativeStopGL(JNIEnv *env, jobject obj) 943{ 944 GET_NATIVE_VIEW(env, obj)->stopGL(); 945} 946 947static jobject nativeGetSelection(JNIEnv *env, jobject obj) 948{ 949 WebView* view = GET_NATIVE_VIEW(env, obj); 950 ALOG_ASSERT(view, "view not set in %s", __FUNCTION__); 951 String selection = view->getSelection(); 952 return wtfStringToJstring(env, selection); 953} 954 955static void nativeDiscardAllTextures(JNIEnv *env, jobject obj) 956{ 957 //discard all textures for debugging/test purposes, but not gl backing memory 958 bool allTextures = true, deleteGLTextures = false; 959 TilesManager::instance()->discardTextures(allTextures, deleteGLTextures); 960} 961 962static void nativeTileProfilingStart(JNIEnv *env, jobject obj) 963{ 964 TilesManager::instance()->getProfiler()->start(); 965} 966 967static float nativeTileProfilingStop(JNIEnv *env, jobject obj) 968{ 969 return TilesManager::instance()->getProfiler()->stop(); 970} 971 972static void nativeTileProfilingClear(JNIEnv *env, jobject obj) 973{ 974 TilesManager::instance()->getProfiler()->clear(); 975} 976 977static int nativeTileProfilingNumFrames(JNIEnv *env, jobject obj) 978{ 979 return TilesManager::instance()->getProfiler()->numFrames(); 980} 981 982static int nativeTileProfilingNumTilesInFrame(JNIEnv *env, jobject obj, int frame) 983{ 984 return TilesManager::instance()->getProfiler()->numTilesInFrame(frame); 985} 986 987static int nativeTileProfilingGetInt(JNIEnv *env, jobject obj, int frame, int tile, jstring jkey) 988{ 989 WTF::String key = jstringToWtfString(env, jkey); 990 TileProfileRecord* record = TilesManager::instance()->getProfiler()->getTile(frame, tile); 991 992 if (key == "left") 993 return record->left; 994 if (key == "top") 995 return record->top; 996 if (key == "right") 997 return record->right; 998 if (key == "bottom") 999 return record->bottom; 1000 if (key == "level") 1001 return record->level; 1002 if (key == "isReady") 1003 return record->isReady ? 1 : 0; 1004 return -1; 1005} 1006 1007static float nativeTileProfilingGetFloat(JNIEnv *env, jobject obj, int frame, int tile, jstring jkey) 1008{ 1009 TileProfileRecord* record = TilesManager::instance()->getProfiler()->getTile(frame, tile); 1010 return record->scale; 1011} 1012 1013#ifdef ANDROID_DUMP_DISPLAY_TREE 1014static void dumpToFile(const char text[], void* file) { 1015 fwrite(text, 1, strlen(text), reinterpret_cast<FILE*>(file)); 1016 fwrite("\n", 1, 1, reinterpret_cast<FILE*>(file)); 1017} 1018#endif 1019 1020// Return true to view invalidate WebView 1021static bool nativeSetProperty(JNIEnv *env, jobject obj, jstring jkey, jstring jvalue) 1022{ 1023 WTF::String key = jstringToWtfString(env, jkey); 1024 WTF::String value = jstringToWtfString(env, jvalue); 1025 if (key == "inverted") { 1026 bool shouldInvert = (value == "true"); 1027 TilesManager::instance()->setInvertedScreen(shouldInvert); 1028 return true; 1029 } 1030 else if (key == "inverted_contrast") { 1031 float contrast = value.toFloat(); 1032 TilesManager::instance()->setInvertedScreenContrast(contrast); 1033 return true; 1034 } 1035 else if (key == "enable_cpu_upload_path") { 1036 TilesManager::instance()->transferQueue()->setTextureUploadType( 1037 value == "true" ? CpuUpload : GpuUpload); 1038 } 1039 else if (key == "use_minimal_memory") { 1040 TilesManager::instance()->setUseMinimalMemory(value == "true"); 1041 } 1042 else if (key == "use_double_buffering") { 1043 TilesManager::instance()->setUseDoubleBuffering(value == "true"); 1044 } 1045 else if (key == "tree_updates") { 1046 TilesManager::instance()->clearContentUpdates(); 1047 } 1048 return false; 1049} 1050 1051static jstring nativeGetProperty(JNIEnv *env, jobject obj, jstring jkey) 1052{ 1053 WTF::String key = jstringToWtfString(env, jkey); 1054 if (key == "tree_updates") { 1055 int updates = TilesManager::instance()->getContentUpdates(); 1056 WTF::String wtfUpdates = WTF::String::number(updates); 1057 return wtfStringToJstring(env, wtfUpdates); 1058 } 1059 return 0; 1060} 1061 1062static void nativeOnTrimMemory(JNIEnv *env, jobject obj, jint level) 1063{ 1064 if (TilesManager::hardwareAccelerationEnabled()) { 1065 // When we got TRIM_MEMORY_MODERATE or TRIM_MEMORY_COMPLETE, we should 1066 // make sure the transfer queue is empty and then abandon the Surface 1067 // Texture to avoid ANR b/c framework may destroy the EGL context. 1068 // Refer to WindowManagerImpl.java for conditions we followed. 1069 TilesManager* tilesManager = TilesManager::instance(); 1070 if ((level >= TRIM_MEMORY_MODERATE 1071 && !tilesManager->highEndGfx()) 1072 || level >= TRIM_MEMORY_COMPLETE) { 1073 ALOGD("OnTrimMemory with EGL Context %p", eglGetCurrentContext()); 1074 tilesManager->cleanupGLResources(); 1075 } 1076 1077 bool freeAllTextures = (level > TRIM_MEMORY_UI_HIDDEN), glTextures = true; 1078 tilesManager->discardTextures(freeAllTextures, glTextures); 1079 } 1080} 1081 1082static void nativeDumpDisplayTree(JNIEnv* env, jobject jwebview, jstring jurl) 1083{ 1084#ifdef ANDROID_DUMP_DISPLAY_TREE 1085 WebView* view = GET_NATIVE_VIEW(env, jwebview); 1086 ALOG_ASSERT(view, "view not set in %s", __FUNCTION__); 1087 1088 if (view && view->getWebViewCore()) { 1089 FILE* file = fopen(DISPLAY_TREE_LOG_FILE, "w"); 1090 if (file) { 1091 SkFormatDumper dumper(dumpToFile, file); 1092 // dump the URL 1093 if (jurl) { 1094 const char* str = env->GetStringUTFChars(jurl, 0); 1095 SkDebugf("Dumping %s to %s\n", str, DISPLAY_TREE_LOG_FILE); 1096 dumpToFile(str, file); 1097 env->ReleaseStringUTFChars(jurl, str); 1098 } 1099 // now dump the display tree 1100 SkDumpCanvas canvas(&dumper); 1101 // this will playback the picture into the canvas, which will 1102 // spew its contents to the dumper 1103 view->draw(&canvas, 0, WebView::DrawExtrasNone, false); 1104 // we're done with the file now 1105 fwrite("\n", 1, 1, file); 1106 fclose(file); 1107 } 1108#if USE(ACCELERATED_COMPOSITING) 1109 const LayerAndroid* baseLayer = view->getBaseLayer(); 1110 if (baseLayer) { 1111 FILE* file = fopen(LAYERS_TREE_LOG_FILE,"w"); 1112 if (file) { 1113 baseLayer->dumpLayers(file, 0); 1114 fclose(file); 1115 } 1116 } 1117#endif 1118 } 1119#endif 1120} 1121 1122static int nativeScrollableLayer(JNIEnv* env, jobject jwebview, jint nativeView, 1123 jint x, jint y, jobject rect, jobject bounds) 1124{ 1125 WebView* webview = reinterpret_cast<WebView*>(nativeView); 1126 ALOG_ASSERT(webview, "webview not set in %s", __FUNCTION__); 1127 SkIRect nativeRect, nativeBounds; 1128 int id = webview->scrollableLayer(x, y, &nativeRect, &nativeBounds); 1129 if (rect) 1130 GraphicsJNI::irect_to_jrect(nativeRect, env, rect); 1131 if (bounds) 1132 GraphicsJNI::irect_to_jrect(nativeBounds, env, bounds); 1133 return id; 1134} 1135 1136static bool nativeScrollLayer(JNIEnv* env, jobject obj, 1137 jint nativeView, jint layerId, jint x, jint y) 1138{ 1139#if ENABLE(ANDROID_OVERFLOW_SCROLL) 1140 WebView* webview = reinterpret_cast<WebView*>(nativeView); 1141 webview->scrollLayer(layerId, x, y); 1142 1143 //TODO: the below only needed for the SW rendering path 1144 LayerAndroid* baseLayer = webview->getBaseLayer(); 1145 if (!baseLayer) 1146 return false; 1147 LayerAndroid* layer = baseLayer->findById(layerId); 1148 if (!layer || !layer->contentIsScrollable()) 1149 return false; 1150 return static_cast<ScrollableLayerAndroid*>(layer)->scrollTo(x, y); 1151#endif 1152 return false; 1153} 1154 1155static void nativeSetIsScrolling(JNIEnv* env, jobject jwebview, jboolean isScrolling) 1156{ 1157 WebView* view = GET_NATIVE_VIEW(env, jwebview); 1158 ALOG_ASSERT(view, "view not set in %s", __FUNCTION__); 1159 view->setIsScrolling(isScrolling); 1160} 1161 1162static void nativeUseHardwareAccelSkia(JNIEnv*, jobject, jboolean enabled) 1163{ 1164 BaseRenderer::setCurrentRendererType(enabled ? BaseRenderer::Ganesh : BaseRenderer::Raster); 1165} 1166 1167static int nativeGetBackgroundColor(JNIEnv* env, jobject obj) 1168{ 1169 WebView* view = GET_NATIVE_VIEW(env, obj); 1170 BaseLayerAndroid* baseLayer = view->getBaseLayer(); 1171 if (baseLayer) { 1172 WebCore::Color color = baseLayer->getBackgroundColor(); 1173 if (color.isValid()) 1174 return SkColorSetARGB(color.alpha(), color.red(), 1175 color.green(), color.blue()); 1176 } 1177 return SK_ColorWHITE; 1178} 1179 1180static void nativeSetPauseDrawing(JNIEnv *env, jobject obj, jint nativeView, 1181 jboolean pause) 1182{ 1183 ((WebView*)nativeView)->m_isDrawingPaused = pause; 1184} 1185 1186static void nativeSetTextSelection(JNIEnv *env, jobject obj, jint nativeView, 1187 jint selectionPtr) 1188{ 1189 SelectText* selection = reinterpret_cast<SelectText*>(selectionPtr); 1190 reinterpret_cast<WebView*>(nativeView)->setTextSelection(selection); 1191} 1192 1193static jint nativeGetHandleLayerId(JNIEnv *env, jobject obj, jint nativeView, 1194 jint handleIndex, jobject cursorPoint, 1195 jobject textQuad) 1196{ 1197 WebView* webview = reinterpret_cast<WebView*>(nativeView); 1198 SkIPoint nativePoint; 1199 FloatQuad nativeTextQuad; 1200 int layerId = webview->getHandleLayerId((SelectText::HandleId) handleIndex, 1201 nativePoint, nativeTextQuad); 1202 if (cursorPoint) 1203 GraphicsJNI::ipoint_to_jpoint(nativePoint, env, cursorPoint); 1204 if (textQuad) 1205 webview->floatQuadToQuadF(env, nativeTextQuad, textQuad); 1206 return layerId; 1207} 1208 1209static jboolean nativeIsBaseFirst(JNIEnv *env, jobject obj, jint nativeView) 1210{ 1211 WebView* webview = reinterpret_cast<WebView*>(nativeView); 1212 SelectText* select = static_cast<SelectText*>( 1213 webview->getDrawExtra(WebView::DrawExtrasSelection)); 1214 return select ? select->isBaseFirst() : false; 1215} 1216 1217static void nativeMapLayerRect(JNIEnv *env, jobject obj, jint nativeView, 1218 jint layerId, jobject rect) 1219{ 1220 WebView* webview = reinterpret_cast<WebView*>(nativeView); 1221 SkIRect nativeRect; 1222 GraphicsJNI::jrect_to_irect(env, rect, &nativeRect); 1223 webview->mapLayerRect(layerId, nativeRect); 1224 GraphicsJNI::irect_to_jrect(nativeRect, env, rect); 1225} 1226 1227static jint nativeSetHwAccelerated(JNIEnv *env, jobject obj, jint nativeView, 1228 jboolean hwAccelerated) 1229{ 1230 WebView* webview = reinterpret_cast<WebView*>(nativeView); 1231 return webview->setHwAccelerated(hwAccelerated); 1232} 1233 1234/* 1235 * JNI registration 1236 */ 1237static JNINativeMethod gJavaWebViewMethods[] = { 1238 { "nativeCreate", "(ILjava/lang/String;Z)V", 1239 (void*) nativeCreate }, 1240 { "nativeDestroy", "()V", 1241 (void*) nativeDestroy }, 1242 { "nativeDraw", "(Landroid/graphics/Canvas;Landroid/graphics/RectF;IIZ)I", 1243 (void*) nativeDraw }, 1244 { "nativeCreateDrawGLFunction", "(ILandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/RectF;FI)I", 1245 (void*) nativeCreateDrawGLFunction }, 1246 { "nativeGetDrawGLFunction", "(I)I", 1247 (void*) nativeGetDrawGLFunction }, 1248 { "nativeUpdateDrawGLFunction", "(ILandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/RectF;F)V", 1249 (void*) nativeUpdateDrawGLFunction }, 1250 { "nativeDumpDisplayTree", "(Ljava/lang/String;)V", 1251 (void*) nativeDumpDisplayTree }, 1252 { "nativeEvaluateLayersAnimations", "(I)Z", 1253 (void*) nativeEvaluateLayersAnimations }, 1254 { "nativeGetSelection", "()Ljava/lang/String;", 1255 (void*) nativeGetSelection }, 1256 { "nativeLayerBounds", "(I)Landroid/graphics/Rect;", 1257 (void*) nativeLayerBounds }, 1258 { "nativeSetHeightCanMeasure", "(Z)V", 1259 (void*) nativeSetHeightCanMeasure }, 1260 { "nativeSetBaseLayer", "(IIZZ)Z", 1261 (void*) nativeSetBaseLayer }, 1262 { "nativeGetBaseLayer", "()I", 1263 (void*) nativeGetBaseLayer }, 1264 { "nativeReplaceBaseContent", "(I)V", 1265 (void*) nativeReplaceBaseContent }, 1266 { "nativeCopyBaseContentToPicture", "(Landroid/graphics/Picture;)V", 1267 (void*) nativeCopyBaseContentToPicture }, 1268 { "nativeHasContent", "()Z", 1269 (void*) nativeHasContent }, 1270 { "nativeDiscardAllTextures", "()V", 1271 (void*) nativeDiscardAllTextures }, 1272 { "nativeTileProfilingStart", "()V", 1273 (void*) nativeTileProfilingStart }, 1274 { "nativeTileProfilingStop", "()F", 1275 (void*) nativeTileProfilingStop }, 1276 { "nativeTileProfilingClear", "()V", 1277 (void*) nativeTileProfilingClear }, 1278 { "nativeTileProfilingNumFrames", "()I", 1279 (void*) nativeTileProfilingNumFrames }, 1280 { "nativeTileProfilingNumTilesInFrame", "(I)I", 1281 (void*) nativeTileProfilingNumTilesInFrame }, 1282 { "nativeTileProfilingGetInt", "(IILjava/lang/String;)I", 1283 (void*) nativeTileProfilingGetInt }, 1284 { "nativeTileProfilingGetFloat", "(IILjava/lang/String;)F", 1285 (void*) nativeTileProfilingGetFloat }, 1286 { "nativeStopGL", "()V", 1287 (void*) nativeStopGL }, 1288 { "nativeScrollableLayer", "(IIILandroid/graphics/Rect;Landroid/graphics/Rect;)I", 1289 (void*) nativeScrollableLayer }, 1290 { "nativeScrollLayer", "(IIII)Z", 1291 (void*) nativeScrollLayer }, 1292 { "nativeSetIsScrolling", "(Z)V", 1293 (void*) nativeSetIsScrolling }, 1294 { "nativeUseHardwareAccelSkia", "(Z)V", 1295 (void*) nativeUseHardwareAccelSkia }, 1296 { "nativeGetBackgroundColor", "()I", 1297 (void*) nativeGetBackgroundColor }, 1298 { "nativeSetProperty", "(Ljava/lang/String;Ljava/lang/String;)Z", 1299 (void*) nativeSetProperty }, 1300 { "nativeGetProperty", "(Ljava/lang/String;)Ljava/lang/String;", 1301 (void*) nativeGetProperty }, 1302 { "nativeOnTrimMemory", "(I)V", 1303 (void*) nativeOnTrimMemory }, 1304 { "nativeSetPauseDrawing", "(IZ)V", 1305 (void*) nativeSetPauseDrawing }, 1306 { "nativeSetTextSelection", "(II)V", 1307 (void*) nativeSetTextSelection }, 1308 { "nativeGetHandleLayerId", "(IILandroid/graphics/Point;Landroid/webkit/QuadF;)I", 1309 (void*) nativeGetHandleLayerId }, 1310 { "nativeIsBaseFirst", "(I)Z", 1311 (void*) nativeIsBaseFirst }, 1312 { "nativeMapLayerRect", "(IILandroid/graphics/Rect;)V", 1313 (void*) nativeMapLayerRect }, 1314 { "nativeSetHwAccelerated", "(IZ)I", 1315 (void*) nativeSetHwAccelerated }, 1316}; 1317 1318int registerWebView(JNIEnv* env) 1319{ 1320 jclass clazz = env->FindClass("android/webkit/WebViewClassic"); 1321 ALOG_ASSERT(clazz, "Unable to find class android/webkit/WebViewClassic"); 1322 gWebViewField = env->GetFieldID(clazz, "mNativeClass", "I"); 1323 ALOG_ASSERT(gWebViewField, "Unable to find android/webkit/WebViewClassic.mNativeClass"); 1324 env->DeleteLocalRef(clazz); 1325 1326 return jniRegisterNativeMethods(env, "android/webkit/WebViewClassic", gJavaWebViewMethods, NELEM(gJavaWebViewMethods)); 1327} 1328 1329} // namespace android 1330